Skip to content

Commit 2677a0a

Browse files
[DependencyInjection] Deprecate default index/priority methods when defining tagged locators/iterators
1 parent d99ed1d commit 2677a0a

27 files changed

+338
-67
lines changed

UPGRADE-7.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ DependencyInjection
5252
+ ],
5353
+]);
5454
```
55+
* Deprecate default index/priority methods when defining tagged locators/iterators; use the `#[AsTaggedItem]` attribute instead
5556

5657
DoctrineBridge
5758
--------------

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

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,66 @@ class TaggedIteratorArgument extends IteratorArgument
2121
private mixed $indexAttribute = null;
2222
private ?string $defaultIndexMethod = null;
2323
private ?string $defaultPriorityMethod = null;
24+
private bool $needsIndexes = false;
25+
private array $exclude = [];
26+
private bool $excludeSelf = true;
2427

2528
/**
2629
* @param string $tag The name of the tag identifying the target services
2730
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
28-
* @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
2931
* @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
30-
* @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
31-
* @param array $exclude Services to exclude from the iterator
32+
* @param string[] $exclude Services to exclude from the iterator
3233
* @param bool $excludeSelf Whether to automatically exclude the referencing service from the iterator
3334
*/
3435
public function __construct(
3536
private string $tag,
3637
?string $indexAttribute = null,
37-
?string $defaultIndexMethod = null,
38-
private bool $needsIndexes = false,
39-
?string $defaultPriorityMethod = null,
40-
private array $exclude = [],
41-
private bool $excludeSelf = true,
38+
bool|string|null $needsIndexes = false,
39+
array|bool $exclude = [],
40+
bool|string|null $excludeSelf = true,
4241
) {
4342
parent::__construct([]);
4443

44+
$defaultIndexMethod = false;
45+
$defaultPriorityMethod = false;
46+
47+
if (\func_num_args() >= 6) {
48+
$defaultIndexMethod = func_get_arg(2);
49+
$needsIndexes = func_get_arg(3);
50+
$defaultPriorityMethod = func_get_arg(4);
51+
$exclude = func_get_arg(5);
52+
$excludeSelf = \func_num_args() >= 7 ? func_get_arg(6) : true;
53+
} else {
54+
if (!\is_bool($needsIndexes)) {
55+
$defaultIndexMethod = $needsIndexes;
56+
$needsIndexes = false;
57+
}
58+
if (!\is_array($exclude)) {
59+
if (false === $defaultIndexMethod) {
60+
$defaultIndexMethod = $exclude;
61+
}
62+
$needsIndexes = $exclude;
63+
$exclude = [];
64+
}
65+
if (!\is_bool($excludeSelf)) {
66+
$defaultPriorityMethod = $excludeSelf;
67+
$excludeSelf = true;
68+
}
69+
}
70+
if (false !== $defaultIndexMethod || false !== $defaultPriorityMethod) {
71+
trigger_deprecation('symfony/dependency-injection', '7.4', 'The $defaultIndexMethod and $defaultPriorityMethod arguments of tagged locators and iterators are deprecated, use the #[AsTaggedItem] attribute instead.');
72+
}
73+
4574
if (null === $indexAttribute && $needsIndexes) {
4675
$indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag;
4776
}
4877

4978
$this->indexAttribute = $indexAttribute;
5079
$this->defaultIndexMethod = $defaultIndexMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Name' : null);
5180
$this->defaultPriorityMethod = $defaultPriorityMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Priority' : null);
81+
$this->needsIndexes = $needsIndexes;
82+
$this->exclude = $exclude;
83+
$this->excludeSelf = $excludeSelf;
5284
}
5385

5486
public function getTag(): string
@@ -61,8 +93,15 @@ public function getIndexAttribute(): ?string
6193
return $this->indexAttribute;
6294
}
6395

64-
public function getDefaultIndexMethod(): ?string
96+
/**
97+
* @deprecated since Symfony 7.4, use the #[AsTaggedItem] attribute instead of default methods
98+
*/
99+
public function getDefaultIndexMethod(/* bool $triggerDeprecation = true */): ?string
65100
{
101+
if (!\func_num_args() || func_get_arg(0)) {
102+
trigger_deprecation('symfony/dependency-injection', '7.4', 'The "%s()" method is deprecated, use the #[AsTaggedItem] attribute instead of default methods.', __METHOD__);
103+
}
104+
66105
return $this->defaultIndexMethod;
67106
}
68107

@@ -71,8 +110,15 @@ public function needsIndexes(): bool
71110
return $this->needsIndexes;
72111
}
73112

74-
public function getDefaultPriorityMethod(): ?string
113+
/**
114+
* @deprecated since Symfony 7.4, use the #[AsTaggedItem] attribute instead of default methods
115+
*/
116+
public function getDefaultPriorityMethod(/* bool $triggerDeprecation = true */): ?string
75117
{
118+
if (!\func_num_args() || func_get_arg(0)) {
119+
trigger_deprecation('symfony/dependency-injection', '7.4', 'The "%s()" method is deprecated, use the #[AsTaggedItem] attribute instead of default methods.', __METHOD__);
120+
}
121+
76122
return $this->defaultPriorityMethod;
77123
}
78124

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

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,41 @@ class AutowireIterator extends Autowire
2222
/**
2323
* @see ServiceSubscriberInterface::getSubscribedServices()
2424
*
25-
* @param string $tag A tag name to search for to populate the iterator
26-
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
27-
* @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
28-
* @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
29-
* @param string|array<string> $exclude A service id or a list of service ids to exclude
30-
* @param bool $excludeSelf Whether to automatically exclude the referencing service from the iterator
25+
* @param string $tag A tag name to search for to populate the iterator
26+
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
27+
* @param string|string[] $exclude A service id or a list of service ids to exclude
28+
* @param bool $excludeSelf Whether to automatically exclude the referencing service from the iterator
3129
*/
3230
public function __construct(
3331
string $tag,
3432
?string $indexAttribute = null,
35-
?string $defaultIndexMethod = null,
36-
?string $defaultPriorityMethod = null,
37-
string|array $exclude = [],
38-
bool $excludeSelf = true,
33+
string|array|null $exclude = [],
34+
bool|string|null $excludeSelf = true,
35+
...$_
3936
) {
40-
parent::__construct(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod, (array) $exclude, $excludeSelf));
37+
$defaultIndexMethod = \array_key_exists('defaultIndexMethod', $_) ? $_['defaultIndexMethod'] : false;
38+
$defaultPriorityMethod = \array_key_exists('defaultPriorityMethod', $_) ? $_['defaultPriorityMethod'] : false;
39+
40+
if (\func_num_args() >= 5) {
41+
$defaultIndexMethod = func_get_arg(2);
42+
$defaultPriorityMethod = func_get_arg(3);
43+
$exclude = func_get_arg(4);
44+
$excludeSelf = \func_num_args() >= 6 ? func_get_arg(5) : true;
45+
} elseif (!\is_bool($excludeSelf)) {
46+
$defaultIndexMethod = $exclude;
47+
$defaultPriorityMethod = $excludeSelf;
48+
$exclude = [];
49+
$excludeSelf = true;
50+
} elseif (false === $defaultIndexMethod && !\is_array($exclude) && str_starts_with($exclude ?? 'get', 'get')) {
51+
$defaultIndexMethod = $exclude;
52+
$exclude = [];
53+
}
54+
if (false !== $defaultIndexMethod || false !== $defaultPriorityMethod) {
55+
parent::__construct(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod, (array) $exclude, $excludeSelf));
56+
57+
return;
58+
}
59+
60+
parent::__construct(new TaggedIteratorArgument($tag, $indexAttribute, false, (array) $exclude, $excludeSelf));
4161
}
4262
}

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

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,49 @@ class AutowireLocator extends Autowire
2828
/**
2929
* @see ServiceSubscriberInterface::getSubscribedServices()
3030
*
31-
* @param string|array<string|Autowire|SubscribedService> $services A tag name or an explicit list of service ids
32-
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the locator
33-
* @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
34-
* @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
35-
* @param string|array $exclude A service id or a list of service ids to exclude
36-
* @param bool $excludeSelf Whether to automatically exclude the referencing service from the locator
31+
* @param string|array<string|Autowire|SubscribedService> $services A tag name or an explicit list of service ids
32+
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the locator
33+
* @param string|string[] $exclude A service id or a list of service ids to exclude
34+
* @param bool $excludeSelf Whether to automatically exclude the referencing service from the locator
3735
*/
3836
public function __construct(
3937
string|array $services,
4038
?string $indexAttribute = null,
41-
?string $defaultIndexMethod = null,
42-
?string $defaultPriorityMethod = null,
43-
string|array $exclude = [],
44-
bool $excludeSelf = true,
39+
string|array|null $exclude = [],
40+
bool|string|null $excludeSelf = true,
41+
...$_
4542
) {
43+
$defaultIndexMethod = \array_key_exists('defaultIndexMethod', $_) ? $_['defaultIndexMethod'] : false;
44+
$defaultPriorityMethod = \array_key_exists('defaultPriorityMethod', $_) ? $_['defaultPriorityMethod'] : false;
45+
46+
if (\func_num_args() >= 5) {
47+
$defaultIndexMethod = func_get_arg(2);
48+
$defaultPriorityMethod = func_get_arg(3);
49+
$exclude = func_get_arg(4);
50+
$excludeSelf = \func_num_args() >= 6 ? func_get_arg(5) : true;
51+
} elseif (!\is_bool($excludeSelf)) {
52+
$defaultIndexMethod = $exclude;
53+
$defaultPriorityMethod = $excludeSelf;
54+
$exclude = [];
55+
$excludeSelf = true;
56+
} elseif (false === $defaultIndexMethod && !\is_array($exclude) && str_starts_with($exclude ?? 'get', 'get')) {
57+
$defaultIndexMethod = $exclude;
58+
$exclude = [];
59+
}
60+
4661
if (\is_string($services)) {
47-
parent::__construct(new ServiceLocatorArgument(new TaggedIteratorArgument($services, $indexAttribute, $defaultIndexMethod, true, $defaultPriorityMethod, (array) $exclude, $excludeSelf)));
62+
if (false !== $defaultIndexMethod || false !== $defaultPriorityMethod) {
63+
parent::__construct(new ServiceLocatorArgument(new TaggedIteratorArgument($services, $indexAttribute, $defaultIndexMethod, true, $defaultPriorityMethod, (array) $exclude, $excludeSelf)));
64+
65+
return;
66+
}
67+
parent::__construct(new ServiceLocatorArgument(new TaggedIteratorArgument($services, $indexAttribute, true, (array) $exclude, $excludeSelf)));
4868

4969
return;
5070
}
71+
if (false !== $defaultIndexMethod || false !== $defaultPriorityMethod) {
72+
trigger_deprecation('symfony/dependency-injection', '7.4', 'The $defaultIndexMethod and $defaultPriorityMethod arguments of tagged locators and iterators attributes are deprecated, use the #[AsTaggedItem] attribute instead of default methods.');
73+
}
5174

5275
$references = [];
5376

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ CHANGELOG
1616
* Deprecate XML configuration format, use YAML or PHP instead
1717
* Deprecate `ExtensionInterface::getXsdValidationBasePath()` and `getNamespace()`
1818
* Deprecate the fluent PHP format for semantic configuration, use `$container->extension()` or return an array instead
19+
* Deprecate default index/priority methods when defining tagged locators/iterators; use the `#[AsTaggedItem]` attribute instead
1920

2021
7.3
2122
---

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ private function findAndSortTaggedServices(string|TaggedIteratorArgument $tagNam
4343

4444
if ($tagName instanceof TaggedIteratorArgument) {
4545
$indexAttribute = $tagName->getIndexAttribute();
46-
$defaultIndexMethod = $tagName->getDefaultIndexMethod();
46+
$defaultIndexMethod = $tagName->getDefaultIndexMethod(false);
4747
$needsIndexes = $tagName->needsIndexes();
48-
$defaultPriorityMethod = $tagName->getDefaultPriorityMethod() ?? 'getDefaultPriority';
48+
$defaultPriorityMethod = $tagName->getDefaultPriorityMethod(false) ?? 'getDefaultPriority';
4949
$exclude = array_merge($exclude, $tagName->getExclude());
5050
$tagName = $tagName->getTag();
5151
}
@@ -171,6 +171,8 @@ public static function getDefault(string $serviceId, \ReflectionClass $r, string
171171
throw new InvalidArgumentException(implode('be public', $message));
172172
}
173173

174+
trigger_deprecation('symfony/dependency-injection', '7.4', 'Calling "%s::%s()" to get the "%s" index is deprecated, use the #[AsTaggedItem] attribute instead.', $class, $defaultMethod, $indexAttribute);
175+
174176
$default = $rm->invoke(null);
175177

176178
if ('priority' === $indexAttribute) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,11 @@ private function convertParameters(array $parameters, string $type, string $keyA
308308
if (null !== $tag->getIndexAttribute()) {
309309
$xmlAttr .= \sprintf(' index-by="%s"', $this->encode($tag->getIndexAttribute()));
310310

311-
if (null !== $tag->getDefaultIndexMethod()) {
312-
$xmlAttr .= \sprintf(' default-index-method="%s"', $this->encode($tag->getDefaultIndexMethod()));
311+
if (null !== $tag->getDefaultIndexMethod(false)) {
312+
$xmlAttr .= \sprintf(' default-index-method="%s"', $this->encode($tag->getDefaultIndexMethod(false)));
313313
}
314-
if (null !== $tag->getDefaultPriorityMethod()) {
315-
$xmlAttr .= \sprintf(' default-priority-method="%s"', $this->encode($tag->getDefaultPriorityMethod()));
314+
if (null !== $tag->getDefaultPriorityMethod(false)) {
315+
$xmlAttr .= \sprintf(' default-priority-method="%s"', $this->encode($tag->getDefaultPriorityMethod(false)));
316316
}
317317
}
318318
if (1 === \count($excludes = $tag->getExclude())) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,11 @@ private function dumpValue(mixed $value): mixed
265265
'index_by' => $tag->getIndexAttribute(),
266266
];
267267

268-
if (null !== $tag->getDefaultIndexMethod()) {
269-
$content['default_index_method'] = $tag->getDefaultIndexMethod();
268+
if (null !== $tag->getDefaultIndexMethod(false)) {
269+
$content['default_index_method'] = $tag->getDefaultIndexMethod(false);
270270
}
271-
if (null !== $tag->getDefaultPriorityMethod()) {
272-
$content['default_priority_method'] = $tag->getDefaultPriorityMethod();
271+
if (null !== $tag->getDefaultPriorityMethod(false)) {
272+
$content['default_priority_method'] = $tag->getDefaultPriorityMethod(false);
273273
}
274274
}
275275
if ($excludes = $tag->getExclude()) {

0 commit comments

Comments
 (0)