forked from GNUsocial/gnu-social
		
	
		
			
	
	
		
			326 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			326 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
|   | <?php | ||
|  | 
 | ||
|  | /* | ||
|  |  * This file is part of the Symfony package. | ||
|  |  * | ||
|  |  * (c) Fabien Potencier <fabien@symfony.com> | ||
|  |  * | ||
|  |  * For the full copyright and license information, please view the LICENSE | ||
|  |  * file that was distributed with this source code. | ||
|  |  */ | ||
|  | 
 | ||
|  | namespace Symfony\Component\Config\Definition; | ||
|  | 
 | ||
|  | use Symfony\Component\Config\Definition\Exception\Exception; | ||
|  | use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; | ||
|  | use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; | ||
|  | use Symfony\Component\Config\Definition\Exception\InvalidTypeException; | ||
|  | 
 | ||
|  | /** | ||
|  |  * The base node class. | ||
|  |  * | ||
|  |  * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
|  |  */ | ||
|  | abstract class BaseNode implements NodeInterface | ||
|  | { | ||
|  |     protected $name; | ||
|  |     protected $parent; | ||
|  |     protected $normalizationClosures = array(); | ||
|  |     protected $finalValidationClosures = array(); | ||
|  |     protected $allowOverwrite = true; | ||
|  |     protected $required = false; | ||
|  |     protected $equivalentValues = array(); | ||
|  |     protected $attributes = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @param string|null        $name   The name of the node | ||
|  |      * @param NodeInterface|null $parent The parent of this node | ||
|  |      * | ||
|  |      * @throws \InvalidArgumentException if the name contains a period | ||
|  |      */ | ||
|  |     public function __construct($name, NodeInterface $parent = null) | ||
|  |     { | ||
|  |         if (false !== strpos($name = (string) $name, '.')) { | ||
|  |             throw new \InvalidArgumentException('The name must not contain ".".'); | ||
|  |         } | ||
|  | 
 | ||
|  |         $this->name = $name; | ||
|  |         $this->parent = $parent; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function setAttribute($key, $value) | ||
|  |     { | ||
|  |         $this->attributes[$key] = $value; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function getAttribute($key, $default = null) | ||
|  |     { | ||
|  |         return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function hasAttribute($key) | ||
|  |     { | ||
|  |         return isset($this->attributes[$key]); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function getAttributes() | ||
|  |     { | ||
|  |         return $this->attributes; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function setAttributes(array $attributes) | ||
|  |     { | ||
|  |         $this->attributes = $attributes; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function removeAttribute($key) | ||
|  |     { | ||
|  |         unset($this->attributes[$key]); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sets an info message. | ||
|  |      * | ||
|  |      * @param string $info | ||
|  |      */ | ||
|  |     public function setInfo($info) | ||
|  |     { | ||
|  |         $this->setAttribute('info', $info); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Returns info message. | ||
|  |      * | ||
|  |      * @return string The info text | ||
|  |      */ | ||
|  |     public function getInfo() | ||
|  |     { | ||
|  |         return $this->getAttribute('info'); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sets the example configuration for this node. | ||
|  |      * | ||
|  |      * @param string|array $example | ||
|  |      */ | ||
|  |     public function setExample($example) | ||
|  |     { | ||
|  |         $this->setAttribute('example', $example); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Retrieves the example configuration for this node. | ||
|  |      * | ||
|  |      * @return string|array The example | ||
|  |      */ | ||
|  |     public function getExample() | ||
|  |     { | ||
|  |         return $this->getAttribute('example'); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Adds an equivalent value. | ||
|  |      * | ||
|  |      * @param mixed $originalValue | ||
|  |      * @param mixed $equivalentValue | ||
|  |      */ | ||
|  |     public function addEquivalentValue($originalValue, $equivalentValue) | ||
|  |     { | ||
|  |         $this->equivalentValues[] = array($originalValue, $equivalentValue); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Set this node as required. | ||
|  |      * | ||
|  |      * @param bool $boolean Required node | ||
|  |      */ | ||
|  |     public function setRequired($boolean) | ||
|  |     { | ||
|  |         $this->required = (bool) $boolean; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sets if this node can be overridden. | ||
|  |      * | ||
|  |      * @param bool $allow | ||
|  |      */ | ||
|  |     public function setAllowOverwrite($allow) | ||
|  |     { | ||
|  |         $this->allowOverwrite = (bool) $allow; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sets the closures used for normalization. | ||
|  |      * | ||
|  |      * @param \Closure[] $closures An array of Closures used for normalization | ||
|  |      */ | ||
|  |     public function setNormalizationClosures(array $closures) | ||
|  |     { | ||
|  |         $this->normalizationClosures = $closures; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Sets the closures used for final validation. | ||
|  |      * | ||
|  |      * @param \Closure[] $closures An array of Closures used for final validation | ||
|  |      */ | ||
|  |     public function setFinalValidationClosures(array $closures) | ||
|  |     { | ||
|  |         $this->finalValidationClosures = $closures; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     public function isRequired() | ||
|  |     { | ||
|  |         return $this->required; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     public function getName() | ||
|  |     { | ||
|  |         return $this->name; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     public function getPath() | ||
|  |     { | ||
|  |         $path = $this->name; | ||
|  | 
 | ||
|  |         if (null !== $this->parent) { | ||
|  |             $path = $this->parent->getPath().'.'.$path; | ||
|  |         } | ||
|  | 
 | ||
|  |         return $path; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     final public function merge($leftSide, $rightSide) | ||
|  |     { | ||
|  |         if (!$this->allowOverwrite) { | ||
|  |             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())); | ||
|  |         } | ||
|  | 
 | ||
|  |         $this->validateType($leftSide); | ||
|  |         $this->validateType($rightSide); | ||
|  | 
 | ||
|  |         return $this->mergeValues($leftSide, $rightSide); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     final public function normalize($value) | ||
|  |     { | ||
|  |         $value = $this->preNormalize($value); | ||
|  | 
 | ||
|  |         // run custom normalization closures
 | ||
|  |         foreach ($this->normalizationClosures as $closure) { | ||
|  |             $value = $closure($value); | ||
|  |         } | ||
|  | 
 | ||
|  |         // replace value with their equivalent
 | ||
|  |         foreach ($this->equivalentValues as $data) { | ||
|  |             if ($data[0] === $value) { | ||
|  |                 $value = $data[1]; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // validate type
 | ||
|  |         $this->validateType($value); | ||
|  | 
 | ||
|  |         // normalize value
 | ||
|  |         return $this->normalizeValue($value); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Normalizes the value before any other normalization is applied. | ||
|  |      * | ||
|  |      * @param $value | ||
|  |      * | ||
|  |      * @return The normalized array value | ||
|  |      */ | ||
|  |     protected function preNormalize($value) | ||
|  |     { | ||
|  |         return $value; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Returns parent node for this node. | ||
|  |      * | ||
|  |      * @return NodeInterface|null | ||
|  |      */ | ||
|  |     public function getParent() | ||
|  |     { | ||
|  |         return $this->parent; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * {@inheritdoc} | ||
|  |      */ | ||
|  |     final public function finalize($value) | ||
|  |     { | ||
|  |         $this->validateType($value); | ||
|  | 
 | ||
|  |         $value = $this->finalizeValue($value); | ||
|  | 
 | ||
|  |         // Perform validation on the final value if a closure has been set.
 | ||
|  |         // The closure is also allowed to return another value.
 | ||
|  |         foreach ($this->finalValidationClosures as $closure) { | ||
|  |             try { | ||
|  |                 $value = $closure($value); | ||
|  |             } catch (Exception $e) { | ||
|  |                 throw $e; | ||
|  |             } catch (\Exception $e) { | ||
|  |                 throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         return $value; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Validates the type of a Node. | ||
|  |      * | ||
|  |      * @param mixed $value The value to validate | ||
|  |      * | ||
|  |      * @throws InvalidTypeException when the value is invalid | ||
|  |      */ | ||
|  |     abstract protected function validateType($value); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Normalizes the value. | ||
|  |      * | ||
|  |      * @param mixed $value The value to normalize | ||
|  |      * | ||
|  |      * @return mixed The normalized value | ||
|  |      */ | ||
|  |     abstract protected function normalizeValue($value); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Merges two values together. | ||
|  |      * | ||
|  |      * @param mixed $leftSide | ||
|  |      * @param mixed $rightSide | ||
|  |      * | ||
|  |      * @return mixed The merged value | ||
|  |      */ | ||
|  |     abstract protected function mergeValues($leftSide, $rightSide); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Finalizes a value. | ||
|  |      * | ||
|  |      * @param mixed $value The value to finalize | ||
|  |      * | ||
|  |      * @return mixed The finalized value | ||
|  |      */ | ||
|  |     abstract protected function finalizeValue($value); | ||
|  | } |