8000 [DependencyInjection] Make `AsTaggedItem` attribute repeatable · symfony/symfony@98b479c · GitHub
[go: up one dir, main page]

Skip to content

Commit 98b479c

Browse files
[DependencyInjection] Make AsTaggedItem attribute repeatable
1 parent 73d4904 commit 98b479c

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

src/Symfony/Component/DependencyInjection/Attribute/AsTaggedItem.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @author Nicolas Grekas <p@tchwork.com>
1818
*/
19-
#[\Attribute(\Attribute::TARGET_CLASS)]
19+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
2020
class AsTaggedItem
2121
{
2222
/**

src/Symfony/Component/DependencyInjection/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Make `AsTaggedItem` attribute repeatable
8+
49
7.2
510
---
611

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

+16
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ private function findAndSortTaggedServices(string|TaggedIteratorArgument $tagNam
9292

9393
$services[] = [$priority, ++$i, $index, $serviceId, $class];
9494
}
95+
96+
if ($class) {
97+
$reflectionClass = new \ReflectionClass($class);
98+
$attributes = $reflectionClass->getAttributes(AsTaggedItem::class);
99+
$attributeCount = \count($attributes);
100+
101+
foreach ($attributes as $attribute) {
102+
$instance = $attribute->newInstance();
103+
104+
if (!$instance->index && 1 < $attributeCount) {
105+
throw new InvalidArgumentException(\sprintf('Attribute "%s" on class "%s" cannot have an empty index when repeated.', AsTaggedItem::class, $class));
106+
}
107+
108+
$services[] = [$instance->priority ?? 0, ++$i, $instance->index ?? $serviceId, $serviceId, $class];
109+
}
110+
}
95111
}
96112

97113
uasort($services, static fn ($a, $b) => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]);

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

+34
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ public function testTaggedItemAttributes()
218218
$container->register('service5', HelloNamedService2::class)
219219
->setAutoconfigured(true)
220220
->addTag('my_custom_tag');
221+
$container->register('service6', MultiTagHelloNamedService::class)
222+
->setAutoconfigured(true)
223+
->addTag('my_custom_tag');
221224

222225
(new ResolveInstanceofConditionalsPass())->process($container);
223226

@@ -226,14 +229,33 @@ public function testTaggedItemAttributes()
226229
$tag = new TaggedIteratorArgument('my_custom_tag', 'foo', 'getFooBar', exclude: ['service4', 'service5']);
227230
$expected = [
228231
'service3' => new TypedReference('service3', HelloNamedService2::class),
232+
'multi_hello_2' => new TypedReference('service6', MultiTagHelloNamedService::class),
229233
'hello' => new TypedReference('service2', HelloNamedService::class),
234+
'multi_hello_1' => new TypedReference('service6', MultiTagHelloNamedService::class),
230235
'service1' => new TypedReference('service1', FooTagClass::class),
231236
];
237+
232238
$services = $priorityTaggedServiceTraitImplementation->test($tag, $container);
233239
$this->assertSame(array_keys($expected), array_keys($services));
234240
$this->assertEquals($expected, $priorityTaggedServiceTraitImplementation->test($tag, $container));
235241
}
236242

243+
public function testTaggedItemAttributesRepeatedWithoutNameThrows()
244+
{
245+
$container = new ContainerBuilder();
246+
$container->register('service1', MultiNoNameTagHelloNamedService::class)
247+
->setAutoconfigured(true)
248+
->addTag('my_custom_tag');
249+
250+
(new ResolveInstanceofConditionalsPass())->process($container);
251+
$tag = new TaggedIteratorArgument('my_custom_tag', 'foo', 'getFooBar', exclude: ['service4', 'service5']);
252+
253+
$this->expectException(InvalidArgumentException::class);
254+
$this->expectExceptionMessage('Attribute "Symfony\Component\DependencyInjection\Attribute\AsTaggedItem" on class "Symfony\Component\DependencyInjection\Tests\Compiler\MultiNoNameTagHelloNamedService" cannot have an empty index when repeated.');
255+
256+
(new PriorityTaggedServiceTraitImplementation())->test($tag, $container);
257+
}
258+
237259
public function testResolveIndexedTags()
238260
{
239261
$container = new ContainerBuilder();
@@ -283,6 +305,18 @@ class HelloNamedService2
283305
{
284306
}
285307

308+
#[AsTaggedItem(index: 'multi_hello_1', priority: 1)]
309+
#[AsTaggedItem(index: 'multi_hello_2', priority: 2)]
310+
class MultiTagHelloNamedService
311+
{
312+
}
313+
314+
#[AsTaggedItem(priority: 1)]
315+
#[AsTaggedItem(priority: 2)]
316+
class MultiNoNameTagHelloNamedService
317+
{
318+
}
319+
286320
interface HelloInterface
287321
{
288322
public static function getFooBar(): string;

0 commit comments

Comments
 (0)
0