Closed (fixed)
Project:
Drupal core
Version:
9.4.x-dev
Component:
update.module
Priority:
Critical
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
9 Sep 2021 at 10:21 UTC
Updated:
10 Sep 2023 at 08:42 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
daffie commentedI could not find any overrides of the class
Drupal\Component\DependencyInjection\Containerin contrib. See: http://grep.xnddx.ru/search?text=Drupal%5CComponent%5CDependencyInjectio...Comment #3
larowlanthis is D10 (php 8) only territory
Comment #4
daffie commentedPart of the Symfony 6 in D10 initiative.
Comment #5
daffie commentedChange "null" to "NULL" as lowercase is not allowed.
Comment #6
daffie commentedChanged
return;toreturn NULL;as it is not the same.Comment #7
daffie commentedThe reason why the testbot has problems with the method
Symfony\Component\DependencyInjection\ContainerInterface::get()having the return type hint?objectis the serviceupdate.rootwhich is defined as:The class
SplStringalways returns a string, which is not a object.In #3074585: [Symfony 5] Replace app.root and site.path string services with container parameters they changed "app.root" and "site.path" into container parameters. Not sure if that is here the right solution.
Comment #8
daffie commentedMoving this to the update module.
Comment #9
andypostTypeError: Drupal\Component\DependencyInjection\Container::get(): Return value must be of type ?object, string returnedComment #10
daffie commentedComment #11
daffie commentedUpdated the issue that it is only for refactoring the "update.root" service. The return type hint will be added in #3238485: [Symfony 6] Add return type hints to the class methods of Drupal\Component\DependencyInjection\Container, only that shall have to go in the 10.0 branch.
Comment #12
dwwI started taking a look at this. The
update.rootserviceisbeing used. Updating the title here accordingly.The following files in core/modules/update all use this service:
./update.authorize.inc
./src/Form/UpdateManagerInstall.php
./src/Form/UpdateReady.php
The "service" is a shim to return the root path that the update manager should use for installing new / updated packages. It's actually something to make update manager more testable. Since the meat of the "service" is this:
I can't believe we have real BC implications to worry about here. I can't imagine real sites are trying to override this "service" to customize Update Manager behavior. I think we just need to reconsider how this should work to be more Symfony 6 friendly. We can probably just change it so that get() returns the service and the service provides a new
getRoot()method or whatever.Comment #13
longwaveIn #3074585: [Symfony 5] Replace app.root and site.path string services with container parameters we converted the app.root service (which returned a similar string) to a container parameter, maybe we can do the same for this service.
edit: @daffie already suggested this :)
Comment #14
longwaveLooking at this again I think this does need to be a simple service that returns a string, as it requires the request stack to be injected; a container parameter is set at container build time and the "current request" isn't available in that context.
Also agree with #12 that this is test-only behaviour, the existing service should probably have been tagged @internal and I suggest we do the same for any new service we provide here.
Comment #15
daffie commentedChanged the service "update.root" to return the removed "update.root.factory" service.
Comment #16
daffie commentedComment #17
daffie commentedThe questions that I have is should we properly deprecate the services "update.root" and "update.root.factory" or can they be replaced? There is very little use in contrib. See: http://grep.xnddx.ru/search?text=update.root&filename=
What should the name be of the "new" service?
I have removed the return type hint for the method
Drupal\Component\DependencyInjection\Container::getParameter()as the type hints is for PHP 8.0 or newer.Comment #18
andypostMaybe you could use service provider to provide required service depending on php version, so old one could be removed in D10
Comment #19
andypostor as we used to for similar case in #3074585: [Symfony 5] Replace app.root and site.path string services with container parameters
Comment #20
catchide_helper has no release or usage (and is a developer module). patchinfo does have stable releases and usage, but the
update.rootusage is only in its test coverage.Given that I think opening an issue against both modules + a CR might be enough here.
On the patch itself:
Nice that setting this back on the container isn't necessary.
#3232095-19: [Symfony 6] Refactor the "update.root" service to return an object not a string - are we able to set container parameters from a module? If so that might work as an alternative approach but I can't think of any examples. The two we changed there are hard-coded in DrupalKernel.
Comment #21
longwave> are we able to set container parameters from a module?
Yes, we can add a service provider to update.module that implements ServiceProviderInterface/ServiceModifierInterface. But the problem is this code:
When the container is being rebuilt are we sure the constant will be set and the "current request" will contain the correct site path? This is much, much earlier than the current factory which does these checks at runtime.
edit: if we can guarantee that DRUPAL_TEST_IN_CHILD_SITE will be set then it would perhaps make sense for that to be a container parameter too!
Comment #22
daffie commentedThis patch will break that behavior. That is why the next change is necessary to make it pass the testbot:
I have tried to use a service "parameter" just like "app.root" and "site.path" in #3074585: [Symfony 5] Replace app.root and site.path string services with container parameters only when setting the parameter in updatetestbase I get the following error: "Impossible to call set() on a frozen ParameterBag.". See:
Comment #23
daffie commentedAdded the CR.
Comment #24
andypostFiled issues and patches, I think it ready according to #20
- used in testing code and probably could be removed #3239550: Fix update.root for 9.3.x core and PHP 8.1
- initial patch #3239551: Fix update.root for 9.3.x core and PHP 8.1
Comment #25
andypostRTBC++
Comment #26
dwwThanks for all the work here. I haven’t reviewed closely, but in principle this all sounds good. Meanwhile, giving this a slightly more clear title.
Comment #27
catchShouldn't the container changes happen in their own issue?
Comment #28
catchYep there's already an issue open, we can always open a 9.x issue for anything we want to do from here, but don't think we should combine the changes in this one.
#3238485: [Symfony 6] Add return type hints to the class methods of Drupal\Component\DependencyInjection\Container.
Comment #29
daffie commentedIn the previous patch we had the change. That change was wrong, because we are no longer testing what we should in this test.
I did not add an interdiff as it not very useful.
Comment #30
longwaveI think this is the simplest thing we can do here to solve the problem at hand.
I tried switching the service to a container parameter in a service provider, but it turns out that in a test the container is built in BTB at module install time, not inside the site under test - so the container builder is unaware of where the container will be used, the DRUPAL_TEST_IN_CHILD_SITE constant is not set, and we have no other way to detect this situation that I can see. As @daffie found earlier we also can't modify the parameter inside the container once it's built, so I think the simplest solution is a small service that returns the correct path at runtime depending on whether it is inside a real site or a site under test, which is what we have here.
Agree with @catch in #20 that we can probably remove the existing update.root "service" without deprecation, as only one module really uses it (ide_helper doesn't count to me), and it's a niche feature that is extremely unlikely to be used by custom code.
Comment #31
dwwCircling back to look at this more closely. Agreed this looks good. Thanks @longwave for trying the other approach and confirming it doesn't work. Saving credits for everyone who participated so far, since everyone has contributed something of substance to getting this done.
I only found one micro-nit. Uploading here as a patch/interdiff, and leaving RTBC. Hope I'm not struck by lightning for that. 🤞😉
Comment #32
andypostusually setters return $this but it's used only one so fine
wondering why not set is equal to empty string
Comment #33
dwwThanks for the review, @andypost. Re: #32:
That said, seems we should add the explicit return type for get() since it always returns a string, never NULL.
Comment #34
andypostI mean
if (isset($var))is more readable and fastComment #35
dwwAhh, gotcha. Sure, why not? 😉
Comment #36
andypostI think it ready)
Comment #37
longwaveI had a thought that we could try using the magic
__toString()method instead ofget(), which would mean to callers that this doesn't require a code change, but that it still satisfies the container in that the service is an object. This works for two of the update tests locally, let's see how the bot gets on.Comment #38
longwaveAgreed with @daffie in Slack that if this passes here we should also test against SF5.4 to ensure there are no issues.
Comment #39
dwwThat's promising! I like it.
How do we test on SF5.4? Is that manual at this point or is there a way to do that via DrupalCI?
Comment #40
longwave@dww The best way is by applying the latest patch in #3161889: [META] Symfony 6 compatibility but Symfony's future return type deprecations are currently causing a lot of unwanted noise and false positives which makes the test results hard to read.
Comment #41
longwaveThere were no update module failures in https://www.drupal.org/pift-ci-job/2228443 which was run from https://www.drupal.org/files/issues/2021-11-05/3161889-186.patch - which is various Symfony 5.4 compatibility fixes plus #37 from this issue.
Comment #42
daffie commentedAll the changes look good to me.
The testbot run with Symfony 5.4 was also good.
For me it is RTBC.
Comment #44
catchThis looks good. Wondered whether we want to keep the __toString() around permanently, but given this is mostly internal to update module anyway I think it's OK.
Committed f96b7fb and pushed to 9.4.x. Thanks!
Comment #46
devad commentedIs this committed to D10.0.x?
Here is an example where the same AdminFunctionalityTest passes the D9.4.x test and fails the D10.0.x test with the error message:
Exception: TypeError: Drupal\Component\DependencyInjection\Container::get(): Return value must be of type ?object, string returned#3257627: Add the AdminFunctionality tests
If this post is out-of-topic here please feel free to reply at the related topic and I will delete this message afterwards.
Comment #47
quietone commentedPublished the change record.