Skip to content

Commit 888137a

Browse files
ogizanaginicolas-grekas
authored andcommitted
[DI] Add "defaults" tag to XML services configuration
1 parent 5eb6954 commit 888137a

File tree

5 files changed

+142
-6
lines changed

5 files changed

+142
-6
lines changed

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

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,28 +116,67 @@ private function parseDefinitions(\DOMDocument $xml, $file)
116116
}
117117

118118
foreach ($services as $service) {
119-
if (null !== $definition = $this->parseDefinition($service, $file)) {
119+
if (null !== $definition = $this->parseDefinition($service, $file, $this->getServiceDefaults($xml))) {
120120
$this->container->setDefinition((string) $service->getAttribute('id'), $definition);
121121
}
122122
}
123123
}
124124

125+
/**
126+
* Get service defaults
127+
*
128+
* @param \DOMDocument $xml
129+
*
130+
* @return array
131+
*/
132+
private function getServiceDefaults(\DOMDocument $xml)
133+
{
134+
$xpath = new \DOMXPath($xml);
135+
$xpath->registerNamespace('container', self::NS);
136+
137+
$defaults = array();
138+
139+
if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) {
140+
return $defaults;
141+
}
142+
143+
if ($defaultsNode->hasAttribute('public')) {
144+
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
145+
}
146+
147+
if ($defaultsNode->hasAttribute('autowire')) {
148+
$defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire'));
149+
}
150+
151+
$defaults['tags'] = $this->getChildren($defaultsNode, 'tag');
152+
153+
$defaults['autowire_methods'] = [];
154+
foreach ($this->getChildren($defaultsNode, 'autowire') as $type) {
155+
$defaults['autowire_methods'][] = $type->textContent;
156+
}
157+
158+
return $defaults;
159+
}
160+
125161
/**
126162
* Parses an individual Definition.
127163
*
128164
* @param \DOMElement $service
129165
* @param string $file
166+
* @param array $defaults
130167
*
131168
* @return Definition|null
132169
*/
133-
private function parseDefinition(\DOMElement $service, $file)
170+
private function parseDefinition(\DOMElement $service, $file, array $defaults = array())
134171
{
135172
if ($alias = $service->getAttribute('alias')) {
136173
$this->validateAlias($service, $file);
137174

138175
$public = true;
139176
if ($publicAttr = $service->getAttribute('public')) {
140177
$public = XmlUtils::phpize($publicAttr);
178+
} elseif (isset($defaults['public'])) {
179+
$public = $defaults['public'];
141180
}
142181
$this->container->setAlias((string) $service->getAttribute('id'), new Alias($alias, $public));
143182

@@ -146,11 +185,18 @@ private function parseDefinition(\DOMElement $service, $file)
146185

147186
if ($parent = $service->getAttribute('parent')) {
148187
$definition = new ChildDefinition($parent);
188+
$defaults = array();
149189
} else {
150190
$definition = new Definition();
151191
}
152192

153-
foreach (array('class', 'shared', 'public', 'synthetic', 'lazy', 'abstract') as $key) {
193+
if ($publicAttr = $service->getAttribute('public')) {
194+
$definition->setPublic(XmlUtils::phpize($publicAttr));
195+
} elseif (isset($defaults['public'])) {
196+
$definition->setPublic($defaults['public']);
197+
}
198+
199+
foreach (array('class', 'shared', 'synthetic', 'lazy', 'abstract') as $key) {
154200
if ($value = $service->getAttribute($key)) {
155201
$method = 'set'.$key;
156202
$definition->$method(XmlUtils::phpize($value));
@@ -159,6 +205,8 @@ private function parseDefinition(\DOMElement $service, $file)
159205

160206
if ($value = $service->getAttribute('autowire')) {
161207
$definition->setAutowired(XmlUtils::phpize($value));
208+
} elseif (isset($defaults['autowire'])) {
209+
$definition->setAutowired($defaults['autowire']);
162210
}
163211

164212
if ($files = $this->getChildren($service, 'file')) {
@@ -214,7 +262,12 @@ private function parseDefinition(\DOMElement $service, $file)
214262
$definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument'));
215263
}
216264

217-
foreach ($this->getChildren($service, 'tag') as $tag) {
265+
$tags = $this->getChildren($service, 'tag');
266+
if (0 === count($tags) && isset($defaults['tags'])) {
267+
$tags = $defaults['tags'];
268+
}
269+
270+
foreach ($tags as $tag) {
218271
$parameters = array();
219272
foreach ($tag->attributes as $name => $node) {
220273
if ('name' === $name) {
@@ -244,6 +297,10 @@ private function parseDefinition(\DOMElement $service, $file)
244297
$autowireTags[] = $type->textContent;
245298
}
246299

300+
if (0 === count($autowireTags) && isset($defaults['autowire_methods'])) {
301+
$autowireTags = $defaults['autowire_methods'];
302+
}
303+
247304
if ($autowireTags) {
248305
if ($service->hasAttribute('autowire')) {
249306
throw new InvalidArgumentException(sprintf('The "autowire" attribute cannot be used together with "<autowire>" tags for service "%s" in %s.', (string) $service->getAttribute('id'), $file));

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@
5252
Enclosing element for the definition of all services
5353
]]></xsd:documentation>
5454
</xsd:annotation>
55-
<xsd:choice minOccurs="1" maxOccurs="unbounded">
56-
<xsd:element name="service" type="service" />
55+
<xsd:choice maxOccurs="unbounded">
56+
<xsd:element name="service" type="service" minOccurs="1" />
57+
<xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" />
5758
</xsd:choice>
5859
</xsd:complexType>
5960

@@ -89,6 +90,20 @@
8990
<xsd:attribute name="function" type="xsd:string" />
9091
</xsd:complexType>
9192

93+
<xsd:complexType name="defaults">
94+
<xsd:annotation>
95+
<xsd:documentation><![CDATA[
96+
Enclosing element for the service definitions' defaults for the current file
97+
]]></xsd:documentation>
98+
</xsd:annotation>
99+
<xsd:choice maxOccurs="unbounded">
100+
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
101+
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
102+
</xsd:choice>
103+
<xsd:attribute name="public" type="boolean" />
104+
<xsd:attribute name="autowire" type="boolean" />
105+
</xsd:complexType>
106+
92107
<xsd:complexType name="service">
93108
<xsd:choice maxOccurs="unbounded">
94109
<xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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 http://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<services>
4+
<defaults public="false" autowire="true">
5+
<tag name="foo" />
6+
</defaults>
7+
8+
<service id="with_defaults" class="Foo" />
9+
<service id="no_defaults" class="Foo" public="true" autowire="false">
10+
<tag name="bar" />
11+
</service>
12+
<service id="no_defaults_child" class="Foo" parent="no_defaults">
13+
<tag name="bar" />
14+
</service>
15+
<service id="with_defaults_child" class="Foo" parent="with_defaults" />
16+
</services>
17+
</container>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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 http://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<services>
4+
<defaults public="false">
5+
<autowire>__construct</autowire>
6+
</defaults>
7+
8+
<service id="with_defaults" class="Foo" />
9+
<service id="no_defaults" class="Foo" public="true">
10+
<autowire>setFoo</autowire>
11+
</service>
12+
<service id="no_defaults_child" class="Foo" parent="no_defaults">
13+
<autowire>setFoo</autowire>
14+
</service>
15+
<service id="with_defaults_child" class="Foo" parent="with_defaults" />
16+
</services>
17+
</container>

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,4 +594,34 @@ public function testArgumentWithKeyOutsideCollection()
594594

595595
$this->assertSame(array('type' => 'foo', 'bar'), $container->getDefinition('foo')->getArguments());
596596
}
597+
598+
public function testDefaults()
599+
{
600+
$container = new ContainerBuilder();
601+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
602+
$loader->load('services29.xml');
603+
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
604+
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
605+
$this->assertTrue($container->getDefinition('no_defaults_child')->isPublic());
606+
$this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges());
607+
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
608+
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults')->getTags());
609+
$this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags());
610+
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getTags());
611+
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
612+
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
613+
$this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired());
614+
$this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges());
615+
}
616+
617+
public function testDefaultsWithAutowiredMethods()
618+
{
619+
$container = new ContainerBuilder();
620+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
621+
$loader->load('services30.xml');
622+
$this->assertSame(array('__construct'), $container->getDefinition('with_defaults')->getAutowiredMethods());
623+
$this->assertSame(array('setFoo'), $container->getDefinition('no_defaults')->getAutowiredMethods());
624+
$this->assertSame(array('setFoo'), $container->getDefinition('no_defaults_child')->getAutowiredMethods());
625+
$this->assertSame(array(), $container->getDefinition('with_defaults_child')->getAutowiredMethods());
626+
}
597627
}

0 commit comments

Comments
 (0)