Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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

ArrayNodeDefinition.php

Zuletzt modifiziert: 01.05.2026, 11:28 - Dateigröße: 14.90 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\Builder;
 013   
 014  use Symfony\Component\Config\Definition\ArrayNode;
 015  use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
 016  use Symfony\Component\Config\Definition\PrototypedArrayNode;
 017   
 018  /**
 019   * This class provides a fluent interface for defining an array node.
 020   *
 021   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 022   */
 023  class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
 024  {
 025      protected $performDeepMerging = true;
 026      protected $ignoreExtraKeys = false;
 027      protected $removeExtraKeys = true;
 028      protected $children = [];
 029      protected $prototype;
 030      protected $atLeastOne = false;
 031      protected $allowNewKeys = true;
 032      protected $key;
 033      protected $removeKeyItem;
 034      protected $addDefaults = false;
 035      protected $addDefaultChildren = false;
 036      protected $nodeBuilder;
 037      protected $normalizeKeys = true;
 038   
 039      /**
 040       * {@inheritdoc}
 041       */
 042      public function __construct($name, NodeParentInterface $parent = null)
 043      {
 044          parent::__construct($name, $parent);
 045   
 046          $this->nullEquivalent = [];
 047          $this->trueEquivalent = [];
 048      }
 049   
 050      /**
 051       * {@inheritdoc}
 052       */
 053      public function setBuilder(NodeBuilder $builder)
 054      {
 055          $this->nodeBuilder = $builder;
 056      }
 057   
 058      /**
 059       * {@inheritdoc}
 060       */
 061      public function children()
 062      {
 063          return $this->getNodeBuilder();
 064      }
 065   
 066      /**
 067       * Sets a prototype for child nodes.
 068       *
 069       * @param string $type The type of node
 070       *
 071       * @return NodeDefinition
 072       */
 073      public function prototype($type)
 074      {
 075          return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
 076      }
 077   
 078      /**
 079       * @return VariableNodeDefinition
 080       */
 081      public function variablePrototype()
 082      {
 083          return $this->prototype('variable');
 084      }
 085   
 086      /**
 087       * @return ScalarNodeDefinition
 088       */
 089      public function scalarPrototype()
 090      {
 091          return $this->prototype('scalar');
 092      }
 093   
 094      /**
 095       * @return BooleanNodeDefinition
 096       */
 097      public function booleanPrototype()
 098      {
 099          return $this->prototype('boolean');
 100      }
 101   
 102      /**
 103       * @return IntegerNodeDefinition
 104       */
 105      public function integerPrototype()
 106      {
 107          return $this->prototype('integer');
 108      }
 109   
 110      /**
 111       * @return FloatNodeDefinition
 112       */
 113      public function floatPrototype()
 114      {
 115          return $this->prototype('float');
 116      }
 117   
 118      /**
 119       * @return ArrayNodeDefinition
 120       */
 121      public function arrayPrototype()
 122      {
 123          return $this->prototype('array');
 124      }
 125   
 126      /**
 127       * @return EnumNodeDefinition
 128       */
 129      public function enumPrototype()
 130      {
 131          return $this->prototype('enum');
 132      }
 133   
 134      /**
 135       * Adds the default value if the node is not set in the configuration.
 136       *
 137       * This method is applicable to concrete nodes only (not to prototype nodes).
 138       * If this function has been called and the node is not set during the finalization
 139       * phase, it's default value will be derived from its children default values.
 140       *
 141       * @return $this
 142       */
 143      public function addDefaultsIfNotSet()
 144      {
 145          $this->addDefaults = true;
 146   
 147          return $this;
 148      }
 149   
 150      /**
 151       * Adds children with a default value when none are defined.
 152       *
 153       * This method is applicable to prototype nodes only.
 154       *
 155       * @param int|string|array|null $children The number of children|The child name|The children names to be added
 156       *
 157       * @return $this
 158       */
 159      public function addDefaultChildrenIfNoneSet($children = null)
 160      {
 161          $this->addDefaultChildren = $children;
 162   
 163          return $this;
 164      }
 165   
 166      /**
 167       * Requires the node to have at least one element.
 168       *
 169       * This method is applicable to prototype nodes only.
 170       *
 171       * @return $this
 172       */
 173      public function requiresAtLeastOneElement()
 174      {
 175          $this->atLeastOne = true;
 176   
 177          return $this;
 178      }
 179   
 180      /**
 181       * Disallows adding news keys in a subsequent configuration.
 182       *
 183       * If used all keys have to be defined in the same configuration file.
 184       *
 185       * @return $this
 186       */
 187      public function disallowNewKeysInSubsequentConfigs()
 188      {
 189          $this->allowNewKeys = false;
 190   
 191          return $this;
 192      }
 193   
 194      /**
 195       * Sets a normalization rule for XML configurations.
 196       *
 197       * @param string $singular The key to remap
 198       * @param string $plural   The plural of the key for irregular plurals
 199       *
 200       * @return $this
 201       */
 202      public function fixXmlConfig($singular, $plural = null)
 203      {
 204          $this->normalization()->remap($singular, $plural);
 205   
 206          return $this;
 207      }
 208   
 209      /**
 210       * Sets the attribute which value is to be used as key.
 211       *
 212       * This is useful when you have an indexed array that should be an
 213       * associative array. You can select an item from within the array
 214       * to be the key of the particular item. For example, if "id" is the
 215       * "key", then:
 216       *
 217       *     [
 218       *         ['id' => 'my_name', 'foo' => 'bar'],
 219       *     ];
 220       *
 221       *   becomes
 222       *
 223       *     [
 224       *         'my_name' => ['foo' => 'bar'],
 225       *     ];
 226       *
 227       * If you'd like "'id' => 'my_name'" to still be present in the resulting
 228       * array, then you can set the second argument of this method to false.
 229       *
 230       * This method is applicable to prototype nodes only.
 231       *
 232       * @param string $name          The name of the key
 233       * @param bool   $removeKeyItem Whether or not the key item should be removed
 234       *
 235       * @return $this
 236       */
 237      public function useAttributeAsKey($name, $removeKeyItem = true)
 238      {
 239          $this->key = $name;
 240          $this->removeKeyItem = $removeKeyItem;
 241   
 242          return $this;
 243      }
 244   
 245      /**
 246       * Sets whether the node can be unset.
 247       *
 248       * @param bool $allow
 249       *
 250       * @return $this
 251       */
 252      public function canBeUnset($allow = true)
 253      {
 254          $this->merge()->allowUnset($allow);
 255   
 256          return $this;
 257      }
 258   
 259      /**
 260       * Adds an "enabled" boolean to enable the current section.
 261       *
 262       * By default, the section is disabled. If any configuration is specified then
 263       * the node will be automatically enabled:
 264       *
 265       * enableableArrayNode: {enabled: true, ...}   # The config is enabled & default values get overridden
 266       * enableableArrayNode: ~                      # The config is enabled & use the default values
 267       * enableableArrayNode: true                   # The config is enabled & use the default values
 268       * enableableArrayNode: {other: value, ...}    # The config is enabled & default values get overridden
 269       * enableableArrayNode: {enabled: false, ...}  # The config is disabled
 270       * enableableArrayNode: false                  # The config is disabled
 271       *
 272       * @return $this
 273       */
 274      public function canBeEnabled()
 275      {
 276          $this
 277              ->addDefaultsIfNotSet()
 278              ->treatFalseLike(['enabled' => false])
 279              ->treatTrueLike(['enabled' => true])
 280              ->treatNullLike(['enabled' => true])
 281              ->beforeNormalization()
 282                  ->ifArray()
 283                  ->then(function ($v) {
 284                      $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;
 285   
 286                      return $v;
 287                  })
 288              ->end()
 289              ->children()
 290                  ->booleanNode('enabled')
 291                      ->defaultFalse()
 292          ;
 293   
 294          return $this;
 295      }
 296   
 297      /**
 298       * Adds an "enabled" boolean to enable the current section.
 299       *
 300       * By default, the section is enabled.
 301       *
 302       * @return $this
 303       */
 304      public function canBeDisabled()
 305      {
 306          $this
 307              ->addDefaultsIfNotSet()
 308              ->treatFalseLike(['enabled' => false])
 309              ->treatTrueLike(['enabled' => true])
 310              ->treatNullLike(['enabled' => true])
 311              ->children()
 312                  ->booleanNode('enabled')
 313                      ->defaultTrue()
 314          ;
 315   
 316          return $this;
 317      }
 318   
 319      /**
 320       * Disables the deep merging of the node.
 321       *
 322       * @return $this
 323       */
 324      public function performNoDeepMerging()
 325      {
 326          $this->performDeepMerging = false;
 327   
 328          return $this;
 329      }
 330   
 331      /**
 332       * Allows extra config keys to be specified under an array without
 333       * throwing an exception.
 334       *
 335       * Those config values are ignored and removed from the resulting
 336       * array. This should be used only in special cases where you want
 337       * to send an entire configuration array through a special tree that
 338       * processes only part of the array.
 339       *
 340       * @param bool $remove Whether to remove the extra keys
 341       *
 342       * @return $this
 343       */
 344      public function ignoreExtraKeys($remove = true)
 345      {
 346          $this->ignoreExtraKeys = true;
 347          $this->removeExtraKeys = $remove;
 348   
 349          return $this;
 350      }
 351   
 352      /**
 353       * Sets key normalization.
 354       *
 355       * @param bool $bool Whether to enable key normalization
 356       *
 357       * @return $this
 358       */
 359      public function normalizeKeys($bool)
 360      {
 361          $this->normalizeKeys = (bool) $bool;
 362   
 363          return $this;
 364      }
 365   
 366      /**
 367       * {@inheritdoc}
 368       */
 369      public function append(NodeDefinition $node)
 370      {
 371          $this->children[$node->name] = $node->setParent($this);
 372   
 373          return $this;
 374      }
 375   
 376      /**
 377       * Returns a node builder to be used to add children and prototype.
 378       *
 379       * @return NodeBuilder The node builder
 380       */
 381      protected function getNodeBuilder()
 382      {
 383          if (null === $this->nodeBuilder) {
 384              $this->nodeBuilder = new NodeBuilder();
 385          }
 386   
 387          return $this->nodeBuilder->setParent($this);
 388      }
 389   
 390      /**
 391       * {@inheritdoc}
 392       */
 393      protected function createNode()
 394      {
 395          if (null === $this->prototype) {
 396              $node = new ArrayNode($this->name, $this->parent);
 397   
 398              $this->validateConcreteNode($node);
 399   
 400              $node->setAddIfNotSet($this->addDefaults);
 401   
 402              foreach ($this->children as $child) {
 403                  $child->parent = $node;
 404                  $node->addChild($child->getNode());
 405              }
 406          } else {
 407              $node = new PrototypedArrayNode($this->name, $this->parent);
 408   
 409              $this->validatePrototypeNode($node);
 410   
 411              if (null !== $this->key) {
 412                  $node->setKeyAttribute($this->key, $this->removeKeyItem);
 413              }
 414   
 415              if (false === $this->allowEmptyValue) {
 416                  @trigger_error(sprintf('Using %s::cannotBeEmpty() at path "%s" has no effect, consider requiresAtLeastOneElement() instead. In 4.0 both methods will behave the same.', __CLASS__, $node->getPath()), \E_USER_DEPRECATED);
 417              }
 418   
 419              if (true === $this->atLeastOne) {
 420                  $node->setMinNumberOfElements(1);
 421              }
 422   
 423              if ($this->default) {
 424                  $node->setDefaultValue($this->defaultValue);
 425              }
 426   
 427              if (false !== $this->addDefaultChildren) {
 428                  $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
 429                  if ($this->prototype instanceof static && null === $this->prototype->prototype) {
 430                      $this->prototype->addDefaultsIfNotSet();
 431                  }
 432              }
 433   
 434              $this->prototype->parent = $node;
 435              $node->setPrototype($this->prototype->getNode());
 436          }
 437   
 438          $node->setAllowNewKeys($this->allowNewKeys);
 439          $node->addEquivalentValue(null, $this->nullEquivalent);
 440          $node->addEquivalentValue(true, $this->trueEquivalent);
 441          $node->addEquivalentValue(false, $this->falseEquivalent);
 442          $node->setPerformDeepMerging($this->performDeepMerging);
 443          $node->setRequired($this->required);
 444          $node->setDeprecated($this->deprecationMessage);
 445          $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys);
 446          $node->setNormalizeKeys($this->normalizeKeys);
 447   
 448          if (null !== $this->normalization) {
 449              $node->setNormalizationClosures($this->normalization->before);
 450              $node->setXmlRemappings($this->normalization->remappings);
 451          }
 452   
 453          if (null !== $this->merge) {
 454              $node->setAllowOverwrite($this->merge->allowOverwrite);
 455              $node->setAllowFalse($this->merge->allowFalse);
 456          }
 457   
 458          if (null !== $this->validation) {
 459              $node->setFinalValidationClosures($this->validation->rules);
 460          }
 461   
 462          return $node;
 463      }
 464   
 465      /**
 466       * Validate the configuration of a concrete node.
 467       *
 468       * @throws InvalidDefinitionException
 469       */
 470      protected function validateConcreteNode(ArrayNode $node)
 471      {
 472          $path = $node->getPath();
 473   
 474          if (null !== $this->key) {
 475              throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path));
 476          }
 477   
 478          if (false === $this->allowEmptyValue) {
 479              @trigger_error(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s". In 4.0 it will throw an exception.', $path), \E_USER_DEPRECATED);
 480          }
 481   
 482          if (true === $this->atLeastOne) {
 483              throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path));
 484          }
 485   
 486          if ($this->default) {
 487              throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path));
 488          }
 489   
 490          if (false !== $this->addDefaultChildren) {
 491              throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path));
 492          }
 493      }
 494   
 495      /**
 496       * Validate the configuration of a prototype node.
 497       *
 498       * @throws InvalidDefinitionException
 499       */
 500      protected function validatePrototypeNode(PrototypedArrayNode $node)
 501      {
 502          $path = $node->getPath();
 503   
 504          if ($this->addDefaults) {
 505              throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path));
 506          }
 507   
 508          if (false !== $this->addDefaultChildren) {
 509              if ($this->default) {
 510                  throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s".', $path));
 511              }
 512   
 513              if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
 514                  throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path));
 515              }
 516   
 517              if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) {
 518                  throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path));
 519              }
 520          }
 521      }
 522  }
 523