diff options
author | Nicolas LÅ“uillet <nicolas.loeuillet@gmail.com> | 2013-08-03 19:26:54 +0200 |
---|---|---|
committer | Nicolas LÅ“uillet <nicolas.loeuillet@gmail.com> | 2013-08-03 19:26:54 +0200 |
commit | 4f5b44bd3bd490309eb2ba7b44df4769816ba729 (patch) | |
tree | 6cefe170dfe0a5a361cb1e2d1fc4d580a3316d02 /vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php | |
parent | 2b840e0cfb63a453bea67a98541f3df9c273c5f5 (diff) | |
download | wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.gz wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.zst wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.zip |
twig implementation
Diffstat (limited to 'vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php')
-rw-r--r-- | vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php b/vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php new file mode 100644 index 00000000..5b958af4 --- /dev/null +++ b/vendor/symfony/options-resolver/Symfony/Component/OptionsResolver/Options.php | |||
@@ -0,0 +1,513 @@ | |||
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\OptionsResolver; | ||
13 | |||
14 | use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; | ||
15 | |||
16 | /** | ||
17 | * Container for resolving inter-dependent options. | ||
18 | * | ||
19 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
20 | */ | ||
21 | class Options implements \ArrayAccess, \Iterator, \Countable | ||
22 | { | ||
23 | /** | ||
24 | * A list of option values. | ||
25 | * @var array | ||
26 | */ | ||
27 | private $options = array(); | ||
28 | |||
29 | /** | ||
30 | * A list of normalizer closures. | ||
31 | * @var array | ||
32 | */ | ||
33 | private $normalizers = array(); | ||
34 | |||
35 | /** | ||
36 | * A list of closures for evaluating lazy options. | ||
37 | * @var array | ||
38 | */ | ||
39 | private $lazy = array(); | ||
40 | |||
41 | /** | ||
42 | * A list containing the currently locked options. | ||
43 | * @var array | ||
44 | */ | ||
45 | private $lock = array(); | ||
46 | |||
47 | /** | ||
48 | * Whether at least one option has already been read. | ||
49 | * | ||
50 | * Once read, the options cannot be changed anymore. This is | ||
51 | * necessary in order to avoid inconsistencies during the resolving | ||
52 | * process. If any option is changed after being read, all evaluated | ||
53 | * lazy options that depend on this option would become invalid. | ||
54 | * | ||
55 | * @var Boolean | ||
56 | */ | ||
57 | private $reading = false; | ||
58 | |||
59 | /** | ||
60 | * Sets the value of a given option. | ||
61 | * | ||
62 | * You can set lazy options by passing a closure with the following | ||
63 | * signature: | ||
64 | * | ||
65 | * <code> | ||
66 | * function (Options $options) | ||
67 | * </code> | ||
68 | * | ||
69 | * This closure will be evaluated once the option is read using | ||
70 | * {@link get()}. The closure has access to the resolved values of | ||
71 | * other options through the passed {@link Options} instance. | ||
72 | * | ||
73 | * @param string $option The name of the option. | ||
74 | * @param mixed $value The value of the option. | ||
75 | * | ||
76 | * @throws OptionDefinitionException If options have already been read. | ||
77 | * Once options are read, the container | ||
78 | * becomes immutable. | ||
79 | */ | ||
80 | public function set($option, $value) | ||
81 | { | ||
82 | // Setting is not possible once an option is read, because then lazy | ||
83 | // options could manipulate the state of the object, leading to | ||
84 | // inconsistent results. | ||
85 | if ($this->reading) { | ||
86 | throw new OptionDefinitionException('Options cannot be set anymore once options have been read.'); | ||
87 | } | ||
88 | |||
89 | // Setting is equivalent to overloading while discarding the previous | ||
90 | // option value | ||
91 | unset($this->options[$option]); | ||
92 | unset($this->lazy[$option]); | ||
93 | |||
94 | $this->overload($option, $value); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * Sets the normalizer for a given option. | ||
99 | * | ||
100 | * Normalizers should be closures with the following signature: | ||
101 | * | ||
102 | * <code> | ||
103 | * function (Options $options, $value) | ||
104 | * </code> | ||
105 | * | ||
106 | * This closure will be evaluated once the option is read using | ||
107 | * {@link get()}. The closure has access to the resolved values of | ||
108 | * other options through the passed {@link Options} instance. | ||
109 | * | ||
110 | * @param string $option The name of the option. | ||
111 | * @param \Closure $normalizer The normalizer. | ||
112 | * | ||
113 | * @throws OptionDefinitionException If options have already been read. | ||
114 | * Once options are read, the container | ||
115 | * becomes immutable. | ||
116 | */ | ||
117 | public function setNormalizer($option, \Closure $normalizer) | ||
118 | { | ||
119 | if ($this->reading) { | ||
120 | throw new OptionDefinitionException('Normalizers cannot be added anymore once options have been read.'); | ||
121 | } | ||
122 | |||
123 | $this->normalizers[$option] = $normalizer; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Replaces the contents of the container with the given options. | ||
128 | * | ||
129 | * This method is a shortcut for {@link clear()} with subsequent | ||
130 | * calls to {@link set()}. | ||
131 | * | ||
132 | * @param array $options The options to set. | ||
133 | * | ||
134 | * @throws OptionDefinitionException If options have already been read. | ||
135 | * Once options are read, the container | ||
136 | * becomes immutable. | ||
137 | */ | ||
138 | public function replace(array $options) | ||
139 | { | ||
140 | if ($this->reading) { | ||
141 | throw new OptionDefinitionException('Options cannot be replaced anymore once options have been read.'); | ||
142 | } | ||
143 | |||
144 | $this->options = array(); | ||
145 | $this->lazy = array(); | ||
146 | $this->normalizers = array(); | ||
147 | |||
148 | foreach ($options as $option => $value) { | ||
149 | $this->overload($option, $value); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Overloads the value of a given option. | ||
155 | * | ||
156 | * Contrary to {@link set()}, this method keeps the previous default | ||
157 | * value of the option so that you can access it if you pass a closure. | ||
158 | * Passed closures should have the following signature: | ||
159 | * | ||
160 | * <code> | ||
161 | * function (Options $options, $value) | ||
162 | * </code> | ||
163 | * | ||
164 | * The second parameter passed to the closure is the current default | ||
165 | * value of the option. | ||
166 | * | ||
167 | * @param string $option The option name. | ||
168 | * @param mixed $value The option value. | ||
169 | * | ||
170 | * @throws OptionDefinitionException If options have already been read. | ||
171 | * Once options are read, the container | ||
172 | * becomes immutable. | ||
173 | */ | ||
174 | public function overload($option, $value) | ||
175 | { | ||
176 | if ($this->reading) { | ||
177 | throw new OptionDefinitionException('Options cannot be overloaded anymore once options have been read.'); | ||
178 | } | ||
179 | |||
180 | // If an option is a closure that should be evaluated lazily, store it | ||
181 | // in the "lazy" property. | ||
182 | if ($value instanceof \Closure) { | ||
183 | $reflClosure = new \ReflectionFunction($value); | ||
184 | $params = $reflClosure->getParameters(); | ||
185 | |||
186 | if (isset($params[0]) && null !== ($class = $params[0]->getClass()) && __CLASS__ === $class->name) { | ||
187 | // Initialize the option if no previous value exists | ||
188 | if (!isset($this->options[$option])) { | ||
189 | $this->options[$option] = null; | ||
190 | } | ||
191 | |||
192 | // Ignore previous lazy options if the closure has no second parameter | ||
193 | if (!isset($this->lazy[$option]) || !isset($params[1])) { | ||
194 | $this->lazy[$option] = array(); | ||
195 | } | ||
196 | |||
197 | // Store closure for later evaluation | ||
198 | $this->lazy[$option][] = $value; | ||
199 | |||
200 | return; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | // Remove lazy options by default | ||
205 | unset($this->lazy[$option]); | ||
206 | |||
207 | $this->options[$option] = $value; | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * Returns the value of the given option. | ||
212 | * | ||
213 | * If the option was a lazy option, it is evaluated now. | ||
214 | * | ||
215 | * @param string $option The option name. | ||
216 | * | ||
217 | * @return mixed The option value. | ||
218 | * | ||
219 | * @throws \OutOfBoundsException If the option does not exist. | ||
220 | * @throws OptionDefinitionException If a cyclic dependency is detected | ||
221 | * between two lazy options. | ||
222 | */ | ||
223 | public function get($option) | ||
224 | { | ||
225 | $this->reading = true; | ||
226 | |||
227 | if (!array_key_exists($option, $this->options)) { | ||
228 | throw new \OutOfBoundsException(sprintf('The option "%s" does not exist.', $option)); | ||
229 | } | ||
230 | |||
231 | if (isset($this->lazy[$option])) { | ||
232 | $this->resolve($option); | ||
233 | } | ||
234 | |||
235 | if (isset($this->normalizers[$option])) { | ||
236 | $this->normalize($option); | ||
237 | } | ||
238 | |||
239 | return $this->options[$option]; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * Returns whether the given option exists. | ||
244 | * | ||
245 | * @param string $option The option name. | ||
246 | * | ||
247 | * @return Boolean Whether the option exists. | ||
248 | */ | ||
249 | public function has($option) | ||
250 | { | ||
251 | return array_key_exists($option, $this->options); | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * Removes the option with the given name. | ||
256 | * | ||
257 | * @param string $option The option name. | ||
258 | * | ||
259 | * @throws OptionDefinitionException If options have already been read. | ||
260 | * Once options are read, the container | ||
261 | * becomes immutable. | ||
262 | */ | ||
263 | public function remove($option) | ||
264 | { | ||
265 | if ($this->reading) { | ||
266 | throw new OptionDefinitionException('Options cannot be removed anymore once options have been read.'); | ||
267 | } | ||
268 | |||
269 | unset($this->options[$option]); | ||
270 | unset($this->lazy[$option]); | ||
271 | unset($this->normalizers[$option]); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * Removes all options. | ||
276 | * | ||
277 | * @throws OptionDefinitionException If options have already been read. | ||
278 | * Once options are read, the container | ||
279 | * becomes immutable. | ||
280 | */ | ||
281 | public function clear() | ||
282 | { | ||
283 | if ($this->reading) { | ||
284 | throw new OptionDefinitionException('Options cannot be cleared anymore once options have been read.'); | ||
285 | } | ||
286 | |||
287 | $this->options = array(); | ||
288 | $this->lazy = array(); | ||
289 | $this->normalizers = array(); | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * Returns the values of all options. | ||
294 | * | ||
295 | * Lazy options are evaluated at this point. | ||
296 | * | ||
297 | * @return array The option values. | ||
298 | */ | ||
299 | public function all() | ||
300 | { | ||
301 | $this->reading = true; | ||
302 | |||
303 | // Performance-wise this is slightly better than | ||
304 | // while (null !== $option = key($this->lazy)) | ||
305 | foreach ($this->lazy as $option => $closures) { | ||
306 | // Double check, in case the option has already been resolved | ||
307 | // by cascade in the previous cycles | ||
308 | if (isset($this->lazy[$option])) { | ||
309 | $this->resolve($option); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | foreach ($this->normalizers as $option => $normalizer) { | ||
314 | if (isset($this->normalizers[$option])) { | ||
315 | $this->normalize($option); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return $this->options; | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * Equivalent to {@link has()}. | ||
324 | * | ||
325 | * @param string $option The option name. | ||
326 | * | ||
327 | * @return Boolean Whether the option exists. | ||
328 | * | ||
329 | * @see \ArrayAccess::offsetExists() | ||
330 | */ | ||
331 | public function offsetExists($option) | ||
332 | { | ||
333 | return $this->has($option); | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Equivalent to {@link get()}. | ||
338 | * | ||
339 | * @param string $option The option name. | ||
340 | * | ||
341 | * @return mixed The option value. | ||
342 | * | ||
343 | * @throws \OutOfBoundsException If the option does not exist. | ||
344 | * @throws OptionDefinitionException If a cyclic dependency is detected | ||
345 | * between two lazy options. | ||
346 | * | ||
347 | * @see \ArrayAccess::offsetGet() | ||
348 | */ | ||
349 | public function offsetGet($option) | ||
350 | { | ||
351 | return $this->get($option); | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * Equivalent to {@link set()}. | ||
356 | * | ||
357 | * @param string $option The name of the option. | ||
358 | * @param mixed $value The value of the option. May be a closure with a | ||
359 | * signature as defined in DefaultOptions::add(). | ||
360 | * | ||
361 | * @throws OptionDefinitionException If options have already been read. | ||
362 | * Once options are read, the container | ||
363 | * becomes immutable. | ||
364 | * | ||
365 | * @see \ArrayAccess::offsetSet() | ||
366 | */ | ||
367 | public function offsetSet($option, $value) | ||
368 | { | ||
369 | $this->set($option, $value); | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * Equivalent to {@link remove()}. | ||
374 | * | ||
375 | * @param string $option The option name. | ||
376 | * | ||
377 | * @throws OptionDefinitionException If options have already been read. | ||
378 | * Once options are read, the container | ||
379 | * becomes immutable. | ||
380 | * | ||
381 | * @see \ArrayAccess::offsetUnset() | ||
382 | */ | ||
383 | public function offsetUnset($option) | ||
384 | { | ||
385 | $this->remove($option); | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * {@inheritdoc} | ||
390 | */ | ||
391 | public function current() | ||
392 | { | ||
393 | return $this->get($this->key()); | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * {@inheritdoc} | ||
398 | */ | ||
399 | public function next() | ||
400 | { | ||
401 | next($this->options); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * {@inheritdoc} | ||
406 | */ | ||
407 | public function key() | ||
408 | { | ||
409 | return key($this->options); | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * {@inheritdoc} | ||
414 | */ | ||
415 | public function valid() | ||
416 | { | ||
417 | return null !== $this->key(); | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * {@inheritdoc} | ||
422 | */ | ||
423 | public function rewind() | ||
424 | { | ||
425 | reset($this->options); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * {@inheritdoc} | ||
430 | */ | ||
431 | public function count() | ||
432 | { | ||
433 | return count($this->options); | ||
434 | } | ||
435 | |||
436 | /** | ||
437 | * Evaluates the given lazy option. | ||
438 | * | ||
439 | * The evaluated value is written into the options array. The closure for | ||
440 | * evaluating the option is discarded afterwards. | ||
441 | * | ||
442 | * @param string $option The option to evaluate. | ||
443 | * | ||
444 | * @throws OptionDefinitionException If the option has a cyclic dependency | ||
445 | * on another option. | ||
446 | */ | ||
447 | private function resolve($option) | ||
448 | { | ||
449 | // The code duplication with normalize() exists for performance | ||
450 | // reasons, in order to save a method call. | ||
451 | // Remember that this method is potentially called a couple of thousand | ||
452 | // times and needs to be as efficient as possible. | ||
453 | if (isset($this->lock[$option])) { | ||
454 | $conflicts = array(); | ||
455 | |||
456 | foreach ($this->lock as $option => $locked) { | ||
457 | if ($locked) { | ||
458 | $conflicts[] = $option; | ||
459 | } | ||
460 | } | ||
461 | |||
462 | throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); | ||
463 | } | ||
464 | |||
465 | $this->lock[$option] = true; | ||
466 | foreach ($this->lazy[$option] as $closure) { | ||
467 | $this->options[$option] = $closure($this, $this->options[$option]); | ||
468 | } | ||
469 | unset($this->lock[$option]); | ||
470 | |||
471 | // The option now isn't lazy anymore | ||
472 | unset($this->lazy[$option]); | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * Normalizes the given option. | ||
477 | * | ||
478 | * The evaluated value is written into the options array. | ||
479 | * | ||
480 | * @param string $option The option to normalizer. | ||
481 | * | ||
482 | * @throws OptionDefinitionException If the option has a cyclic dependency | ||
483 | * on another option. | ||
484 | */ | ||
485 | private function normalize($option) | ||
486 | { | ||
487 | // The code duplication with resolve() exists for performance | ||
488 | // reasons, in order to save a method call. | ||
489 | // Remember that this method is potentially called a couple of thousand | ||
490 | // times and needs to be as efficient as possible. | ||
491 | if (isset($this->lock[$option])) { | ||
492 | $conflicts = array(); | ||
493 | |||
494 | foreach ($this->lock as $option => $locked) { | ||
495 | if ($locked) { | ||
496 | $conflicts[] = $option; | ||
497 | } | ||
498 | } | ||
499 | |||
500 | throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); | ||
501 | } | ||
502 | |||
503 | /** @var \Closure $normalizer */ | ||
504 | $normalizer = $this->normalizers[$option]; | ||
505 | |||
506 | $this->lock[$option] = true; | ||
507 | $this->options[$option] = $normalizer($this, array_key_exists($option, $this->options) ? $this->options[$option] : null); | ||
508 | unset($this->lock[$option]); | ||
509 | |||
510 | // The option is now normalized | ||
511 | unset($this->normalizers[$option]); | ||
512 | } | ||
513 | } | ||