8000 [DI] ignore extra tags added by autoconfiguration in PriorityTaggedSe… · symfony/symfony@b55bd7d · GitHub
[go: up one dir, main page]

Skip to content

Commit b55bd7d

Browse files
[DI] ignore extra tags added by autoconfiguration in PriorityTaggedServiceTrait
1 parent d246e94 commit b55bd7d

File tree

2 files changed

+106
-57
lines changed

2 files changed

+106
-57
lines changed

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

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -54,88 +54,104 @@ private function findAndSortTaggedServices($tagName, ContainerBuilder $container
5454

5555
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
5656
$class = $r = null;
57-
5857
$defaultPriority = null;
5958
$defaultIndex = null;
6059

6160
foreach ($attributes as $attribute) {
6261
$index = $priority = null;
6362

6463
if (isset($attribute['priority'])) {
65-
$priority = $attribute['priority'];
64+
$priority = (int) $attribute['priority'];
6665
} elseif (null === $defaultPriority && $defaultPriorityMethod) {
67-
$class = $container->getDefinition($serviceId)->getClass();
68-
$class = $container->getParameterBag()->resolveValue($class) ?: null;
69-
70-
if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultPriorityMethod)) {
71-
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
72-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
73-
}
74-
75-
if (!$rm->isPublic()) {
76-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
77-
}
78-
79-
$defaultPriority = $rm->invoke(null);
80-
81-
if (!\is_int($defaultPriority)) {
82-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId));
83-
}
84-
}
66+
[$defaultPriority, $class, $r] = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $defaultPriorityMethod, $r, $tagName);
8567
}
68+
$priority = $priority ?? $defaultPriority ?? $defaultPriority = 0;
8669

87-
$priority = $priority ?? $defaultPriority ?? 0;
70+
if (null === $indexAttribute && !$needsIndexes) {
71+
$services[$priority][] = new Reference($serviceId);
72+
continue 2;
73+
}
8874

8975
if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
9076
$index = $attribute[$indexAttribute];
91-
} elseif (null === $defaultIndex && null === $indexAttribute && !$needsIndexes) {
92-
// With partially associative array, insertion to get next key is simpler.
93-
$services[$priority][] = null;
94-
end($services[$priority]);
95-
$defaultIndex = key($services[$priority]);
9677
} elseif (null === $defaultIndex && $defaultIndexMethod) {
97-
$class = $container->getDefinition($serviceId)->getClass();
98-
$class = $container->getParameterBag()->resolveValue($class) ?: null;
78+
[$defaultIndex, $class, $r] = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $defaultIndexMethod, $r, $tagName, $indexAttribute);
79+
}
80+
$index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId;
9981

100-
if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultIndexMethod)) {
101-
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
102-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
103-
}
82+
$services[$priority][$index] = new Reference($serviceId);
83+
}
84+
}
10485

105-
if (!$rm->isPublic()) {
106-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
107-
}
86+
if ($services) {
87+
krsort($services);
88+
$services = array_merge(...$services);
89+
}
10890

109-
$defaultIndex = $rm->invoke(null);
91+
return $services;
92+
}
93+
}
11094

111-
if (!\is_string($defaultIndex)) {
112-
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($defaultIndex), $tagName, $serviceId, $indexAttribute));
113-
}
114-
}
95+
/**
96+
* @internal
97+
*/
98+
class PriorityTaggedServiceUtil
99+
{
100+
/**
101+
* Gets the index defined by the default index method.
102+
*/
103+
public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $defaultIndexMethod, ?\ReflectionClass $r, string $tagName, string $indexAttribute): ?array
104+
{
105+
$class = $container->getDefinition($serviceId)->getClass();
106+
$class = $container->getParameterBag()->resolveValue($class) ?: null;
115107

116-
$defaultIndex = $defaultIndex ?? $serviceId;
117-
}
108+
if (!($r = $r ?? $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) {
109+
return null;
110+
}
118111

119-
$index = $index ?? $defaultIndex;
112+
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
113+
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
114+
}
120115

121-
$reference = null;
122-
if (!$class || 'stdClass' === $class) {
123-
$reference = new Reference($serviceId);
124-
} elseif ($index === $serviceId) {
125-
$reference = new TypedReference($serviceId, $class);
126-
} else {
127-
$reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, \is_string($index) ? $index : null);
128-
}
116+
if (!$rm->isPublic()) {
117+
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
118+
}
129119

130-
$services[$priority][$index] = $reference;
131-
}
120+
$defaultIndex = $rm->invoke(null);
121+
122+
if (!\is_string($defaultIndex)) {
123+
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should return a string (got %s) or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, \gettype($defaultIndex), $tagName, $serviceId, $indexAttribute));
132124
}
133125

134-
if ($services) {
135-
krsort($services);
136-
$services = array_merge(...$services);
126+
return [$defaultIndex, $class, $r];
127+
}
128+
129+
/**
130+
* Gets the priority defined by the default priority method.
131+
*/
132+
public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $defaultPriorityMethod, ?\ReflectionClass $r, string $tagName): ?array
133+
{
134+
$class = $container->getDefinition($serviceId)->getClass();
135+
$class = $container->getParameterBag()->resolveValue($class) ?: null;
136+
137+
if (!($r = $r ?? $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) {
138+
return null;
137139
}
138140

139-
return $services;
141+
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
142+
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
143+
}
144+
145+
if (!$rm->isPublic()) {
146+
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
147+
}
148+
149+
$defaultPriority = $rm->invoke(null);
150+
151+
if (!\is_int($defaultPriority)) {
152+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer (got %s) or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, \gettype($defaultPriority), $tagName, $serviceId));
153+
}
154+
155+
return [$defaultPriority, $class, $r];
140156
}
141157
}

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1516
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
1820

1921
class PriorityTaggedServiceTraitTest extends TestCase
2022
{
@@ -85,6 +87,37 @@ public function testWithEmptyArray()
8587
$priorityTaggedServiceTraitImplementation = new PriorityTaggedServiceTraitImplementation();
8688
$this->assertEquals([], $priorityTaggedServiceTraitImplementation->test('my_custom_tag', $container));
8789
}
90+
91+
public function testOnlyTheFirstNonIndexedTagIsListed()
92+
{
93+
$container = new ContainerBuilder();
94+
$container->register('service1')->addTag('my_custom_tag', ['foo' => 'bar']);
95+
96+
$definition = $container->register('service2', BarTagClass::class);
97+
$definition->addTag('my_custom_tag', ['priority' => 100]);
98+
$definition->addTag('my_custom_tag', ['foo' => 'a']);
99+
$definition->addTag('my_custom_tag', ['foo' => 'b']);
100+
$definition->addTag('my_custom_tag', []);
101+
102+
$priorityTaggedServiceTraitImplementation = new PriorityTaggedServiceTraitImplementation();
103+
104+
$expected = [
105+
new Reference('service2'),
106+
new Reference('service1'),
107+
];
108+
$this->assertEquals($expected, $priorityTaggedServiceTraitImplementation->test('my_custom_tag', $container));
109+
110+
$tag = new TaggedIteratorArgument('my_custom_tag', 'foo');
111+
$expected = [
112+
'bar_tag_class' => new Reference('service2'),
113+
'bar' => new Reference('service1'),
114+
'a' => new Reference('service2'),
115+
'b' => new Reference('service2'),
116+
];
117+
$services = $priorityTaggedServiceTraitImplementation->test($tag, $container);
118+
$this->assertSame(array_keys($expected), array_keys($services));
119+
$this->assertEquals($expected, $priorityTaggedServiceTraitImplementation->test($tag, $container));
120+
}
88121
}
89122

90123
class PriorityTaggedServiceTraitImplementation

0 commit comments

Comments
 (0)
0