Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit df261c2

Browse filesBrowse files
[DI] Fix missing DefinitionDecorator resolution in ContainerBuilder::createService()
1 parent a1afa21 commit df261c2
Copy full SHA for df261c2

File tree

4 files changed

+134
-89
lines changed
Filter options

4 files changed

+134
-89
lines changed

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
+1-89Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -73,96 +73,8 @@ private function resolveDefinition($id, DefinitionDecorator $definition)
7373
}
7474

7575
$this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent));
76-
$def = new Definition();
7776

78-
// merge in parent definition
79-
// purposely ignored attributes: scope, abstract, tags
80-
$def->setClass($parentDef->getClass());
81-
$def->setArguments($parentDef->getArguments());
82-
$def->setMethodCalls($parentDef->getMethodCalls());
83-
$def->setProperties($parentDef->getProperties());
84-
if ($parentDef->getFactoryClass(false)) {
85-
$def->setFactoryClass($parentDef->getFactoryClass(false));
86-
}
87-
if ($parentDef->getFactoryMethod(false)) {
88-
$def->setFactoryMethod($parentDef->getFactoryMethod(false));
89-
}
90-
if ($parentDef->getFactoryService(false)) {
91-
$def->setFactoryService($parentDef->getFactoryService(false));
92-
}
93-
$def->setFactory($parentDef->getFactory());
94-
$def->setConfigurator($parentDef->getConfigurator());
95-
$def->setFile($parentDef->getFile());
96-
$def->setPublic($parentDef->isPublic());
97-
$def->setLazy($parentDef->isLazy());
98-
99-
// overwrite with values specified in the decorator
100-
$changes = $definition->getChanges();
101-
if (isset($changes['class'])) {
102-
$def->setClass($definition->getClass());
103-
}
104-
if (isset($changes['factory_class'])) {
105-
$def->setFactoryClass($definition->getFactoryClass(false));
106-
}
107-
if (isset($changes['factory_method'])) {
108-
$def->setFactoryMethod($definition->getFactoryMethod(false));
109-
}
110-
if (isset($changes['factory_service'])) {
111-
$def->setFactoryService($definition->getFactoryService(false));
112-
}
113-
if (isset($changes['factory'])) {
114-
$def->setFactory($definition->getFactory());
115-
}
116-
if (isset($changes['configurator'])) {
117-
$def->setConfigurator($definition->getConfigurator());
118-
}
119-
if (isset($changes['file'])) {
120-
$def->setFile($definition->getFile());
121-
}
122-
if (isset($changes['public'])) {
123-
$def->setPublic($definition->isPublic());
124-
}
125-
if (isset($changes['lazy'])) {
126-
$def->setLazy($definition->isLazy());
127-
}
128-
if (isset($changes['decorated_service'])) {
129-
$decoratedService = $definition->getDecoratedService();
130-
if (null === $decoratedService) {
131-
$def->setDecoratedService($decoratedService);
132-
} else {
133-
$def->setDecoratedService($decoratedService[0], $decoratedService[1]);
134-
}
135-
}
136-
137-
// merge arguments
138-
foreach ($definition->getArguments() as $k => $v) {
139-
if (is_numeric($k)) {
140-
$def->addArgument($v);
141-
continue;
142-
}
143-
144-
if (0 !== strpos($k, 'index_')) {
145-
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
146-
}
147-
148-
$index = (int) substr($k, strlen('index_'));
149-
$def->replaceArgument($index, $v);
150-
}
151-
152-
// merge properties
153-
foreach ($definition->getProperties() as $k => $v) {
154-
$def->setProperty($k, $v);
155-
}
156-
157-
// append method calls
158-
if (count($calls = $definition->getMethodCalls()) > 0) {
159-
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
160-
}
161-
162-
// these attributes are always taken from the child
163-
$def->setAbstract($definition->isAbstract());
164-
$def->setScope($definition->getScope());
165-
$def->setTags($definition->getTags());
77+
$def = $definition->resolveChanges($parentDef);
16678

