Skip to content

Commit b82dcb5

Browse files
committed
[DependencyInjection] added Ability to define a priority method for tagged service
1 parent 41a450b commit b82dcb5

File tree

6 files changed

+57
-13
lines changed

6 files changed

+57
-13
lines changed

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ class TaggedIteratorArgument extends IteratorArgument
2424
private $needsIndexes = false;
2525

2626
/**
27-
* @param string $tag The name of the tag identifying the target services
28-
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
29-
* @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute
30-
* @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
27+
* @param string $tag The name of the tag identifying the target services
28+
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
29+
* @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute
30+
* @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
31+
* @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the previous attribute
3132
*/
32-
public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false)
33+
public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null)
3334
{
3435
parent::__construct([]);
3536

@@ -41,6 +42,7 @@ public function __construct(string $tag, string $indexAttribute = null, string $
4142
$this->indexAttribute = $indexAttribute;
4243
$this->defaultIndexMethod = $defaultIndexMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Name');
4344
$this->needsIndexes = $needsIndexes;
45+
$this->defaultPriorityMethod = $defaultPriorityMethod;
4446
}
4547

4648
public function getTag()
@@ -62,4 +64,9 @@ public function needsIndexes(): bool
6264
{
6365
return $this->needsIndexes;
6466
}
67+
68+
public function getDefaultPriorityMethod(): ?string
69+
{
70+
return $this->defaultPriorityMethod;
71+
}
6572
}

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* deprecated `tagged` in favor of `tagged_iterator`
1111
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
1212
* added support for binding iterable and tagged services
13+
* added ability to define a priority method for tagged service
1314

1415
4.3.0
1516
-----

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,66 @@ trait PriorityTaggedServiceTrait
4040
*/
4141
private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array
4242
{
43-
$indexAttribute = $defaultIndexMethod = $needsIndexes = null;
43+
$indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null;
4444

4545
if ($tagName instanceof TaggedIteratorArgument) {
4646
$indexAttribute = $tagName->getIndexAttribute();
4747
$defaultIndexMethod = $tagName->getDefaultIndexMethod();
4848
$needsIndexes = $tagName->needsIndexes();
49+
$defaultPriorityMethod = $tagName->getDefaultPriorityMethod();
4950
$tagName = $tagName->getTag();
5051
}
5152

5253
$services = [];
5354

5455
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
55-
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
56+
$class = $r = null;
57+
$priority = 0;
58+
if (isset($attributes[0]['priority'])) {
59+
$priority = $attributes[0]['priority'];
60+
} elseif ($defaultPriorityMethod) {
61+
$class = $container->getDefinition($serviceId)->getClass();
62+
$class = $container->getParameterBag()->resolveValue($class) ?: null;
63+
64+
if (!$r = $container->getReflectionClass($class)) {
65+
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId));
66+
}
67+
68+
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
69+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
70+
}
71+
72+
if (!$rm->isPublic()) {
73+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
74+
}
75+
76+
$priority = $rm->invoke(null);
77+
78+
if (!\is_int($priority)) {
79+
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId));
80+
}
81+
} else {
82+
$priority = 0;
83+
}
5684

5785
if (null === $indexAttribute && !$needsIndexes) {
5886
$services[$priority][] = new Reference($serviceId);
5987

6088
continue;
6189
}
6290

63-
$class = $container->getDefinition($serviceId)->getClass();
64-
$class = $container->getParameterBag()->resolveValue($class) ?: null;
91+
if (!$class) {
92+
$class = $container->getDefinition($serviceId)->getClass();
93+
$class = $container->getParameterBag()->resolveValue($class) ?: null;
94+
}
6595

6696
if (null !== $indexAttribute && isset($attributes[0][$indexAttribute])) {
6797
$services[$priority][$attributes[0][$indexAttribute]] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $attributes[0][$indexAttribute]);
6898

6999
continue;
70100
}
71101

72-
if (!$r = $container->getReflectionClass($class)) {
102+
if (!$r && !$r = $container->getReflectionClass($class)) {
73103
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId));
74104
}
75105

src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ private function convertParameters(array $parameters, string $type, \DOMElement
274274
if (null !== $tag->getDefaultIndexMethod()) {
275275
$element->setAttribute('default-index-method', $tag->getDefaultIndexMethod());
276276
}
277+
if (null !== $tag->getDefaultPriorityMethod()) {
278+
$element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod());
279+
}
277280
}
278281
} elseif ($value instanceof IteratorArgument) {
279282
$element->setAttribute('type', 'iterator');

src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ private function dumpValue($value)
244244
if (null !== $tag->getDefaultIndexMethod()) {
245245
$content['default_index_method'] = $tag->getDefaultIndexMethod();
246246
}
247+
if (null !== $tag->getDefaultPriorityMethod()) {
248+
$content['default_priority_method'] = $tag->getDefaultPriorityMethod();
249+
}
247250
}
248251

249252
return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,11 +720,11 @@ private function resolveServices($value, string $file, bool $isParameter = false
720720
$forLocator = 'tagged_locator' === $value->getTag();
721721

722722
if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
723-
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method'])) {
724-
throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by" and "default_index_method".', $value->getTag(), implode('"", "', $diff)));
723+
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) {
724+
throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by", "default_index_method", and "default_priority_method".', $value->getTag(), implode('"", "', $diff)));
725725
}
726726

727-
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator);
727+
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null);
728728
} elseif (\is_string($argument) && $argument) {
729729
$argument = new TaggedIteratorArgument($argument, null, null, $forLocator);
730730
} else {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy