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