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