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

ArrayNode.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 10.96 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;
013   
014  use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
015  use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
016  use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
017   
018  /**
019   * Represents an Array node in the config tree.
020   *
021   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
022   */
023  class ArrayNode extends BaseNode implements PrototypeNodeInterface
024  {
025      protected $xmlRemappings;
026      protected $children;
027      protected $allowFalse;
028      protected $allowNewKeys;
029      protected $addIfNotSet;
030      protected $performDeepMerging;
031      protected $ignoreExtraKeys;
032      protected $normalizeKeys;
033   
034      /**
035       * Constructor.
036       *
037       * @param string        $name   The Node's name
038       * @param NodeInterface $parent The node parent
039       */
040      public function __construct($name, NodeInterface $parent = null)
041      {
042          parent::__construct($name, $parent);
043   
044          $this->children = array();
045          $this->xmlRemappings = array();
046          $this->removeKeyAttribute = true;
047          $this->allowFalse = false;
048          $this->addIfNotSet = false;
049          $this->allowNewKeys = true;
050          $this->performDeepMerging = true;
051          $this->normalizeKeys = true;
052      }
053   
054      public function setNormalizeKeys($normalizeKeys)
055      {
056          $this->normalizeKeys = (bool) $normalizeKeys;
057      }
058   
059      /**
060       * Normalizes keys between the different configuration formats.
061       *
062       * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
063       * After running this method, all keys are normalized to foo_bar.
064       *
065       * If you have a mixed key like foo-bar_moo, it will not be altered.
066       * The key will also not be altered if the target key already exists.
067       *
068       * @param mixed $value
069       *
070       * @return array The value with normalized keys
071       */
072      protected function preNormalize($value)
073      {
074          if (!$this->normalizeKeys || !is_array($value)) {
075              return $value;
076          }
077   
078          foreach ($value as $k => $v) {
079              if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
080                  $value[$normalizedKey] = $v;
081                  unset($value[$k]);
082              }
083          }
084   
085          return $value;
086      }
087   
088      /**
089       * Retrieves the children of this node.
090       *
091       * @return array The children
092       */
093      public function getChildren()
094      {
095          return $this->children;
096      }
097   
098      /**
099       * Sets the xml remappings that should be performed.
100       *
101       * @param array $remappings an array of the form array(array(string, string))
102       */
103      public function setXmlRemappings(array $remappings)
104      {
105          $this->xmlRemappings = $remappings;
106      }
107   
108      /**
109       * Sets whether to add default values for this array if it has not been
110       * defined in any of the configuration files.
111       *
112       * @param bool    $boolean
113       */
114      public function setAddIfNotSet($boolean)
115      {
116          $this->addIfNotSet = (bool) $boolean;
117      }
118   
119      /**
120       * Sets whether false is allowed as value indicating that the array should be unset.
121       *
122       * @param bool    $allow
123       */
124      public function setAllowFalse($allow)
125      {
126          $this->allowFalse = (bool) $allow;
127      }
128   
129      /**
130       * Sets whether new keys can be defined in subsequent configurations.
131       *
132       * @param bool    $allow
133       */
134      public function setAllowNewKeys($allow)
135      {
136          $this->allowNewKeys = (bool) $allow;
137      }
138   
139      /**
140       * Sets if deep merging should occur.
141       *
142       * @param bool    $boolean
143       */
144      public function setPerformDeepMerging($boolean)
145      {
146          $this->performDeepMerging = (bool) $boolean;
147      }
148   
149      /**
150       * Whether extra keys should just be ignore without an exception.
151       *
152       * @param bool    $boolean To allow extra keys
153       */
154      public function setIgnoreExtraKeys($boolean)
155      {
156          $this->ignoreExtraKeys = (bool) $boolean;
157      }
158   
159      /**
160       * Sets the node Name.
161       *
162       * @param string $name The node's name
163       */
164      public function setName($name)
165      {
166          $this->name = $name;
167      }
168   
169      /**
170       * Checks if the node has a default value.
171       *
172       * @return bool
173       */
174      public function hasDefaultValue()
175      {
176          return $this->addIfNotSet;
177      }
178   
179      /**
180       * Retrieves the default value.
181       *
182       * @return array The default value
183       *
184       * @throws \RuntimeException if the node has no default value
185       */
186      public function getDefaultValue()
187      {
188          if (!$this->hasDefaultValue()) {
189              throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
190          }
191   
192          $defaults = array();
193          foreach ($this->children as $name => $child) {
194              if ($child->hasDefaultValue()) {
195                  $defaults[$name] = $child->getDefaultValue();
196              }
197          }
198   
199          return $defaults;
200      }
201   
202      /**
203       * Adds a child node.
204       *
205       * @param NodeInterface $node The child node to add
206       *
207       * @throws \InvalidArgumentException when the child node has no name
208       * @throws \InvalidArgumentException when the child node's name is not unique
209       */
210      public function addChild(NodeInterface $node)
211      {
212          $name = $node->getName();
213          if (!strlen($name)) {
214              throw new \InvalidArgumentException('Child nodes must be named.');
215          }
216          if (isset($this->children[$name])) {
217              throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name));
218          }
219   
220          $this->children[$name] = $node;
221      }
222   
223      /**
224       * Finalizes the value of this node.
225       *
226       * @param mixed $value
227       *
228       * @return mixed The finalised value
229       *
230       * @throws UnsetKeyException
231       * @throws InvalidConfigurationException if the node doesn't have enough children
232       */
233      protected function finalizeValue($value)
234      {
235          if (false === $value) {
236              $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
237              throw new UnsetKeyException($msg);
238          }
239   
240          foreach ($this->children as $name => $child) {
241              if (!array_key_exists($name, $value)) {
242                  if ($child->isRequired()) {
243                      $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath());
244                      $ex = new InvalidConfigurationException($msg);
245                      $ex->setPath($this->getPath());
246   
247                      throw $ex;
248                  }
249   
250                  if ($child->hasDefaultValue()) {
251                      $value[$name] = $child->getDefaultValue();
252                  }
253   
254                  continue;
255              }
256   
257              try {
258                  $value[$name] = $child->finalize($value[$name]);
259              } catch (UnsetKeyException $unset) {
260                  unset($value[$name]);
261              }
262          }
263   
264          return $value;
265      }
266   
267      /**
268       * Validates the type of the value.
269       *
270       * @param mixed $value
271       *
272       * @throws InvalidTypeException
273       */
274      protected function validateType($value)
275      {
276          if (!is_array($value) && (!$this->allowFalse || false !== $value)) {
277              $ex = new InvalidTypeException(sprintf(
278                  'Invalid type for path "%s". Expected array, but got %s',
279                  $this->getPath(),
280                  gettype($value)
281              ));
282              $ex->setPath($this->getPath());
283   
284              throw $ex;
285          }
286      }
287   
288      /**
289       * Normalizes the value.
290       *
291       * @param mixed $value The value to normalize
292       *
293       * @return mixed The normalized value
294       *
295       * @throws InvalidConfigurationException
296       */
297      protected function normalizeValue($value)
298      {
299          if (false === $value) {
300              return $value;
301          }
302   
303          $value = $this->remapXml($value);
304   
305          $normalized = array();
306          foreach ($value as $name => $val) {
307              if (isset($this->children[$name])) {
308                  $normalized[$name] = $this->children[$name]->normalize($val);
309                  unset($value[$name]);
310              }
311          }
312   
313          // if extra fields are present, throw exception
314          if (count($value) && !$this->ignoreExtraKeys) {
315              $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath());
316              $ex = new InvalidConfigurationException($msg);
317              $ex->setPath($this->getPath());
318   
319              throw $ex;
320          }
321   
322          return $normalized;
323      }
324   
325      /**
326       * Remaps multiple singular values to a single plural value.
327       *
328       * @param array $value The source values
329       *
330       * @return array The remapped values
331       */
332      protected function remapXml($value)
333      {
334          foreach ($this->xmlRemappings as $transformation) {
335              list($singular, $plural) = $transformation;
336   
337              if (!isset($value[$singular])) {
338                  continue;
339              }
340   
341              $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
342              unset($value[$singular]);
343          }
344   
345          return $value;
346      }
347   
348      /**
349       * Merges values together.
350       *
351       * @param mixed $leftSide  The left side to merge.
352       * @param mixed $rightSide The right side to merge.
353       *
354       * @return mixed The merged values
355       *
356       * @throws InvalidConfigurationException
357       * @throws \RuntimeException
358       */
359      protected function mergeValues($leftSide, $rightSide)
360      {
361          if (false === $rightSide) {
362              // if this is still false after the last config has been merged the
363              // finalization pass will take care of removing this key entirely
364              return false;
365          }
366   
367          if (false === $leftSide || !$this->performDeepMerging) {
368              return $rightSide;
369          }
370   
371          foreach ($rightSide as $k => $v) {
372              // no conflict
373              if (!array_key_exists($k, $leftSide)) {
374                  if (!$this->allowNewKeys) {
375                      $ex = new InvalidConfigurationException(sprintf(
376                          'You are not allowed to define new elements for path "%s". '
377                         .'Please define all elements for this path in one config file. '
378                         .'If you are trying to overwrite an element, make sure you redefine it '
379                         .'with the same name.',
380                          $this->getPath()
381                      ));
382                      $ex->setPath($this->getPath());
383   
384                      throw $ex;
385                  }
386   
387                  $leftSide[$k] = $v;
388                  continue;
389              }
390   
391              if (!isset($this->children[$k])) {
392                  throw new \RuntimeException('merge() expects a normalized config array.');
393              }
394   
395              $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
396          }
397   
398          return $leftSide;
399      }
400  }
401