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

Skip to content

Commit b750077

Browse files
committed
Allow to choose an index for tagged collection
1 parent f2590d1 commit b750077

File tree

5 files changed

+71
-10
lines changed

5 files changed

+71
-10
lines changed

src/Symfony/Component/DependencyInjection/Argument/TaggedIteratorArgument.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,30 @@
1919
class TaggedIteratorArgument extends IteratorArgument
2020
{
2121
private $tag;
22+
private $indexAttribute;
23+
private $defaultIndexMethod;
2224

23-
public function __construct(string $tag)
25+
public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null)
2426
{
2527
parent::__construct(array());
2628

2729
$this->tag = $tag;
30+
$this->indexAttribute = $indexAttribute;
31+
$this->defaultIndexMethod = $defaultIndexMethod;
2832
}
2933

3034
public function getTag()
3135
{
3236
return $this->tag;
3337
}
38+
39+
public function getIndexAttribute(): ?string
40+
{
41+
return $this->indexAttribute;
42+
}
43+
44+
public function getDefaultIndexMethod(): ?string
45+
{
46+
return $this->defaultIndexMethod;
47+
}
3448
}

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16+
use Symfony\Component\DependencyInjection\Exception\LogicException;
1517
use Symfony\Component\DependencyInjection\Reference;
1618

1719
/**
@@ -36,13 +38,56 @@ trait PriorityTaggedServiceTrait
3638
*
3739
* @return Reference[]
3840
*/
39-
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
41+
private function findAndSortTaggedServices($tagName, ContainerBuilder $container, string $indexAttribute = null, string $defaultIndexMethod = null)
4042
{
4143
$services = array();
4244

45+
if (null === $indexAttribute && null !== $defaultIndexMethod) {
46+
throw new InvalidArgumentException('Default index method cannot be used without specifying a tag attribute.');
47+
}
48+
4349
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
4450
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
45-
$services[$priority][] = new Reference($serviceId);
51+
52+
if (null === $indexAttribute && null === $defaultIndexMethod) {
53+
$services[$priority][] = new Reference($serviceId);
54+
55+
continue;
56+
}
57+
58+
if (isset($attributes[0][$indexAttribute])) {
59+
$services[$priority][$attributes[0][$indexAttribute]] = new Reference($serviceId);
60+
61+
continue;
62+
}
63+
64+
if (null === $defaultIndexMethod) {
65+
throw new LogicException(sprintf('Tag "%s" on service "%s" is missing "%s" attribute.', $tagName, $serviceId, $indexAttribute));
66+
}
67+
68+
if (!$r = $container->getReflectionClass($class = $container->getDefinition($serviceId)->getClass())) {
69+
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId));
70+
}
71+
72+
if (!$r->hasMethod($defaultIndexMethod)) {
73+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" not found: Tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
74+
}
75+
76+
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
77+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" used for service "%s" must be static.', $class, $defaultIndexMethod, $serviceId));
78+
}
79+
80+
if (!$rm->isPublic()) {
81+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" used for service "%s" must be public.', $class, $defaultIndexMethod, $serviceId));
82+
}
83+
84+
$key = $rm->invoke(null);
85+
86+
if (!\is_string($key)) {
87+
throw new LogicException(sprintf('Return value of method "%s::%s()" used for service "%s" must be of type string.', $class, $defaultIndexMethod, $serviceId));
88+
}
89+
90+
$services[$priority][$key] = new Reference($serviceId);
4691
}
4792

4893
if ($services) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protected function processValue($value, $isRoot = false)
3131
return parent::processValue($value, $isRoot);
3232
}
3333

34-
$value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container));
34+
$value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container, $value->getIndexAttribute(), $value->getDefaultIndexMethod()));
3535

3636
return $value;
3737
}

src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ function iterator(array $values): IteratorArgument
116116
/**
117117
* Creates a lazy iterator by tag name.
118118
*/
119-
function tagged(string $tag): TaggedIteratorArgument
119+
function tagged(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null): TaggedIteratorArgument
120120
{
121-
return new TaggedIteratorArgument($tag);
121+
return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod);
122122
}
123123

124124
/**

src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,11 +706,13 @@ private function resolveServices($value, $file, $isParameter = false)
706706
}
707707
}
708708
if ('tagged' === $value->getTag()) {
709-
if (!\is_string($argument) || !$argument) {
710-
throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts non empty string in "%s".', $file));
709+
if (\is_string($argument) && $argument) {
710+
return new TaggedIteratorArgument($argument);
711+
} elseif (\is_array($argument) && isset($argument['name']) && $argument['name']) {
712+
return new TaggedIteratorArgument($argument['name'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null);
713+
} else {
714+
throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts a non empty string or an array with a key "name" in "%s".', $file));
711715
}
712-
713-
return new TaggedIteratorArgument($argument);
714716
}
715717
if ('service' === $value->getTag()) {
716718
if ($isParameter) {

0 commit comments

Comments
 (0)