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 $deprecationMessage = null;
33 protected $equivalentValues = array();
34 protected $attributes = array();
37 * @param string|null $name The name of the node
38 * @param NodeInterface|null $parent The parent of this node
40 * @throws \InvalidArgumentException if the name contains a period
42 public function __construct($name, NodeInterface $parent = null)
44 if (false !== strpos($name = (string) $name, '.')) {
45 throw new \InvalidArgumentException('The name must not contain ".".');
49 $this->parent = $parent;
52 public function setAttribute($key, $value)
54 $this->attributes[$key] = $value;
57 public function getAttribute($key, $default = null)
59 return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
62 public function hasAttribute($key)
64 return isset($this->attributes[$key]);
67 public function getAttributes()
69 return $this->attributes;
72 public function setAttributes(array $attributes)
74 $this->attributes = $attributes;
77 public function removeAttribute($key)
79 unset($this->attributes[$key]);
83 * Sets an info message.
87 public function setInfo($info)
89 $this->setAttribute('info', $info);
93 * Returns info message.
95 * @return string The info text
97 public function getInfo()
99 return $this->getAttribute('info');
103 * Sets the example configuration for this node.
105 * @param string|array $example
107 public function setExample($example)
109 $this->setAttribute('example', $example);
113 * Retrieves the example configuration for this node.
115 * @return string|array The example
117 public function getExample()
119 return $this->getAttribute('example');
123 * Adds an equivalent value.
125 * @param mixed $originalValue
126 * @param mixed $equivalentValue
128 public function addEquivalentValue($originalValue, $equivalentValue)
130 $this->equivalentValues[] = array($originalValue, $equivalentValue);
134 * Set this node as required.
136 * @param bool $boolean Required node
138 public function setRequired($boolean)
140 $this->required = (bool) $boolean;
144 * Sets this node as deprecated.
146 * You can use %node% and %path% placeholders in your message to display,
147 * respectively, the node name and its complete path.
149 * @param string|null $message Deprecated message
151 public function setDeprecated($message)
153 $this->deprecationMessage = $message;
157 * Sets if this node can be overridden.
161 public function setAllowOverwrite($allow)
163 $this->allowOverwrite = (bool) $allow;
167 * Sets the closures used for normalization.
169 * @param \Closure[] $closures An array of Closures used for normalization
171 public function setNormalizationClosures(array $closures)
173 $this->normalizationClosures = $closures;
177 * Sets the closures used for final validation.
179 * @param \Closure[] $closures An array of Closures used for final validation
181 public function setFinalValidationClosures(array $closures)
183 $this->finalValidationClosures = $closures;
189 public function isRequired()
191 return $this->required;
195 * Checks if this node is deprecated.
199 public function isDeprecated()
201 return null !== $this->deprecationMessage;
205 * Returns the deprecated message.
207 * @param string $node the configuration node name
208 * @param string $path the path of the node
212 public function getDeprecationMessage($node, $path)
214 return strtr($this->deprecationMessage, array('%node%' => $node, '%path%' => $path));
220 public function getName()
228 public function getPath()
232 if (null !== $this->parent) {
233 $path = $this->parent->getPath().'.'.$path;
242 final public function merge($leftSide, $rightSide)
244 if (!$this->allowOverwrite) {
245 throw new ForbiddenOverwriteException(sprintf('Configuration path "%s" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one configuration section.', $this->getPath()));
248 $this->validateType($leftSide);
249 $this->validateType($rightSide);
251 return $this->mergeValues($leftSide, $rightSide);
257 final public function normalize($value)
259 $value = $this->preNormalize($value);
261 // run custom normalization closures
262 foreach ($this->normalizationClosures as $closure) {
263 $value = $closure($value);
266 // replace value with their equivalent
267 foreach ($this->equivalentValues as $data) {
268 if ($data[0] === $value) {
274 $this->validateType($value);
277 return $this->normalizeValue($value);
281 * Normalizes the value before any other normalization is applied.
285 * @return $value The normalized array value
287 protected function preNormalize($value)
293 * Returns parent node for this node.
295 * @return NodeInterface|null
297 public function getParent()
299 return $this->parent;
305 final public function finalize($value)
307 $this->validateType($value);
309 $value = $this->finalizeValue($value);
311 // Perform validation on the final value if a closure has been set.
312 // The closure is also allowed to return another value.
313 foreach ($this->finalValidationClosures as $closure) {
315 $value = $closure($value);
316 } catch (Exception $e) {
318 } catch (\Exception $e) {
319 throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e);
327 * Validates the type of a Node.
329 * @param mixed $value The value to validate
331 * @throws InvalidTypeException when the value is invalid
333 abstract protected function validateType($value);
336 * Normalizes the value.
338 * @param mixed $value The value to normalize
340 * @return mixed The normalized value
342 abstract protected function normalizeValue($value);
345 * Merges two values together.
347 * @param mixed $leftSide
348 * @param mixed $rightSide
350 * @return mixed The merged value
352 abstract protected function mergeValues($leftSide, $rightSide);
357 * @param mixed $value The value to finalize
359 * @return mixed The finalized value
361 abstract protected function finalizeValue($value);