This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | // +---------------------------------------------------------------------------+ |
||
4 | // | This file is part of the Agavi package. | |
||
5 | // | Copyright (c) 2005-2011 the Agavi Project. | |
||
6 | // | | |
||
7 | // | For the full copyright and license information, please view the LICENSE | |
||
8 | // | file that was distributed with this source code. You can also view the | |
||
9 | // | LICENSE file online at http://www.agavi.org/LICENSE.txt | |
||
10 | // | vi: set noexpandtab: | |
||
11 | // | Local Variables: | |
||
12 | // | indent-tabs-mode: t | |
||
13 | // | End: | |
||
14 | // +---------------------------------------------------------------------------+ |
||
15 | |||
16 | namespace Agavi\Util; |
||
17 | |||
18 | /** |
||
19 | * PathDefinition implements handling of virtual paths |
||
20 | * |
||
21 | * This class does not implement real filesystem path handling, but uses virtual |
||
22 | * paths. It is primary used in the validation system for handling arrays of |
||
23 | * input. |
||
24 | * |
||
25 | * @package agavi |
||
26 | * @subpackage util |
||
27 | * |
||
28 | * @author Uwe Mesecke <[email protected]> |
||
29 | * @author Dominik del Bondio <[email protected]> |
||
30 | * @copyright Authors |
||
31 | * @copyright The Agavi Project |
||
32 | * |
||
33 | * @since 0.11.0 |
||
34 | * |
||
35 | * @version $Id$ |
||
36 | */ |
||
37 | final class ArrayPathDefinition |
||
38 | { |
||
39 | /** |
||
40 | * constructor |
||
41 | * |
||
42 | * @author Dominik del Bondio <[email protected]> |
||
43 | * @since 0.11.0 |
||
44 | */ |
||
45 | private function __construct() |
||
46 | { |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Converts the given argument to an array of parts for use in the path getter/setters |
||
51 | * @param array|string $partsArrayOrPathString The path string or an array containing the path |
||
52 | * divided into its individual parts. |
||
53 | * |
||
54 | * @return array The array of parts. |
||
55 | * |
||
56 | * @author Dominik del Bondio <[email protected]> |
||
57 | * @since 0.11.6 |
||
58 | */ |
||
59 | protected static function preparePartsArray($partsArrayOrPathString) |
||
60 | { |
||
61 | if (is_array($partsArrayOrPathString)) { |
||
62 | return $partsArrayOrPathString; |
||
63 | } else { |
||
64 | $partInfo = self::getPartsFromPath($partsArrayOrPathString); |
||
65 | $parts = $partInfo['parts']; |
||
66 | if (!$partInfo['absolute']) { |
||
67 | // the value wasn't absolute, so an empty string is used for the first part |
||
68 | array_unshift($parts, ''); |
||
69 | } |
||
70 | return $parts; |
||
71 | } |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Unsets a value at the given path. |
||
76 | * |
||
77 | * @param array|string $partsArrayOrPathString The path string or an array containing the path |
||
78 | * divided into its individual parts. |
||
79 | * @param array $array The array we should operate on. |
||
80 | * |
||
81 | * @return mixed The previously stored value. |
||
82 | * |
||
83 | * @author Dominik del Bondio <[email protected]> |
||
84 | * @since 0.11.0 |
||
85 | */ |
||
86 | public static function &unsetValue($partsArrayOrPathString, array &$array) |
||
87 | { |
||
88 | $parts = self::preparePartsArray($partsArrayOrPathString); |
||
89 | |||
90 | $a =& $array; |
||
91 | |||
92 | $c = count($parts); |
||
93 | for ($i = 0; $i < $c; ++$i) { |
||
94 | $part = $parts[$i]; |
||
95 | $last = ($i+1 == $c); |
||
96 | if ($part !== null) { |
||
97 | if (is_array($a) && is_numeric($part) && strpos($part, '.') === false && strpos($part, ',') === false && (isset($a[(int)$part]) || array_key_exists((int)$part, $a))) { |
||
98 | $part = (int)$part; |
||
99 | } |
||
100 | if (is_array($a) && (isset($a[$part]) || array_key_exists($part, $a))) { |
||
101 | if ($last) { |
||
102 | $oldValue =& $a[$part]; |
||
103 | unset($a[$part]); |
||
104 | return $oldValue; |
||
105 | } else { |
||
106 | $a =& $a[$part]; |
||
107 | } |
||
108 | } else { |
||
109 | $retval = null; |
||
110 | return $retval; |
||
111 | } |
||
112 | } |
||
113 | } |
||
114 | $retval = null; |
||
115 | return $retval; |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Checks whether the array has a value at the given path. |
||
120 | * |
||
121 | * @param array|string $partsArrayOrPathString The path string or an array containing the path |
||
122 | * divided into its individual parts. |
||
123 | * @param array $array The array we should operate on. |
||
124 | * |
||
125 | * @return bool Whether the path exists in this array. |
||
126 | * |
||
127 | * @author Dominik del Bondio <[email protected]> |
||
128 | * @since 0.11.0 |
||
129 | */ |
||
130 | public static function hasValue($partsArrayOrPathString, array &$array) |
||
131 | { |
||
132 | $parts = self::preparePartsArray($partsArrayOrPathString); |
||
133 | |||
134 | $a = $array; |
||
135 | |||
136 | View Code Duplication | foreach ($parts as $part) { |
|
0 ignored issues
–
show
|
|||
137 | if ($part !== null) { |
||
138 | if (is_array($a) && is_numeric($part) && strpos($part, '.') === false && strpos($part, ',') === false && (isset($a[(int)$part]) || array_key_exists((int)$part, $a))) { |
||
139 | $part = (int)$part; |
||
140 | } |
||
141 | if (is_array($a) && (isset($a[$part]) || array_key_exists($part, $a))) { |
||
142 | $a = $a[$part]; |
||
143 | } else { |
||
144 | return false; |
||
145 | } |
||
146 | } |
||
147 | } |
||
148 | |||
149 | return true; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Returns the value at the given path. |
||
154 | * |
||
155 | * @param array|string $partsArrayOrPathString The path string or an array containing the path |
||
156 | * divided into its individual parts. |
||
157 | * @param array $array The array we should operate on. |
||
158 | * @param mixed $default A default value if the path doesn't exist in the array. |
||
159 | * |
||
160 | * @return mixed The value stored at the given path. |
||
161 | * |
||
162 | * @author Dominik del Bondio <[email protected]> |
||
163 | * @since 0.11.0 |
||
164 | */ |
||
165 | public static function &getValue($partsArrayOrPathString, array &$array, $default = null) |
||
166 | { |
||
167 | $parts = self::preparePartsArray($partsArrayOrPathString); |
||
168 | |||
169 | $a = &$array; |
||
170 | |||
171 | View Code Duplication | foreach ($parts as $part) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
172 | if ($part !== null) { |
||
173 | if (is_array($a) && is_numeric($part) && strpos($part, '.') === false && strpos($part, ',') === false && (isset($a[(int)$part]) || array_key_exists((int)$part, $a))) { |
||
174 | $part = (int)$part; |
||
175 | } |
||
176 | if (is_array($a) && (isset($a[$part]) || array_key_exists($part, $a))) { |
||
177 | $a = &$a[$part]; |
||
178 | } else { |
||
179 | //throw new AgaviException('The part: ' . $part . ' does not exist in the given array'); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
48% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
180 | return $default; |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | |||
185 | return $a; |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Sets the value at the given path. |
||
190 | * |
||
191 | * @param array|string $partsArrayOrPathString The path string or an array containing the path |
||
192 | * divided into its individual parts. |
||
193 | * @param array $array The array we should operate on. |
||
194 | * @param mixed $value The value. |
||
195 | * |
||
196 | * @author Dominik del Bondio <[email protected]> |
||
197 | * @since 0.11.0 |
||
198 | */ |
||
199 | public static function setValue($partsArrayOrPathString, array &$array, $value) |
||
200 | { |
||
201 | $parts = self::preparePartsArray($partsArrayOrPathString); |
||
202 | |||
203 | $a = &$array; |
||
204 | |||
205 | foreach ($parts as $part) { |
||
206 | if ($part !== null) { |
||
207 | if (is_array($a) && is_numeric($part) && strpos($part, '.') === false && strpos($part, ',') === false && (isset($a[(int)$part]) || array_key_exists((int)$part, $a))) { |
||
208 | $part = (int)$part; |
||
209 | } |
||
210 | if (!isset($a[$part]) || !is_array($a[$part]) || (is_array($a) && !(isset($a[$part]) || array_key_exists($part, $a)))) { |
||
211 | $a[$part] = array(); |
||
212 | } |
||
213 | $a = &$a[$part]; |
||
214 | } |
||
215 | } |
||
216 | |||
217 | $a = $value; |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Returns an array with the single parts of the given path. |
||
222 | * |
||
223 | * @param string $path The path. |
||
224 | * |
||
225 | * @return array The parts of the given path. |
||
226 | * |
||
227 | * @author Dominik del Bondio <[email protected]> |
||
228 | * @since 0.11.0 |
||
229 | */ |
||
230 | public static function getPartsFromPath($path) |
||
231 | { |
||
232 | if (strlen($path) == 0) { |
||
233 | return array('parts' => array(), 'absolute' => true); |
||
234 | } |
||
235 | |||
236 | $parts = array(); |
||
237 | $absolute = ($path[0] != '['); |
||
238 | if (($pos = strpos($path, '[')) === false) { |
||
239 | if (strpos($path, ']') !== false) { |
||
240 | throw new \InvalidArgumentException('Invalid "]" without opening "[" found'); |
||
241 | } |
||
242 | $parts[] = $path; |
||
243 | } else { |
||
244 | $state = 0; |
||
245 | $cur = ''; |
||
246 | foreach (str_split($path) as $c) { |
||
247 | // this is the fastest way to loop over an string |
||
248 | switch ($state) { |
||
249 | // the order is significant for performance |
||
250 | case 2: |
||
251 | // match all characters between [] |
||
252 | if ($c == ']') { |
||
253 | $parts[] = $cur; |
||
254 | $cur = ''; |
||
255 | $state = 1; |
||
256 | } elseif ($c == '[') { |
||
257 | throw new \InvalidArgumentException('Invalid "[[" found'); |
||
258 | } else { |
||
259 | $cur .= $c; |
||
260 | } |
||
261 | |||
262 | break; |
||
263 | |||
264 | case 0: |
||
265 | // match everything to the first '[' |
||
266 | if ($c != '[') { |
||
267 | $cur .= $c; |
||
268 | } else { |
||
269 | if ($cur !== '') { |
||
270 | $parts[] = $cur; |
||
271 | $cur = ''; |
||
272 | } |
||
273 | $state = 2; |
||
274 | } |
||
275 | break; |
||
276 | |||
277 | case 1: |
||
278 | // match exactly '[' |
||
279 | if ($c == '[') { |
||
280 | $state = 2; |
||
281 | } else { |
||
282 | throw new \InvalidArgumentException('Invalid character after "]" found'); |
||
283 | } |
||
284 | break; |
||
285 | } |
||
286 | } |
||
287 | if ($state == 0) { |
||
288 | $parts[] = $cur; |
||
289 | } elseif ($state == 2) { |
||
290 | throw new \InvalidArgumentException('Missing "]" after opening "["'); |
||
291 | } |
||
292 | } |
||
293 | |||
294 | return array('parts' => $parts, 'absolute' => $absolute); |
||
295 | } |
||
296 | |||
297 | |||
298 | /** |
||
299 | * Returns the flat key names of an array. |
||
300 | * |
||
301 | * This method calls itself recursively to flatten the keys. |
||
302 | * |
||
303 | * @param array $array The array which keys should be returned. |
||
304 | * @param string $prefix The prefix for the name (only for internal use). |
||
305 | * |
||
306 | * @return array The flattened keys. |
||
307 | * |
||
308 | * @author Dominik del Bondio <[email protected]> |
||
309 | * @since 0.11.0 |
||
310 | */ |
||
311 | View Code Duplication | public static function getFlatKeyNames(array $array, $prefix = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
312 | { |
||
313 | $names = array(); |
||
314 | foreach ($array as $key => $value) { |
||
315 | if ($prefix === null) { |
||
316 | // create the top node when no prefix was given |
||
317 | if (strlen($key) == 0) { |
||
318 | // when an empty key was used at top level, create a "relative" path, so the empty string doesn't get lost |
||
319 | $name = '[' . $key . ']'; |
||
320 | } else { |
||
321 | $name = $key; |
||
322 | } |
||
323 | } else { |
||
324 | $name = $prefix . '[' . $key . ']'; |
||
325 | } |
||
326 | |||
327 | if (is_array($value)) { |
||
328 | $names = array_merge($names, ArrayPathDefinition::getFlatKeyNames($value, $name)); |
||
329 | } else { |
||
330 | $names[] = $name; |
||
331 | } |
||
332 | } |
||
333 | return $names; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * Returns the flattened version of an array. So the returned array |
||
338 | * will be one dimensional with the flattened key names as keys |
||
339 | * and their values from the original array as values. |
||
340 | * |
||
341 | * This method calls itself recursively to flatten the array. |
||
342 | * |
||
343 | * @param array $array The array which should be flattened. |
||
344 | * @param string $prefix The prefix for the key names (only for internal use). |
||
345 | * |
||
346 | * @return array The flattened array. |
||
347 | * |
||
348 | * @author Dominik del Bondio <[email protected]> |
||
349 | * @since 1.0.0 |
||
350 | */ |
||
351 | View Code Duplication | public static function flatten($array, $prefix = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
352 | { |
||
353 | $flatArray = array(); |
||
354 | foreach ($array as $key => $value) { |
||
355 | if ($prefix === null) { |
||
356 | // create the top node when no prefix was given |
||
357 | if (strlen($key) == 0) { |
||
358 | // when an empty key was used at top level, create a "relative" path, so the empty string doesn't get lost |
||
359 | $name = '[' . $key . ']'; |
||
360 | } else { |
||
361 | $name = $key; |
||
362 | } |
||
363 | } else { |
||
364 | $name = $prefix . '[' . $key . ']'; |
||
365 | } |
||
366 | |||
367 | if (is_array($value)) { |
||
368 | $flatArray += ArrayPathDefinition::flatten($value, $name); |
||
369 | } else { |
||
370 | $flatArray[$name] = $value; |
||
371 | } |
||
372 | } |
||
373 | return $flatArray; |
||
374 | } |
||
375 | } |
||
376 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.