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. |
|
(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;
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