[ 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; 13 14 use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; 15 use Symfony\Component\Config\Definition\Exception\InvalidTypeException; 16 use Symfony\Component\Config\Definition\Exception\UnsetKeyException; 17 18 /** 19 * Represents an Array node in the config tree. 20 * 21 * @author Johannes M. Schmitt <schmittjoh@gmail.com> 22 */ 23 class ArrayNode extends BaseNode implements PrototypeNodeInterface 24 { 25 protected $xmlRemappings = []; 26 protected $children = []; 27 protected $allowFalse = false; 28 protected $allowNewKeys = true; 29 protected $addIfNotSet = false; 30 protected $performDeepMerging = true; 31 protected $ignoreExtraKeys = false; 32 protected $removeExtraKeys = true; 33 protected $normalizeKeys = true; 34 35 public function setNormalizeKeys($normalizeKeys) 36 { 37 $this->normalizeKeys = (bool) $normalizeKeys; 38 } 39 40 /** 41 * {@inheritdoc} 42 * 43 * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. 44 * After running this method, all keys are normalized to foo_bar. 45 * 46 * If you have a mixed key like foo-bar_moo, it will not be altered. 47 * The key will also not be altered if the target key already exists. 48 */ 49 protected function preNormalize($value) 50 { 51 if (!$this->normalizeKeys || !\is_array($value)) { 52 return $value; 53 } 54 55 $normalized = []; 56 57 foreach ($value as $k => $v) { 58 if (false !== strpos($k, '-') && false === strpos($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { 59 $normalized[$normalizedKey] = $v; 60 } else { 61 $normalized[$k] = $v; 62 } 63 } 64 65 return $normalized; 66 } 67 68 /** 69 * Retrieves the children of this node. 70 * 71 * @return array The children 72 */ 73 public function getChildren() 74 { 75 return $this->children; 76 } 77 78 /** 79 * Sets the xml remappings that should be performed. 80 * 81 * @param array $remappings An array of the form [[string, string]] 82 */ 83 public function setXmlRemappings(array $remappings) 84 { 85 $this->xmlRemappings = $remappings; 86 } 87 88 /** 89 * Gets the xml remappings that should be performed. 90 * 91 * @return array an array of the form [[string, string]] 92 */ 93 public function getXmlRemappings() 94 { 95 return $this->xmlRemappings; 96 } 97 98 /** 99 * 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 }
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 |