Skip to content

Commit 140f807

Browse files
committed
[DependencyInjection] Update dumpers and loaders, add unit tests
1 parent 1eb1f4d commit 140f807

22 files changed

+316
-13
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1514
use Symfony\Component\DependencyInjection\ContainerBuilder;
1615
use Symfony\Component\DependencyInjection\Alias;
1716

@@ -29,26 +28,27 @@ public function process(ContainerBuilder $container)
2928
if (!$decorated = $definition->getDecoratedService()) {
3029
continue;
3130
}
31+
$definition->setDecoratedService(null);
3232

33-
list ($decorated, $renamedId) = $decorated;
33+
list ($inner, $renamedId) = $decorated;
3434
if (!$renamedId) {
3535
$renamedId = $id.'.inner';
3636
}
3737

3838
// we create a new alias/service for the service we are replacing
3939
// to be able to reference it in the new one
40-
if ($container->hasAlias($decorated)) {
41-
$alias = $container->getAlias($decorated);
40+
if ($container->hasAlias($inner)) {
41+
$alias = $container->getAlias($inner);
4242
$public = $alias->isPublic();
4343
$container->setAlias($renamedId, new Alias((string) $alias, false));
4444
} else {
45-
$definition = $container->getDefinition($decorated);
45+
$definition = $container->getDefinition($inner);
4646
$public = $definition->isPublic();
4747
$definition->setPublic(false);
4848
$container->setDefinition($renamedId, $definition);
4949
}
5050

51-
$container->setAlias($decorated, new Alias($id, $public));
51+
$container->setAlias($inner, new Alias($id, $public));
5252
}
5353
}
5454
}

src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,32 @@ public function setFactoryMethod($factoryMethod)
104104
/**
105105
* Sets the service that this service is decorating.
106106
*
107-
* @param string $id The decorated service id
108-
* @param string $renamedId The new decorated service id
107+
* @param null|string $id The decorated service id, use null to remove decoration
108+
* @param null|string $renamedId The new decorated service id
109+
*
110+
* @return Definition The current instance
111+
*
112+
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
109113
*/
110114
public function setDecoratedService($id, $renamedId = null)
111115
{
112116
if ($renamedId && $id == $renamedId) {
113-
throw new \LogicException(sprintf('The decorated service parent name for "%s" must be different than the service name itself.', $id));
117+
throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
114118
}
115119

116-
$this->decoratedService = array($id, $renamedId);
120+
if (null === $id) {
121+
$this->decoratedService = null;
122+
} else {
123+
$this->decoratedService = array($id, $renamedId);
124+
}
125+
126+
return $this;
117127
}
118128

119129
/**
120130
* Gets the service that decorates this service.
121131
*
122-
* @return array An array composed of the decorated service id and the new id for it
132+
* @return null|array An array composed of the decorated service id and the new id for it, null if no service is decorated
123133
*/
124134
public function getDecoratedService()
125135
{

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ private function addService($definition, $id, \DOMElement $parent)
138138
if ($definition->isLazy()) {
139139
$service->setAttribute('lazy', 'true');
140140
}
141+
if (null !== $decorated = $definition->getDecoratedService()) {
142+
list ($decorated, $renamedId) = $decorated;
143+
$service->setAttribute('decorates', $decorated);
144+
if (null !== $renamedId) {
145+
$service->setAttribute('decoration-inner-name', $renamedId);
146+
}
147+
}
141148

142149
foreach ($definition->getTags() as $name => $tags) {
143150
foreach ($tags as $attributes) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ private function addService($id, $definition)
139139
$code .= sprintf(" scope: %s\n", $scope);
140140
}
141141

142+
if (null !== $decorated = $definition->getDecoratedService()) {
143+
list ($decorated, $renamedId) = $decorated;
144+
$code .= sprintf(" decorates: %s\n", $decorated);
145+
if (null !== $renamedId) {
146+
$code .= sprintf(" decoration-inner-name: %s\n", $renamedId);
147+
}
148+
}
149+
142150
if ($callable = $definition->getConfigurator()) {
143151
if (is_array($callable)) {
144152
if ($callable[0] instanceof Reference) {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ private function parseDefinition($id, $service, $file)
197197
$definition->addTag((string) $tag['name'], $parameters);
198198
}
199199

200+
if (isset($service['decorates'])) {
201+
$renameId = isset($service['decoration-inner-name']) ? (string) $service['decoration-inner-name'] : null;
202+
$definition->setDecoratedService((string) $service['decorates'], $renameId);
203+
}
204+
200205
$this->container->setDefinition($id, $definition);
201206
}
202207

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ private function parseDefinition($id, $service, $file)
234234
}
235235
}
236236

237+
if (isset($service['decorates'])) {
238+
$renameId = isset($service['decoration-inner-name']) ? $service['decoration-inner-name'] : null;
239+
$definition->setDecoratedService($service['decorates'], $renameId);
240+
}
241+
237242
$this->container->setDefinition($id, $definition);
238243
}
239244

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
@@ -94,6 +94,8 @@
9494
<xsd:attribute name="factory-service" type="xsd:string" />
9595
<xsd:attribute name="alias" type="xsd:string" />
9696
<xsd:attribute name="parent" type="xsd:string" />
97+
<xsd:attribute name="decorates" type="xsd:string" />
98+
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
9799
</xsd:complexType>
98100

