Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / dependency-injection / Compiler / ReplaceAliasByActualDefinitionPass.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\ContainerBuilder;
15 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16 use Symfony\Component\DependencyInjection\Reference;
17
18 /**
19  * Replaces aliases with actual service definitions, effectively removing these
20  * aliases.
21  *
22  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
23  */
24 class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
25 {
26     private $compiler;
27     private $formatter;
28
29     /**
30      * Process the Container to replace aliases with service definitions.
31      *
32      * @param ContainerBuilder $container
33      *
34      * @throws InvalidArgumentException if the service definition does not exist
35      */
36     public function process(ContainerBuilder $container)
37     {
38         // Setup
39         $this->compiler = $container->getCompiler();
40         $this->formatter = $this->compiler->getLoggingFormatter();
41         // First collect all alias targets that need to be replaced
42         $seenAliasTargets = array();
43         $replacements = array();
44         foreach ($container->getAliases() as $definitionId => $target) {
45             $targetId = (string) $target;
46             // Special case: leave this target alone
47             if ('service_container' === $targetId) {
48                 continue;
49             }
50             // Check if target needs to be replaces
51             if (isset($replacements[$targetId])) {
52                 $container->setAlias($definitionId, $replacements[$targetId]);
53             }
54             // No need to process the same target twice
55             if (isset($seenAliasTargets[$targetId])) {
56                 continue;
57             }
58             // Process new target
59             $seenAliasTargets[$targetId] = true;
60             try {
61                 $definition = $container->getDefinition($targetId);
62             } catch (InvalidArgumentException $e) {
63                 throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
64             }
65             if ($definition->isPublic()) {
66                 continue;
67             }
68             // Remove private definition and schedule for replacement
69             $definition->setPublic(true);
70             $container->setDefinition($definitionId, $definition);
71             $container->removeDefinition($targetId);
72             $replacements[$targetId] = $definitionId;
73         }
74
75         // Now replace target instances in all definitions
76         foreach ($container->getDefinitions() as $definitionId => $definition) {
77             $definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
78             $definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
79             $definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
80             $definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
81         }
82     }
83
84     /**
85      * Recursively updates references in an array.
86      *
87      * @param array  $replacements Table of aliases to replace
88      * @param string $definitionId Identifier of this definition
89      * @param array  $arguments    Where to replace the aliases
90      *
91      * @return array
92      */
93     private function updateArgumentReferences(array $replacements, $definitionId, array $arguments)
94     {
95         foreach ($arguments as $k => $argument) {
96             // Handle recursion step
97             if (is_array($argument)) {
98                 $arguments[$k] = $this->updateArgumentReferences($replacements, $definitionId, $argument);
99                 continue;
100             }
101             // Skip arguments that don't need replacement
102             if (!$argument instanceof Reference) {
103                 continue;
104             }
105             $referenceId = (string) $argument;
106             if (!isset($replacements[$referenceId])) {
107                 continue;
108             }
109             // Perform the replacement
110             $newId = $replacements[$referenceId];
111             $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
112             $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $definitionId, $referenceId, $newId));
113         }
114
115         return $arguments;
116     }
117
118     private function updateFactoryReference(array $replacements, $factory)
119     {
120         if (is_array($factory) && $factory[0] instanceof Reference && isset($replacements[$referenceId = (string) $factory[0]])) {
121             $factory[0] = new Reference($replacements[$referenceId], $factory[0]->getInvalidBehavior());
122         }
123
124         return $factory;
125     }
126 }