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

PrototypedArrayNode.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 10.10 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\DuplicateKeyException;
 016  use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
 017  use Symfony\Component\Config\Definition\Exception\Exception;
 018   
 019  /**
 020   * Represents a prototyped Array node in the config tree.
 021   *
 022   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 023   */
 024  class PrototypedArrayNode extends ArrayNode
 025  {
 026      protected $prototype;
 027      protected $keyAttribute;
 028      protected $removeKeyAttribute;
 029      protected $minNumberOfElements;
 030      protected $defaultValue;
 031      protected $defaultChildren;
 032   
 033      /**
 034       * Constructor.
 035       *
 036       * @param string        $name   The Node's name
 037       * @param NodeInterface $parent The node parent
 038       */
 039      public function __construct($name, NodeInterface $parent = null)
 040      {
 041          parent::__construct($name, $parent);
 042   
 043          $this->minNumberOfElements = 0;
 044          $this->defaultValue = array();
 045      }
 046   
 047      /**
 048       * Sets the minimum number of elements that a prototype based node must
 049       * contain. By default this is zero, meaning no elements.
 050       *
 051       * @param int     $number
 052       */
 053      public function setMinNumberOfElements($number)
 054      {
 055          $this->minNumberOfElements = $number;
 056      }
 057   
 058      /**
 059       * Sets the attribute which value is to be used as key.
 060       *
 061       * This is useful when you have an indexed array that should be an
 062       * associative array. You can select an item from within the array
 063       * to be the key of the particular item. For example, if "id" is the
 064       * "key", then:
 065       *
 066       *     array(
 067       *         array('id' => 'my_name', 'foo' => 'bar'),
 068       *     );
 069       *
 070       *  becomes
 071       *
 072       *      array(
 073       *          'my_name' => array('foo' => 'bar'),
 074       *      );
 075       *
 076       * If you'd like "'id' => 'my_name'" to still be present in the resulting
 077       * array, then you can set the second argument of this method to false.
 078       *
 079       * @param string  $attribute The name of the attribute which value is to be used as a key
 080       * @param bool    $remove    Whether or not to remove the key
 081       */
 082      public function setKeyAttribute($attribute, $remove = true)
 083      {
 084          $this->keyAttribute = $attribute;
 085          $this->removeKeyAttribute = $remove;
 086      }
 087   
 088      /**
 089       * Retrieves the name of the attribute which value should be used as key.
 090       *
 091       * @return string The name of the attribute
 092       */
 093      public function getKeyAttribute()
 094      {
 095          return $this->keyAttribute;
 096      }
 097   
 098      /**
 099       * Sets the default value of this node.
 100       *
 101       * @param string $value
 102       *
 103       * @throws \InvalidArgumentException if the default value is not an array
 104       */
 105      public function setDefaultValue($value)
 106      {
 107          if (!is_array($value)) {
 108              throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.');
 109          }
 110   
 111          $this->defaultValue = $value;
 112      }
 113   
 114      /**
 115       * Checks if the node has a default value.
 116       *
 117       * @return bool
 118       */
 119      public function hasDefaultValue()
 120      {
 121          return true;
 122      }
 123   
 124      /**
 125       * Adds default children when none are set.
 126       *
 127       * @param int|string|array|null     $children The number of children|The child name|The children names to be added
 128       */
 129      public function setAddChildrenIfNoneSet($children = array('defaults'))
 130      {
 131          if (null === $children) {
 132              $this->defaultChildren = array('defaults');
 133          } else {
 134              $this->defaultChildren = is_integer($children) && $children > 0 ? range(1, $children) : (array) $children;
 135          }
 136      }
 137   
 138      /**
 139       * Retrieves the default value.
 140       *
 141       * The default value could be either explicited or derived from the prototype
 142       * default value.
 143       *
 144       * @return array The default value
 145       */
 146      public function getDefaultValue()
 147      {
 148          if (null !== $this->defaultChildren) {
 149              $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array();
 150              $defaults = array();
 151              foreach (array_values($this->defaultChildren) as $i => $name) {
 152                  $defaults[null === $this->keyAttribute ? $i : $name] = $default;
 153              }
 154   
 155              return $defaults;
 156          }
 157   
 158          return $this->defaultValue;
 159      }
 160   
 161      /**
 162       * Sets the node prototype.
 163       *
 164       * @param PrototypeNodeInterface $node
 165       */
 166      public function setPrototype(PrototypeNodeInterface $node)
 167      {
 168          $this->prototype = $node;
 169      }
 170   
 171      /**
 172       * Retrieves the prototype
 173       *
 174       * @return PrototypeNodeInterface The prototype
 175       */
 176      public function getPrototype()
 177      {
 178          return $this->prototype;
 179      }
 180   
 181      /**
 182       * Disable adding concrete children for prototyped nodes.
 183       *
 184       * @param NodeInterface $node The child node to add
 185       *
 186       * @throws Exception
 187       */
 188      public function addChild(NodeInterface $node)
 189      {
 190          throw new Exception('A prototyped array node can not have concrete children.');
 191      }
 192   
 193      /**
 194       * Finalizes the value of this node.
 195       *
 196       * @param mixed $value
 197       *
 198       * @return mixed The finalized value
 199       *
 200       * @throws UnsetKeyException
 201       * @throws InvalidConfigurationException if the node doesn't have enough children
 202       */
 203      protected function finalizeValue($value)
 204      {
 205          if (false === $value) {
 206              $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
 207              throw new UnsetKeyException($msg);
 208          }
 209   
 210          foreach ($value as $k => $v) {
 211              $this->prototype->setName($k);
 212              try {
 213                  $value[$k] = $this->prototype->finalize($v);
 214              } catch (UnsetKeyException $unset) {
 215                  unset($value[$k]);
 216              }
 217          }
 218   
 219          if (count($value) < $this->minNumberOfElements) {
 220              $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements);
 221              $ex = new InvalidConfigurationException($msg);
 222              $ex->setPath($this->getPath());
 223   
 224              throw $ex;
 225          }
 226   
 227          return $value;
 228      }
 229   
 230      /**
 231       * Normalizes the value.
 232       *
 233       * @param mixed $value The value to normalize
 234       *
 235       * @return mixed The normalized value
 236       *
 237       * @throws InvalidConfigurationException
 238       * @throws DuplicateKeyException
 239       */
 240      protected function normalizeValue($value)
 241      {
 242          if (false === $value) {
 243              return $value;
 244          }
 245   
 246          $value = $this->remapXml($value);
 247   
 248          $isAssoc = array_keys($value) !== range(0, count($value) -1);
 249          $normalized = array();
 250          foreach ($value as $k => $v) {
 251              if (null !== $this->keyAttribute && is_array($v)) {
 252                  if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) {
 253                      $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath());
 254                      $ex = new InvalidConfigurationException($msg);
 255                      $ex->setPath($this->getPath());
 256   
 257                      throw $ex;
 258                  } elseif (isset($v[$this->keyAttribute])) {
 259                      $k = $v[$this->keyAttribute];
 260   
 261                      // remove the key attribute when required
 262                      if ($this->removeKeyAttribute) {
 263                          unset($v[$this->keyAttribute]);
 264                      }
 265   
 266                      // if only "value" is left
 267                      if (1 == count($v) && isset($v['value'])) {
 268                          $v = $v['value'];
 269                      }
 270                  }
 271   
 272                  if (array_key_exists($k, $normalized)) {
 273                      $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath());
 274                      $ex = new DuplicateKeyException($msg);
 275                      $ex->setPath($this->getPath());
 276   
 277                      throw $ex;
 278                  }
 279              }
 280   
 281              $this->prototype->setName($k);
 282              if (null !== $this->keyAttribute || $isAssoc) {
 283                  $normalized[$k] = $this->prototype->normalize($v);
 284              } else {
 285                  $normalized[] = $this->prototype->normalize($v);
 286              }
 287          }
 288   
 289          return $normalized;
 290      }
 291   
 292      /**
 293       * Merges values together.
 294       *
 295       * @param mixed $leftSide  The left side to merge.
 296       * @param mixed $rightSide The right side to merge.
 297       *
 298       * @return mixed The merged values
 299       *
 300       * @throws InvalidConfigurationException
 301       * @throws \RuntimeException
 302       */
 303      protected function mergeValues($leftSide, $rightSide)
 304      {
 305          if (false === $rightSide) {
 306              // if this is still false after the last config has been merged the
 307              // finalization pass will take care of removing this key entirely
 308              return false;
 309          }
 310   
 311          if (false === $leftSide || !$this->performDeepMerging) {
 312              return $rightSide;
 313          }
 314   
 315          foreach ($rightSide as $k => $v) {
 316              // prototype, and key is irrelevant, so simply append the element
 317              if (null === $this->keyAttribute) {
 318                  $leftSide[] = $v;
 319                  continue;
 320              }
 321   
 322              // no conflict
 323              if (!array_key_exists($k, $leftSide)) {
 324                  if (!$this->allowNewKeys) {
 325                      $ex = new InvalidConfigurationException(sprintf(
 326                          'You are not allowed to define new elements for path "%s". '.
 327                          'Please define all elements for this path in one config file.',
 328                          $this->getPath()
 329                      ));
 330                      $ex->setPath($this->getPath());
 331   
 332                      throw $ex;
 333                  }
 334   
 335                  $leftSide[$k] = $v;
 336                  continue;
 337              }
 338   
 339              $this->prototype->setName($k);
 340              $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v);
 341          }
 342   
 343          return $leftSide;
 344      }
 345  }
 346