1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Symfony package. |
5
|
|
|
* |
6
|
|
|
* (c) Fabien Potencier <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Symfony\Component\DependencyInjection\Compiler; |
13
|
|
|
|
14
|
|
|
use Symfony\Component\DependencyInjection\Definition; |
15
|
|
|
use Symfony\Component\DependencyInjection\DefinitionDecorator; |
16
|
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder; |
17
|
|
|
use Symfony\Component\DependencyInjection\Exception\RuntimeException; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* This replaces all DefinitionDecorator instances with their equivalent fully |
21
|
|
|
* merged Definition instance. |
22
|
|
|
* |
23
|
|
|
* @author Johannes M. Schmitt <[email protected]> |
24
|
|
|
*/ |
25
|
|
|
class ResolveDefinitionTemplatesPass implements CompilerPassInterface |
26
|
|
|
{ |
27
|
|
|
private $container; |
28
|
|
|
private $compiler; |
29
|
|
|
private $formatter; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances. |
33
|
|
|
* |
34
|
|
|
* @param ContainerBuilder $container |
35
|
|
|
*/ |
36
|
|
|
public function process(ContainerBuilder $container) |
37
|
|
|
{ |
38
|
|
|
$this->container = $container; |
39
|
|
|
$this->compiler = $container->getCompiler(); |
40
|
|
|
$this->formatter = $this->compiler->getLoggingFormatter(); |
41
|
|
|
|
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
|
|
|
} |
49
|
|
|
|
50
|
|
|
$this->resolveDefinition($id, $definition); |
51
|
|
|
} |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Resolves the definition. |
56
|
|
|
* |
57
|
|
|
* @param string $id The definition identifier |
58
|
|
|
* @param DefinitionDecorator $definition |
59
|
|
|
* |
60
|
|
|
* @return Definition |
61
|
|
|
* |
62
|
|
|
* @throws \RuntimeException When the definition is invalid |
63
|
|
|
*/ |
64
|
|
|
private function resolveDefinition($id, DefinitionDecorator $definition) |
65
|
|
|
{ |
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)); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
$parentDef = $this->container->getDefinition($parent); |
71
|
|
|
if ($parentDef instanceof DefinitionDecorator) { |
72
|
|
|
$parentDef = $this->resolveDefinition($parent, $parentDef); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
$this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent)); |
76
|
|
|
$def = new Definition(); |
77
|
|
|
|
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
|
|
|
|
129
|
|
|
// merge arguments |
130
|
|
|
foreach ($definition->getArguments() as $k => $v) { |
131
|
|
|
if (is_numeric($k)) { |
132
|
|
|
$def->addArgument($v); |
133
|
|
|
continue; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
if (0 !== strpos($k, 'index_')) { |
137
|
|
|
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k)); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
$index = (int) substr($k, strlen('index_')); |
141
|
|
|
$def->replaceArgument($index, $v); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
// merge properties |
145
|
|
|
foreach ($definition->getProperties() as $k => $v) { |
146
|
|
|
$def->setProperty($k, $v); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
// append method calls |
150
|
|
|
if (count($calls = $definition->getMethodCalls()) > 0) { |
151
|
|
|
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// these attributes are always taken from the child |
155
|
|
|
$def->setAbstract($definition->isAbstract()); |
156
|
|
|
$def->setScope($definition->getScope()); |
157
|
|
|
$def->setTags($definition->getTags()); |
158
|
|
|
|
159
|
|
|
// set new definition on container |
160
|
|
|
$this->container->setDefinition($id, $def); |
161
|
|
|
|
162
|
|
|
return $def; |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.