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