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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
ArrayNode.php
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