[DI] Allow definitions to inherit tags from parent context
This commit is contained in:
parent
05f24d5a6d
commit
beec1cff8f
@ -4,11 +4,13 @@ CHANGELOG
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* Add "iterator" argument type for lazy iteration over a set of values and services
|
||||
|
||||
* Using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
|
||||
will not be supported anymore in 4.0.
|
||||
|
||||
* added "iterator" argument type for lazy iteration over a set of values and services
|
||||
* added "closure-proxy" argument type for turning services' methods into lazy callables
|
||||
* added file-wide configurable defaults for service attributes "public", "tags",
|
||||
"autowire" and a new "inherit-tags"
|
||||
* made the "class" attribute optional, using the "id" as fallback
|
||||
* using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
|
||||
will not be supported anymore in 4.0
|
||||
* deprecated the `DefinitionDecorator` class in favor of `ChildDefinition`
|
||||
|
||||
3.2.0
|
||||
|
@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
|
||||
class ChildDefinition extends Definition
|
||||
{
|
||||
private $parent;
|
||||
private $inheritTags = false;
|
||||
private $changes = array();
|
||||
|
||||
/**
|
||||
@ -54,6 +55,30 @@ class ChildDefinition extends Definition
|
||||
return $this->changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether tags should be inherited from the parent or not.
|
||||
*
|
||||
* @param bool $boolean
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInheritTags($boolean)
|
||||
{
|
||||
$this->inheritTags = (bool) $boolean;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether tags should be inherited from the parent or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getInheritTags()
|
||||
{
|
||||
return $this->inheritTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -216,6 +216,15 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
|
||||
$def->setShared($definition->isShared());
|
||||
$def->setTags($definition->getTags());
|
||||
|
||||
// append parent tags when inheriting is enabled
|
||||
if ($definition->getInheritTags()) {
|
||||
foreach ($parentDef->getTags() as $k => $v) {
|
||||
foreach ($v as $v) {
|
||||
$def->addTag($k, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $def;
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,9 @@ class XmlFileLoader extends FileLoader
|
||||
if ($defaultsNode->hasAttribute('public')) {
|
||||
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
|
||||
}
|
||||
if ($defaultsNode->hasAttribute('inherit-tags')) {
|
||||
$defaults['inherit-tags'] = XmlUtils::phpize($defaultsNode->getAttribute('inherit-tags'));
|
||||
}
|
||||
if (!$defaultsNode->hasAttribute('autowire')) {
|
||||
foreach ($defaults['autowire'] as $k => $v) {
|
||||
$defaults['autowire'][$k] = $v->textContent;
|
||||
@ -194,6 +197,12 @@ class XmlFileLoader extends FileLoader
|
||||
|
||||
if ($parent = $service->getAttribute('parent')) {
|
||||
$definition = new ChildDefinition($parent);
|
||||
|
||||
if ($value = $service->getAttribute('inherit-tags')) {
|
||||
$definition->setInheritTags(XmlUtils::phpize($value));
|
||||
} elseif (isset($defaults['inherit-tags'])) {
|
||||
$definition->setInheritTags($defaults['inherit-tags']);
|
||||
}
|
||||
$defaults = array();
|
||||
} else {
|
||||
$definition = new Definition();
|
||||
@ -270,8 +279,15 @@ class XmlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
$tags = $this->getChildren($service, 'tag');
|
||||
if (!$tags && !empty($defaults['tags'])) {
|
||||
$tags = $defaults['tags'];
|
||||
|
||||
if (empty($defaults['tags'])) {
|
||||
// no-op
|
||||
} elseif (!$value = $service->getAttribute('inherit-tags')) {
|
||||
if (!$tags) {
|
||||
$tags = $defaults['tags'];
|
||||
}
|
||||
} elseif (XmlUtils::phpize($value)) {
|
||||
$tags = array_merge($tags, $defaults['tags']);
|
||||
}
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
|
@ -52,6 +52,7 @@ class YamlFileLoader extends FileLoader
|
||||
'configurator' => 'configurator',
|
||||
'calls' => 'calls',
|
||||
'tags' => 'tags',
|
||||
'inherit_tags' => 'inherit_tags',
|
||||
'decorates' => 'decorates',
|
||||
'decoration_inner_name' => 'decoration_inner_name',
|
||||
'decoration_priority' => 'decoration_priority',
|
||||
@ -156,7 +157,7 @@ class YamlFileLoader extends FileLoader
|
||||
@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);
|
||||
$defaults = array();
|
||||
} else {
|
||||
$defaultKeys = array('public', 'tags', 'autowire');
|
||||
$defaultKeys = array('public', 'tags', 'inherit_tags', 'autowire');
|
||||
unset($content['services']['_defaults']);
|
||||
|
||||
foreach ($defaults as $key => $default) {
|
||||
@ -240,6 +241,11 @@ class YamlFileLoader extends FileLoader
|
||||
|
||||
if (isset($service['parent'])) {
|
||||
$definition = new ChildDefinition($service['parent']);
|
||||
|
||||
$inheritTag = isset($service['inherit_tags']) ? $service['inherit_tags'] : (isset($defaults['inherit_tags']) ? $defaults['inherit_tags'] : null);
|
||||
if (null !== $inheritTag) {
|
||||
$definition->setInheritTags($inheritTag);
|
||||
}
|
||||
$defaults = array();
|
||||
} else {
|
||||
$definition = new Definition();
|
||||
@ -312,7 +318,18 @@ class YamlFileLoader extends FileLoader
|
||||
}
|
||||
}
|
||||
|
||||
$tags = isset($service['tags']) ? $service['tags'] : (isset($defaults['tags']) ? $defaults['tags'] : null);
|
||||
$tags = isset($service['tags']) ? $service['tags'] : array();
|
||||
|
||||
if (!isset($defaults['tags'])) {
|
||||
// no-op
|
||||
} elseif (!isset($service['inherit_tags'])) {
|
||||
if (!isset($service['tags'])) {
|
||||
$tags = $defaults['tags'];
|
||||
}
|
||||
} elseif ($service['inherit_tags']) {
|
||||
$tags = array_merge($tags, $defaults['tags']);
|
||||
}
|
||||
|
||||
if (null !== $tags) {
|
||||
if (!is_array($tags)) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
|
||||
|
@ -102,6 +102,7 @@
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="public" type="boolean" />
|
||||
<xsd:attribute name="autowire" type="boolean" />
|
||||
<xsd:attribute name="inherit-tags" type="boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="service">
|
||||
@ -130,6 +131,7 @@
|
||||
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
|
||||
<xsd:attribute name="decoration-priority" type="xsd:integer" />
|
||||
<xsd:attribute name="autowire" type="boolean" />
|
||||
<xsd:attribute name="inherit-tags" type="boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="tag">
|
||||
|
@ -6,12 +6,13 @@
|
||||
</defaults>
|
||||
|
||||
<service id="with_defaults" class="Foo" />
|
||||
<service id="no_defaults" class="Foo" public="true" autowire="false">
|
||||
<tag name="bar" />
|
||||
<service id="no_defaults" class="Foo" public="true" autowire="false" inherit-tags="false">
|
||||
</service>
|
||||
<service id="no_defaults_child" class="Foo" parent="no_defaults">
|
||||
<tag name="bar" />
|
||||
</service>
|
||||
<service id="with_defaults_child" class="Foo" parent="with_defaults" />
|
||||
<service id="with_defaults_child" class="Foo" parent="with_defaults" public="true" inherit-tags="true">
|
||||
<tag name="baz" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -10,9 +10,9 @@ services:
|
||||
|
||||
with_null:
|
||||
class: Foo
|
||||
public: ~
|
||||
public: true
|
||||
autowire: ~
|
||||
tags: ~
|
||||
inherit_tags: false
|
||||
|
||||
no_defaults:
|
||||
class: Foo
|
||||
@ -28,3 +28,7 @@ services:
|
||||
|
||||
with_defaults_child:
|
||||
parent: with_defaults
|
||||
public: true
|
||||
inherit_tags: true
|
||||
tags:
|
||||
- name: baz
|
||||
|
@ -625,19 +625,23 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->load('services29.xml');
|
||||
|
||||
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
|
||||
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
|
||||
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
|
||||
|
||||
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
|
||||
$container->compile();
|
||||
|
||||
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
|
||||
$this->assertTrue($container->getDefinition('no_defaults_child')->isPublic());
|
||||
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
|
||||
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
|
||||
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults')->getTags());
|
||||
$this->assertSame(array(), $container->getDefinition('no_defaults')->getTags());
|
||||
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags());
|
||||
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getTags());
|
||||
$this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags());
|
||||
|
||||
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
|
||||
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
|
||||
$this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired());
|
||||
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
}
|
||||
|
||||
public function testDefaultsWithAutowiredMethods()
|
||||
|
@ -359,22 +359,26 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->load('services28.yml');
|
||||
|
||||
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
|
||||
$this->assertFalse($container->getDefinition('with_null')->isPublic());
|
||||
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
|
||||
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
|
||||
|
||||
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
|
||||
$container->compile();
|
||||
|
||||
$this->assertTrue($container->getDefinition('with_null')->isPublic());
|
||||
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
|
||||
$this->assertTrue($container->getDefinition('no_defaults_child')->isPublic());
|
||||
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
|
||||
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
|
||||
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_null')->getTags());
|
||||
$this->assertSame(array(), $container->getDefinition('with_null')->getTags());
|
||||
$this->assertSame(array(), $container->getDefinition('no_defaults')->getTags());
|
||||
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags());
|
||||
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getTags());
|
||||
$this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags());
|
||||
|
||||
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
|
||||
$this->assertTrue($container->getDefinition('with_null')->isAutowired());
|
||||
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
|
||||
$this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired());
|
||||
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user