Skip to content

Commit e5763ce

Browse files
[DependencyInjection] Allow anonymous DefinitionDecorator resolving
1 parent bd66434 commit e5763ce

File tree

3 files changed

+102
-42
lines changed

3 files changed

+102
-42
lines changed

src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,40 +48,24 @@ public function process(ContainerBuilder $container)
4848
$this->formatter = $this->compiler->getLoggingFormatter();
4949
$this->graph = $this->compiler->getServiceReferenceGraph();
5050

51-
foreach ($container->getDefinitions() as $id => $definition) {
52-
$this->currentId = $id;
53-
54-
$definition->setArguments(
55-
$this->inlineArguments($container, $definition->getArguments())
56-
);
57-
58-
$definition->setMethodCalls(
59-
$this->inlineArguments($container, $definition->getMethodCalls())
60-
);
61-
62-
$definition->setProperties(
63-
$this->inlineArguments($container, $definition->getProperties())
64-
);
65-
66-
$configurator = $this->inlineArguments($container, array($definition->getConfigurator()));
67-
$definition->setConfigurator($configurator[0]);
68-
69-
$factory = $this->inlineArguments($container, array($definition->getFactory()));
70-
$definition->setFactory($factory[0]);
71-
}
51+
$container->setDefinitions($this->inlineArguments($container, $container->getDefinitions(), true));
7252
}
7353

7454
/**
7555
* Processes inline arguments.
7656
*
7757
* @param ContainerBuilder $container The ContainerBuilder
7858
* @param array $arguments An array of arguments
59+
* @param bool $isRoot If we are processing the root definitions or not
7960
*
8061
* @return array
8162
*/
82-
private function inlineArguments(ContainerBuilder $container, array $arguments)
63+
private function inlineArguments(ContainerBuilder $container, array $arguments, $isRoot = false)
8364
{
8465
foreach ($arguments as $k => $argument) {
66+
if ($isRoot) {
67+
$this->currentId = $k;
68+
}
8569
if (is_array($argument)) {
8670
$arguments[$k] = $this->inlineArguments($container, $argument);
8771
} elseif ($argument instanceof Reference) {
@@ -102,6 +86,12 @@ private function inlineArguments(ContainerBuilder $container, array $arguments)
10286
$argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
10387
$argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
10488
$argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
89+
90+
$configurator = $this->inlineArguments($container, array($argument->getConfigurator()));
91+
$argument->setConfigurator($configurator[0]);
92+
93+
$factory = $this->inlineArguments($container, array($argument->getFactory()));
94+
$argument->setFactory($factory[0]);
10595
}
10696
}
10797

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

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
* merged Definition instance.
2222
*
2323
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
24+
* @author Nicolas Grekas <p@tchwork.com>
2425
*/
2526
class ResolveDefinitionTemplatesPass implements CompilerPassInterface
2627
{
27-
private $container;
2828
private $compiler;
2929
private $formatter;
30+
private $currentId;
3031

3132
/**
3233
* Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
@@ -35,44 +36,80 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
3536
*/
3637
public function process(ContainerBuilder $container)
3738
{
38-
$this->container = $container;
3939
$this->compiler = $container->getCompiler();
4040
$this->formatter = $this->compiler->getLoggingFormatter();
4141

42-
foreach ($container->getDefinitions() as $id => $definition) {
43-
// yes, we are specifically fetching the definition from the
44-
// container to ensure we are not operating on stale data
45-
$definition = $container->getDefinition($id);
46-
if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) {
47-
continue;
48-
}
42+
$container->setDefinitions($this->resolveArguments($container, $container->getDefinitions(), true));
43+
}
4944

50-
$this->resolveDefinition($id, $definition);
45+
/**
46+
* Resolves definition decorator arguments.
47+
*
48+
* @param ContainerBuilder $container The ContainerBuilder
49+
* @param array $arguments An array of arguments
50+
* @param bool $isRoot If we are processing the root definitions or not
51+
*
52+
* @return array
53+
*/
54+
private function resolveArguments(ContainerBuilder $container, array $arguments, $isRoot = false)
55+
{
56+
foreach ($arguments as $k => $argument) {
57+
if ($isRoot) {
58+
// yes, we are specifically fetching the definition from the
59+
// container to ensure we are not operating on stale data
60+
$arguments[$k] = $argument = $container->getDefinition($k);
61+
$this->currentId = $k;
62+
}
63+
if (is_array($argument)) {
64+
$arguments[$k] = $this->resolveArguments($container, $argument);
65+
} elseif ($argument instanceof Definition) {
66+
if ($argument instanceof DefinitionDecorator) {
67+
$arguments[$k] = $argument = $this->resolveDefinition($container, $argument);
68+
if ($isRoot) {
69+
$container->setDefinition($k, $argument);
70+
}
71+
}
72+
$argument->setArguments($this->resolveArguments($container, $argument->getArguments()));
73+
$argument->setMethodCalls($this->resolveArguments($container, $argument->getMethodCalls()));
74+
$argument->setProperties($this->resolveArguments($container, $argument->getProperties()));
75+
76+
$configurator = $this->resolveArguments($container, array($argument->getConfigurator()));
77+
$argument->setConfigurator($configurator[0]);
78+
79+
$factory = $this->resolveArguments($container, array($argument->getFactory()));
80+
$argument->setFactory($factory[0]);
81+
}
5182
}
83+
84+
return $arguments;
5285
}
5386

5487
/**
5588
* Resolves the definition.
5689
*
57-
* @param string $id The definition identifier
90+
* @param ContainerBuilder $container The ContainerBuilder
5891
* @param DefinitionDecorator $definition
5992
*
6093
* @return Definition
6194
*
6295
* @throws \RuntimeException When the definition is invalid
6396
*/
64-
private function resolveDefinition($id, DefinitionDecorator $definition)
97+
private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition)
6598
{
66-
if (!$this->container->hasDefinition($parent = $definition->getParent())) {
67-
throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id));
99+
if (!$container->hasDefinition($parent = $definition->getParent())) {
100+
throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $this->currentId));
68101
}
69102

