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

ArrayNodeDefinition.php

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