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();
36 * @param string|null $name The name of the node
37 * @param NodeInterface|null $parent The parent of this node
39 * @throws \InvalidArgumentException if the name contains a period
41 public function __construct($name, NodeInterface
$parent = null)
43 if (false !== strpos($name = (string) $name, '.')) {
44 throw new \
InvalidArgumentException('The name must not contain ".".');
48 $this->parent
= $parent;
51 public function setAttribute($key, $value)
53 $this->attributes
[$key] = $value;
56 public function getAttribute($key, $default = null)
58 return isset($this->attributes
[$key]) ?
$this->attributes
[$key] : $default;
61 public function hasAttribute($key)
63 return isset($this->attributes
[$key]);
66 public function getAttributes()
68 return $this->attributes
;
71 public function setAttributes(array $attributes)
73 $this->attributes
= $attributes;
76 public function removeAttribute($key)
78 unset($this->attributes
[$key]);
82 * Sets an info message.
86 public function setInfo($info)
88 $this->setAttribute('info', $info);
92 * Returns info message.
94 * @return string The info text
96 public function getInfo()
98 return $this->getAttribute('info');
102 * Sets the example configuration for this node.
104 * @param string|array $example
106 public function setExample($example)
108 $this->setAttribute('example', $example);
112 * Retrieves the example configuration for this node.
114 * @return string|array The example
116 public function getExample()
118 return $this->getAttribute('example');
122 * Adds an equivalent value.
124 * @param mixed $originalValue
125 * @param mixed $equivalentValue
127 public function addEquivalentValue($originalValue, $equivalentValue)
129 $this->equivalentValues
[] = array($originalValue, $equivalentValue);
133 * Set this node as required.
135 * @param bool $boolean Required node
137 public function setRequired($boolean)
139 $this->required
= (bool) $boolean;
143 * Sets if this node can be overridden.
147 public function setAllowOverwrite($allow)
149 $this->allowOverwrite
= (bool) $allow;
153 * Sets the closures used for normalization.
155 * @param \Closure[] $closures An array of Closures used for normalization
157 public function setNormalizationClosures(array $closures)
159 $this->normalizationClosures
= $closures;
163 * Sets the closures used for final validation.
165 * @param \Closure[] $closures An array of Closures used for final validation
167 public function setFinalValidationClosures(array $closures)
169 $this->finalValidationClosures
= $closures;
175 public function isRequired()
177 return $this->required
;
183 public function getName()
191 public function getPath()
195 if (null !== $this->parent
) {
196 $path = $this->parent
->getPath().'.'.$path;
205 final public function merge($leftSide, $rightSide)
207 if (!$this->allowOverwrite
) {
208 throw new ForbiddenOverwriteException(sprintf(
209 'Configuration path "%s" cannot be overwritten. You have to '
210 .'define all options for this path, and any of its sub-paths in '
211 .'one configuration section.',
216 $this->validateType($leftSide);
217 $this->validateType($rightSide);
219 return $this->mergeValues($leftSide, $rightSide);
225 final public function normalize($value)
227 $value = $this->preNormalize($value);
229 // run custom normalization closures
230 foreach ($this->normalizationClosures
as $closure) {
231 $value = $closure($value);
234 // replace value with their equivalent
235 foreach ($this->equivalentValues
as $data) {
236 if ($data[0] === $value) {
242 $this->validateType($value);
245 return $this->normalizeValue($value);
249 * Normalizes the value before any other normalization is applied.
253 * @return $value The normalized array value
255 protected function preNormalize($value)
261 * Returns parent node for this node.
263 * @return NodeInterface|null
265 public function getParent()
267 return $this->parent
;
273 final public function finalize($value)
275 $this->validateType($value);
277 $value = $this->finalizeValue($value);
279 // Perform validation on the final value if a closure has been set.
280 // The closure is also allowed to return another value.
281 foreach ($this->finalValidationClosures
as $closure) {
283 $value = $closure($value);
284 } catch (Exception
$e) {
286 } catch (\Exception
$e) {
287 throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e);
295 * Validates the type of a Node.
297 * @param mixed $value The value to validate
299 * @throws InvalidTypeException when the value is invalid
301 abstract protected function validateType($value);
304 * Normalizes the value.
306 * @param mixed $value The value to normalize
308 * @return mixed The normalized value
310 abstract protected function normalizeValue($value);
313 * Merges two values together.
315 * @param mixed $leftSide
316 * @param mixed $rightSide
318 * @return mixed The merged value
320 abstract protected function mergeValues($leftSide, $rightSide);
325 * @param mixed $value The value to finalize
327 * @return mixed The finalized value
329 abstract protected function finalizeValue($value);