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

ArrayNodeDefinition.php

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