Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

ArrayNode.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 10.96 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\Config\Definition;
 013   
 014  use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
 015  use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
 016  use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
 017   
 018  /**
 019   * Represents an Array node in the config tree.
 020   *
 021   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 022   */
 023  class ArrayNode extends BaseNode implements PrototypeNodeInterface
 024  {
 025      protected $xmlRemappings;
 026      protected $children;
 027      protected $allowFalse;
 028      protected $allowNewKeys;
 029      protected $addIfNotSet;
 030      protected $performDeepMerging;
 031      protected $ignoreExtraKeys;
 032      protected $normalizeKeys;
 033   
 034      /**
 035       * Constructor.
 036       *
 037       * @param string        $name   The Node's name
 038       * @param NodeInterface $parent The node parent
 039       */
 040      public function __construct($name, NodeInterface $parent = null)
 041      {
 042          parent::__construct($name, $parent);
 043   
 044          $this->children = array();
 045          $this->xmlRemappings = array();
 046          $this->removeKeyAttribute = true;
 047          $this->allowFalse = false;
 048          $this->addIfNotSet = false;
 049          $this->allowNewKeys = true;
 050          $this->performDeepMerging = true;
 051          $this->normalizeKeys = true;
 052      }
 053   
 054      public function setNormalizeKeys($normalizeKeys)
 055      {
 056          $this->normalizeKeys = (bool) $normalizeKeys;
 057      }
 058   
 059      /**
 060       * Normalizes keys between the different configuration formats.
 061       *
 062       * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
 063       * After running this method, all keys are normalized to foo_bar.
 064       *
 065       * If you have a mixed key like foo-bar_moo, it will not be altered.
 066       * The key will also not be altered if the target key already exists.
 067       *
 068       * @param mixed $value
 069       *
 070       * @return array The value with normalized keys
 071       */
 072      protected function preNormalize($value)
 073      {
 074          if (!$this->normalizeKeys || !is_array($value)) {
 075              return $value;
 076          }
 077   
 078          foreach ($value as $k => $v) {
 079              if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
 080                  $value[$normalizedKey] = $v;
 081                  unset($value[$k]);
 082              }
 083          }
 084   
 085          return $value;
 086      }
 087   
 088      /**
 089       * Retrieves the children of this node.
 090       *
 091       * @return array The children
 092       */
 093      public function getChildren()
 094      {
 095          return $this->children;
 096      }
 097   
 098      /**
 099       * Sets the xml remappings that should be performed.
 100       *
 101       * @param array $remappings an array of the form array(array(string, string))
 102       */
 103      public function setXmlRemappings(array $remappings)
 104      {
 105          $this->xmlRemappings = $remappings;
 106      }
 107   
 108      /**
 109       * Sets whether to add default values for this array if it has not been
 110       * defined in any of the configuration files.
 111       *
 112       * @param bool    $boolean
 113       */
 114      public function setAddIfNotSet($boolean)
 115      {
 116          $this->addIfNotSet = (bool) $boolean;
 117      }
 118   
 119      /**
 120       * Sets whether false is allowed as value indicating that the array should be unset.
 121       *
 122       * @param bool    $allow
 123       */
 124      public function setAllowFalse($allow)
 125      {
 126          $this->allowFalse = (bool) $allow;
 127      }
 128   
 129      /**
 130       * Sets whether new keys can be defined in subsequent configurations.
 131       *
 132       * @param bool    $allow
 133       */
 134      public function setAllowNewKeys($allow)
 135      {
 136          $this->allowNewKeys = (bool) $allow;
 137      }
 138   
 139      /**
 140       * Sets if deep merging should occur.
 141       *
 142       * @param bool    $boolean
 143       */
 144      public function setPerformDeepMerging($boolean)
 145      {
 146          $this->performDeepMerging = (bool) $boolean;
 147      }
 148   
 149      /**
 150       * Whether extra keys should just be ignore without an exception.
 151       *
 152       * @param bool    $boolean To allow extra keys
 153       */
 154      public function setIgnoreExtraKeys($boolean)
 155      {
 156          $this->ignoreExtraKeys = (bool) $boolean;
 157      }
 158   
 159      /**
 160       * Sets the node Name.
 161       *
 162       * @param string $name The node's name
 163       */
 164      public function setName($name)
 165      {
 166          $this->name = $name;
 167      }
 168   
 169      /**
 170       * Checks if the node has a default value.
 171       *
 172       * @return bool
 173       */
 174      public function hasDefaultValue()
 175      {
 176          return $this->addIfNotSet;
 177      }
 178   
 179      /**
 180       * Retrieves the default value.
 181       *
 182       * @return array The default value
 183       *
 184       * @throws \RuntimeException if the node has no default value
 185       */
 186      public function getDefaultValue()
 187      {
 188          if (!$this->hasDefaultValue()) {
 189              throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
 190          }
 191   
 192          $defaults = array();
 193          foreach ($this->children as $name => $child) {
 194              if ($child->hasDefaultValue()) {
 195                  $defaults[$name] = $child->getDefaultValue();
 196              }
 197          }
 198   
 199          return $defaults;
 200      }
 201   
 202      /**
 203       * Adds a child node.
 204       *
 205       * @param NodeInterface $node The child node to add
 206       *
 207       * @throws \InvalidArgumentException when the child node has no name
 208       * @throws \InvalidArgumentException when the child node's name is not unique
 209       */
 210      public function addChild(NodeInterface $node)
 211      {
 212          $name = $node->getName();
 213          if (!strlen($name)) {
 214              throw new \InvalidArgumentException('Child nodes must be named.');
 215          }
 216          if (isset($this->children[$name])) {
 217              throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name));
 218          }
 219   
 220          $this->children[$name] = $node;
 221      }
 222   
 223      /**
 224       * Finalizes the value of this node.
 225       *
 226       * @param mixed $value
 227       *
 228       * @return mixed The finalised value
 229       *
 230       * @throws UnsetKeyException
 231       * @throws InvalidConfigurationException if the node doesn't have enough children
 232       */
 233      protected function finalizeValue($value)
 234      {
 235          if (false === $value) {
 236              $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
 237              throw new UnsetKeyException($msg);
 238          }
 239   
 240          foreach ($this->children as $name => $child) {
 241              if (!array_key_exists($name, $value)) {
 242                  if ($child->isRequired()) {
 243                      $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath());
 244                      $ex = new InvalidConfigurationException($msg);
 245                      $ex->setPath($this->getPath());
 246   
 247                      throw $ex;
 248                  }
 249   
 250                  if ($child->hasDefaultValue()) {
 251                      $value[$name] = $child->getDefaultValue();
 252                  }
 253   
 254                  continue;
 255              }
 256   
 257              try {
 258                  $value[$name] = $child->finalize($value[$name]);
 259              } catch (UnsetKeyException $unset) {
 260                  unset($value[$name]);
 261              }
 262          }
 263   
 264          return $value;
 265      }
 266   
 267      /**
 268       * Validates the type of the value.
 269       *
 270       * @param mixed $value
 271       *
 272       * @throws InvalidTypeException
 273       */
 274      protected function validateType($value)
 275      {
 276          if (!is_array($value) && (!$this->allowFalse || false !== $value)) {
 277              $ex = new InvalidTypeException(sprintf(
 278                  'Invalid type for path "%s". Expected array, but got %s',
 279                  $this->getPath(),
 280                  gettype($value)
 281              ));
 282              $ex->setPath($this->getPath());
 283   
 284              throw $ex;
 285          }
 286      }
 287   
 288      /**
 289       * Normalizes the value.
 290       *
 291       * @param mixed $value The value to normalize
 292       *
 293       * @return mixed The normalized value
 294       *
 295       * @throws InvalidConfigurationException
 296       */
 297      protected function normalizeValue($value)
 298      {
 299          if (false === $value) {
 300              return $value;
 301          }
 302   
 303          $value = $this->remapXml($value);
 304   
 305          $normalized = array();
 306          foreach ($value as $name => $val) {
 307              if (isset($this->children[$name])) {
 308                  $normalized[$name] = $this->children[$name]->normalize($val);
 309                  unset($value[$name]);
 310              }
 311          }
 312   
 313          // if extra fields are present, throw exception
 314          if (count($value) && !$this->ignoreExtraKeys) {
 315              $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath());
 316              $ex = new InvalidConfigurationException($msg);
 317              $ex->setPath($this->getPath());
 318   
 319              throw $ex;
 320          }
 321   
 322          return $normalized;
 323      }
 324   
 325      /**
 326       * Remaps multiple singular values to a single plural value.
 327       *
 328       * @param array $value The source values
 329       *
 330       * @return array The remapped values
 331       */
 332      protected function remapXml($value)
 333      {
 334          foreach ($this->xmlRemappings as $transformation) {
 335              list($singular, $plural) = $transformation;
 336   
 337              if (!isset($value[$singular])) {
 338                  continue;
 339              }
 340   
 341              $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
 342              unset($value[$singular]);
 343          }
 344   
 345          return $value;
 346      }
 347   
 348      /**
 349       * Merges values together.
 350       *
 351       * @param mixed $leftSide  The left side to merge.
 352       * @param mixed $rightSide The right side to merge.
 353       *
 354       * @return mixed The merged values
 355       *
 356       * @throws InvalidConfigurationException
 357       * @throws \RuntimeException
 358       */
 359      protected function mergeValues($leftSide, $rightSide)
 360      {
 361          if (false === $rightSide) {
 362              // if this is still false after the last config has been merged the
 363              // finalization pass will take care of removing this key entirely
 364              return false;
 365          }
 366   
 367          if (false === $leftSide || !$this->performDeepMerging) {
 368              return $rightSide;
 369          }
 370   
 371          foreach ($rightSide as $k => $v) {
 372              // no conflict
 373              if (!array_key_exists($k, $leftSide)) {
 374                  if (!$this->allowNewKeys) {
 375                      $ex = new InvalidConfigurationException(sprintf(
 376                          'You are not allowed to define new elements for path "%s". '
 377                         .'Please define all elements for this path in one config file. '
 378                         .'If you are trying to overwrite an element, make sure you redefine it '
 379                         .'with the same name.',
 380                          $this->getPath()
 381                      ));
 382                      $ex->setPath($this->getPath());
 383   
 384                      throw $ex;
 385                  }
 386   
 387                  $leftSide[$k] = $v;
 388                  continue;
 389              }
 390   
 391              if (!isset($this->children[$k])) {
 392                  throw new \RuntimeException('merge() expects a normalized config array.');
 393              }
 394   
 395              $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
 396          }
 397   
 398          return $leftSide;
 399      }
 400  }
 401