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

Skip to content

Commit 1aa9a24

Browse files
[DependencyInjection] fix dumping service-closure-arguments
1 parent 89c1be8 commit 1aa9a24

File tree

12 files changed

+97
-5
lines changed

12 files changed

+97
-5
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,6 @@ private function convertParameters(array $parameters, string $type, \DOMElement
264264
$element->setAttribute($keyAttribute, $key);
265265
}
266266

267-
if ($value instanceof ServiceClosureArgument) {
268-
$value = $value->getValues()[0];
269-
}
270267
if (\is_array($tag = $value)) {
271268
$element->setAttribute('type', 'collection');
272269
$this->convertParameters($value, $type, $element, 'key');
@@ -290,8 +287,12 @@ private function convertParameters(array $parameters, string $type, \DOMElement
290287
} elseif ($value instanceof ServiceLocatorArgument) {
291288
$element->setAttribute('type', 'service_locator');
292289
$this->convertParameters($value->getValues(), $type, $element, 'key');
293-
} elseif ($value instanceof Reference) {
290+
} elseif ($value instanceof Reference || $value instanceof ServiceClosureArgument) {
294291
$element->setAttribute('type', 'service');
292+
if ($value instanceof ServiceClosureArgument) {
293+
$element->setAttribute('type', 'service_closure');
294+
$value = $value->getValues()[0];
295+
}
295296
$element->setAttribute('id', (string) $value);
296297
$behavior = $value->getInvalidBehavior();
297298
if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ private function dumpValue($value)
234234
{
235235
if ($value instanceof ServiceClosureArgument) {
236236
$value = $value->getValues()[0];
237+
238+
return new TaggedValue('service_closure', $this->getServiceCall((string) $value, $value));
237239
}
238240
if ($value instanceof ArgumentInterface) {
239241
$tag = $value;

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\DependencyInjection\Alias;
1616
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1717
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
18+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1819
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1920
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
2021
use Symfony\Component\DependencyInjection\ChildDefinition;
@@ -507,6 +508,13 @@ private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file
507508
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file));
508509
}
509510
break;
511+
case 'service_closure':
512+
if ('' === $arg->getAttribute('id')) {
513+
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_closure" has no or empty "id" attribute in "%s".', $name, $file));
514+
}
515+
516+
$arguments[$key] = new ServiceClosureArgument(new Reference($arg->getAttribute('id'), $invalidBehavior));
517+
break;
510518
case 'service_locator':
511519
$arg = $this->getArgumentsAsPhp($arg, $name, $file);
512520
try {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
1616
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1717
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
18+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1819
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1920
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
2021
use Symfony\Component\DependencyInjection\ChildDefinition;
@@ -745,6 +746,15 @@ private function resolveServices($value, string $file, bool $isParameter = false
745746
throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file));
746747
}
747748
}
749+
if ('service_closure' === $value->getTag()) {
750+
$argument = $this->resolveServices($argument, $file, $isParameter);
751+
752+
if (!$argument instanceof Reference) {
753+
throw new InvalidArgumentException(sprintf('"!service_closure" tag only accepts service references in "%s".', $file));
754+
}
755+
756+
return new ServiceClosureArgument($argument);
757+
}
748758
if ('service_locator' === $value->getTag()) {
749759
if (!\is_array($argument)) {
750760
throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps in "%s".', $file));

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
<xsd:enumeration value="constant" />
268268
<xsd:enumeration value="binary" />
269269
<xsd:enumeration value="iterator" />
270+
<xsd:enumeration value="service_closure" />
270271
<xsd:enumeration value="service_locator" />
271272
<!-- "tagged" is an alias of "tagged_iterator", using "tagged_iterator" is preferred. -->
272273
<xsd:enumeration value="tagged" />

src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Config\FileLocator;
16+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1617
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1718
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1819
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -230,6 +231,17 @@ public function testTaggedArguments()
230231
$this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_with_tagged_arguments.xml', $dumper->dump());
231232
}
232233

234+
public function testServiceClosure()
235+
{
236+
$container = new ContainerBuilder();
237+
$container->register('foo', 'Foo')
238+
->addArgument(new ServiceClosureArgument(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))
239+
;
240+
241+
$dumper = new XmlDumper($container);
242+
$this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_with_service_closure.xml', $dumper->dump());
243+
}
244+
233245
public function testDumpAbstractServices()
234246
{
235247
$container = include self::$fixturesPath.'/containers/container_abstract.php';

src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Config\FileLocator;
16+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1617
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1718
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1819
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -117,6 +118,17 @@ public function testTaggedArguments()
117118
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_with_tagged_argument.yml', $dumper->dump());
118119
}
119120

121+
public function testServiceClosure()
122+
{
123+
$container = new ContainerBuilder();
124+
$container->register('foo', 'Foo')
125+
->addArgument(new ServiceClosureArgument(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))
126+
;
127+
128+
$dumper = new YamlDumper($container);
129+
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_with_service_closure.yml', $dumper->dump());
130+
}
131+
120132
private function assertEqualYamlStructure(string $expected, string $yaml, string $message = '')
121133
{
122134
$parser = new Parser();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<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 https://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<services>
4+
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
5+
<service id="foo" class="Foo">
6+
<argument type="service_closure" id="bar" on-invalid="ignore"/>
7+
</service>
8+
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
9+
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
10+
</services>
11+
</container>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
foo:
8+
class: Foo
9+
arguments: [!service_closure '@?bar']
10+
Psr\Container\ContainerInterface:
11+
alias: service_container
12+
public: false
13+
Symfony\Component\DependencyInjection\ContainerInterface:
14+
alias: service_container
15+
public: false

src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Config\Util\Exception\XmlParsingException;
2222
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
2323
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
24+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
2425
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
2526
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
2627
use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
@@ -376,6 +377,15 @@ public function testParseTaggedArgumentsWithIndexBy()
376377
$this->assertEquals(new ServiceLocatorArgument($taggedIterator), $container->getDefinition('foo_tagged_locator')->getArgument(0));
377378
}
378379

380+
public function testParseServiceClosure()
381+
{
382+
$container = new ContainerBuilder();
383+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
384+
$loader->load('services_with_service_closure.xml');
385+
386+
$this->assertEquals(new ServiceClosureArgument(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)), $container->getDefinition('foo')->getArgument(0));
387+
}
388+
379389
public function testParseTagsWithoutNameThrowsException()
380390
{
381391
$this->expectException(InvalidArgumentException::class);

src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Config\Resource\GlobResource;
2121
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
2222
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
23+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
2324
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
2425
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
2526
use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
@@ -364,6 +365,15 @@ public function testTaggedArgumentsWithIndex()
364365
}
365366
}
366367

368+
public function testParseServiceClosure()
369+
{
370+
$container = new ContainerBuilder();
371+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
372+
$loader->load('services_with_service_closure.yml');
373+
374+
$this->assertEquals(new ServiceClosureArgument(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)), $container->getDefinition('foo')->getArgument(0));
375+
}
376+
367377
public function testNameOnlyTagsAreAllowedAsString()
368378
{
369379
$container = new ContainerBuilder();

src/Symfony/Component/DependencyInjection/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"symfony/service-contracts": "^1.1.6|^2"
2222
},
2323
"require-dev": {
24-
"symfony/yaml": "^3.4|^4.0|^5.0",
24+
"symfony/yaml": "^4.4|^5.0",
2525
"symfony/config": "^4.3",
2626
"symfony/expression-language": "^3.4|^4.0|^5.0"
2727
},

0 commit comments

Comments
 (0)