Skip to content

Commit

Permalink
bug #27214 [HttpKernel] Fix services are no longer injected into __in…
Browse files Browse the repository at this point in the history
…voke controllers method (ogizanagi)

This PR was merged into the 4.1 branch.

Discussion
----------

[HttpKernel] Fix services are no longer injected into __invoke controllers method

| Q             | A
| ------------- | ---
| Branch?       | 4.1 <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | #27208   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A

_TL;DR:_ The `RemoveEmptyControllerArgumentLocatorsPass` is the one adding the `Controller::_invoke` => `Controller` shortcut missing from the service locator. It isn't properly executed on some cases. This fixes it.

Since #26833, the resolvers are decorated by a `TraceableValueResolver`, which usually isn't much an issue to deal within passes. But the `RemoveEmptyControllerArgumentLocatorsPass` happens late (`TYPE_BEFORE_REMOVING`), when decoration inheritance is already resolved, so accessing `$controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0));` isn't accessing the controller locator, but the decorated service instead.

Commits
-------

ee44903 [HttpKernel] Fix services are no longer injected into __invoke controllers method
  • Loading branch information
fabpot committed May 14, 2018
2 parents 906a05c + ee44903 commit 5f0e2d6
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 11 deletions.
Expand Up @@ -33,11 +33,13 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
{
private $resolverServiceId;
private $controllerTag;
private $controllerLocator;

public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments')
public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator')
{
$this->resolverServiceId = $resolverServiceId;
$this->controllerTag = $controllerTag;
$this->controllerLocator = $controllerLocator;
}

public function process(ContainerBuilder $container)
Expand Down Expand Up @@ -179,6 +181,8 @@ public function process(ContainerBuilder $container)
}

$container->getDefinition($this->resolverServiceId)
->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers));
->replaceArgument(0, $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers));

$container->setAlias($this->controllerLocator, (string) $controllerLocatorRef);
}
}
Expand Up @@ -21,21 +21,16 @@
*/
class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
{
private $resolverServiceId;
private $controllerLocator;

public function __construct(string $resolverServiceId = 'argument_resolver.service')
public function __construct(string $controllerLocator = 'argument_resolver.controller_locator')
{
$this->resolverServiceId = $resolverServiceId;
$this->controllerLocator = $controllerLocator;
}

public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition($this->resolverServiceId)) {
return;
}

$serviceResolver = $container->getDefinition($this->resolverServiceId);
$controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0));
$controllerLocator = $container->findDefinition($this->controllerLocator);
$controllers = $controllerLocator->getArgument(0);

foreach ($controllers as $controller => $argumentRef) {
Expand Down

0 comments on commit 5f0e2d6

Please sign in to comment.