Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / config / Definition / BaseNode.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\Config\Definition;
13
14 use Symfony\Component\Config\Definition\Exception\Exception;
15 use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
16 use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
17 use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
18
19 /**
20  * The base node class.
21  *
22  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
23  */
24 abstract class BaseNode implements NodeInterface
25 {
26     protected $name;
27     protected $parent;
28     protected $normalizationClosures = array();
29     protected $finalValidationClosures = array();
30     protected $allowOverwrite = true;
31     protected $required = false;
32     protected $equivalentValues = array();
33     protected $attributes = array();
34
35     /**
36      * Constructor.
37      *
38      * @param string        $name   The name of the node
39      * @param NodeInterface $parent The parent of this node
40      *
41      * @throws \InvalidArgumentException if the name contains a period.
42      */
43     public function __construct($name, NodeInterface $parent = null)
44     {
45         if (false !== strpos($name, '.')) {
46             throw new \InvalidArgumentException('The name must not contain ".".');
47         }
48
49         $this->name = $name;
50         $this->parent = $parent;
51     }
52
53     public function setAttribute($key, $value)
54     {
55         $this->attributes[$key] = $value;
56     }
57
58     public function getAttribute($key, $default = null)
59     {
60         return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
61     }
62
63     public function hasAttribute($key)
64     {
65         return isset($this->attributes[$key]);
66     }
67
68     public function getAttributes()
69     {
70         return $this->attributes;
71     }
72
73     public function setAttributes(array $attributes)
74     {
75         $this->attributes = $attributes;
76     }
77
78     public function removeAttribute($key)
79     {
80         unset($this->attributes[$key]);
81     }
82
83     /**
84      * Sets an info message.
85      *
86      * @param string $info
87      */
88     public function setInfo($info)
89     {
90         $this->setAttribute('info', $info);
91     }
92
93     /**
94      * Returns info message.
95      *
96      * @return string The info text
97      */
98     public function getInfo()
99     {
100         return $this->getAttribute('info');
101     }
102
103     /**
104      * Sets the example configuration for this node.
105      *
106      * @param string|array $example
107      */
108     public function setExample($example)
109     {
110         $this->setAttribute('example', $example);
111     }
112
113     /**
114      * Retrieves the example configuration for this node.
115      *
116      * @return string|array The example
117      */
118     public function getExample()
119     {
120         return $this->getAttribute('example');
121     }
122
123     /**
124      * Adds an equivalent value.
125      *
126      * @param mixed $originalValue
127      * @param mixed $equivalentValue
128      */
129     public function addEquivalentValue($originalValue, $equivalentValue)
130     {
131         $this->equivalentValues[] = array($originalValue, $equivalentValue);
132     }
133
134     /**
135      * Set this node as required.
136      *
137      * @param bool $boolean Required node
138      */
139     public function setRequired($boolean)
140     {
141         $this->required = (bool) $boolean;
142     }
143
144     /**
145      * Sets if this node can be overridden.
146      *
147      * @param bool $allow
148      */
149     public function setAllowOverwrite($allow)
150     {
151         $this->allowOverwrite = (bool) $allow;
152     }
153
154     /**
155      * Sets the closures used for normalization.
156      *
157      * @param \Closure[] $closures An array of Closures used for normalization
158      */
159     public function setNormalizationClosures(array $closures)
160     {
161         $this->normalizationClosures = $closures;
162     }
163
164     /**
165      * Sets the closures used for final validation.
166      *
167      * @param \Closure[] $closures An array of Closures used for final validation
168      */
169     public function setFinalValidationClosures(array $closures)
170     {
171         $this->finalValidationClosures = $closures;
172     }
173
174     /**
175      * Checks if this node is required.
176      *
177      * @return bool
178      */
179     public function isRequired()
180     {
181         return $this->required;
182     }
183
184     /**
185      * Returns the name of this node.
186      *
187      * @return string The Node's name
188      */
189     public function getName()
190     {
191         return $this->name;
192     }
193
194     /**
195      * Retrieves the path of this node.
196      *
197      * @return string The Node's path
198      */
199     public function getPath()
200     {
201         $path = $this->name;
202
203         if (null !== $this->parent) {
204             $path = $this->parent->getPath().'.'.$path;
205         }
206
207         return $path;
208     }
209
210     /**
211      * Merges two values together.
212      *
213      * @param mixed $leftSide
214      * @param mixed $rightSide
215      *
216      * @return mixed The merged value
217      *
218      * @throws ForbiddenOverwriteException
219      */
220     final public function merge($leftSide, $rightSide)
221     {
222         if (!$this->allowOverwrite) {
223             throw new ForbiddenOverwriteException(sprintf(
224                 'Configuration path "%s" cannot be overwritten. You have to '
225                .'define all options for this path, and any of its sub-paths in '
226                .'one configuration section.',
227                 $this->getPath()
228             ));
229         }
230
231         $this->validateType($leftSide);
232         $this->validateType($rightSide);
233
234         return $this->mergeValues($leftSide, $rightSide);
235     }
236
237     /**
238      * Normalizes a value, applying all normalization closures.
239      *
240      * @param mixed $value Value to normalize
241      *
242      * @return mixed The normalized value
243      */
244     final public function normalize($value)
245     {
246         $value = $this->preNormalize($value);
247
248         // run custom normalization closures
249         foreach ($this->normalizationClosures as $closure) {
250             $value = $closure($value);
251         }
252
253         // replace value with their equivalent
254         foreach ($this->equivalentValues as $data) {
255             if ($data[0] === $value) {
256                 $value = $data[1];
257             }
258         }
259
260         // validate type
261         $this->validateType($value);
262
263         // normalize value
264         return $this->normalizeValue($value);
265     }
266
267     /**
268      * Normalizes the value before any other normalization is applied.
269      *
270      * @param $value
271      *
272      * @return $value The normalized array value
273      */
274     protected function preNormalize($value)
275     {
276         return $value;
277     }
278
279     /**
280      * Returns parent node for this node.
281      *
282      * @return NodeInterface|null
283      */
284     public function getParent()
285     {
286         return $this->parent;
287     }
288
289     /**
290      * Finalizes a value, applying all finalization closures.
291      *
292      * @param mixed $value The value to finalize
293      *
294      * @return mixed The finalized value
295      *
296      * @throws Exception
297      * @throws InvalidConfigurationException
298      */
299     final public function finalize($value)
300     {
301         $this->validateType($value);
302
303         $value = $this->finalizeValue($value);
304
305         // Perform validation on the final value if a closure has been set.
306         // The closure is also allowed to return another value.
307         foreach ($this->finalValidationClosures as $closure) {
308             try {
309                 $value = $closure($value);
310             } catch (Exception $e) {
311                 throw $e;
312             } catch (\Exception $e) {
313                 throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e);
314             }
315         }
316
317         return $value;
318     }
319
320     /**
321      * Validates the type of a Node.
322      *
323      * @param mixed $value The value to validate
324      *
325      * @throws InvalidTypeException when the value is invalid
326      */
327     abstract protected function validateType($value);
328
329     /**
330      * Normalizes the value.
331      *
332      * @param mixed $value The value to normalize
333      *
334      * @return mixed The normalized value
335      */
336     abstract protected function normalizeValue($value);
337
338     /**
339      * Merges two values together.
340      *
341      * @param mixed $leftSide
342      * @param mixed $rightSide
343      *
344      * @return mixed The merged value
345      */
346     abstract protected function mergeValues($leftSide, $rightSide);
347
348     /**
349      * Finalizes a value.
350      *
351      * @param mixed $value The value to finalize
352      *
353      * @return mixed The finalized value
354      */
355     abstract protected function finalizeValue($value);
356 }