[ Index ]

PHP Cross Reference of phpBB-3.3.11-deutsch

title

Body

[close]

/vendor/symfony/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\Exception\InvalidDefinitionException;
  16  use Symfony\Component\Config\Definition\PrototypedArrayNode;
  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 = true;
  26      protected $ignoreExtraKeys = false;
  27      protected $removeExtraKeys = true;
  28      protected $children = [];
  29      protected $prototype;
  30      protected $atLeastOne = false;
  31      protected $allowNewKeys = true;
  32      protected $key;
  33      protected $removeKeyItem;
  34      protected $addDefaults = false;
  35      protected $addDefaultChildren = false;
  36      protected $nodeBuilder;
  37      protected $normalizeKeys = true;
  38  
  39      /**
  40       * {@inheritdoc}
  41       */
  42      public function __construct($name, NodeParentInterface $parent = null)
  43      {
  44          parent::__construct($name, $parent);
  45  
  46          $this->nullEquivalent = [];
  47          $this->trueEquivalent = [];
  48      }
  49  
  50      /**
  51       * {@inheritdoc}
  52       */
  53      public function setBuilder(NodeBuilder $builder)
  54      {
  55          $this->nodeBuilder = $builder;
  56      }
  57  
  58      /**
  59       * {@inheritdoc}
  60       */
  61      public function children()
  62      {
  63          return $this->getNodeBuilder();
  64      }
  65  
  66      /**
  67       * Sets a prototype for child nodes.
  68       *
  69       * @param string $type The type of node
  70       *
  71       * @return NodeDefinition
  72       */
  73      public function prototype($type)
  74      {
  75          return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
  76      }
  77  
  78      /**
  79       * @return VariableNodeDefinition
  80       */
  81      public function variablePrototype()
  82      {
  83          return $this->prototype('variable');
  84      }
  85  
  86      /**
  87       * @return ScalarNodeDefinition
  88       */
  89      public function scalarPrototype()
  90      {
  91          return $this->prototype('scalar');
  92      }
  93  
  94      /**
  95       * @return BooleanNodeDefinition
  96       */
  97      public function booleanPrototype()
  98      {
  99          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  }


Generated: Sat Nov 4 14:26:03 2023 Cross-referenced by PHPXref 0.7.1