Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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