[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\Config\Definition\Builder; 13 14 use Symfony\Component\Config\Definition\ArrayNode; 15 use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; 16 use Symfony\Component\Config\Definition\PrototypedArrayNode; 17 18 /** 19 * This class provides a fluent interface for defining an array node. 20 * 21 * @author Johannes M. Schmitt <schmittjoh@gmail.com> 22 */ 23 class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface 24 { 25 protected $performDeepMerging = true; 26 protected $ignoreExtraKeys = false; 27 protected $removeExtraKeys = true; 28 protected $children = []; 29 protected $prototype; 30 protected $atLeastOne = false; 31 protected $allowNewKeys = true; 32 protected $key; 33 protected $removeKeyItem; 34 protected $addDefaults = false; 35 protected $addDefaultChildren = false; 36 protected $nodeBuilder; 37 protected $normalizeKeys = true; 38 39 /** 40 * {@inheritdoc} 41 */ 42 public function __construct($name, NodeParentInterface $parent = null) 43 { 44 parent::__construct($name, $parent); 45 46 $this->nullEquivalent = []; 47 $this->trueEquivalent = []; 48 } 49 50 /** 51 * {@inheritdoc} 52 */ 53 public function setBuilder(NodeBuilder $builder) 54 { 55 $this->nodeBuilder = $builder; 56 } 57 58 /** 59 * {@inheritdoc} 60 */ 61 public function children() 62 { 63 return $this->getNodeBuilder(); 64 } 65 66 /** 67 * Sets a prototype for child nodes. 68 * 69 * @param string $type The type of node 70 * 71 * @return NodeDefinition 72 */ 73 public function prototype($type) 74 { 75 return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); 76 } 77 78 /** 79 * @return VariableNodeDefinition 80 */ 81 public function variablePrototype() 82 { 83 return $this->prototype('variable'); 84 } 85 86 /** 87 * @return ScalarNodeDefinition 88 */ 89 public function scalarPrototype() 90 { 91 return $this->prototype('scalar'); 92 } 93 94 /** 95 * @return BooleanNodeDefinition 96 */ 97 public function booleanPrototype() 98 { 99 return $this->prototype('boolean'); 100 } 101 102 /** 103 * @return IntegerNodeDefinition 104 */ 105 public function integerPrototype() 106 { 107 return $this->prototype('integer'); 108 } 109 110 /** 111 * @return FloatNodeDefinition 112 */ 113 public function floatPrototype() 114 { 115 return $this->prototype('float'); 116 } 117 118 /** 119 * @return ArrayNodeDefinition 120 */ 121 public function arrayPrototype() 122 { 123 return $this->prototype('array'); 124 } 125 126 /** 127 * @return EnumNodeDefinition 128 */ 129 public function enumPrototype() 130 { 131 return $this->prototype('enum'); 132 } 133 134 /** 135 * Adds the default value if the node is not set in the configuration. 136 * 137 * This method is applicable to concrete nodes only (not to prototype nodes). 138 * If this function has been called and the node is not set during the finalization 139 * phase, it's default value will be derived from its children default values. 140 * 141 * @return $this 142 */ 143 public function addDefaultsIfNotSet() 144 { 145 $this->addDefaults = true; 146 147 return $this; 148 } 149 150 /** 151 * Adds children with a default value when none are defined. 152 * 153 * This method is applicable to prototype nodes only. 154 * 155 * @param int|string|array|null $children The number of children|The child name|The children names to be added 156 * 157 * @return $this 158 */ 159 public function addDefaultChildrenIfNoneSet($children = null) 160 { 161 $this->addDefaultChildren = $children; 162 163 return $this; 164 } 165 166 /** 167 * Requires the node to have at least one element. 168 * 169 * This method is applicable to prototype nodes only. 170 * 171 * @return $this 172 */ 173 public function requiresAtLeastOneElement() 174 { 175 $this->atLeastOne = true; 176 177 return $this; 178 } 179 180 /** 181 * Disallows adding news keys in a subsequent configuration. 182 * 183 * If used all keys have to be defined in the same configuration file. 184 * 185 * @return $this 186 */ 187 public function disallowNewKeysInSubsequentConfigs() 188 { 189 $this->allowNewKeys = false; 190 191 return $this; 192 } 193 194 /** 195 * Sets a normalization rule for XML configurations. 196 * 197 * @param string $singular The key to remap 198 * @param string $plural The plural of the key for irregular plurals 199 * 200 * @return $this 201 */ 202 public function fixXmlConfig($singular, $plural = null) 203 { 204 $this->normalization()->remap($singular, $plural); 205 206 return $this; 207 } 208 209 /** 210 * Sets the attribute which value is to be used as key. 211 * 212 * This is useful when you have an indexed array that should be an 213 * associative array. You can select an item from within the array 214 * to be the key of the particular item. For example, if "id" is the 215 * "key", then: 216 * 217 * [ 218 * ['id' => 'my_name', 'foo' => 'bar'], 219 * ]; 220 * 221 * becomes 222 * 223 * [ 224 * 'my_name' => ['foo' => 'bar'], 225 * ]; 226 * 227 * If you'd like "'id' => 'my_name'" to still be present in the resulting 228 * array, then you can set the second argument of this method to false. 229 * 230 * This method is applicable to prototype nodes only. 231 * 232 * @param string $name The name of the key 233 * @param bool $removeKeyItem Whether or not the key item should be removed 234 * 235 * @return $this 236 */ 237 public function useAttributeAsKey($name, $removeKeyItem = true) 238 { 239 $this->key = $name; 240 $this->removeKeyItem = $removeKeyItem; 241 242 return $this; 243 } 244 245 /** 246 * Sets whether the node can be unset. 247 * 248 * @param bool $allow 249 * 250 * @return $this 251 */ 252 public function canBeUnset($allow = true) 253 { 254 $this->merge()->allowUnset($allow); 255 256 return $this; 257 } 258 259 /** 260 * Adds an "enabled" boolean to enable the current section. 261 * 262 * By default, the section is disabled. If any configuration is specified then 263 * the node will be automatically enabled: 264 * 265 * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden 266 * enableableArrayNode: ~ # The config is enabled & use the default values 267 * enableableArrayNode: true # The config is enabled & use the default values 268 * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden 269 * enableableArrayNode: {enabled: false, ...} # The config is disabled 270 * enableableArrayNode: false # The config is disabled 271 * 272 * @return $this 273 */ 274 public function canBeEnabled() 275 { 276 $this 277 ->addDefaultsIfNotSet() 278 ->treatFalseLike(['enabled' => false]) 279 ->treatTrueLike(['enabled' => true]) 280 ->treatNullLike(['enabled' => true]) 281 ->beforeNormalization() 282 ->ifArray() 283 ->then(function ($v) { 284 $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; 285 286 return $v; 287 }) 288 ->end() 289 ->children() 290 ->booleanNode('enabled') 291 ->defaultFalse() 292 ; 293 294 return $this; 295 } 296 297 /** 298 * Adds an "enabled" boolean to enable the current section. 299 * 300 * By default, the section is enabled. 301 * 302 * @return $this 303 */ 304 public function canBeDisabled() 305 { 306 $this 307 ->addDefaultsIfNotSet() 308 ->treatFalseLike(['enabled' => false]) 309 ->treatTrueLike(['enabled' => true]) 310 ->treatNullLike(['enabled' => true]) 311 ->children() 312 ->booleanNode('enabled') 313 ->defaultTrue() 314 ; 315 316 return $this; 317 } 318 319 /** 320 * Disables the deep merging of the node. 321 * 322 * @return $this 323 */ 324 public function performNoDeepMerging() 325 { 326 $this->performDeepMerging = false; 327 328 return $this; 329 } 330 331 /** 332 * Allows extra config keys to be specified under an array without 333 * throwing an exception. 334 * 335 * Those config values are ignored and removed from the resulting 336 * array. This should be used only in special cases where you want 337 * to send an entire configuration array through a special tree that 338 * processes only part of the array. 339 * 340 * @param bool $remove Whether to remove the extra keys 341 * 342 * @return $this 343 */ 344 public function ignoreExtraKeys($remove = true) 345 { 346 $this->ignoreExtraKeys = true; 347 $this->removeExtraKeys = $remove; 348 349 return $this; 350 } 351 352 /** 353 * Sets key normalization. 354 * 355 * @param bool $bool Whether to enable key normalization 356 * 357 * @return $this 358 */ 359 public function normalizeKeys($bool) 360 { 361 $this->normalizeKeys = (bool) $bool; 362 363 return $this; 364 } 365 366 /** 367 * {@inheritdoc} 368 */ 369 public function append(NodeDefinition $node) 370 { 371 $this->children[$node->name] = $node->setParent($this); 372 373 return $this; 374 } 375 376 /** 377 * Returns a node builder to be used to add children and prototype. 378 * 379 * @return NodeBuilder The node builder 380 */ 381 protected function getNodeBuilder() 382 { 383 if (null === $this->nodeBuilder) { 384 $this->nodeBuilder = new NodeBuilder(); 385 } 386 387 return $this->nodeBuilder->setParent($this); 388 } 389 390 /** 391 * {@inheritdoc} 392 */ 393 protected function createNode() 394 { 395 if (null === $this->prototype) { 396 $node = new ArrayNode($this->name, $this->parent); 397 398 $this->validateConcreteNode($node); 399 400 $node->setAddIfNotSet($this->addDefaults); 401 402 foreach ($this->children as $child) { 403 $child->parent = $node; 404 $node->addChild($child->getNode()); 405 } 406 } else { 407 $node = new PrototypedArrayNode($this->name, $this->parent); 408 409 $this->validatePrototypeNode($node); 410 411 if (null !== $this->key) { 412 $node->setKeyAttribute($this->key, $this->removeKeyItem); 413 } 414 415 if (false === $this->allowEmptyValue) { 416 @trigger_error(sprintf('Using %s::cannotBeEmpty() at path "%s" has no effect, consider requiresAtLeastOneElement() instead. In 4.0 both methods will behave the same.', __CLASS__, $node->getPath()), \E_USER_DEPRECATED); 417 } 418 419 if (true === $this->atLeastOne) { 420 $node->setMinNumberOfElements(1); 421 } 422 423 if ($this->default) { 424 $node->setDefaultValue($this->defaultValue); 425 } 426 427 if (false !== $this->addDefaultChildren) { 428 $node->setAddChildrenIfNoneSet($this->addDefaultChildren); 429 if ($this->prototype instanceof static && null === $this->prototype->prototype) { 430 $this->prototype->addDefaultsIfNotSet(); 431 } 432 } 433 434 $this->prototype->parent = $node; 435 $node->setPrototype($this->prototype->getNode()); 436 } 437 438 $node->setAllowNewKeys($this->allowNewKeys); 439 $node->addEquivalentValue(null, $this->nullEquivalent); 440 $node->addEquivalentValue(true, $this->trueEquivalent); 441 $node->addEquivalentValue(false, $this->falseEquivalent); 442 $node->setPerformDeepMerging($this->performDeepMerging); 443 $node->setRequired($this->required); 444 $node->setDeprecated($this->deprecationMessage); 445 $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); 446 $node->setNormalizeKeys($this->normalizeKeys); 447 448 if (null !== $this->normalization) { 449 $node->setNormalizationClosures($this->normalization->before); 450 $node->setXmlRemappings($this->normalization->remappings); 451 } 452 453 if (null !== $this->merge) { 454 $node->setAllowOverwrite($this->merge->allowOverwrite); 455 $node->setAllowFalse($this->merge->allowFalse); 456 } 457 458 if (null !== $this->validation) { 459 $node->setFinalValidationClosures($this->validation->rules); 460 } 461 462 return $node; 463 } 464 465 /** 466 * Validate the configuration of a concrete node. 467 * 468 * @throws InvalidDefinitionException 469 */ 470 protected function validateConcreteNode(ArrayNode $node) 471 { 472 $path = $node->getPath(); 473 474 if (null !== $this->key) { 475 throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path)); 476 } 477 478 if (false === $this->allowEmptyValue) { 479 @trigger_error(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s". In 4.0 it will throw an exception.', $path), \E_USER_DEPRECATED); 480 } 481 482 if (true === $this->atLeastOne) { 483 throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path)); 484 } 485 486 if ($this->default) { 487 throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path)); 488 } 489 490 if (false !== $this->addDefaultChildren) { 491 throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path)); 492 } 493 } 494 495 /** 496 * Validate the configuration of a prototype node. 497 * 498 * @throws InvalidDefinitionException 499 */ 500 protected function validatePrototypeNode(PrototypedArrayNode $node) 501 { 502 $path = $node->getPath(); 503 504 if ($this->addDefaults) { 505 throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path)); 506 } 507 508 if (false !== $this->addDefaultChildren) { 509 if ($this->default) { 510 throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s".', $path)); 511 } 512 513 if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { 514 throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path)); 515 } 516 517 if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) { 518 throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path)); 519 } 520 } 521 } 522 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |