Skip to content

Commit 2bbcf6c

Browse files
[DI] Allow definitions to inherit tags from parent context
1 parent 2cf2a66 commit 2bbcf6c

File tree

10 files changed

+111
-27
lines changed

10 files changed

+111
-27
lines changed

CHANGELOG.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ CHANGELOG
44
3.3.0
55
-----
66

7-
* Add "iterator" argument type for lazy iteration over a set of values and services
8-
9-
* Using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
10-
will not be supported anymore in 4.0.
11-
7+
* added "iterator" argument type for lazy iteration over a set of values and services
8+
* added "closure-proxy" argument type for turning services' methods into lazy callables
9+
* added file-wide configurable defaults for service attributes "public", "tags",
10+
"autowire" and a new "inherit-tags"
11+
* made the "class" attribute optional, using the "id" as fallback
12+
* using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
13+
will not be supported anymore in 4.0
1214
* deprecated the `DefinitionDecorator` class in favor of `ChildDefinition`
1315

1416
3.2.0

ChildDefinition.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
class ChildDefinition extends Definition
2323
{
2424
private $parent;
25+
private $inheritTags = false;
2526
private $changes = array();
2627

2728
/**
@@ -54,6 +55,30 @@ public function getChanges()
5455
return $this->changes;
5556
}
5657

58+
/**
59+
* Sets whether tags should be inherited from the parent or not.
60+
*
61+
* @param bool $boolean
62+
*
63+
* @return $this
64+
*/
65+
public function setInheritTags($boolean)
66+
{
67+
$this->inheritTags = (bool) $boolean;
68+
69+
return $this;
70+
}
71+
72+
/**
73+
* Returns whether tags should be inherited from the parent or not.
74+
*
75+
* @return bool
76+
*/
77+
public function getInheritTags()
78+
{
79+
return $this->inheritTags;
80+
}
81+
5782
/**
5883
* {@inheritdoc}
5984
*/

Compiler/ResolveDefinitionTemplatesPass.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ private function doResolveDefinition(ContainerBuilder $container, ChildDefinitio
216216
$def->setShared($definition->isShared());
217217
$def->setTags($definition->getTags());
218218

219+
// append parent tags when inheriting is enabled
220+
if ($definition->getInheritTags()) {
221+
foreach ($parentDef->getTags() as $k => $v) {
222+
foreach ($v as $v) {
223+
$def->addTag($k, $v);
224+
}
225+
}
226+
}
227+
219228
return $def;
220229
}
221230
}

Loader/XmlFileLoader.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ private function getServiceDefaults(\DOMDocument $xml, $file)
150150
if ($defaultsNode->hasAttribute('public')) {
151151
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
152152
}
153+
if ($defaultsNode->hasAttribute('inherit-tags')) {
154+
$defaults['inherit-tags'] = XmlUtils::phpize($defaultsNode->getAttribute('inherit-tags'));
155+
}
153156
if (!$defaultsNode->hasAttribute('autowire')) {
154157
foreach ($defaults['autowire'] as $k => $v) {
155158
$defaults['autowire'][$k] = $v->textContent;
@@ -194,6 +197,12 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
194197

195198
if ($parent = $service->getAttribute('parent')) {
196199
$definition = new ChildDefinition($parent);
200+
201+
if ($value = $service->getAttribute('inherit-tags')) {
202+
$definition->setInheritTags(XmlUtils::phpize($value));
203+
} elseif (isset($defaults['inherit-tags'])) {
204+
$definition->setInheritTags($defaults['inherit-tags']);
205+
}
197206
$defaults = array();
198207
} else {
199208
$definition = new Definition();
@@ -270,8 +279,15 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
270279
}
271280

272281
$tags = $this->getChildren($service, 'tag');
273-
if (!$tags && !empty($defaults['tags'])) {
274-
$tags = $defaults['tags'];
282+
283+
if (empty($defaults['tags'])) {
284+
// no-op
285+
} elseif (!$value = $service->getAttribute('inherit-tags')) {
286+
if (!$tags) {
287+
$tags = $defaults['tags'];
288+
}
289+
} elseif (XmlUtils::phpize($value)) {
290+
$tags = array_merge($tags, $defaults['tags']);
275291
}
276292

277293
foreach ($tags as $tag) {

Loader/YamlFileLoader.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class YamlFileLoader extends FileLoader
5252
'configurator' => 'configurator',
5353
'calls' => 'calls',
5454
'tags' => 'tags',
55+
'inherit_tags' => 'inherit_tags',
5556
'decorates' => 'decorates',
5657
'decoration_inner_name' => 'decoration_inner_name',
5758
'decoration_priority' => 'decoration_priority',
@@ -156,7 +157,7 @@ private function parseDefinitions($content, $file)
156157
@trigger_error('Giving a service the "_defaults" name is deprecated since Symfony 3.3 and will be forbidden in 4.0. Rename your service.', E_USER_DEPRECATED);
157158
$defaults = array();
158159
} else {
159-
$defaultKeys = array('public', 'tags', 'autowire');
160+
$defaultKeys = array('public', 'tags', 'inherit_tags', 'autowire');
160161
unset($content['services']['_defaults']);
161162

162163
foreach ($defaults as $key => $default) {
@@ -240,6 +241,11 @@ private function parseDefinition($id, $service, $file, array $defaults)
240241

241242
if (isset($service['parent'])) {
242243
$definition = new ChildDefinition($service['parent']);
244+
245+
$inheritTag = isset($service['inherit_tags']) ? $service['inherit_tags'] : (isset($defaults['inherit_tags']) ? $defaults['inherit_tags'] : null);
246+
if (null !== $inheritTag) {
247+
$definition->setInheritTags($inheritTag);
248+
}
243249
$defaults = array();
244250
} else {
245251
$definition = new Definition();
@@ -312,7 +318,18 @@ private function parseDefinition($id, $service, $file, array $defaults)
312318
}
313319
}
314320

315-
$tags = isset($service['tags']) ? $service['tags'] : (isset($defaults['tags']) ? $defaults['tags'] : null);
321+
$tags = isset($service['tags']) ? $service['tags'] : array();
322+
323+
if (!isset($defaults['tags'])) {
324+
// no-op
325+
} elseif (!isset($service['inherit_tags'])) {
326+
if (!isset($service['tags'])) {
327+
$tags = $defaults['tags'];
328+
}
329+
} elseif ($service['inherit_tags']) {
330+
$tags = array_merge($tags, $defaults['tags']);
331+
}
332+
316333
if (null !== $tags) {
317334
if (!is_array($tags)) {
318335
throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
</xsd:choice>
103103
<xsd:attribute name="public" type="boolean" />
104104
<xsd:attribute name="autowire" type="boolean" />
105+
<xsd:attribute name="inherit-tags" type="boolean" />
105106
</xsd:complexType>
106107

107108
<xsd:complexType name="service">
@@ -130,6 +131,7 @@
130131
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
131132
<xsd:attribute name="decoration-priority" type="xsd:integer" />
132133
<xsd:attribute name="autowire" type="boolean" />
134+
<xsd:attribute name="inherit-tags" type="boolean" />
133135
</xsd:complexType>
134136

135137
<xsd:complexType name="tag">

Tests/Fixtures/xml/services29.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
</defaults>
77

88
<service id="with_defaults" class="Foo" />
9-
<service id="no_defaults" class="Foo" public="true" autowire="false">
10-
<tag name="bar" />
9+
<service id="no_defaults" class="Foo" public="true" autowire="false" inherit-tags="false">
1110
</service>
1211
<service id="no_defaults_child" class="Foo" parent="no_defaults">
1312
<tag name="bar" />
1413
</service>
15-
<service id="with_defaults_child" class="Foo" parent="with_defaults" />
14+
<service id="with_defaults_child" class="Foo" parent="with_defaults" public="true" inherit-tags="true">
15+
<tag name="baz" />
16+
</service>
1617
</services>
1718
</container>

Tests/Fixtures/yaml/services28.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ services:
1010

1111
with_null:
1212
class: Foo
13-
public: ~
13+
public: true
1414
autowire: ~
15-
tags: ~
15+
inherit_tags: false
1616

1717
no_defaults:
1818
class: Foo
@@ -28,3 +28,7 @@ services:
2828

2929
with_defaults_child:
3030
parent: with_defaults
31+
public: true
32+
inherit_tags: true
33+
tags:
34+
- name: baz

Tests/Loader/XmlFileLoaderTest.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -625,19 +625,23 @@ public function testDefaults()
625625
$loader->load('services29.xml');
626626

627627
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
628+
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
629+
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
630+
631+
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
632+
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
633+
634+
$container->compile();
635+
628636
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
629637
$this->assertTrue($container->getDefinition('no_defaults_child')->isPublic());
630-
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
631638

632-
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
633-
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults')->getTags());
639+
$this->assertSame(array(), $container->getDefinition('no_defaults')->getTags());
634640
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags());
635-
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getTags());
641+
$this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags());
636642

637-
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
638643
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
639644
$this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired());
640-
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
641645
}
642646

643647
public function testDefaultsWithAutowiredMethods()

Tests/Loader/YamlFileLoaderTest.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,22 +359,26 @@ public function testDefaults()
359359
$loader->load('services28.yml');
360360

361361
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
362-
$this->assertFalse($container->getDefinition('with_null')->isPublic());
362+
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
363+
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
364+
365+
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
366+
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
367+
368+
$container->compile();
369+
370+
$this->assertTrue($container->getDefinition('with_null')->isPublic());
363371
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
364372
$this->assertTrue($container->getDefinition('no_defaults_child')->isPublic());
365-
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
366373

367-
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
368-
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_null')->getTags());
374+
$this->assertSame(array(), $container->getDefinition('with_null')->getTags());
369375
$this->assertSame(array(), $container->getDefinition('no_defaults')->getTags());
370376
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags());
371-
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getTags());
377+
$this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags());
372378

373-
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
374379
$this->assertTrue($container->getDefinition('with_null')->isAutowired());
375380
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
376381
$this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired());
377-
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
378382
}
379383

380384
/**

0 commit comments

Comments
 (0)