Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / dependency-injection / Compiler / ResolveInvalidReferencesPass.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\ContainerInterface;
15 use Symfony\Component\DependencyInjection\Reference;
16 use Symfony\Component\DependencyInjection\ContainerBuilder;
17 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
18
19 /**
20  * Emulates the invalid behavior if the reference is not found within the
21  * container.
22  *
23  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
24  */
25 class ResolveInvalidReferencesPass implements CompilerPassInterface
26 {
27     private $container;
28
29     /**
30      * Process the ContainerBuilder to resolve invalid references.
31      *
32      * @param ContainerBuilder $container
33      */
34     public function process(ContainerBuilder $container)
35     {
36         $this->container = $container;
37         foreach ($container->getDefinitions() as $definition) {
38             if ($definition->isSynthetic() || $definition->isAbstract()) {
39                 continue;
40             }
41
42             $definition->setArguments(
43                 $this->processArguments($definition->getArguments())
44             );
45
46             $calls = array();
47             foreach ($definition->getMethodCalls() as $call) {
48                 try {
49                     $calls[] = array($call[0], $this->processArguments($call[1], true));
50                 } catch (RuntimeException $e) {
51                     // this call is simply removed
52                 }
53             }
54             $definition->setMethodCalls($calls);
55
56             $properties = array();
57             foreach ($definition->getProperties() as $name => $value) {
58                 try {
59                     $value = $this->processArguments(array($value), true);
60                     $properties[$name] = reset($value);
61                 } catch (RuntimeException $e) {
62                     // ignore property
63                 }
64             }
65             $definition->setProperties($properties);
66         }
67     }
68
69     /**
70      * Processes arguments to determine invalid references.
71      *
72      * @param array $arguments    An array of Reference objects
73      * @param bool  $inMethodCall
74      * @param bool  $inCollection
75      *
76      * @return array
77      *
78      * @throws RuntimeException When the config is invalid
79      */
80     private function processArguments(array $arguments, $inMethodCall = false, $inCollection = false)
81     {
82         $isNumeric = array_keys($arguments) === range(0, count($arguments) - 1);
83
84         foreach ($arguments as $k => $argument) {
85             if (is_array($argument)) {
86                 $arguments[$k] = $this->processArguments($argument, $inMethodCall, true);
87             } elseif ($argument instanceof Reference) {
88                 $id = (string) $argument;
89
90                 $invalidBehavior = $argument->getInvalidBehavior();
91                 $exists = $this->container->has($id);
92
93                 // resolve invalid behavior
94                 if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
95                     $arguments[$k] = null;
96                 } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
97                     if ($inCollection) {
98                         unset($arguments[$k]);
99                         continue;
100                     }
101                     if ($inMethodCall) {
102                         throw new RuntimeException('Method shouldn\'t be called.');
103                     }
104
105                     $arguments[$k] = null;
106                 }
107             }
108         }
109
110         // Ensure numerically indexed arguments have sequential numeric keys.
111         if ($isNumeric) {
112             $arguments = array_values($arguments);
113         }
114
115         return $arguments;
116     }
117 }