Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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