70-
$parentDef = $this->container->getDefinition($parent);
103+
$parentDef = $container->getDefinition($parent);
71104
if ($parentDef instanceof DefinitionDecorator) {
72-
$parentDef = $this->resolveDefinition($parent, $parentDef);
105+
$id = $this->currentId;
106+
$this->currentId = $parent;
107+
$parentDef = $this->resolveDefinition($container, $parentDef);
108+
$container->setDefinition($parent, $parentDef);
109+
$this->currentId = $id;
73110
}
74111

75-
$this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent));
112+
$this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $this->currentId, $parent));
76113
$def = new Definition();
77114

78115
// merge in parent definition
@@ -156,9 +193,6 @@ private function resolveDefinition($id, DefinitionDecorator $definition)
156193
$def->setScope($definition->getScope(false), false);
157194
$def->setTags($definition->getTags());
158195

159-
// set new definition on container
160-
$this->container->setDefinition($id, $def);
161-
162196
return $def;
163197
}
164198
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,42 @@ public function testSetLazyOnServiceIsParent()
176176
$this->assertTrue($container->getDefinition('child1')->isLazy());
177177
}
178178

179+
public function testDeepDefinitionsResolving()
180+
{
181+
$container = new ContainerBuilder();
182+
183+
$container->register('parent', 'parentClass');
184+
$container->register('sibling', 'siblingClass')
185+
->setConfigurator(new DefinitionDecorator('parent'), 'foo')
186+
->setFactory(array(new DefinitionDecorator('parent'), 'foo'))
187+
->addArgument(new DefinitionDecorator('parent'))
188+
->setProperty('prop', new DefinitionDecorator('parent'))
189+
->addMethodCall('meth', array(new DefinitionDecorator('parent')))
190+
;
191+
192+
$this->process($container);
193+
194+
$configurator = $container->getDefinition('sibling')->getConfigurator();
195+
$this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($configurator));
196+
$this->assertSame('parentClass', $configurator->getClass());
197+
198+
$factory = $container->getDefinition('sibling')->getFactory();
199+
$this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($factory[0]));
200+
$this->assertSame('parentClass', $factory[0]->getClass());
201+
202+
$argument = $container->getDefinition('sibling')->getArgument(0);
203+
$this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($argument));
204+
$this->assertSame('parentClass', $argument->getClass());
205+
206+
$properties = $container->getDefinition('sibling')->getProperties();
207+
$this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($properties['prop']));
208+
$this->assertSame('parentClass', $properties['prop']->getClass());
209+
210+
$methodCalls = $container->getDefinition('sibling')->getMethodCalls();
211+
$this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($methodCalls[0][1][0]));
212+
$this->assertSame('parentClass', $methodCalls[0][1][0]->getClass());
213+
}
214+
179215
protected function process(ContainerBuilder $container)
180216
{
181217
$pass = new ResolveDefinitionTemplatesPass();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy