8000 [DI] change name to tag + add XMl support + adding yaml/xml tests · symfony/symfony@d18fd9a · GitHub
[go: up one dir, main page]

Skip to content

Commit d18fd9a

Browse files
author
Anthony MARTIN
committed
[DI] change name to tag + add XMl support + adding yaml/xml tests
| Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | yno | Tests pass? | yes | Fixed tickets | #29203 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> This is the continuity of the PR # Add a way to specify an index based on a tag attribute when injecting a tag collection into services, but also a a way to fallback to a static method on the service class. ```yaml services: foo_service: class: Foo tags: - foo foo_service_tagged: class: Bar arguments: - !tagged { tag: 'foo'', index_by: 'tag_attribute_name', default_index_method: 'static_method'} ``` ```xml <?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="foo" class="Foo"> <tag name="foo_tag" /> </service> <service id="foo_tagged_iterator" class="Bar" public="true"> <argument type="tagged" tag="foo_tag" index-by="tag_attribute_name" default-index-method="static_method" /> </service> </services> </container> ``` Tasks * [x] Support PHP loader/dumper * [x] Support YAML loader/dumper * [x] Support XML loader/dump (update XSD too) * [x] Add tests
1 parent 453b01a commit d18fd9a

17 files changed

+586
-6
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,14 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent
286286
} elseif ($value instanceof TaggedIteratorArgument) {
287287
$element->setAttribute('type', 'tagged');
288288
$element->setAttribute('tag', $value->getTag());
289+
290+
if (null !== $value->getIndexAttribute()) {
291+
$element->setAttribute('index-by', $value->getIndexAttribute());
292+
}
293+
294+
if (null !== $value->getDefaultIndexMethod()) {
295+
$element->setAttribute('default-index-method', $value->getDefaultIndexMethod());
296+
}
289297
} elseif ($value instanceof IteratorArgument) {
290298
$element->setAttribute('type', 'iterator');
291299
$this->convertParameters($value->getValues(), $type, $element, 'key');

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,19 @@ private function dumpValue($value)
233233
}
234234
if ($value instanceof ArgumentInterface) {
235235
if ($value instanceof TaggedIteratorArgument) {
236+
if (null !== $value->getIndexAttribute()) {
237+
$taggedValueContent = [
238+
'tag' => $value->getTag(),
239+
'index_by' => $value->getIndexAttribute(),
240+
];
241+
242+
if (null !== $value->getDefaultIndexMethod()) {
243+
$taggedValueContent['default_index_method'] = $value->getDefaultIndexMethod();
244+
}
245+
246+
return new TaggedValue('tagged', $taggedValueContent);
247+
}
248+
236249
return new TaggedValue('tagged', $value->getTag());
237250
}
238251
if ($value instanceof IteratorArgument) {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,8 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
537537
if (!$arg->getAttribute('tag')) {
538538
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="tagged" has no or empty "tag" attribute in "%s".', $name, $file));
539539
}
540-
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
540+
541+
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null);
541542
break;
542543
case 'binary':
543544
if (false === $value = base64_decode($arg->nodeValue)) {

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -713,14 +713,16 @@ private function resolveServices($value, $file, $isParameter = false)
713713
if (\is_string($argument) && $argument) {
714714
return new TaggedIteratorArgument($argument);
715715
}
716-
if (\is_array($argument) && isset($argument['name']) && $argument['name']) {
717-
if (array_diff(array_keys($argument), ['name', 'index_by', 'default_index_method'])) {
718-
throw new InvalidArgumentException('"!tagged" tag contains unsupported keys. Supported are: "name, index_by, default_index_method".');
716+
717+
if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
718+
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method'])) {
719+
throw new InvalidArgumentException(sprintf('"!tagged" tag contains unsupported key "%s"; supported ones are "tag", "index_by" and "default_index_method".', implode(', ', $diff)));
719720
}
720721

721-
return new TaggedIteratorArgument($argument['name'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null);
722+
return new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null);
722723
}
723-
throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts a non empty string or an array with a key "name" in "%s".', $file));
724+
725+
throw new InvalidArgumentException(sprintf('"!tagged" tags only accept a non empty string or an array with a key "tag" in "%s".', $file));
724726
}
725727
if ('service' === $value->getTag()) {
726728
if ($isParameter) {

src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@
234234
<xsd:attribute name="index" type="xsd:integer" />
235235
<xsd:attribute name="on-invalid" type="invalid_sequence" />
236236
<xsd:attribute name="tag" type="xsd:string" />
237+
<xsd:attribute name="index-by" type="xsd:string" />
238+
<xsd:attribute name="default-index-method" type="xsd:string" />
237239
</xsd:complexType>
238240

239241
<xsd:complexType name="call">

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Config\FileLocator;
1616
use Symfony\Component\DependencyInjection\Alias;
17+
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1718
use Symfony\Component\DependencyInjection\ContainerBuilder;
1819
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
1920
use Symfony\Component\DependencyInjection\Reference;
2021
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
22+
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
23+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedClass;
24+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooTagClass;
2125

2226
/**
2327
* This class tests the integration of the different compiler passes.
@@ -234,6 +238,70 @@ public function getYamlCompileTests()
234238
$container,
235239
];
236240
}
241+
242+
public function testTaggedServiceWithIndexAttribute()
243+
{
244+
$container = new ContainerBuilder();
245+
$container->register('bar_tag_service', BarTagClass::class)
246+
->setPublic(true)
247+
->addTag('foo_bar', ['foo' => 'bar'])
248+
;
249+
$container->register('foo_tag_service', FooTagClass::class)
250+
->setPublic(true)
251+
->addTag('foo_bar', ['foo' => 'foo'])
252+
;
253+
$container->register('foobar_tagged_service', FooBarTaggedClass::class)
254+
->addArgument(new TaggedIteratorArgument('foo_bar', 'foo'))
255+
->setPublic(true)
256+
;
257+
258+
$container->compile();
259+
$this->assertNotNull($container->getDefinition('bar_tag_service'));
260+
$this->assertNotNull($container->getDefinition('foo_tag_service'));
261+
$this->assertNotNull($container->getDefinition('foobar_tagged_service'));
262+
263+
$s = $container->get('foobar_tagged_service');
264+
$this->assertTrue($s instanceof FooBarTaggedClass, 'The service foobar_tagged_service should be an instance of Bar\FooBarTaggedClass');
265+
266+
$param = iterator_to_array($s->getParam()->getIterator());
267+
$this->assertCount(2, $param);
268+
$this->assertArrayHasKey('foo', $param);
269+
$this->assertArrayHasKey('bar', $param);
270+
$this->assertEquals($param['foo'], $container->get('foo_tag_service'));
271+
$this->assertEquals($param['bar'], $container->get('bar_tag_service'));
272+
}
273+
274+
public function testTaggedServiceWithIndexAttributeAndDefaultMethod()
275+
{
276+
$container = new ContainerBuilder();
277+
$container->register('bar_tag_service', BarTagClass::class)
278+
->setPublic(true)
279+
->addTag('foo_bar', ['foo' => 'bar'])
280+
;
281+
$container->register('foo_tag_service', FooTagClass::class)
282+
->setPublic(true)
283+
->addTag('foo_bar< CA2C /span>', ['foo' => 'foo'])
284+
;
285+
$container->register('foobar_tagged_service', FooBarTaggedClass::class)
286+
->addArgument(new TaggedIteratorArgument('foo_bar', 'foo', 'getFooBar'))
287+
->setPublic(true)
288+
;
289+
290+
$container->compile();
291+
$this->assertNotNull($container->getDefinition('bar_tag_service'));
292+
$this->assertNotNull($container->getDefinition('foo_tag_service'));
293+
$this->assertNotNull($container->getDefinition('foobar_tagged_service'));
294+
295+
$s = $container->get('foobar_tagged_service');
296+
$this->assertTrue($s instanceof FooBarTaggedClass, 'The service foobar_tagged_service should be an instance of Bar\FooBarTaggedClass');
297+
298+
$param = iterator_to_array($s->getParam()->getIterator());
299+
$this->assertCount(2, $param);
300+
$this->assertArrayHasKey('foo', $param);
301+
$this->assertArrayHasKey('bar', $param);
302+
$this->assertEquals($param['foo'], $container->get('foo_tag_service'));
303+
$this->assertEquals($param['bar'], $container->get('bar_tag_service'));
304+
}
237305
}
238306

239307
class ServiceSubscriberStub implements ServiceSubscriberInterface

0 commit comments

Comments
 (0)
0