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