From f4dd3e70226d49fe3d5f3c78dbed1c07664e29ce Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 30 Mar 2020 11:45:21 +0200 Subject: [PATCH] [DI] fix generating TypedReference from PriorityTaggedServiceTrait --- .../Compiler/PriorityTaggedServiceTrait.php | 39 +++++++++++-------- .../PriorityTaggedServiceTraitTest.php | 7 ++-- .../ResolveTaggedIteratorArgumentPassTest.php | 3 +- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php b/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php index c24d5976b3cc..caa2e03e71de 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; /** * Trait that allows a generic method to find and sort service by priority option in the tag. @@ -55,41 +56,51 @@ private function findAndSortTaggedServices($tagName, ContainerBuilder $container foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) { $defaultPriority = null; $defaultIndex = null; + $class = $container->getDefinition($serviceId)->getClass(); + $class = $container->getParameterBag()->resolveValue($class) ?: null; foreach ($attributes as $attribute) { $index = $priority = null; if (isset($attribute['priority'])) { $priority = $attribute['priority']; - } elseif (null === $defaultPriority && $defaultPriorityMethod) { - $defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $defaultPriorityMethod, $tagName); + } elseif (null === $defaultPriority && $defaultPriorityMethod && $class) { + $defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $class, $defaultPriorityMethod, $tagName); } $priority = $priority ?? $defaultPriority ?? $defaultPriority = 0; if (null === $indexAttribute && !$needsIndexes) { - $services[] = [$priority, ++$i, null, $serviceId]; + $services[] = [$priority, ++$i, null, $serviceId, null]; continue 2; } if (null !== $indexAttribute && isset($attribute[$indexAttribute])) { $index = $attribute[$indexAttribute]; - } elseif (null === $defaultIndex && $defaultIndexMethod) { - $defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $defaultIndexMethod, $tagName, $indexAttribute); + } elseif (null === $defaultIndex && $defaultIndexMethod && $class) { + $defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $class, $defaultIndexMethod, $tagName, $indexAttribute); } $index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId; - $services[] = [$priority, ++$i, $index, $serviceId]; + $services[] = [$priority, ++$i, $index, $serviceId, $class]; } } uasort($services, static function ($a, $b) { return $b[0] <=> $a[0] ?: $a[1] <=> $b[1]; }); $refs = []; - foreach ($services as [, , $index, $serviceId]) { + foreach ($services as [, , $index, $serviceId, $class]) { + if (!$class) { + $reference = new Reference($serviceId); + } elseif ($index === $serviceId) { + $reference = new TypedReference($serviceId, $class); + } else { + $reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index); + } + if (null === $index) { - $refs[] = new Reference($serviceId); + $refs[] = $reference; } else { - $refs[$index] = new Reference($serviceId); + $refs[$index] = $reference; } } @@ -105,11 +116,8 @@ class PriorityTaggedServiceUtil /** * Gets the index defined by the default index method. */ - public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $defaultIndexMethod, string $tagName, string $indexAttribute): ?string + public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $class, string $defaultIndexMethod, string $tagName, string $indexAttribute): ?string { - $class = $container->getDefinition($serviceId)->getClass(); - $class = $container->getParameterBag()->resolveValue($class) ?: null; - if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) { return null; } @@ -134,11 +142,8 @@ public static function getDefaultIndex(ContainerBuilder $container, string $serv /** * Gets the priority defined by the default priority method. */ - public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $defaultPriorityMethod, string $tagName): ?int + public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $class, string $defaultPriorityMethod, string $tagName): ?int { - $class = $container->getDefinition($serviceId)->getClass(); - $class = $container->getParameterBag()->resolveValue($class) ?: null; - if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) { return null; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/PriorityTaggedServiceTraitTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/PriorityTaggedServiceTraitTest.php index 25ac59784452..3feafac3d323 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/PriorityTaggedServiceTraitTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/PriorityTaggedServiceTraitTest.php @@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass; +use Symfony\Component\DependencyInjection\TypedReference; class PriorityTaggedServiceTraitTest extends TestCase { @@ -122,10 +123,10 @@ public function testOnlyTheIndexedTagsAreListed() $tag = new TaggedIteratorArgument('my_custom_tag', 'foo'); $expected = [ - 'bar_tag_class' => new Reference('service2'), - 'b' => new Reference('service2'), + 'bar_tag_class' => new TypedReference('service2', BarTagClass::class), + 'b' => new TypedReference('service2', BarTagClass::class), 'bar' => new Reference('service1'), - 'a' => new Reference('service2'), + 'a' => new TypedReference('service2', BarTagClass::class), ]; $services = $priorityTaggedServiceTraitImplementation->test($tag, $container); $this->assertSame(array_keys($expected), array_keys($services)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php index 2a07f2617898..a62a585c6ef0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; /** * @author Roland Franssen @@ -50,7 +51,7 @@ public function testProcessWithIndexes() $properties = $container->getDefinition('service_c')->getProperties(); $expected = new TaggedIteratorArgument('foo', 'key'); - $expected->setValues(['1' => new Reference('service_a'), '2' => new Reference('service_b')]); + $expected->setValues(['1' => new TypedReference('service_a', 'stdClass'), '2' => new TypedReference('service_b', 'stdClass')]); $this->assertEquals($expected, $properties['foos']); } }