Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / dependency-injection / ParameterBag / ParameterBag.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\ParameterBag;
13
14 use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
15 use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
16 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
17
18 /**
19  * Holds parameters.
20  *
21  * @author Fabien Potencier <fabien@symfony.com>
22  */
23 class ParameterBag implements ParameterBagInterface
24 {
25     protected $parameters = array();
26     protected $resolved = false;
27
28     /**
29      * @param array $parameters An array of parameters
30      */
31     public function __construct(array $parameters = array())
32     {
33         $this->add($parameters);
34     }
35
36     /**
37      * Clears all parameters.
38      */
39     public function clear()
40     {
41         $this->parameters = array();
42     }
43
44     /**
45      * Adds parameters to the service container parameters.
46      *
47      * @param array $parameters An array of parameters
48      */
49     public function add(array $parameters)
50     {
51         foreach ($parameters as $key => $value) {
52             $this->parameters[strtolower($key)] = $value;
53         }
54     }
55
56     /**
57      * {@inheritdoc}
58      */
59     public function all()
60     {
61         return $this->parameters;
62     }
63
64     /**
65      * {@inheritdoc}
66      */
67     public function get($name)
68     {
69         $name = strtolower($name);
70
71         if (!array_key_exists($name, $this->parameters)) {
72             if (!$name) {
73                 throw new ParameterNotFoundException($name);
74             }
75
76             $alternatives = array();
77             foreach ($this->parameters as $key => $parameterValue) {
78                 $lev = levenshtein($name, $key);
79                 if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
80                     $alternatives[] = $key;
81                 }
82             }
83
84             $nonNestedAlternative = null;
85             if (!count($alternatives) && false !== strpos($name, '.')) {
86                 $namePartsLength = array_map('strlen', explode('.', $name));
87                 $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength)));
88                 while (count($namePartsLength)) {
89                     if ($this->has($key)) {
90                         if (is_array($this->get($key))) {
91                             $nonNestedAlternative = $key;
92                         }
93                         break;
94                     }
95
96                     $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength)));
97                 }
98             }
99
100             throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
101         }
102
103         return $this->parameters[$name];
104     }
105
106     /**
107      * Sets a service container parameter.
108      *
109      * @param string $name  The parameter name
110      * @param mixed  $value The parameter value
111      */
112     public function set($name, $value)
113     {
114         $this->parameters[strtolower($name)] = $value;
115     }
116
117     /**
118      * {@inheritdoc}
119      */
120     public function has($name)
121     {
122         return array_key_exists(strtolower($name), $this->parameters);
123     }
124
125     /**
126      * Removes a parameter.
127      *
128      * @param string $name The parameter name
129      */
130     public function remove($name)
131     {
132         unset($this->parameters[strtolower($name)]);
133     }
134
135     /**
136      * {@inheritdoc}
137      */
138     public function resolve()
139     {
140         if ($this->resolved) {
141             return;
142         }
143
144         $parameters = array();
145         foreach ($this->parameters as $key => $value) {
146             try {
147                 $value = $this->resolveValue($value);
148                 $parameters[$key] = $this->unescapeValue($value);
149             } catch (ParameterNotFoundException $e) {
150                 $e->setSourceKey($key);
151
152                 throw $e;
153             }
154         }
155
156         $this->parameters = $parameters;
157         $this->resolved = true;
158     }
159
160     /**
161      * Replaces parameter placeholders (%name%) by their values.
162      *
163      * @param mixed $value     A value
164      * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
165      *
166      * @return mixed The resolved value
167      *
168      * @throws ParameterNotFoundException          if a placeholder references a parameter that does not exist
169      * @throws ParameterCircularReferenceException if a circular reference if detected
170      * @throws RuntimeException                    when a given parameter has a type problem.
171      */
172     public function resolveValue($value, array $resolving = array())
173     {
174         if (is_array($value)) {
175             $args = array();
176             foreach ($value as $k => $v) {
177                 $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
178             }
179
180             return $args;
181         }
182
183         if (!is_string($value)) {
184             return $value;
185         }
186
187         return $this->resolveString($value, $resolving);
188     }
189
190     /**
191      * Resolves parameters inside a string.
192      *
193      * @param string $value     The string to resolve
194      * @param array  $resolving An array of keys that are being resolved (used internally to detect circular references)
195      *
196      * @return string The resolved string
197      *
198      * @throws ParameterNotFoundException          if a placeholder references a parameter that does not exist
199      * @throws ParameterCircularReferenceException if a circular reference if detected
200      * @throws RuntimeException                    when a given parameter has a type problem.
201      */
202     public function resolveString($value, array $resolving = array())
203     {
204         // we do this to deal with non string values (Boolean, integer, ...)
205         // as the preg_replace_callback throw an exception when trying
206         // a non-string in a parameter value
207         if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
208             $key = $match[1];
209             $lcKey = strtolower($key);
210
211             if (isset($resolving[$lcKey])) {
212                 throw new ParameterCircularReferenceException(array_keys($resolving));
213             }
214
215             $resolving[$lcKey] = true;
216
217             return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
218         }
219
220         return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) {
221             // skip %%
222             if (!isset($match[1])) {
223                 return '%%';
224             }
225
226             $key = $match[1];
227             $lcKey = strtolower($key);
228             if (isset($resolving[$lcKey])) {
229                 throw new ParameterCircularReferenceException(array_keys($resolving));
230             }
231
232             $resolved = $this->get($key);
233
234             if (!is_string($resolved) && !is_numeric($resolved)) {
235                 throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value));
236             }
237
238             $resolved = (string) $resolved;
239             $resolving[$lcKey] = true;
240
241             return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
242         }, $value);
243     }
244
245     public function isResolved()
246     {
247         return $this->resolved;
248     }
249
250     /**
251      * {@inheritdoc}
252      */
253     public function escapeValue($value)
254     {
255         if (is_string($value)) {
256             return str_replace('%', '%%', $value);
257         }
258
259         if (is_array($value)) {
260             $result = array();
261             foreach ($value as $k => $v) {
262                 $result[$k] = $this->escapeValue($v);
263             }
264
265             return $result;
266         }
267
268         return $value;
269     }
270
271     /**
272      * {@inheritdoc}
273      */
274     public function unescapeValue($value)
275     {
276         if (is_string($value)) {
277             return str_replace('%%', '%', $value);
278         }
279
280         if (is_array($value)) {
281             $result = array();
282             foreach ($value as $k => $v) {
283                 $result[$k] = $this->unescapeValue($v);
284             }
285
286             return $result;
287         }
288
289         return $value;
290     }
291 }