8000 feature #15416 [DependencyInjection] Added a way to define the priori… · symfony/dependency-injection@b0e1cef · GitHub
[go: up one dir, main page]

Skip to content

Commit b0e1cef

Browse files
committed
feature #15416 [DependencyInjection] Added a way to define the priority of service decoration (dosten)
This PR was merged into the 2.8 branch. Discussion ---------- [DependencyInjection] Added a way to define the priority of service decoration | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #10634 | License | MIT | Doc PR | symfony/symfony-docs#5600 This PR adds a way to define the priority of service decoration, so, the service with the highest priority will be applied first (the default priority is zero). ```yaml services: foo: class: Foo bar: class: Bar arguments: ['@bar.inner'] decorates: foo public: false foobar: class: Foobar arguments: ['@foobar.inner'] decorates: foo decoration_priority: 1 public: false ``` This will result in this code: ```php $this->services['foo'] = new Bar(new Foobar(new Foo))); ``` Commits ------- 75c98cb Added a way to define the priority of service decoration
2 parents 9f4e9f0 + 96d5a95 commit b0e1cef

16 files changed

+94
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* deprecated the concept of scopes
99
* added `Definition::setShared()` and `Definition::isShared()`
1010
* added ResettableContainerInterface to be able to reset the container to release memory on shutdown
11+
* added a way to define the priority of service decoration
1112

1213
2.7.0
1314
-----

