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 |
ArrayNodeDefinition.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\Builder;
013
014 use Symfony\Component\Config\Definition\ArrayNode;
015 use Symfony\Component\Config\Definition\PrototypedArrayNode;
016 use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
017
018 /**
019 * This class provides a fluent interface for defining an array node.
020 *
021 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
022 */
023 class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
024 {
025 protected $performDeepMerging;
026 protected $ignoreExtraKeys;
027 protected $children;
028 protected $prototype;
029 protected $atLeastOne;
030 protected $allowNewKeys;
031 protected $key;
032 protected $removeKeyItem;
033 protected $addDefaults;
034 protected $addDefaultChildren;
035 protected $nodeBuilder;
036 protected $normalizeKeys;
037
038 /**
039 * {@inheritdoc}
040 */
041 public function __construct($name, NodeParentInterface $parent = null)
042 {
043 parent::__construct($name, $parent);
044
045 $this->children = array();
046 $this->addDefaults = false;
047 $this->addDefaultChildren = false;
048 $this->allowNewKeys = true;
049 $this->atLeastOne = false;
050 $this->allowEmptyValue = true;
051 $this->performDeepMerging = true;
052 $this->nullEquivalent = array();
053 $this->trueEquivalent = array();
054 $this->normalizeKeys = true;
055 }
056
057 /**
058 * Sets a custom children builder.
059 *
060 * @param NodeBuilder $builder A custom NodeBuilder
061 */
062 public function setBuilder(NodeBuilder $builder)
063 {
064 $this->nodeBuilder = $builder;
065 }
066
067 /**
068 * Returns a builder to add children nodes.
069 *
070 * @return NodeBuilder
071 */
072 public function children()
073 {
074 return $this->getNodeBuilder();
075 }
076
077 /**
078 * Sets a prototype for child nodes.
079 *
080 * @param string $type the type of node
081 *
082 * @return NodeDefinition
083 */
084 public function prototype($type)
085 {
086 return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
087 }
088
089 /**
090 * Adds the default value if the node is not set in the configuration.
091 *
092 * This method is applicable to concrete nodes only (not to prototype nodes).
093 * If this function has been called and the node is not set during the finalization
094 * phase, it's default value will be derived from its children default values.
095 *
096 * @return ArrayNodeDefinition
097 */
098 public function addDefaultsIfNotSet()
099 {
100 $this->addDefaults = true;
101
102 return $this;
103 }
104
105 /**
106 * Adds children with a default value when none are defined.
107 *
108 * @param int|string|array|null $children The number of children|The child name|The children names to be added
109 *
110 * This method is applicable to prototype nodes only.
111 *
112 * @return ArrayNodeDefinition
113 */
114 public function addDefaultChildrenIfNoneSet($children = null)
115 {
116 $this->addDefaultChildren = $children;
117
118 return $this;
119 }
120
121 /**
122 * Requires the node to have at least one element.
123 *
124 * This method is applicable to prototype nodes only.
125 *
126 * @return ArrayNodeDefinition
127 */
128 public function requiresAtLeastOneElement()
129 {
130 $this->atLeastOne = true;
131
132 return $this;
133 }
134
135 /**
136 * Disallows adding news keys in a subsequent configuration.
137 *
138 * If used all keys have to be defined in the same configuration file.
139 *
140 * @return ArrayNodeDefinition
141 */
142 public function disallowNewKeysInSubsequentConfigs()
143 {
144 $this->allowNewKeys = false;
145
146 return $this;
147 }
148
149 /**
150 * Sets a normalization rule for XML configurations.
151 *
152 * @param string $singular The key to remap
153 * @param string $plural The plural of the key for irregular plurals
154 *
155 * @return ArrayNodeDefinition
156 */
157 public function fixXmlConfig($singular, $plural = null)
158 {
159 $this->normalization()->remap($singular, $plural);
160
161 return $this;
162 }
163
164 /**
165 * Sets the attribute which value is to be used as key.
166 *
167 * This is useful when you have an indexed array that should be an
168 * associative array. You can select an item from within the array
169 * to be the key of the particular item. For example, if "id" is the
170 * "key", then:
171 *
172 * array(
173 * array('id' => 'my_name', 'foo' => 'bar'),
174 * );
175 *
176 * becomes
177 *
178 * array(
179 * 'my_name' => array('foo' => 'bar'),
180 * );
181 *
182 * If you'd like "'id' => 'my_name'" to still be present in the resulting
183 * array, then you can set the second argument of this method to false.
184 *
185 * This method is applicable to prototype nodes only.
186 *
187 * @param string $name The name of the key
188 * @param bool $removeKeyItem Whether or not the key item should be removed.
189 *
190 * @return ArrayNodeDefinition
191 */
192 public function useAttributeAsKey($name, $removeKeyItem = true)
193 {
194 $this->key = $name;
195 $this->removeKeyItem = $removeKeyItem;
196
197 return $this;
198 }
199
200 /**
201 * Sets whether the node can be unset.
202 *
203 * @param bool $allow
204 *
205 * @return ArrayNodeDefinition
206 */
207 public function canBeUnset($allow = true)
208 {
209 $this->merge()->allowUnset($allow);
210
211 return $this;
212 }
213
214 /**
215 * Adds an "enabled" boolean to enable the current section.
216 *
217 * By default, the section is disabled. If any configuration is specified then
218 * the node will be automatically enabled:
219 *
220 * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden
221 * enableableArrayNode: ~ # The config is enabled & use the default values
222 * enableableArrayNode: true # The config is enabled & use the default values
223 * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden
224 * enableableArrayNode: {enabled: false, ...} # The config is disabled
225 * enableableArrayNode: false # The config is disabled
226 *
227 * @return ArrayNodeDefinition
228 */
229 public function canBeEnabled()
230 {
231 $this
232 ->addDefaultsIfNotSet()
233 ->treatFalseLike(array('enabled' => false))
234 ->treatTrueLike(array('enabled' => true))
235 ->treatNullLike(array('enabled' => true))
236 ->beforeNormalization()
237 ->ifArray()
238 ->then(function ($v) {
239 $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;
240
241 return $v;
242 })
243 ->end()
244 ->children()
245 ->booleanNode('enabled')
246 ->defaultFalse()
247 ;
248
249 return $this;
250 }
251
252 /**
253 * Adds an "enabled" boolean to enable the current section.
254 *
255 * By default, the section is enabled.
256 *
257 * @return ArrayNodeDefinition
258 */
259 public function canBeDisabled()
260 {
261 $this
262 ->addDefaultsIfNotSet()
263 ->treatFalseLike(array('enabled' => false))
264 ->treatTrueLike(array('enabled' => true))
265 ->treatNullLike(array('enabled' => true))
266 ->children()
267 ->booleanNode('enabled')
268 ->defaultTrue()
269 ;
270
271 return $this;
272 }
273
274 /**
275 * Disables the deep merging of the node.
276 *
277 * @return ArrayNodeDefinition
278 */
279 public function performNoDeepMerging()
280 {
281 $this->performDeepMerging = false;
282
283 return $this;
284 }
285
286 /**
287 * Allows extra config keys to be specified under an array without
288 * throwing an exception.
289 *
290 * Those config values are simply ignored. This should be used only
291 * in special cases where you want to send an entire configuration
292 * array through a special tree that processes only part of the array.
293 *
294 * @return ArrayNodeDefinition
295 */
296 public function ignoreExtraKeys()
297 {
298 $this->ignoreExtraKeys = true;
299
300 return $this;
301 }
302
303 /**
304 * Sets key normalization.
305 *
306 * @param bool $bool Whether to enable key normalization
307 *
308 * @return ArrayNodeDefinition
309 */
310 public function normalizeKeys($bool)
311 {
312 $this->normalizeKeys = (bool) $bool;
313
314 return $this;
315 }
316
317 /**
318 * Appends a node definition.
319 *
320 * $node = new ArrayNodeDefinition()
321 * ->children()
322 * ->scalarNode('foo')->end()
323 * ->scalarNode('baz')->end()
324 * ->end()
325 * ->append($this->getBarNodeDefinition())
326 * ;
327 *
328 * @param NodeDefinition $node A NodeDefinition instance
329 *
330 * @return ArrayNodeDefinition This node
331 */
332 public function append(NodeDefinition $node)
333 {
334 $this->children[$node->name] = $node->setParent($this);
335
336 return $this;
337 }
338
339 /**
340 * Returns a node builder to be used to add children and prototype
341 *
342 * @return NodeBuilder The node builder
343 */
344 protected function getNodeBuilder()
345 {
346 if (null === $this->nodeBuilder) {
347 $this->nodeBuilder = new NodeBuilder();
348 }
349
350 return $this->nodeBuilder->setParent($this);
351 }
352
353 /**
354 * {@inheritdoc}
355 */
356 protected function createNode()
357 {
358 if (null === $this->prototype) {
359 $node = new ArrayNode($this->name, $this->parent);
360
361 $this->validateConcreteNode($node);
362
363 $node->setAddIfNotSet($this->addDefaults);
364
365 foreach ($this->children as $child) {
366 $child->parent = $node;
367 $node->addChild($child->getNode());
368 }
369 } else {
370 $node = new PrototypedArrayNode($this->name, $this->parent);
371
372 $this->validatePrototypeNode($node);
373
374 if (null !== $this->key) {
375 $node->setKeyAttribute($this->key, $this->removeKeyItem);
376 }
377
378 if (true === $this->atLeastOne) {
379 $node->setMinNumberOfElements(1);
380 }
381
382 if ($this->default) {
383 $node->setDefaultValue($this->defaultValue);
384 }
385
386 if (false !== $this->addDefaultChildren) {
387 $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
388 if ($this->prototype instanceof static && null === $this->prototype->prototype) {
389 $this->prototype->addDefaultsIfNotSet();
390 }
391 }
392
393 $this->prototype->parent = $node;
394 $node->setPrototype($this->prototype->getNode());
395 }
396
397 $node->setAllowNewKeys($this->allowNewKeys);
398 $node->addEquivalentValue(null, $this->nullEquivalent);
399 $node->addEquivalentValue(true, $this->trueEquivalent);
400 $node->addEquivalentValue(false, $this->falseEquivalent);
401 $node->setPerformDeepMerging($this->performDeepMerging);
402 $node->setRequired($this->required);
403 $node->setIgnoreExtraKeys($this->ignoreExtraKeys);
404 $node->setNormalizeKeys($this->normalizeKeys);
405
406 if (null !== $this->normalization) {
407 $node->setNormalizationClosures($this->normalization->before);
408 $node->setXmlRemappings($this->normalization->remappings);
409 }
410
411 if (null !== $this->merge) {
412 $node->setAllowOverwrite($this->merge->allowOverwrite);
413 $node->setAllowFalse($this->merge->allowFalse);
414 }
415
416 if (null !== $this->validation) {
417 $node->setFinalValidationClosures($this->validation->rules);
418 }
419
420 return $node;
421 }
422
423 /**
424 * Validate the configuration of a concrete node.
425 *
426 * @param ArrayNode $node The related node
427 *
428 * @throws InvalidDefinitionException
429 */
430 protected function validateConcreteNode(ArrayNode $node)
431 {
432 $path = $node->getPath();
433
434 if (null !== $this->key) {
435 throw new InvalidDefinitionException(
436 sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)
437 );
438 }
439
440 if (true === $this->atLeastOne) {
441 throw new InvalidDefinitionException(
442 sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)
443 );
444 }
445
446 if ($this->default) {
447 throw new InvalidDefinitionException(
448 sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)
449 );
450 }
451
452 if (false !== $this->addDefaultChildren) {
453 throw new InvalidDefinitionException(
454 sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)
455 );
456 }
457 }
458
459 /**
460 * Validate the configuration of a prototype node.
461 *
462 * @param PrototypedArrayNode $node The related node
463 *
464 * @throws InvalidDefinitionException
465 */
466 protected function validatePrototypeNode(PrototypedArrayNode $node)
467 {
468 $path = $node->getPath();
469
470 if ($this->addDefaults) {
471 throw new InvalidDefinitionException(
472 sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)
473 );
474 }
475
476 if (false !== $this->addDefaultChildren) {
477 if ($this->default) {
478 throw new InvalidDefinitionException(
479 sprintf('A default value and default children might not be used together at path "%s"', $path)
480 );
481 }
482
483 if (null !== $this->key && (null === $this->addDefaultChildren || is_integer($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
484 throw new InvalidDefinitionException(
485 sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)
486 );
487 }
488
489 if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) {
490 throw new InvalidDefinitionException(
491 sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)
492 );
493 }
494 }
495 }
496 }
497