68b2a0217263cff3c8675eaa89e71ab1a3fcb26d
[yaffs-website] / vendor / symfony / dependency-injection / Compiler / AnalyzeServiceReferencesPass.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\Definition;
15 use Symfony\Component\DependencyInjection\ExpressionLanguage;
16 use Symfony\Component\DependencyInjection\Reference;
17 use Symfony\Component\DependencyInjection\ContainerBuilder;
18 use Symfony\Component\ExpressionLanguage\Expression;
19
20 /**
21  * Run this pass before passes that need to know more about the relation of
22  * your services.
23  *
24  * This class will populate the ServiceReferenceGraph with information. You can
25  * retrieve the graph in other passes from the compiler.
26  *
27  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
28  */
29 class AnalyzeServiceReferencesPass implements RepeatablePassInterface
30 {
31     private $graph;
32     private $container;
33     private $currentId;
34     private $currentDefinition;
35     private $repeatedPass;
36     private $onlyConstructorArguments;
37     private $expressionLanguage;
38
39     /**
40      * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
41      */
42     public function __construct($onlyConstructorArguments = false)
43     {
44         $this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
45     }
46
47     /**
48      * {@inheritdoc}
49      */
50     public function setRepeatedPass(RepeatedPass $repeatedPass)
51     {
52         $this->repeatedPass = $repeatedPass;
53     }
54
55     /**
56      * Processes a ContainerBuilder object to populate the service reference graph.
57      *
58      * @param ContainerBuilder $container
59      */
60     public function process(ContainerBuilder $container)
61     {
62         $this->container = $container;
63         $this->graph = $container->getCompiler()->getServiceReferenceGraph();
64         $this->graph->clear();
65
66         foreach ($container->getDefinitions() as $id => $definition) {
67             if ($definition->isSynthetic() || $definition->isAbstract()) {
68                 continue;
69             }
70
71             $this->currentId = $id;
72             $this->currentDefinition = $definition;
73
74             $this->processArguments($definition->getArguments());
75             if (is_array($definition->getFactory())) {
76                 $this->processArguments($definition->getFactory());
77             }
78
79             if (!$this->onlyConstructorArguments) {
80                 $this->processArguments($definition->getMethodCalls());
81                 $this->processArguments($definition->getProperties());
82                 if ($definition->getConfigurator()) {
83                     $this->processArguments(array($definition->getConfigurator()));
84                 }
85             }
86         }
87
88         foreach ($container->getAliases() as $id => $alias) {
89             $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null);
90         }
91     }
92
93     /**
94      * Processes service definitions for arguments to find relationships for the service graph.
95      *
96      * @param array $arguments An array of Reference or Definition objects relating to service definitions
97      */
98     private function processArguments(array $arguments)
99     {
100         foreach ($arguments as $argument) {
101             if (is_array($argument)) {
102                 $this->processArguments($argument);
103             } elseif ($argument instanceof Expression) {
104                 $this->getExpressionLanguage()->compile((string) $argument, array('this' => 'container'));
105             } elseif ($argument instanceof Reference) {
106                 $this->graph->connect(
107                     $this->currentId,
108                     $this->currentDefinition,
109                     $this->getDefinitionId((string) $argument),
110                     $this->getDefinition((string) $argument),
111                     $argument
112                 );
113             } elseif ($argument instanceof Definition) {
114                 $this->processArguments($argument->getArguments());
115                 $this->processArguments($argument->getMethodCalls());
116                 $this->processArguments($argument->getProperties());
117
118                 if (is_array($argument->getFactory())) {
119                     $this->processArguments($argument->getFactory());
120                 }
121             }
122         }
123     }
124
125     /**
126      * Returns a service definition given the full name or an alias.
127      *
128      * @param string $id A full id or alias for a service definition
129      *
130      * @return Definition|null The definition related to the supplied id
131      */
132     private function getDefinition($id)
133     {
134         $id = $this->getDefinitionId($id);
135
136         return null === $id ? null : $this->container->getDefinition($id);
137     }
138
139     private function getDefinitionId($id)
140     {
141         while ($this->container->hasAlias($id)) {
142             $id = (string) $this->container->getAlias($id);
143         }
144
145         if (!$this->container->hasDefinition($id)) {
146             return;
147         }
148
149         return $id;
150     }
151
152     private function getExpressionLanguage()
153     {
154         if (null === $this->expressionLanguage) {
155             $providers = $this->container->getExpressionLanguageProviders();
156             $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
157                 if ('""' === substr_replace($arg, '', 1, -1)) {
158                     $id = stripcslashes(substr($arg, 1, -1));
159
160                     $this->graph->connect(
161                         $this->currentId,
162                         $this->currentDefinition,
163                         $this->getDefinitionId($id),
164                         $this->getDefinition($id)
165                     );
166                 }
167
168                 return sprintf('$this->get(%s)', $arg);
169             });
170         }
171
172         return $this->expressionLanguage;
173     }
174 }