16779
// set new definition on container
16880
$this->container->setDefinition($id, $def);

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,24 @@ public function findDefinition($id)
840840
*/
841841
public function createService(Definition $definition, $id, $tryProxy = true)
842842
{
843+
if ($definition instanceof DefinitionDecorator) {
844+
$parents = array();
845+
$currentId = $id;
846+
$currentDef = $definition;
847+
do {
848+
if (!$this->has($parent = $currentDef->getParent())) {
849+
throw new RuntimeException(sprintf('Service "%s": Parent definition "%s" does not exist.', $currentId, $parent));
850+
}
851+
$parents[] = $currentDef = $this->findDefinition($parent);
852+
$currentId = $parent;
853+
} while ($currentDef instanceof DefinitionDecorator);
854+
855+
for ($i = count($parents) - 1; 0 < $i; --$i) {
856+
$parents[$i - 1] = $parents[$i - 1]->resolveChanges($parents[$i]);
857+
}
858+
$definition = $definition->resolveChanges($parents[0]);
859+
}
860+
843861
if ($definition->isSynthetic()) {
844862
throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
845863
}

‎src/Symfony/Component/DependencyInjection/DefinitionDecorator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/DefinitionDecorator.php
+105Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1515
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
16+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1617

1718
/**
1819
* This definition decorates another definition.
@@ -206,4 +207,108 @@ public function replaceArgument($index, $value)
206207

207208
return $this;
208209
}
210+
211+
/**
212+
* Creates a new Definition by merging the current decorator with the given parent definition.
213+
*
214+
* @return Definition
215+
*/
216+
public function resolveChanges(Definition $parentDef)
217+
{
218+
if ($parentDef instanceof self) {
219+
throw new InvalidArgumentException('$parenfDef must be a resolved Definition.');
220+
}
221+
$def = new Definition();
222+
223+
// merge in parent definition
224+
// purposely ignored attributes: scope, abstract, tags
225+
$def->setClass($parentDef->getClass());
226+
$def->setArguments($parentDef->getArguments());
227+
$def->setMethodCalls($parentDef->getMethodCalls());
228+
$def->setProperties($parentDef->getProperties());
229+
if ($parentDef->getFactoryClass(false)) {
230+
$def->setFactoryClass($parentDef->getFactoryClass(false));
231+
}
232+
if ($parentDef->getFactoryMethod(false)) {
233+
$def->setFactoryMethod($parentDef->getFactoryMethod(false));
234+
}
235+
if ($parentDef->getFactoryService(false)) {
236+
$def->setFactoryService($parentDef->getFactoryService(false));
237+
}
238+
$def->setFactory($parentDef->getFactory());
239+
$def->setConfigurator($parentDef->getConfigurator());
240+
$def->setFile($parentDef->getFile());
241+
$def->setPublic($parentDef->isPublic());
242+
$def->setLazy($parentDef->isLazy());
243+
244+
// overwrite with values specified in the decorator
245+
$changes = $this->getChanges();
246+
if (isset($changes['class'])) {
247+
$def->setClass($this->getClass());
248+
}
249+
if (isset($changes['factory_class'])) {
250+
$def->setFactoryClass($this->getFactoryClass(false));
251+
}
252+
if (isset($changes['factory_method'])) {
253+
$def->setFactoryMethod($this->getFactoryMethod(false));
254+
}
255+
if (isset($changes['factory_service'])) {
256+
$def->setFactoryService($this->getFactoryService(false));
257+
}
258+
if (isset($changes['factory'])) {
259+
$def->setFactory($this->getFactory());
260+
}
261+
if (isset($changes['configurator'])) {
262+
$def->setConfigurator($this->getConfigurator());
263+
}
264+
if (isset($changes['file'])) {
265+
$def->setFile($this->getFile());
266+
}
267+
if (isset($changes['public'])) {
268+
$def->setPublic($this->isPublic());
269+
}
270+
if (isset($changes['lazy'])) {
271+
$def->setLazy($this->isLazy());
272+
}
273+
if (isset($changes['decorated_service'])) {
274+
$decoratedService = $this->getDecoratedService();
275+
if (null === $decoratedService) {
276+
$def->setDecoratedService($decoratedService);
277+
} else {
278+
$def->setDecoratedService($decoratedService[0], $decoratedService[1]);
279+
}
280+
}
281+
282+
// merge arguments
283+
foreach ($this->getArguments() as $k => $v) {
284+
if (is_numeric($k)) {
285+
$def->addArgument($v);
286+
continue;
287+
}
288+
289+
if (0 !== strpos($k, 'index_')) {
290+
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
291+
}
292+
293+
$index = (int) substr($k, strlen('index_'));
294+
$def->replaceArgument($index, $v);
295+
}
296+
297+
// merge properties
298+
foreach ($this->getProperties() as $k => $v) {
299+
$def->setProperty($k, $v);
300+
}
301+
302+
// append method calls
303+
if (count($calls = $this->getMethodCalls()) > 0) {
304+
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
305+
}
306+
307+
// these attributes are always taken from the child
308+
$def->setAbstract($this->isAbstract());
309+
$def->setScope($this->getScope());
310+
$def->setTags($this->getTags());
311+
312+
return $def;
313+
}
209314
}

‎src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\DependencyInjection\ContainerBuilder;
2020
use Symfony\Component\DependencyInjection\ContainerInterface;
2121
use Symfony\Component\DependencyInjection\Definition;
22+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
2223
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
2324
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
2425
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
@@ -404,6 +405,15 @@ public function testResolveServices()
404405
$this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
405406
}
406407

408+
public function testResolveServicesWithDecoratedDefinition()
409+
{
410+
$builder = new ContainerBuilder();
411+
$builder->setDefinition('grandpa', new Definition('stdClass'));
412+
$builder->setDefinition('parent', new DefinitionDecorator('grandpa'));
413+
414+
$this->assertInstanceOf('stdClass', $builder->resolveServices(new DefinitionDecorator('parent')));
415+
}
416+
407417
public function testMerge()
408418
{
409419
$container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.