Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / vendor / symfony / dependency-injection / Compiler / ResolveChildDefinitionsPass.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
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\ChildDefinition;
15 use Symfony\Component\DependencyInjection\Definition;
16 use Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
17 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
18 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
19
20 /**
21  * This replaces all ChildDefinition instances with their equivalent fully
22  * merged Definition instance.
23  *
24  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
25  * @author Nicolas Grekas <p@tchwork.com>
26  */
27 class ResolveChildDefinitionsPass extends AbstractRecursivePass
28 {
29     private $currentPath;
30
31     protected function processValue($value, $isRoot = false)
32     {
33         if (!$value instanceof Definition) {
34             return parent::processValue($value, $isRoot);
35         }
36         if ($isRoot) {
37             // yes, we are specifically fetching the definition from the
38             // container to ensure we are not operating on stale data
39             $value = $this->container->getDefinition($this->currentId);
40         }
41         if ($value instanceof ChildDefinition) {
42             $this->currentPath = array();
43             $value = $this->resolveDefinition($value);
44             if ($isRoot) {
45                 $this->container->setDefinition($this->currentId, $value);
46             }
47         }
48
49         return parent::processValue($value, $isRoot);
50     }
51
52     /**
53      * Resolves the definition.
54      *
55      * @return Definition
56      *
57      * @throws RuntimeException When the definition is invalid
58      */
59     private function resolveDefinition(ChildDefinition $definition)
60     {
61         try {
62             return $this->doResolveDefinition($definition);
63         } catch (ServiceCircularReferenceException $e) {
64             throw $e;
65         } catch (ExceptionInterface $e) {
66             $r = new \ReflectionProperty($e, 'message');
67             $r->setAccessible(true);
68             $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage()));
69
70             throw $e;
71         }
72     }
73
74     private function doResolveDefinition(ChildDefinition $definition)
75     {
76         if (!$this->container->has($parent = $definition->getParent())) {
77             throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
78         }
79
80         $searchKey = array_search($parent, $this->currentPath);
81         $this->currentPath[] = $parent;
82
83         if (false !== $searchKey) {
84             throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey));
85         }
86
87         $parentDef = $this->container->findDefinition($parent);
88         if ($parentDef instanceof ChildDefinition) {
89             $id = $this->currentId;
90             $this->currentId = $parent;
91             $parentDef = $this->resolveDefinition($parentDef);
92             $this->container->setDefinition($parent, $parentDef);
93             $this->currentId = $id;
94         }
95
96         $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent));
97         $def = new Definition();
98
99         // merge in parent definition
100         // purposely ignored attributes: abstract, shared, tags, autoconfigured
101         $def->setClass($parentDef->getClass());
102         $def->setArguments($parentDef->getArguments());
103         $def->setMethodCalls($parentDef->getMethodCalls());
104         $def->setProperties($parentDef->getProperties());
105         if ($parentDef->getAutowiringTypes(false)) {
106             $def->setAutowiringTypes($parentDef->getAutowiringTypes(false));
107         }
108         if ($parentDef->isDeprecated()) {
109             $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
110         }
111         $def->setFactory($parentDef->getFactory());
112         $def->setConfigurator($parentDef->getConfigurator());
113         $def->setFile($parentDef->getFile());
114         $def->setPublic($parentDef->isPublic());
115         $def->setLazy($parentDef->isLazy());
116         $def->setAutowired($parentDef->isAutowired());
117         $def->setChanges($parentDef->getChanges());
118
119         $def->setBindings($definition->getBindings() + $parentDef->getBindings());
120
121         // overwrite with values specified in the decorator
122         $changes = $definition->getChanges();
123         if (isset($changes['class'])) {
124             $def->setClass($definition->getClass());
125         }
126         if (isset($changes['factory'])) {
127             $def->setFactory($definition->getFactory());
128         }
129         if (isset($changes['configurator'])) {
130             $def->setConfigurator($definition->getConfigurator());
131         }
132         if (isset($changes['file'])) {
133             $def->setFile($definition->getFile());
134         }
135         if (isset($changes['public'])) {
136             $def->setPublic($definition->isPublic());
137         } else {
138             $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate());
139         }
140         if (isset($changes['lazy'])) {
141             $def->setLazy($definition->isLazy());
142         }
143         if (isset($changes['deprecated'])) {
144             $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
145         }
146         if (isset($changes['autowired'])) {
147             $def->setAutowired($definition->isAutowired());
148         }
149         if (isset($changes['shared'])) {
150             $def->setShared($definition->isShared());
151         }
152         if (isset($changes['decorated_service'])) {
153             $decoratedService = $definition->getDecoratedService();
154             if (null === $decoratedService) {
155                 $def->setDecoratedService($decoratedService);
156             } else {
157                 $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
158             }
159         }
160
161         // merge arguments
162         foreach ($definition->getArguments() as $k => $v) {
163             if (is_numeric($k)) {
164                 $def->addArgument($v);
165             } elseif (0 === strpos($k, 'index_')) {
166                 $def->replaceArgument((int) substr($k, \strlen('index_')), $v);
167             } else {
168                 $def->setArgument($k, $v);
169             }
170         }
171
172         // merge properties
173         foreach ($definition->getProperties() as $k => $v) {
174             $def->setProperty($k, $v);
175         }
176
177         // append method calls
178         if ($calls = $definition->getMethodCalls()) {
179             $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
180         }
181
182         // merge autowiring types
183         foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
184             $def->addAutowiringType($autowiringType);
185         }
186
187         // these attributes are always taken from the child
188         $def->setAbstract($definition->isAbstract());
189         $def->setTags($definition->getTags());
190         // autoconfigure is never taken from parent (on purpose)
191         // and it's not legal on an instanceof
192         $def->setAutoconfigured($definition->isAutoconfigured());
193
194         return $def;
195     }
196 }
197
198 class_alias(ResolveChildDefinitionsPass::class, ResolveDefinitionTemplatesPass::class);