Skip to content

Commit 261cc00

Browse files
committed
[DI] Add support for tagged iterators/locators exclude option to xml and yaml
1 parent 95c55bb commit 261cc00

12 files changed

+126
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
* Change the signature of `ContainerAwareInterface::setContainer()` to `setContainer(?ContainerInterface)`
1313
* Deprecate calling `ContainerAwareTrait::setContainer()` without arguments
1414
* Deprecate using numeric parameter names
15+
* Add support for tagged iterators/locators `exclude` option to the xml and yaml loaders/dumpers
1516

1617
6.1
1718
---

Dumper/XmlDumper.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,15 @@ private function convertParameters(array $parameters, string $type, \DOMElement
287287
$element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod());
288288
}
289289
}
290+
if ($excludes = $tag->getExclude()) {
291+
if (1 === \count($excludes)) {
292+
$element->setAttribute('exclude', $excludes[0]);
293+
} else {
294+
foreach ($excludes as $exclude) {
295+
$element->appendChild($this->document->createElement('exclude', $exclude));
296+
}
297+
}
298+
}
290299
} elseif ($value instanceof IteratorArgument) {
291300
$element->setAttribute('type', 'iterator');
292301
$this->convertParameters($value->getValues(), $type, $element, 'key');

Dumper/YamlDumper.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ private function dumpValue(mixed $value): mixed
266266
$content['default_priority_method'] = $tag->getDefaultPriorityMethod();
267267
}
268268
}
269+
if ($excludes = $tag->getExclude()) {
270+
if (!\is_array($content)) {
271+
$content = ['tag' => $content];
272+
}
273+
$content['exclude'] = 1 === \count($excludes) ? $excludes[0] : $excludes;
274+
}
269275

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

Loader/XmlFileLoader.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,15 @@ private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file
538538
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file));
539539
}
540540

541-
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null);
541+
$excludes = array_column($this->getChildren($arg, 'exclude'), 'nodeValue');
542+
if ($arg->hasAttribute('exclude')) {
543+
if (\count($excludes) > 0) {
544+
throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
545+
}
546+
$excludes = [$arg->getAttribute('exclude')];
547+
}
548+
549+
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null, $excludes);
542550

543551
if ($forLocator) {
544552
$arguments[$key] = new ServiceLocatorArgument($arguments[$key]);

Loader/YamlFileLoader.php

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

834834
if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
835-
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) {
836-
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)));
835+
if ($diff = array_diff(array_keys($argument), $supportedKeys = ['tag', 'index_by', 'default_index_method', 'default_priority_method', 'exclude'])) {
836+
throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "%s".', $value->getTag(), implode('", "', $diff), implode('", "', $supportedKeys)));
837837
}
838838

839-
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null);
839+
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null, (array) ($argument['exclude'] ?? null));
840840
} elseif (\is_string($argument) && $argument) {
841841
$argument = new TaggedIteratorArgument($argument, null, null, $forLocator);
842842
} else {

Loader/schema/dic/services/services-1.0.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@
284284
<xsd:choice minOccurs="0">
285285
<xsd:element name="argument" type="argument" maxOccurs="unbounded" />
286286
<xsd:element name="service" type="service" />
287+
<xsd:element name="exclude" type="xsd:string" maxOccurs="unbounded" />
287288
</xsd:choice>
288289
<xsd:attribute name="type" type="argument_type" />
289290
<xsd:attribute name="id" type="xsd:string" />
@@ -294,6 +295,7 @@
294295
<xsd:attribute name="index-by" type="xsd:string" />
295296
<xsd:attribute name="default-index-method" type="xsd:string" />
296297
<xsd:attribute name="default-priority-method" type="xsd:string" />
298+
<xsd:attribute name="exclude" type="xsd:string" />
297299
</xsd:complexType>
298300

299301
<xsd:complexType name="call">

Tests/Dumper/XmlDumperTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,40 @@ public function testDumpLoad()
203203
public function testTaggedArguments()
204204
{
205205
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', false, 'getPriority');
206+
$taggedIterator2 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz']);
207+
$taggedIterator3 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz', 'qux']);
208+
206209
$container = new ContainerBuilder();
210+
207211
$container->register('foo', 'Foo')->addTag('foo_tag');
212+
$container->register('baz', 'Baz')->addTag('foo_tag');
213+
$container->register('qux', 'Qux')->addTag('foo_tag');
214+
208215
$container->register('foo_tagged_iterator', 'Bar')
209216
->setPublic(true)
210217
->addArgument($taggedIterator)
211218
;
219+
$container->register('foo2_tagged_iterator', 'Bar')
220+
->setPublic(true)
221+
->addArgument($taggedIterator2)
222+
;
223+
$container->register('foo3_tagged_iterator', 'Bar')
224+
->setPublic(true)
225+
->addArgument($taggedIterator3)
226+
;
227+
212228
$container->register('foo_tagged_locator', 'Bar')
213229
->setPublic(true)
214230
->addArgument(new ServiceLocatorArgument($taggedIterator))
215231
;
232+
$container->register('foo2_tagged_locator', 'Bar')
233+
->setPublic(true)
234+
->addArgument(new ServiceLocatorArgument($taggedIterator2))
235+
;
236+
$container->register('foo3_tagged_locator', 'Bar')
237+
->setPublic(true)
238+
->addArgument(new ServiceLocatorArgument($taggedIterator3))
239+
;
216240

217241
$dumper = new XmlDumper($container);
218242
$this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_with_tagged_arguments.xml', $dumper->dump());

Tests/Dumper/YamlDumperTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,22 @@ public function testInlineServices()
112112
public function testTaggedArguments()
113113
{
114114
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar', false, 'getPriority');
115+
$taggedIterator2 = new TaggedIteratorArgument('foo', null, null, false, null, ['baz']);
116+
$taggedIterator3 = new TaggedIteratorArgument('foo', null, null, false, null, ['baz', 'qux']);
117+
115118
$container = new ContainerBuilder();
119+
116120
$container->register('foo_service', 'Foo')->addTag('foo');
121+
$container->register('baz_service', 'Baz')->addTag('foo');
122+
$container->register('qux_service', 'Qux')->addTag('foo');
123+
117124
$container->register('foo_service_tagged_iterator', 'Bar')->addArgument($taggedIterator);
125+
$container->register('foo2_service_tagged_iterator', 'Bar')->addArgument($taggedIterator2);
126+
$container->register('foo3_service_tagged_iterator', 'Bar')->addArgument($taggedIterator3);
127+
118128
$container->register('foo_service_tagged_locator', 'Bar')->addArgument(new ServiceLocatorArgument($taggedIterator));
129+
$container->register('foo2_service_tagged_locator', 'Bar')->addArgument(new ServiceLocatorArgument($taggedIterator2));
130+
$container->register('foo3_service_tagged_locator', 'Bar')->addArgument(new ServiceLocatorArgument($taggedIterator3));
119131
$container->register('bar_service_tagged_locator', 'Bar')->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo')));
120132

121133
$dumper = new YamlDumper($container);

Tests/Fixtures/xml/services_with_tagged_arguments.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,35 @@
55
<service id="foo" class="Foo">
66
<tag name="foo_tag"/>
77
</service>
8+
<service id="baz" class="Baz">
9+
<tag name="foo_tag"/>
10+
</service>
11+
<service id="qux" class="Qux">
12+
<tag name="foo_tag"/>
13+
</service>
814
<service id="foo_tagged_iterator" class="Bar" public="true">
915
<argument type="tagged_iterator" tag="foo_tag" index-by="barfoo" default-index-method="foobar" default-priority-method="getPriority"/>
1016
</service>
17+
<service id="foo2_tagged_iterator" class="Bar" public="true">
18+
<argument type="tagged_iterator" tag="foo_tag" exclude="baz"/>
19+
</service>
20+
<service id="foo3_tagged_iterator" class="Bar" public="true">
21+
<argument type="tagged_iterator" tag="foo_tag">
22+
<exclude>baz</exclude>
23+
<exclude>qux</exclude>
24+
</argument>
25+
</service>
1126
<service id="foo_tagged_locator" class="Bar" public="true">
1227
<argument type="tagged_locator" tag="foo_tag" index-by="barfoo" default-index-method="foobar" default-priority-method="getPriority"/>
1328
</service>
29+
<service id="foo2_tagged_locator" class="Bar" public="true">
30+
<argument type="tagged_locator" tag="foo_tag" exclude="baz"/>
31+
</service>
32+
<service id="foo3_tagged_locator" class="Bar" public="true">
33+
<argument type="tagged_locator" tag="foo_tag">
34+
<exclude>baz</exclude>
35+
<exclude>qux</exclude>
36+
</argument>
37+
</service>
1438
</services>
1539
</container>

Tests/Fixtures/yaml/services_with_tagged_argument.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,32 @@ services:
88
class: Foo
99
tags:
1010
- foo
11+
baz_service:
12+
class: Baz
13+
tags:
14+
- foo
15+
qux_service:
16+
class: Qux
17+
tags:
18+
- foo
1119
foo_service_tagged_iterator:
1220
class: Bar
1321
arguments: [!tagged_iterator { tag: foo, index_by: barfoo, default_index_method: foobar, default_priority_method: getPriority }]
22+
foo2_service_tagged_iterator:
23+
class: Bar
24+
arguments: [!tagged_iterator { tag: foo, exclude: baz }]
25+
foo3_service_tagged_iterator:
26+
class: Bar
27+
arguments: [!tagged_iterator { tag: foo, exclude: [baz, qux] }]
1428
foo_service_tagged_locator:
1529
class: Bar
1630
arguments: [!tagged_locator { tag: foo, index_by: barfoo, default_index_method: foobar, default_priority_method: getPriority }]
31+
foo2_service_tagged_locator:
32+
class: Bar
33+
arguments: [!tagged_locator { tag: foo, exclude: baz }]
34+
foo3_service_tagged_locator:
35+
class: Bar
36+
arguments: [!tagged_locator { tag: foo, exclude: [baz, qux] }]
1737
bar_service_tagged_locator:
1838
class: Bar
1939
arguments: [!tagged_locator foo]

0 commit comments

Comments
 (0)