Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b2783a7

Browse files
Okhoshinicolas-grekas
authored andcommitted
[DependencyInjection] Fix autowiring tagged arguments from attributes
1 parent 67f43b0 commit b2783a7

File tree

7 files changed

+46
-13
lines changed

7 files changed

+46
-13
lines changed

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

Lines changed: 2 additions & 4 deletions
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ public function __construct()
6262
new AutowireRequiredMethodsPass(),
6363
new AutowireRequiredPropertiesPass(),
6464
new ResolveBindingsPass(),
65-
new CheckDefinitionValidityPass(),
66-
new AutowirePass(false),
6765
new ServiceLocatorTagPass(),
6866
new DecoratorServicePass(),
67+
new CheckDefinitionValidityPass(),
68+
new AutowirePass(false),
6969
new ResolveTaggedIteratorArgumentPass(),
7070
new ResolveServiceSubscribersPass(),
7171
new ResolveReferencesToAliasesPass(),

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1516

1617
/**
17-
* Resolves all TaggedIteratorArgument arguments.
18+
* Resolves TaggedIteratorArgument and ServiceLocatorArgument.
1819
*
1920
* @author Roland Franssen <[email protected]>
2021
*/
@@ -27,6 +28,14 @@ class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass
2728
*/
2829
protected function processValue($value, bool $isRoot = false)
2930
{
31+
if ($value instanceof ServiceLocatorArgument) {
32+
if ($value->getTaggedIteratorArgument()) {
33+
$value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container));
34+
}
35+
36+
return ServiceLocatorTagPass::register($this->container, $value->getValues());
37+
}
38+
3039
if (!$value instanceof TaggedIteratorArgument) {
3140
return parent::processValue($value, $isRoot);
3241
}

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

Lines changed: 5 additions & 4 deletions
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

Lines changed: 27 additions & 0 deletions
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
*/

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ public function getRemovedIds(): array
4646
return [
4747
'.service_locator.DlIAmAe' => true,
4848
'.service_locator.DlIAmAe.foo_service' => true,
49-
'.service_locator.t5IGRMW' => true,
5049
'Psr\\Container\\ContainerInterface' => true,
5150
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
5251
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber_php81.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ public function getRemovedIds(): array
4646
return [
4747
'.service_locator.JmEob1b' => true,
4848
'.service_locator.JmEob1b.foo_service' => true,
49-
'.service_locator.KIgkoLM' => true,
5049
'Psr\\Container\\ContainerInterface' => true,
5150
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
5251
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,

0 commit comments

Comments
 (0)