[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/config/Symfony/Component/Config/Definition/ -> ArrayNode.php (source)

   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\InvalidConfigurationException;
  15  use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
  16  use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
  17  
  18  /**
  19   * Represents an Array node in the config tree.
  20   *
  21   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  22   */
  23  class ArrayNode extends BaseNode implements PrototypeNodeInterface
  24  {
  25      protected $xmlRemappings;
  26      protected $children;
  27      protected $allowFalse;
  28      protected $allowNewKeys;
  29      protected $addIfNotSet;
  30      protected $performDeepMerging;
  31      protected $ignoreExtraKeys;
  32      protected $normalizeKeys;
  33  
  34      /**
  35       * Constructor.
  36       *
  37       * @param string        $name   The Node's name
  38       * @param NodeInterface $parent The node parent
  39       */
  40      public function __construct($name, NodeInterface $parent = null)
  41      {
  42          parent::__construct($name, $parent);
  43  
  44          $this->children = array();
  45          $this->xmlRemappings = array();
  46          $this->removeKeyAttribute = true;
  47          $this->allowFalse = false;
  48          $this->addIfNotSet = false;
  49          $this->allowNewKeys = true;
  50          $this->performDeepMerging = true;
  51          $this->normalizeKeys = true;
  52      }
  53  
  54      public function setNormalizeKeys($normalizeKeys)
  55      {
  56          $this->normalizeKeys = (bool) $normalizeKeys;
  57      }
  58  
  59      /**
  60       * Normalizes keys between the different configuration formats.
  61       *
  62       * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
  63       * After running this method, all keys are normalized to foo_bar.
  64       *
  65       * If you have a mixed key like foo-bar_moo, it will not be altered.
  66       * The key will also not be altered if the target key already exists.
  67       *
  68       * @param mixed $value
  69       *
  70       * @return array The value with normalized keys
  71       */
  72      protected function preNormalize($value)
  73      {
  74          if (!$this->normalizeKeys || !is_array($value)) {
  75              return $value;
  76          }
  77  
  78          $normalized = array();
  79  
  80          foreach ($value as $k => $v) {
  81              if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
  82                  $normalized[$normalizedKey] = $v;
  83              } else {
  84                  $normalized[$k] = $v;
  85              }
  86          }
  87  
  88          return $normalized;
  89      }
  90  
  91      /**
  92       * Retrieves the children of this node.
  93       *
  94       * @return array The children
  95       */
  96      public function getChildren()
  97      {
  98          return $this->children;
  99      }
 100  
 101      /**
 102       * Sets the xml remappings that should be performed.
 103       *
 104       * @param array $remappings an array of the form array(array(string, string))
 105       */
 106      public function setXmlRemappings(array $remappings)
 107      {
 108          $this->xmlRemappings = $remappings;
 109      }
 110  
 111      /**
 112       * Sets whether to add default values for this array if it has not been
 113       * defined in any of the configuration files.
 114       *
 115       * @param bool $boolean
 116       */
 117      public function setAddIfNotSet($boolean)
 118      {
 119          $this->addIfNotSet = (bool) $boolean;
 120      }
 121  
 122      /**
 123       * Sets whether false is allowed as value indicating that the array should be unset.
 124       *
 125       * @param bool $allow
 126       */
 127      public function setAllowFalse($allow)
 128      {
 129          $this->allowFalse = (bool) $allow;
 130      }
 131  
 132      /**
 133       * Sets whether new keys can be defined in subsequent configurations.
 134       *
 135       * @param bool $allow
 136       */
 137      public function setAllowNewKeys($allow)
 138      {
 139          $this->allowNewKeys = (bool) $allow;
 140      }
 141  
 142      /**
 143       * Sets if deep merging should occur.
 144       *
 145       * @param bool $boolean
 146       */
 147      public function setPerformDeepMerging($boolean)
 148      {
 149          $this->performDeepMerging = (bool) $boolean;
 150      }
 151  
 152      /**
 153       * Whether extra keys should just be ignore without an exception.
 154       *
 155       * @param bool $boolean To allow extra keys
 156       */
 157      public function setIgnoreExtraKeys($boolean)
 158      {
 159          $this->ignoreExtraKeys = (bool) $boolean;
 160      }
 161  
 162      /**
 163       * Sets the node Name.
 164       *
 165       * @param string $name The node's name
 166       */
 167      public function setName($name)
 168      {
 169          $this->name = $name;
 170      }
 171  
 172      /**
 173       * Checks if the node has a default value.
 174       *
 175       * @return bool
 176       */
 177      public function hasDefaultValue()
 178      {
 179          return $this->addIfNotSet;
 180      }
 181  
 182      /**
 183       * Retrieves the default value.
 184       *
 185       * @return array The default value
 186       *
 187       * @throws \RuntimeException if the node has no default value
 188       */
 189      public function getDefaultValue()
 190      {
 191          if (!$this->hasDefaultValue()) {
 192              throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
 193          }
 194  
 195          $defaults = array();
 196          foreach ($this->children as $name => $child) {
 197              if ($child->hasDefaultValue()) {
 198                  $defaults[$name] = $child->getDefaultValue();
 199              }
 200          }
 201  
 202          return $defaults;
 203      }
 204  
 205      /**
 206       * Adds a child node.
 207       *
 208       * @param NodeInterface $node The child node to add
 209       *
 210       * @throws \InvalidArgumentException when the child node has no name
 211       * @throws \InvalidArgumentException when the child node's name is not unique
 212       */
 213      public function addChild(NodeInterface $node)
 214      {
 215          $name = $node->getName();
 216          if (!strlen($name)) {
 217              throw new \InvalidArgumentException('Child nodes must be named.');
 218          }
 219          if (isset($this->children[$name])) {
 220              throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name));
 221          }
 222  
 223          $this->children[$name] = $node;
 224      }
 225  
 226      /**
 227       * Finalizes the value of this node.
 228       *
 229       * @param mixed $value
 230       *
 231       * @return mixed The finalised value
 232       *
 233       * @throws UnsetKeyException
 234       * @throws InvalidConfigurationException if the node doesn't have enough children
 235       */
 236      protected function finalizeValue($value)
 237      {
 238          if (false === $value) {
 239              $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
 240              throw new UnsetKeyException($msg);
 241          }
 242  
 243          foreach ($this->children as $name => $child) {
 244              if (!array_key_exists($name, $value)) {
 245                  if ($child->isRequired()) {
 246                      $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath());
 247                      $ex = new InvalidConfigurationException($msg);
 248                      $ex->setPath($this->getPath());
 249  
 250                      throw $ex;
 251                  }
 252  
 253                  if ($child->hasDefaultValue()) {
 254                      $value[$name] = $child->getDefaultValue();
 255                  }
 256  
 257                  continue;
 258              }
 259  
 260              try {
 261                  $value[$name] = $child->finalize($value[$name]);
 262              } catch (UnsetKeyException $e) {
 263                  unset($value[$name]);
 264              }
 265          }
 266  
 267          return $value;
 268      }
 269  
 270      /**
 271       * Validates the type of the value.
 272       *
 273       * @param mixed $value
 274       *
 275       * @throws InvalidTypeException
 276       */
 277      protected function validateType($value)
 278      {
 279          if (!is_array($value) && (!$this->allowFalse || false !== $value)) {
 280              $ex = new InvalidTypeException(sprintf(
 281                  'Invalid type for path "%s". Expected array, but got %s',
 282                  $this->getPath(),
 283                  gettype($value)
 284              ));
 285              $ex->setPath($this->getPath());
 286  
 287              throw $ex;
 288          }
 289      }
 290  
 291      /**
 292       * Normalizes the value.
 293       *
 294       * @param mixed $value The value to normalize
 295       *
 296       * @return mixed The normalized value
 297       *
 298       * @throws InvalidConfigurationException
 299       */
 300      protected function normalizeValue($value)
 301      {
 302          if (false === $value) {
 303              return $value;
 304          }
 305  
 306          $value = $this->remapXml($value);
 307  
 308          $normalized = array();
 309          foreach ($value as $name => $val) {
 310              if (isset($this->children[$name])) {
 311                  $normalized[$name] = $this->children[$name]->normalize($val);
 312                  unset($value[$name]);
 313              }
 314          }
 315  
 316          // if extra fields are present, throw exception
 317          if (count($value) && !$this->ignoreExtraKeys) {
 318              $msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath());
 319              $ex = new InvalidConfigurationException($msg);
 320              $ex->setPath($this->getPath());
 321  
 322              throw $ex;
 323          }
 324  
 325          return $normalized;
 326      }
 327  
 328      /**
 329       * Remaps multiple singular values to a single plural value.
 330       *
 331       * @param array $value The source values
 332       *
 333       * @return array The remapped values
 334       */
 335      protected function remapXml($value)
 336      {
 337          foreach ($this->xmlRemappings as $transformation) {
 338              list($singular, $plural) = $transformation;
 339  
 340              if (!isset($value[$singular])) {
 341                  continue;
 342              }
 343  
 344              $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
 345              unset($value[$singular]);
 346          }
 347  
 348          return $value;
 349      }
 350  
 351      /**
 352       * Merges values together.
 353       *
 354       * @param mixed $leftSide  The left side to merge.
 355       * @param mixed $rightSide The right side to merge.
 356       *
 357       * @return mixed The merged values
 358       *
 359       * @throws InvalidConfigurationException
 360       * @throws \RuntimeException
 361       */
 362      protected function mergeValues($leftSide, $rightSide)
 363      {
 364          if (false === $rightSide) {
 365              // if this is still false after the last config has been merged the
 366              // finalization pass will take care of removing this key entirely
 367              return false;
 368          }
 369  
 370          if (false === $leftSide || !$this->performDeepMerging) {
 371              return $rightSide;
 372          }
 373  
 374          foreach ($rightSide as $k => $v) {
 375              // no conflict
 376              if (!array_key_exists($k, $leftSide)) {
 377                  if (!$this->allowNewKeys) {
 378                      $ex = new InvalidConfigurationException(sprintf(
 379                          'You are not allowed to define new elements for path "%s". '
 380                         .'Please define all elements for this path in one config file. '
 381                         .'If you are trying to overwrite an element, make sure you redefine it '
 382                         .'with the same name.',
 383                          $this->getPath()
 384                      ));
 385                      $ex->setPath($this->getPath());
 386  
 387                      throw $ex;
 388                  }
 389  
 390                  $leftSide[$k] = $v;
 391                  continue;
 392              }
 393  
 394              if (!isset($this->children[$k])) {
 395                  throw new \RuntimeException('merge() expects a normalized config array.');
 396              }
 397  
 398              $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
 399          }
 400  
 401          return $leftSide;
 402      }
 403  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1