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 |
PrototypedArrayNode.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\DuplicateKeyException;
016 use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
017 use Symfony\Component\Config\Definition\Exception\Exception;
018
019 /**
020 * Represents a prototyped Array node in the config tree.
021 *
022 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
023 */
024 class PrototypedArrayNode extends ArrayNode
025 {
026 protected $prototype;
027 protected $keyAttribute;
028 protected $removeKeyAttribute = false;
029 protected $minNumberOfElements = 0;
030 protected $defaultValue = array();
031 protected $defaultChildren;
032
033 /**
034 * Sets the minimum number of elements that a prototype based node must
035 * contain. By default this is zero, meaning no elements.
036 *
037 * @param int $number
038 */
039 public function setMinNumberOfElements($number)
040 {
041 $this->minNumberOfElements = $number;
042 }
043
044 /**
045 * Sets the attribute which value is to be used as key.
046 *
047 * This is useful when you have an indexed array that should be an
048 * associative array. You can select an item from within the array
049 * to be the key of the particular item. For example, if "id" is the
050 * "key", then:
051 *
052 * array(
053 * array('id' => 'my_name', 'foo' => 'bar'),
054 * );
055 *
056 * becomes
057 *
058 * array(
059 * 'my_name' => array('foo' => 'bar'),
060 * );
061 *
062 * If you'd like "'id' => 'my_name'" to still be present in the resulting
063 * array, then you can set the second argument of this method to false.
064 *
065 * @param string $attribute The name of the attribute which value is to be used as a key
066 * @param bool $remove Whether or not to remove the key
067 */
068 public function setKeyAttribute($attribute, $remove = true)
069 {
070 $this->keyAttribute = $attribute;
071 $this->removeKeyAttribute = $remove;
072 }
073
074 /**
075 * Retrieves the name of the attribute which value should be used as key.
076 *
077 * @return string The name of the attribute
078 */
079 public function getKeyAttribute()
080 {
081 return $this->keyAttribute;
082 }
083
084 /**
085 * Sets the default value of this node.
086 *
087 * @param string $value
088 *
089 * @throws \InvalidArgumentException if the default value is not an array
090 */
091 public function setDefaultValue($value)
092 {
093 if (!is_array($value)) {
094 throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.');
095 }
096
097 $this->defaultValue = $value;
098 }
099
100 /**
101 * Checks if the node has a default value.
102 *
103 * @return bool
104 */
105 public function hasDefaultValue()
106 {
107 return true;
108 }
109
110 /**
111 * Adds default children when none are set.
112 *
113 * @param int|string|array|null $children The number of children|The child name|The children names to be added
114 */
115 public function setAddChildrenIfNoneSet($children = array('defaults'))
116 {
117 if (null === $children) {
118 $this->defaultChildren = array('defaults');
119 } else {
120 $this->defaultChildren = is_int($children) && $children > 0 ? range(1, $children) : (array) $children;
121 }
122 }
123
124 /**
125 * Retrieves the default value.
126 *
127 * The default value could be either explicited or derived from the prototype
128 * default value.
129 *
130 * @return array The default value
131 */
132 public function getDefaultValue()
133 {
134 if (null !== $this->defaultChildren) {
135 $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array();
136 $defaults = array();
137 foreach (array_values($this->defaultChildren) as $i => $name) {
138 $defaults[null === $this->keyAttribute ? $i : $name] = $default;
139 }
140
141 return $defaults;
142 }
143
144 return $this->defaultValue;
145 }
146
147 /**
148 * Sets the node prototype.
149 *
150 * @param PrototypeNodeInterface $node
151 */
152 public function setPrototype(PrototypeNodeInterface $node)
153 {
154 $this->prototype = $node;
155 }
156
157 /**
158 * Retrieves the prototype.
159 *
160 * @return PrototypeNodeInterface The prototype
161 */
162 public function getPrototype()
163 {
164 return $this->prototype;
165 }
166
167 /**
168 * Disable adding concrete children for prototyped nodes.
169 *
170 * @param NodeInterface $node The child node to add
171 *
172 * @throws Exception
173 */
174 public function addChild(NodeInterface $node)
175 {
176 throw new Exception('A prototyped array node can not have concrete children.');
177 }
178
179 /**
180 * Finalizes the value of this node.
181 *
182 * @param mixed $value
183 *
184 * @return mixed The finalized value
185 *
186 * @throws UnsetKeyException
187 * @throws InvalidConfigurationException if the node doesn't have enough children
188 */
189 protected function finalizeValue($value)
190 {
191 if (false === $value) {
192 $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
193 throw new UnsetKeyException($msg);
194 }
195
196 foreach ($value as $k => $v) {
197 $this->prototype->setName($k);
198 try {
199 $value[$k] = $this->prototype->finalize($v);
200 } catch (UnsetKeyException $e) {
201 unset($value[$k]);
202 }
203 }
204
205 if (count($value) < $this->minNumberOfElements) {
206 $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements);
207 $ex = new InvalidConfigurationException($msg);
208 $ex->setPath($this->getPath());
209
210 throw $ex;
211 }
212
213 return $value;
214 }
215
216 /**
217 * Normalizes the value.
218 *
219 * @param mixed $value The value to normalize
220 *
221 * @return mixed The normalized value
222 *
223 * @throws InvalidConfigurationException
224 * @throws DuplicateKeyException
225 */
226 protected function normalizeValue($value)
227 {
228 if (false === $value) {
229 return $value;
230 }
231
232 $value = $this->remapXml($value);
233
234 $isAssoc = array_keys($value) !== range(0, count($value) - 1);
235 $normalized = array();
236 foreach ($value as $k => $v) {
237 if (null !== $this->keyAttribute && is_array($v)) {
238 if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) {
239 $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath());
240 $ex = new InvalidConfigurationException($msg);
241 $ex->setPath($this->getPath());
242
243 throw $ex;
244 } elseif (isset($v[$this->keyAttribute])) {
245 $k = $v[$this->keyAttribute];
246
247 // remove the key attribute when required
248 if ($this->removeKeyAttribute) {
249 unset($v[$this->keyAttribute]);
250 }
251
252 // if only "value" is left
253 if (1 == count($v) && isset($v['value'])) {
254 $v = $v['value'];
255 }
256 }
257
258 if (array_key_exists($k, $normalized)) {
259 $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath());
260 $ex = new DuplicateKeyException($msg);
261 $ex->setPath($this->getPath());
262
263 throw $ex;
264 }
265 }
266
267 $this->prototype->setName($k);
268 if (null !== $this->keyAttribute || $isAssoc) {
269 $normalized[$k] = $this->prototype->normalize($v);
270 } else {
271 $normalized[] = $this->prototype->normalize($v);
272 }
273 }
274
275 return $normalized;
276 }
277
278 /**
279 * Merges values together.
280 *
281 * @param mixed $leftSide The left side to merge
282 * @param mixed $rightSide The right side to merge
283 *
284 * @return mixed The merged values
285 *
286 * @throws InvalidConfigurationException
287 * @throws \RuntimeException
288 */
289 protected function mergeValues($leftSide, $rightSide)
290 {
291 if (false === $rightSide) {
292 // if this is still false after the last config has been merged the
293 // finalization pass will take care of removing this key entirely
294 return false;
295 }
296
297 if (false === $leftSide || !$this->performDeepMerging) {
298 return $rightSide;
299 }
300
301 foreach ($rightSide as $k => $v) {
302 // prototype, and key is irrelevant, so simply append the element
303 if (null === $this->keyAttribute) {
304 $leftSide[] = $v;
305 continue;
306 }
307
308 // no conflict
309 if (!array_key_exists($k, $leftSide)) {
310 if (!$this->allowNewKeys) {
311 $ex = new InvalidConfigurationException(sprintf(
312 'You are not allowed to define new elements for path "%s". '.
313 'Please define all elements for this path in one config file.',
314 $this->getPath()
315 ));
316 $ex->setPath($this->getPath());
317
318 throw $ex;
319 }
320
321 $leftSide[$k] = $v;
322 continue;
323 }
324
325 $this->prototype->setName($k);
326 $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v);
327 }
328
329 return $leftSide;
330 }
331 }
332