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