99101
<xsd:complexType name="tag">
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Alias;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
8+
9+
class DecoratorServicePassTest extends \PHPUnit_Framework_TestCase
10+
{
11+
public function testProcessWithoutAlias()
12+
{
13+
$container = new ContainerBuilder();
14+
$fooDefinition = $container
15+
->register('foo')
16+
->setPublic(false)
17+
;
18+
$fooExtendedDefinition = $container
19+
->register('foo.extended')
20+
->setPublic(true)
21+
->setDecoratedService('foo')
22+
;
23+
$barDefinition = $container
24+
->register('bar')
25+
->setPublic(true)
26+
;
27+
$barExtendedDefinition = $container
28+
->register('bar.extended')
29+
->setPublic(true)
30+
->setDecoratedService('bar', 'bar.yoo')
31+
;
32+
33+
$this->process($container);
34+
35+
$this->assertEquals('foo.extended', $container->getAlias('foo'));
36+
$this->assertFalse($container->getAlias('foo')->isPublic());
37+
38+
$this->assertEquals('bar.extended', $container->getAlias('bar'));
39+
$this->assertTrue($container->getAlias('bar')->isPublic());
40+
41+
$this->assertSame($fooDefinition, $container->getDefinition('foo.extended.inner'));
42+
$this->assertFalse($container->getDefinition('foo.extended.inner')->isPublic());
43+
44+
$this->assertSame($barDefinition, $container->getDefinition('bar.yoo'));
45+
$this->assertFalse($container->getDefinition('bar.yoo')->isPublic());
46+
47+
$this->assertNull($fooExtendedDefinition->getDecoratedService());
48+
$this->assertNull($barExtendedDefinition->getDecoratedService());
49+
}
50+
51+
public function testProcessWithAlias()
52+
{
53+
$container = new ContainerBuilder();
54+
$container
55+
->register('foo')
56+
->setPublic(true)
57+
;
58+
$container->setAlias('foo.alias', new Alias('foo', false));
59+
$fooExtendedDefinition = $container
60+
->register('foo.extended')
61+
->setPublic(true)
62+
->setDecoratedService('foo.alias')
63+
;
64+
65+
$this->process($container);
66+
67+
$this->assertEquals('foo.extended', $container->getAlias('foo.alias'));
68+
$this->assertFalse($container->getAlias('foo.alias')->isPublic());
69+
70+
$this->assertEquals('foo', $container->getAlias('foo.extended.inner'));
71+
$this->assertFalse($container->getAlias('foo.extended.inner')->isPublic());
72+
73+
$this->assertNull($fooExtendedDefinition->getDecoratedService());
74+
}
75+
76+
protected function process(ContainerBuilder $container)
77+
{
78+
$repeatedPass = new DecoratorServicePass();
79+
$repeatedPass->process($container);
80+
}
81+
}

src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,26 @@ public function testSetGetClass()
6262
$this->assertEquals('foo', $def->getClass(), '->getClass() returns the class name');
6363
}
6464

65+
public function testSetGetDecoratedService()
66+
{
67+
$def = new Definition('stdClass');
68+
$this->assertNull($def->getDecoratedService());
69+
$def->setDecoratedService('foo', 'foo.renamed');
70+
$this->assertEquals(array('foo', 'foo.renamed'), $def->getDecoratedService());
71+
$def->setDecoratedService(null);
72+
$this->assertNull($def->getDecoratedService());
73+
74+
$def = new Definition('stdClass');
75+
$def->setDecoratedService('foo');
76+
$this->assertEquals(array('foo', null), $def->getDecoratedService());
77+
$def->setDecoratedService(null);
78+
$this->assertNull($def->getDecoratedService());
79+
80+
$def = new Definition('stdClass');
81+
$this->setExpectedException('InvalidArgumentException', 'The decorated service inner name for "foo" must be different than the service name itself.');
82+
$def->setDecoratedService('foo', 'foo');
83+
}
84+
6585
/**
6686
* @covers Symfony\Component\DependencyInjection\Definition::setArguments
6787
* @covers Symfony\Component\DependencyInjection\Definition::getArguments

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function testAddService()
6666

6767
public function testDumpAnonymousServices()
6868
{
69-
include self::$fixturesPath.'/containers/container11.php';
69+
$container = include self::$fixturesPath.'/containers/container11.php';
7070
$dumper = new XmlDumper($container);
7171
$this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
7272
<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\">
@@ -87,7 +87,7 @@ public function testDumpAnonymousServices()
8787

8888
public function testDumpEntities()
8989
{
90-
include self::$fixturesPath.'/containers/container12.php';
90+
$container = include self::$fixturesPath.'/containers/container12.php';
9191
$dumper = new XmlDumper($container);
9292
$this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
9393
<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\">
@@ -100,4 +100,35 @@ public function testDumpEntities()
100100
</container>
101101
", $dumper->dump());
102102
}
103+
104+
/**
105+
* @dataProvider provideDecoratedServicesData
106+
*/
107+
public function testDumpDecoratedServices($expectedXmlDump, $container)
108+
{
109+
$dumper = new XmlDumper($container);
110+
$this->assertEquals($expectedXmlDump, $dumper->dump());
111+
}
112+
113+
public function provideDecoratedServicesData()
114+
{
115+
$fixturesPath = realpath(__DIR__.'/../Fixtures/');
116+
117+
return array(
118+
array("<?xml version=\"1.0\" encoding=\"utf-8\"?>
119+
<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\">
120+
<services>
121+
<service id=\"foo\" class=\"FooClass\Foo\" decorates=\"bar\" decoration-inner-name=\"bar.woozy\"/>
122+
</services>
123+
</container>
124+
", include $fixturesPath.'/containers/container15.php'),
125+
array("<?xml version=\"1.0\" encoding=\"utf-8\"?>
126+
<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\">
127+
<services>
128+
<service id=\"foo\" class=\"FooClass\Foo\" decorates=\"bar\"/>
129+
</services>
130+
</container>
131+
", include $fixturesPath.'/containers/container16.php'),
132+
);
133+
}
103134
}

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