bug #36262 [DI] fix generating TypedReference from PriorityTaggedServiceTrait (nicolas-grekas)
This PR was merged into the 4.4 branch.
Discussion
----------
[DI] fix generating TypedReference from PriorityTaggedServiceTrait
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Fix #36258
| License | MIT
| Doc PR | -
Commits
-------
f4dd3e7022
[DI] fix generating TypedReference from PriorityTaggedServiceTrait
This commit is contained in:
commit
fe091d41d2
@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||
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 @@ trait PriorityTaggedServiceTrait
|
||||
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]) {
|
||||
if (null === $index) {
|
||||
$refs[] = new Reference($serviceId);
|
||||
foreach ($services as [, , $index, $serviceId, $class]) {
|
||||
if (!$class) {
|
||||
$reference = new Reference($serviceId);
|
||||
} elseif ($index === $serviceId) {
|
||||
$reference = new TypedReference($serviceId, $class);
|
||||
} else {
|
||||
$refs[$index] = new Reference($serviceId);
|
||||
$reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index);
|
||||
}
|
||||
|
||||
if (null === $index) {
|
||||
$refs[] = $reference;
|
||||
} else {
|
||||
$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 @@ class PriorityTaggedServiceUtil
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
|
||||
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 @@ class PriorityTaggedServiceTraitTest extends TestCase
|
||||
|
||||
$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));
|
||||
|
@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
|
||||
/**
|
||||
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||
@ -50,7 +51,7 @@ class ResolveTaggedIteratorArgumentPassTest extends TestCase
|
||||
$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']);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user