Skip to content

Commit 97c32a1

Browse files
bug #43579 [DependencyInjection] Fix autowiring tagged arguments from attributes (Okhoshi)
This PR was merged into the 5.3 branch. Discussion ---------- [DependencyInjection] Fix autowiring tagged arguments from attributes | Q | A | ------------- | --- | Branch? | 5.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #43272 | License | MIT | Doc PR | no Reimplement #40406 with `AttributeAutoconfigurationPass` to avoid the BC following the change in `CompilerPass` ordering in `PassConfig`. Also revert the various fix made in an attempt to recover the BC introduced by #40406. ~Note: `5.4` branch was needed because `AttributeAutoconfigurationPass` is not handling parameters in 5.3~ To-do: - [x] Add a test to cover the breakage presented in #43272 Commits ------- 4c7566f [DependencyInjection] Fix autowiring tagged arguments from attributes
2 parents 773a05d + 4c7566f commit 97c32a1

File tree

4 files changed

+36
-9
lines changed

4 files changed

+36
-9
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

+2-4
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,8 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
159159
$this->decoratedClass = null;
160160
$this->getPreviousValue = null;
161161

162-
if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && ($decoratedDefinition = $definition->getDecoratedService()) && null !== ($innerId = $decoratedDefinition[0]) && $this->container->has($innerId)) {
163-
// If the class references to itself and is decorated, provide the inner service id and class to not get a circular reference
164-
$this->decoratedClass = $this->container->findDefinition($innerId)->getClass();
165-
$this->decoratedId = $decoratedDefinition[1] ?? $this->currentId.'.inner';
162+
if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && null !== ($this->decoratedId = $definition->innerServiceId) && $this->container->has($this->decoratedId)) {
163+
$this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass();
166164
}
167165

168166
$patchedIndexes = [];

src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ public function __construct()
6262
new AutowireRequiredMethodsPass(),
6363
new AutowireRequiredPropertiesPass(),
6464
new ResolveBindingsPass(),
65+
new ServiceLocatorTagPass(),
66+
new DecoratorServicePass(),
6567
new CheckDefinitionValidityPass(),
6668
new AutowirePass(false),
6769
new ServiceLocatorTagPass(),
68-
new DecoratorServicePass(),
6970
new ResolveTaggedIteratorArgumentPass(),
7071
new ResolveServiceSubscribersPass(),
7172
new ResolveReferencesToAliasesPass(),

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,8 @@ public function testAutowireDecorator()
985985
->setAutowired(true)
986986
;
987987

988-
(new AutowirePass())->process($container);
989988
(new DecoratorServicePass())->process($container);
989+
(new AutowirePass())->process($container);
990990

991991
$definition = $container->getDefinition(Decorator::class);
992992
$this->assertSame(Decorator::class.'.inner', (string) $definition->getArgument(1));
@@ -1008,8 +1008,8 @@ public function testAutowireDecoratorChain()
10081008
->setAutowired(true)
10091009
;
10101010

1011-
(new AutowirePass())->process($container);
10121011
(new DecoratorServicePass())->process($container);
1012+
(new AutowirePass())->process($container);
10131013

10141014
$definition = $container->getDefinition(DecoratedDecorator::class);
10151015
$this->assertSame(DecoratedDecorator::class.'.inner', (string) $definition->getArgument(0));
@@ -1026,8 +1026,8 @@ public function testAutowireDecoratorRenamedId()
10261026
->setAutowired(true)
10271027
;
10281028

1029-
(new AutowirePass())->process($container);
10301029
(new DecoratorServicePass())->process($container);
1030+
(new AutowirePass())->process($container);
10311031

10321032
$definition = $container->getDefinition(Decorator::class);
10331033
$this->assertSame('renamed', (string) $definition->getArgument(1));
@@ -1044,11 +1044,12 @@ public function testDoNotAutowireDecoratorWhenSeveralArgumentOfTheType()
10441044
->setAutowired(true)
10451045
;
10461046

1047+
(new DecoratorServicePass())->process($container);
10471048
try {
10481049
(new AutowirePass())->process($container);
10491050
$this->fail('AutowirePass should have thrown an exception');
10501051
} catch (AutowiringFailedException $e) {
1051-
$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());
1052+
$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());
10521053
}
10531054
}
10541055

src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php

+27
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,33 @@ public function testCanDecorateServiceLocator()
175175
$this->assertSame($container->get('foo'), $container->get(DecoratedServiceLocator::class)->get('foo'));
176176
}
177177

178+
public function testAliasDecoratedService()
179+
{
180+
$container = new ContainerBuilder();
181+
182+
$container->register('service', ServiceLocator::class)
183+
->setPublic(true)
184+
->setArguments([[]])
185+
;
186+
$container->register('decorator', DecoratedServiceLocator::class)
187+
->setDecoratedService('service')
188+
->setAutowired(true)
189+
->setPublic(true)
190+
;
191+
$container->setAlias(ServiceLocator::class, 'decorator.inner')
192+
->setPublic(true)
193+
;
194+
$container->register('user_service', DecoratedServiceLocator::class)
195+
->setAutowired(true)
196+
;
197+
198+
$container->compile();
199+
200+
$this->assertInstanceOf(DecoratedServiceLocator::class, $container->get('service'));
201+
$this->assertInstanceOf(ServiceLocator::class, $container->get(ServiceLocator::class));
202+
$this->assertSame($container->get('service'), $container->get('decorator'));
203+
}
204+
178205
/**
179206
* @dataProvider getYamlCompileTests
180207
*/

0 commit comments

Comments
 (0)