Compiler/DecoratorServicePass.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,28 @@
1919
*
2020
* @author Christophe Coevoet <stof@notk.org>
2121
* @author Fabien Potencier <fabien@symfony.com>
22+
* @author Diego Saint Esteben <diego@saintesteben.me>
2223
*/
2324
class DecoratorServicePass implements CompilerPassInterface
2425
{
2526
public function process(ContainerBuilder $container)
2627
{
28+
$definitions = new \SplPriorityQueue();
29+
$order = PHP_INT_MAX;
30+
2731
foreach ($container->getDefinitions() as $id => $definition) {
2832
if (!$decorated = $definition->getDecoratedService()) {
2933
continue;
3034
}
35+
$definitions->insert(array($id, $definition), array($decorated[2], --$order));
36+
}
37+
38+
foreach ($definitions as $arr) {
39+
list($id, $definition) = $arr;
40+
list($inner, $renamedId) = $definition->getDecoratedService();
41+
3142
$definition->setDecoratedService(null);
3243

33-
list($inner, $renamedId) = $decorated;
3444
if (!$renamedId) {
3545
$renamedId = $id.'.inner';
3646
}

Definition.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,13 @@ public function setFactoryMethod($factoryMethod)
150150
*
151151
* @param null|string $id The decorated service id, use null to remove decoration
152152
* @param null|string $renamedId The new decorated service id
153+
* @param int $priority The priority of decoration
153154
*
154155
* @return Definition The current instance
155156
*
156157
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
157158
*/
158-
public function setDecoratedService($id, $renamedId = null)
159+
public function setDecoratedService($id, $renamedId = null, $priority = 0)
159160
{
160161
if ($renamedId && $id == $renamedId) {
161162
throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
@@ -164,7 +165,7 @@ public function setDecoratedService($id, $renamedId = null)
164165
if (null === $id) {
165166
$this->decoratedService = null;
166167
} else {
167-
$this->decoratedService = array($id, $renamedId);
168+
$this->decoratedService = array($id, $renamedId, (int) $priority);
168169
}
169170

170171
return $this;
@@ -173,7 +174,7 @@ public function setDecoratedService($id, $renamedId = null)
173174
/**
174175
* Gets the service that decorates this service.
175176
*
176-
* @return null|array An array composed of the decorated service id and the new id for it, null if no service is decorated
177+
* @return null|array An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated
177178
*/
178179
public function getDecoratedService()
179180
{

DefinitionDecorator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,11 @@ public function setLazy($boolean)
173173
/**
174174
* {@inheritdoc}
175175
*/
176-
public function setDecoratedService($id, $renamedId = null)
176+
public function setDecoratedService($id, $renamedId = null, $priority = 0)
177177
{
178178
$this->changes['decorated_service'] = true;
179179

180-
return parent::setDecoratedService($id, $renamedId);
180+
return parent::setDecoratedService($id, $renamedId, $priority);
181181
}
182182

183183
/**

Dumper/XmlDumper.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,14 @@ private function addService($definition, $id, \DOMElement $parent)
149149
$service->setAttribute('lazy', 'true');
150150
}
151151
if (null !== $decorated = $definition->getDecoratedService()) {
152-
list($decorated, $renamedId) = $decorated;
152+
list($decorated, $renamedId, $priority) = $decorated;
153153
$service->setAttribute('decorates', $decorated);
154154
if (null !== $renamedId) {
155155
$service->setAttribute('decoration-inner-name', $renamedId);
156156
}
157+
if (0 !== $priority) {
158+
$service->setAttribute('decoration-priority', $priority);
159+
}
157160
}
158161

159162
foreach ($definition->getTags() as $name => $tags) {

Dumper/YamlDumper.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,14 @@ private function addService($id, $definition)
141141
}
142142

143143
if (null !== $decorated = $definition->getDecoratedService()) {
144-
list($decorated, $renamedId) = $decorated;
144+
list($decorated, $renamedId, $priority) = $decorated;
145145
$code .= sprintf(" decorates: %s\n", $decorated);
146146
if (null !== $renamedId) {
147147
$code .= sprintf(" decoration_inner_name: %s\n", $renamedId);
148148
}
149+
if (0 !== $priority) {
150+
$code .= sprintf(" decoration_priority: %s\n", $priority);
151+
}
149152
}
150153

151154
if ($callable = $definition->getFactory()) {

Loader/XmlFileLoader.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ private function parseDefinition(\DOMElement $service, $file)
245245

246246
if ($value = $service->getAttribute('decorates')) {
247247
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
248-
$definition->setDecoratedService($value, $renameId);
248+
$priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;
249+
$definition->setDecoratedService($value, $renameId, $priority);
249250
}
250251

251252
return $definition;

Loader/YamlFileLoader.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ private function parseDefinition($id, $service, $file)
290290

291291
if (isset($service['decorates'])) {
292292
$renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null;
293-
$definition->setDecoratedService($service['decorates'], $renameId);
293+
$priority = isset($service['decoration_priority']) ? $service['decoration_priority'] : 0;
294+
$definition->setDecoratedService($service['decorates'], $renameId, $priority);
294295
}
295296

296297
$this->container->setDefinition($id, $definition);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<xsd:attribute name="parent" type="xsd:string" />
102102
<xsd:attribute name="decorates" type="xsd:string" />
103103
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
104+
<xsd:attribute name="decoration-priority" type="xsd:integer" />
104105
</xsd:complexType>
105106

106107
<xsd:complexType name="tag">

Tests/Compiler/DecoratorServicePassTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,48 @@ public function testProcessWithAlias()
7373
$this->assertNull($fooExtendedDefinition->getDecoratedService());
7474
}
7575

76+
public function testProcessWithPriority()
77+
{
78+
$container = new ContainerBuilder();
79+
$fooDefinition = $container
80+
->register('foo')
81+
->setPublic(false)
82+
;
83+
$barDefinition = $container
84+
->register('bar')
85+
->setPublic(true)
86+
->setDecoratedService('foo')
87+
;
88+
$bazDefinition = $container
89+
->register('baz')
90+
->setPublic(true)
91+
->setDecoratedService('foo', null, 5)
92+
;
93+
$quxDefinition = $container
94+
->register('qux')
95+
->setPublic(true)
96+
->setDecoratedService('foo', null, 3)
97+
;
98+
99+
$this->process($container);
100+
101+
$this->assertEquals('bar', $container->getAlias('foo'));
102+
$this->assertFalse($container->getAlias('foo')->isPublic());
103+
104+
$this->assertSame($fooDefinition, $container->getDefinition('baz.inner'));
105+
$this->assertFalse($container->getDefinition('baz.inner')->isPublic());
106+
107+
$this->assertEquals('qux', $container->getAlias('bar.inner'));
108+
$this->assertFalse($container->getAlias('bar.inner')->isPublic());
109+
110+
$this->assertEquals('baz', $container->getAlias('qux.inner'));
111+
$this->assertFalse($container->getAlias('qux.inner')->isPublic());
112+
113+
$this->assertNull($barDefinition->getDecoratedService());
114+
$this->assertNull($bazDefinition->getDecoratedService());
115+
$this->assertNull($quxDefinition->getDecoratedService());
116+
}
117+
76118
protected function process(ContainerBuilder $container)
77119
{
78120
$repeatedPass = new DecoratorServicePass();

Tests/Compiler/ResolveDefinitionTemplatesPassTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public function testSetDecoratedServiceOnServiceHasParent()
241241
->setDecoratedService('foo', 'foo_inner')
242242
;
243243

244-
$this->assertEquals(array('foo', 'foo_inner'), $container->getDefinition('child1')->getDecoratedService());
244+
$this->assertEquals(array('foo', 'foo_inner', 0), $container->getDefinition('child1')->getDecoratedService());
245245
}
246246

247247
protected function process(ContainerBuilder $container)

Tests/DefinitionTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,23 @@ public function testSetGetClass()
5656

5757
public function testSetGetDecoratedService()
5858
{
59+
$def = new Definition('stdClass');
60+
$this->assertNull($def->getDecoratedService());
61+
$def->setDecoratedService('foo', 'foo.renamed', 5);
62+
$this->assertEquals(array('foo', 'foo.renamed', 5), $def->getDecoratedService());
63+
$def->setDecoratedService(null);
64+
$this->assertNull($def->getDecoratedService());
65+
5966
$def = new Definition('stdClass');
6067
$this->assertNull($def->getDecoratedService());
6168
$def->setDecoratedService('foo', 'foo.renamed');
62-
$this->assertEquals(array('foo', 'foo.renamed'), $def->getDecoratedService());
69+
$this->assertEquals(array('foo', 'foo.renamed', 0), $def->getDecoratedService());
6370
$def->setDecoratedService(null);
6471
$this->assertNull($def->getDecoratedService());
6572

6673
$def = new Definition('stdClass');
6774
$def->setDecoratedService('foo');
68-
$this->assertEquals(array('foo', null), $def->getDecoratedService());
75+
$this->assertEquals(array('foo', null, 0), $def->getDecoratedService());
6976
$def->setDecoratedService(null);
7077
$this->assertNull($def->getDecoratedService());
7178

Tests/Fixtures/xml/services6.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<service id="another_alias_for_foo" alias="foo" public="false" />
4848
<service id="decorator_service" decorates="decorated" />
4949
<service id="decorator_service_with_name" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/>
50+
<service id="decorator_service_with_name_and_priority" decorates="decorated" decoration-inner-name="decorated.pif-pouf" decoration-priority="5"/>
5051
<service id="new_factory1" class="FooBarClass">
5152
<factory function="factory" />
5253
</service>

Tests/Fixtures/yaml/services6.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ services:
2626
decorator_service_with_name:
2727
decorates: decorated
2828
decoration_inner_name: decorated.pif-pouf
29+
decorator_service_with_name_and_priority:
30+
decorates: decorated
31+
decoration_inner_name: decorated.pif-pouf
32+
decoration_priority: 5
2933
new_factory1: { class: FooBarClass, factory: factory}
3034
new_factory2: { class: FooBarClass, factory: [@baz, getClass]}
3135
new_factory3: { class: FooBarClass, factory: [BazClass, getInstance]}

Tests/Loader/XmlFileLoaderTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@ public function testLoadServices()
242242
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
243243
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
244244

245-
$this->assertEquals(array('decorated', null), $services['decorator_service']->getDecoratedService());
246-
$this->assertEquals(array('decorated', 'decorated.pif-pouf'), $services['decorator_service_with_name']->getDecoratedService());
245+
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
246+
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
247+
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
247248
}
248249

249250
public function testParsesTags()

Tests/Loader/YamlFileLoaderTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ public function testLoadServices()
171171
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
172172
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
173173

174-
$this->assertEquals(array('decorated', null), $services['decorator_service']->getDecoratedService());
175-
$this->assertEquals(array('decorated', 'decorated.pif-pouf'), $services['decorator_service_with_name']->getDecoratedService());
174+
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
175+
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
176+
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
176177
}
177178

178179
public function testLoadFactoryShortSyntax()

0 commit comments

Comments
 (0)
0