Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / dependency-injection / Compiler / AbstractRecursivePass.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\Argument\ArgumentInterface;
15 use Symfony\Component\DependencyInjection\ContainerBuilder;
16 use Symfony\Component\DependencyInjection\Definition;
17 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
18 use Symfony\Component\DependencyInjection\Reference;
19
20 /**
21  * @author Nicolas Grekas <p@tchwork.com>
22  */
23 abstract class AbstractRecursivePass implements CompilerPassInterface
24 {
25     /**
26      * @var ContainerBuilder
27      */
28     protected $container;
29     protected $currentId;
30
31     /**
32      * {@inheritdoc}
33      */
34     public function process(ContainerBuilder $container)
35     {
36         $this->container = $container;
37
38         try {
39             $this->processValue($container->getDefinitions(), true);
40         } finally {
41             $this->container = null;
42         }
43     }
44
45     /**
46      * Processes a value found in a definition tree.
47      *
48      * @param mixed $value
49      * @param bool  $isRoot
50      *
51      * @return mixed The processed value
52      */
53     protected function processValue($value, $isRoot = false)
54     {
55         if (\is_array($value)) {
56             foreach ($value as $k => $v) {
57                 if ($isRoot) {
58                     $this->currentId = $k;
59                 }
60                 if ($v !== $processedValue = $this->processValue($v, $isRoot)) {
61                     $value[$k] = $processedValue;
62                 }
63             }
64         } elseif ($value instanceof ArgumentInterface) {
65             $value->setValues($this->processValue($value->getValues()));
66         } elseif ($value instanceof Definition) {
67             $value->setArguments($this->processValue($value->getArguments()));
68             $value->setProperties($this->processValue($value->getProperties()));
69             $value->setMethodCalls($this->processValue($value->getMethodCalls()));
70
71             $changes = $value->getChanges();
72             if (isset($changes['factory'])) {
73                 $value->setFactory($this->processValue($value->getFactory()));
74             }
75             if (isset($changes['configurator'])) {
76                 $value->setConfigurator($this->processValue($value->getConfigurator()));
77             }
78         }
79
80         return $value;
81     }
82
83     /**
84      * @param Definition $definition
85      * @param bool       $required
86      *
87      * @return \ReflectionFunctionAbstract|null
88      *
89      * @throws RuntimeException
90      */
91     protected function getConstructor(Definition $definition, $required)
92     {
93         if (is_string($factory = $definition->getFactory())) {
94             if (!function_exists($factory)) {
95                 throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory));
96             }
97             $r = new \ReflectionFunction($factory);
98             if (false !== $r->getFileName() && file_exists($r->getFileName())) {
99                 $this->container->fileExists($r->getFileName());
100             }
101
102             return $r;
103         }
104
105         if ($factory) {
106             list($class, $method) = $factory;
107             if ($class instanceof Reference) {
108                 $class = $this->container->findDefinition((string) $class)->getClass();
109             } elseif (null === $class) {
110                 $class = $definition->getClass();
111             }
112             if ('__construct' === $method) {
113                 throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
114             }
115
116             return $this->getReflectionMethod(new Definition($class), $method);
117         }
118
119         $class = $definition->getClass();
120
121         if (!$r = $this->container->getReflectionClass($class)) {
122             throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
123         }
124         if (!$r = $r->getConstructor()) {
125             if ($required) {
126                 throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class)));
127             }
128         } elseif (!$r->isPublic()) {
129             throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class)));
130         }
131
132         return $r;
133     }
134
135     /**
136      * @param Definition $definition
137      * @param string     $method
138      *
139      * @throws RuntimeException
140      *
141      * @return \ReflectionFunctionAbstract
142      */
143     protected function getReflectionMethod(Definition $definition, $method)
144     {
145         if ('__construct' === $method) {
146             return $this->getConstructor($definition, true);
147         }
148
149         if (!$class = $definition->getClass()) {
150             throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
151         }
152
153         if (!$r = $this->container->getReflectionClass($class)) {
154             throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
155         }
156
157         if (!$r->hasMethod($method)) {
158             throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
159         }
160
161         $r = $r->getMethod($method);
162         if (!$r->isPublic()) {
163             throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
164         }
165
166         return $r;
167     }
168 }