4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Config\Definition;
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;
20 * The base node class.
22 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
24 abstract class BaseNode implements NodeInterface
28 protected $normalizationClosures = array();
29 protected $finalValidationClosures = array();
30 protected $allowOverwrite = true;
31 protected $required = false;
32 protected $equivalentValues = array();
33 protected $attributes = array();
38 * @param string $name The name of the node
39 * @param NodeInterface $parent The parent of this node
41 * @throws \InvalidArgumentException if the name contains a period.
43 public function __construct($name, NodeInterface $parent = null)
45 if (false !== strpos($name, '.')) {
46 throw new \InvalidArgumentException('The name must not contain ".".');
50 $this->parent = $parent;
53 public function setAttribute($key, $value)
55 $this->attributes[$key] = $value;
58 public function getAttribute($key, $default = null)
60 return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
63 public function hasAttribute($key)
65 return isset($this->attributes[$key]);
68 public function getAttributes()
70 return $this->attributes;
73 public function setAttributes(array $attributes)
75 $this->attributes = $attributes;
78 public function removeAttribute($key)
80 unset($this->attributes[$key]);
84 * Sets an info message.
88 public function setInfo($info)
90 $this->setAttribute('info', $info);
94 * Returns info message.
96 * @return string The info text
98 public function getInfo()
100 return $this->getAttribute('info');
104 * Sets the example configuration for this node.
106 * @param string|array $example
108 public function setExample($example)
110 $this->setAttribute('example', $example);
114 * Retrieves the example configuration for this node.
116 * @return string|array The example
118 public function getExample()
120 return $this->getAttribute('example');
124 * Adds an equivalent value.
126 * @param mixed $originalValue
127 * @param mixed $equivalentValue
129 public function addEquivalentValue($originalValue, $equivalentValue)
131 $this->equivalentValues[] = array($originalValue, $equivalentValue);
135 * Set this node as required.
137 * @param bool $boolean Required node
139 public function setRequired($boolean)
141 $this->required = (bool) $boolean;
145 * Sets if this node can be overridden.
149 public function setAllowOverwrite($allow)
151 $this->allowOverwrite = (bool) $allow;
155 * Sets the closures used for normalization.
157 * @param \Closure[] $closures An array of Closures used for normalization
159 public function setNormalizationClosures(array $closures)
161 $this->normalizationClosures = $closures;
165 * Sets the closures used for final validation.
167 * @param \Closure[] $closures An array of Closures used for final validation
169 public function setFinalValidationClosures(array $closures)
171 $this->finalValidationClosures = $closures;
175 * Checks if this node is required.
179 public function isRequired()
181 return $this->required;
185 * Returns the name of this node.
187 * @return string The Node's name
189 public function getName()
195 * Retrieves the path of this node.
197 * @return string The Node's path
199 public function getPath()
203 if (null !== $this->parent) {
204 $path = $this->parent->getPath().'.'.$path;
211 * Merges two values together.
213 * @param mixed $leftSide
214 * @param mixed $rightSide
216 * @return mixed The merged value
218 * @throws ForbiddenOverwriteException
220 final public function merge($leftSide, $rightSide)
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.',
231 $this->validateType($leftSide);
232 $this->validateType($rightSide);
234 return $this->mergeValues($leftSide, $rightSide);
238 * Normalizes a value, applying all normalization closures.
240 * @param mixed $value Value to normalize
242 * @return mixed The normalized value
244 final public function normalize($value)
246 $value = $this->preNormalize($value);
248 // run custom normalization closures
249 foreach ($this->normalizationClosures as $closure) {
250 $value = $closure($value);
253 // replace value with their equivalent
254 foreach ($this->equivalentValues as $data) {
255 if ($data[0] === $value) {
261 $this->validateType($value);
264 return $this->normalizeValue($value);
268 * Normalizes the value before any other normalization is applied.
272 * @return $value The normalized array value
274 protected function preNormalize($value)
280 * Returns parent node for this node.
282 * @return NodeInterface|null
284 public function getParent()
286 return $this->parent;
290 * Finalizes a value, applying all finalization closures.
292 * @param mixed $value The value to finalize
294 * @return mixed The finalized value
297 * @throws InvalidConfigurationException
299 final public function finalize($value)
301 $this->validateType($value);
303 $value = $this->finalizeValue($value);
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) {
309 $value = $closure($value);
310 } catch (Exception $e) {
312 } catch (\Exception $e) {
313 throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e);
321 * Validates the type of a Node.
323 * @param mixed $value The value to validate
325 * @throws InvalidTypeException when the value is invalid
327 abstract protected function validateType($value);
330 * Normalizes the value.
332 * @param mixed $value The value to normalize
334 * @return mixed The normalized value
336 abstract protected function normalizeValue($value);
339 * Merges two values together.
341 * @param mixed $leftSide
342 * @param mixed $rightSide
344 * @return mixed The merged value
346 abstract protected function mergeValues($leftSide, $rightSide);
351 * @param mixed $value The value to finalize
353 * @return mixed The finalized value
355 abstract protected function finalizeValue($value);