diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index f5a31a2e302a9..b4c1615b396c7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -159,10 +159,8 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot, $this->decoratedClass = null; $this->getPreviousValue = null; - if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && ($decoratedDefinition = $definition->getDecoratedService()) && null !== ($innerId = $decoratedDefinition[0]) && $this->container->has($innerId)) { - // If the class references to itself and is decorated, provide the inner service id and class to not get a circular reference - $this->decoratedClass = $this->container->findDefinition($innerId)->getClass(); - $this->decoratedId = $decoratedDefinition[1] ?? $this->currentId.'.inner'; + if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && null !== ($this->decoratedId = $definition->innerServiceId) && $this->container->has($this->decoratedId)) { + $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass(); } $patchedIndexes = []; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 47f51c2478940..ed8e696bb2853 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -62,10 +62,11 @@ public function __construct() new AutowireRequiredMethodsPass(), new AutowireRequiredPropertiesPass(), new ResolveBindingsPass(), + new ServiceLocatorTagPass(), + new DecoratorServicePass(), new CheckDefinitionValidityPass(), new AutowirePass(false), new ServiceLocatorTagPass(), - new DecoratorServicePass(), new ResolveTaggedIteratorArgumentPass(), new ResolveServiceSubscribersPass(), new ResolveReferencesToAliasesPass(), diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 33e9adecfb4ea..9867e73293653 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -985,8 +985,8 @@ public function testAutowireDecorator() ->setAutowired(true) ; - (new AutowirePass())->process($container); (new DecoratorServicePass())->process($container); + (new AutowirePass())->process($container); $definition = $container->getDefinition(Decorator::class); $this->assertSame(Decorator::class.'.inner', (string) $definition->getArgument(1)); @@ -1008,8 +1008,8 @@ public function testAutowireDecoratorChain() ->setAutowired(true) ; - (new AutowirePass())->process($container); (new DecoratorServicePass())->process($container); + (new AutowirePass())->process($container); $definition = $container->getDefinition(DecoratedDecorator::class); $this->assertSame(DecoratedDecorator::class.'.inner', (string) $definition->getArgument(0)); @@ -1026,8 +1026,8 @@ public function testAutowireDecoratorRenamedId() ->setAutowired(true) ; - (new AutowirePass())->process($container); (new DecoratorServicePass())->process($container); + (new AutowirePass())->process($container); $definition = $container->getDefinition(Decorator::class); $this->assertSame('renamed', (string) $definition->getArgument(1)); @@ -1044,11 +1044,12 @@ public function testDoNotAutowireDecoratorWhenSeveralArgumentOfTheType() ->setAutowired(true) ; + (new DecoratorServicePass())->process($container); try { (new AutowirePass())->process($container); $this->fail('AutowirePass should have thrown an exception'); } catch (AutowiringFailedException $e) { - $this->assertSame('Cannot autowire service "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator": argument "$decorated1" of method "__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DecoratorInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "Symfony\Component\DependencyInjection\Tests\Compiler\Decorated", "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator".', (string) $e->getMessage()); + $this->assertSame('Cannot autowire service "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator": argument "$decorated1" of method "__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DecoratorInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator", "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator.inner".', (string) $e->getMessage()); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php index 848bb7445e10a..2cc52e91d88e8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -175,6 +175,33 @@ public function testCanDecorateServiceLocator() $this->assertSame($container->get('foo'), $container->get(DecoratedServiceLocator::class)->get('foo')); } + public function testAliasDecoratedService() + { + $container = new ContainerBuilder(); + + $container->register('service', ServiceLocator::class) + ->setPublic(true) + ->setArguments([[]]) + ; + $container->register('decorator', DecoratedServiceLocator::class) + ->setDecoratedService('service') + ->setAutowired(true) + ->setPublic(true) + ; + $container->setAlias(ServiceLocator::class, 'decorator.inner') + ->setPublic(true) + ; + $container->register('user_service', DecoratedServiceLocator::class) + ->setAutowired(true) + ; + + $container->compile(); + + $this->assertInstanceOf(DecoratedServiceLocator::class, $container->get('service')); + $this->assertInstanceOf(ServiceLocator::class, $container->get(ServiceLocator::class)); + $this->assertSame($container->get('service'), $container->get('decorator')); + } + /** * @dataProvider getYamlCompileTests */