[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ -> ArrayNodeDefinition.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\Config\Definition\Builder;
  13  
  14  use Symfony\Component\Config\Definition\ArrayNode;
  15  use Symfony\Component\Config\Definition\PrototypedArrayNode;
  16  use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
  17  
  18  /**
  19   * This class provides a fluent interface for defining an array node.
  20   *
  21   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  22   */
  23  class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
  24  {
  25      protected $performDeepMerging;
  26      protected $ignoreExtraKeys;
  27      protected $children;
  28      protected $prototype;
  29      protected $atLeastOne;
  30      protected $allowNewKeys;
  31      protected $key;
  32      protected $removeKeyItem;
  33      protected $addDefaults;
  34      protected $addDefaultChildren;
  35      protected $nodeBuilder;
  36      protected $normalizeKeys;
  37  
  38      /**
  39       * {@inheritdoc}
  40       */
  41      public function __construct($name, NodeParentInterface $parent = null)
  42      {
  43          parent::__construct($name, $parent);
  44  
  45          $this->children = array();
  46          $this->addDefaults = false;
  47          $this->addDefaultChildren = false;
  48          $this->allowNewKeys = true;
  49          $this->atLeastOne = false;
  50          $this->allowEmptyValue = true;
  51          $this->performDeepMerging = true;
  52          $this->nullEquivalent = array();
  53          $this->trueEquivalent = array();
  54          $this->normalizeKeys = true;
  55      }
  56  
  57      /**
  58       * Sets a custom children builder.
  59       *
  60       * @param NodeBuilder $builder A custom NodeBuilder
  61       */
  62      public function setBuilder(NodeBuilder $builder)
  63      {
  64          $this->nodeBuilder = $builder;
  65      }
  66  
  67      /**
  68       * Returns a builder to add children nodes.
  69       *
  70       * @return NodeBuilder
  71       */
  72      public function children()
  73      {
  74          return $this->getNodeBuilder();
  75      }
  76  
  77      /**
  78       * Sets a prototype for child nodes.
  79       *
  80       * @param string $type the type of node
  81       *
  82       * @return NodeDefinition
  83       */
  84      public function prototype($type)
  85      {
  86          return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
  87      }
  88  
  89      /**
  90       * Adds the default value if the node is not set in the configuration.
  91       *
  92       * This method is applicable to concrete nodes only (not to prototype nodes).
  93       * If this function has been called and the node is not set during the finalization
  94       * phase, it's default value will be derived from its children default values.
  95       *
  96       * @return ArrayNodeDefinition
  97       */
  98      public function addDefaultsIfNotSet()
  99      {
 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 and removed from the
 291       * resulting array. This should be used only in special cases where
 292       * you want to send an entire configuration array through a special
 293       * tree that processes only part of the array.
 294       *
 295       * @return ArrayNodeDefinition
 296       */
 297      public function ignoreExtraKeys()
 298      {
 299          $this->ignoreExtraKeys = true;
 300  
 301          return $this;
 302      }
 303  
 304      /**
 305       * Sets key normalization.
 306       *
 307       * @param bool $bool Whether to enable key normalization
 308       *
 309       * @return ArrayNodeDefinition
 310       */
 311      public function normalizeKeys($bool)
 312      {
 313          $this->normalizeKeys = (bool) $bool;
 314  
 315          return $this;
 316      }
 317  
 318      /**
 319       * Appends a node definition.
 320       *
 321       *     $node = new ArrayNodeDefinition()
 322       *         ->children()
 323       *             ->scalarNode('foo')->end()
 324       *             ->scalarNode('baz')->end()
 325       *         ->end()
 326       *         ->append($this->getBarNodeDefinition())
 327       *     ;
 328       *
 329       * @param NodeDefinition $node A NodeDefinition instance
 330       *
 331       * @return ArrayNodeDefinition This node
 332       */
 333      public function append(NodeDefinition $node)
 334      {
 335          $this->children[$node->name] = $node->setParent($this);
 336  
 337          return $this;
 338      }
 339  
 340      /**
 341       * Returns a node builder to be used to add children and prototype.
 342       *
 343       * @return NodeBuilder The node builder
 344       */
 345      protected function getNodeBuilder()
 346      {
 347          if (null === $this->nodeBuilder) {
 348              $this->nodeBuilder = new NodeBuilder();
 349          }
 350  
 351          return $this->nodeBuilder->setParent($this);
 352      }
 353  
 354      /**
 355       * {@inheritdoc}
 356       */
 357      protected function createNode()
 358      {
 359          if (null === $this->prototype) {
 360              $node = new ArrayNode($this->name, $this->parent);
 361  
 362              $this->validateConcreteNode($node);
 363  
 364              $node->setAddIfNotSet($this->addDefaults);
 365  
 366              foreach ($this->children as $child) {
 367                  $child->parent = $node;
 368                  $node->addChild($child->getNode());
 369              }
 370          } else {
 371              $node = new PrototypedArrayNode($this->name, $this->parent);
 372  
 373              $this->validatePrototypeNode($node);
 374  
 375              if (null !== $this->key) {
 376                  $node->setKeyAttribute($this->key, $this->removeKeyItem);
 377              }
 378  
 379              if (true === $this->atLeastOne) {
 380                  $node->setMinNumberOfElements(1);
 381              }
 382  
 383              if ($this->default) {
 384                  $node->setDefaultValue($this->defaultValue);
 385              }
 386  
 387              if (false !== $this->addDefaultChildren) {
 388                  $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
 389                  if ($this->prototype instanceof static && null === $this->prototype->prototype) {
 390                      $this->prototype->addDefaultsIfNotSet();
 391                  }
 392              }
 393  
 394              $this->prototype->parent = $node;
 395              $node->setPrototype($this->prototype->getNode());
 396          }
 397  
 398          $node->setAllowNewKeys($this->allowNewKeys);
 399          $node->addEquivalentValue(null, $this->nullEquivalent);
 400          $node->addEquivalentValue(true, $this->trueEquivalent);
 401          $node->addEquivalentValue(false, $this->falseEquivalent);
 402          $node->setPerformDeepMerging($this->performDeepMerging);
 403          $node->setRequired($this->required);
 404          $node->setIgnoreExtraKeys($this->ignoreExtraKeys);
 405          $node->setNormalizeKeys($this->normalizeKeys);
 406  
 407          if (null !== $this->normalization) {
 408              $node->setNormalizationClosures($this->normalization->before);
 409              $node->setXmlRemappings($this->normalization->remappings);
 410          }
 411  
 412          if (null !== $this->merge) {
 413              $node->setAllowOverwrite($this->merge->allowOverwrite);
 414              $node->setAllowFalse($this->merge->allowFalse);
 415          }
 416  
 417          if (null !== $this->validation) {
 418              $node->setFinalValidationClosures($this->validation->rules);
 419          }
 420  
 421          return $node;
 422      }
 423  
 424      /**
 425       * Validate the configuration of a concrete node.
 426       *
 427       * @param ArrayNode $node The related node
 428       *
 429       * @throws InvalidDefinitionException
 430       */
 431      protected function validateConcreteNode(ArrayNode $node)
 432      {
 433          $path = $node->getPath();
 434  
 435          if (null !== $this->key) {
 436              throw new InvalidDefinitionException(
 437                  sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)
 438              );
 439          }
 440  
 441          if (true === $this->atLeastOne) {
 442              throw new InvalidDefinitionException(
 443                  sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)
 444              );
 445          }
 446  
 447          if ($this->default) {
 448              throw new InvalidDefinitionException(
 449                  sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)
 450              );
 451          }
 452  
 453          if (false !== $this->addDefaultChildren) {
 454              throw new InvalidDefinitionException(
 455                  sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)
 456              );
 457          }
 458      }
 459  
 460      /**
 461       * Validate the configuration of a prototype node.
 462       *
 463       * @param PrototypedArrayNode $node The related node
 464       *
 465       * @throws InvalidDefinitionException
 466       */
 467      protected function validatePrototypeNode(PrototypedArrayNode $node)
 468      {
 469          $path = $node->getPath();
 470  
 471          if ($this->addDefaults) {
 472              throw new InvalidDefinitionException(
 473                  sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)
 474              );
 475          }
 476  
 477          if (false !== $this->addDefaultChildren) {
 478              if ($this->default) {
 479                  throw new InvalidDefinitionException(
 480                      sprintf('A default value and default children might not be used together at path "%s"', $path)
 481                  );
 482              }
 483  
 484              if (null !== $this->key && (null === $this->addDefaultChildren || is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
 485                  throw new InvalidDefinitionException(
 486                      sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)
 487                  );
 488              }
 489  
 490              if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) {
 491                  throw new InvalidDefinitionException(
 492                      sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)
 493                  );
 494              }
 495          }
 496      }
 497  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1