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 | namespace kint\inc; |
|||||||||||
4 | ||||||||||||
5 | use kint\decorators\Kint_Decorators_Rich; |
|||||||||||
6 | use kint\Kint; |
|||||||||||
7 | use voku\helper\UTF8; |
|||||||||||
8 | ||||||||||||
9 | /** |
|||||||||||
10 | * Class KintParser |
|||||||||||
11 | */ |
|||||||||||
12 | abstract class KintParser extends KintVariableData |
|||||||||||
13 | { |
|||||||||||
14 | /** |
|||||||||||
15 | * @var int |
|||||||||||
16 | */ |
|||||||||||
17 | private static $_level = 0; |
|||||||||||
18 | ||||||||||||
19 | /** |
|||||||||||
20 | * @var bool |
|||||||||||
21 | */ |
|||||||||||
22 | private static $_dealingWithGlobals = false; |
|||||||||||
23 | ||||||||||||
24 | /** |
|||||||||||
25 | * @var bool |
|||||||||||
26 | */ |
|||||||||||
27 | private static $_placeFullStringInValue = false; |
|||||||||||
28 | ||||||||||||
29 | /** |
|||||||||||
30 | * @var array |
|||||||||||
31 | */ |
|||||||||||
32 | private static $_customDataTypes = array( |
|||||||||||
33 | 'ClassMethods', |
|||||||||||
34 | 'ClassStatics', |
|||||||||||
35 | 'Color', |
|||||||||||
36 | 'FsPath', |
|||||||||||
37 | 'Json', |
|||||||||||
38 | 'Microtime', |
|||||||||||
39 | 'ObjectIterateable', |
|||||||||||
40 | 'SplObjectStorage', |
|||||||||||
41 | 'Timestamp', |
|||||||||||
42 | 'Xml', |
|||||||||||
43 | ); |
|||||||||||
44 | ||||||||||||
45 | /** |
|||||||||||
46 | * @var array |
|||||||||||
47 | */ |
|||||||||||
48 | private static $_objectParsers = array( |
|||||||||||
49 | 'Closure', |
|||||||||||
50 | 'Smarty', |
|||||||||||
51 | 'SplFileInfo', |
|||||||||||
52 | ); |
|||||||||||
53 | ||||||||||||
54 | /** |
|||||||||||
55 | * @var array |
|||||||||||
56 | */ |
|||||||||||
57 | private static $_objects = array(); |
|||||||||||
58 | ||||||||||||
59 | /** |
|||||||||||
60 | * @var mixed |
|||||||||||
61 | */ |
|||||||||||
62 | private static $_marker; |
|||||||||||
63 | ||||||||||||
64 | /** |
|||||||||||
65 | * @var bool |
|||||||||||
66 | */ |
|||||||||||
67 | private static $_skipAlternatives = false; |
|||||||||||
68 | ||||||||||||
69 | /** |
|||||||||||
70 | * @return bool |
|||||||||||
71 | */ |
|||||||||||
72 | 2 | private static function _checkDepth() |
||||||||||
73 | { |
|||||||||||
74 | 2 | return Kint::$maxLevels != 0 && self::$_level >= Kint::$maxLevels; |
||||||||||
75 | } |
|||||||||||
76 | ||||||||||||
77 | /** |
|||||||||||
78 | * @param KintVariableData $kintVar |
|||||||||||
79 | * |
|||||||||||
80 | * @return string |
|||||||||||
81 | */ |
|||||||||||
82 | private static function _decorateCell(KintVariableData $kintVar) |
|||||||||||
83 | { |
|||||||||||
84 | if ($kintVar->extendedValue !== null || !empty($kintVar->_alternatives)) { |
|||||||||||
85 | return '<td>' . Kint_Decorators_Rich::decorate($kintVar) . '</td>'; |
|||||||||||
86 | } |
|||||||||||
87 | ||||||||||||
88 | $output = '<td'; |
|||||||||||
89 | ||||||||||||
90 | if ($kintVar->value !== null) { |
|||||||||||
91 | $output .= ' title="' . $kintVar->type; |
|||||||||||
92 | ||||||||||||
93 | if ($kintVar->size !== null) { |
|||||||||||
94 | $output .= ' (' . $kintVar->size . ')'; |
|||||||||||
95 | } |
|||||||||||
96 | ||||||||||||
97 | $output .= '">' . $kintVar->value; |
|||||||||||
98 | } else { |
|||||||||||
99 | $output .= '>'; |
|||||||||||
100 | ||||||||||||
101 | if ($kintVar->type !== 'NULL') { |
|||||||||||
102 | $output .= '<u>' . $kintVar->type; |
|||||||||||
103 | ||||||||||||
104 | if ($kintVar->size !== null) { |
|||||||||||
105 | $output .= '(' . $kintVar->size . ')'; |
|||||||||||
106 | } |
|||||||||||
107 | ||||||||||||
108 | $output .= '</u>'; |
|||||||||||
109 | } else { |
|||||||||||
110 | $output .= '<u>NULL</u>'; |
|||||||||||
111 | } |
|||||||||||
112 | } |
|||||||||||
113 | ||||||||||||
114 | ||||||||||||
115 | return $output . '</td>'; |
|||||||||||
116 | } |
|||||||||||
117 | ||||||||||||
118 | /** |
|||||||||||
119 | * @param array $variable |
|||||||||||
120 | * |
|||||||||||
121 | * @return array|bool |
|||||||||||
122 | */ |
|||||||||||
123 | 2 | private static function _isArrayTabular(array &$variable) |
||||||||||
124 | { |
|||||||||||
125 | 2 | if (Kint::enabled() !== Kint::MODE_RICH) { |
||||||||||
126 | 1 | return false; |
||||||||||
127 | } |
|||||||||||
128 | ||||||||||||
129 | 1 | $arrayKeys = array(); |
||||||||||
130 | 1 | $keys = null; |
||||||||||
131 | 1 | $closeEnough = false; |
||||||||||
132 | 1 | foreach ($variable as $row) { |
||||||||||
133 | 1 | if (!is_array($row) || empty($row)) { |
||||||||||
134 | 1 | return false; |
||||||||||
135 | } |
|||||||||||
136 | ||||||||||||
137 | foreach ($row as $col) { |
|||||||||||
138 | if (!empty($col) && !is_scalar($col)) { |
|||||||||||
139 | return false; |
|||||||||||
140 | } // TODO: add tabular "tolerance" |
|||||||||||
141 | } |
|||||||||||
142 | ||||||||||||
143 | if (isset($keys) && !$closeEnough) { |
|||||||||||
144 | # let's just see if the first two rows have same keys, that's faster and has the |
|||||||||||
145 | # positive side effect of easily spotting missing keys in later rows |
|||||||||||
146 | if ($keys !== array_keys($row)) { |
|||||||||||
147 | return false; |
|||||||||||
148 | } |
|||||||||||
149 | ||||||||||||
150 | $closeEnough = true; |
|||||||||||
151 | } else { |
|||||||||||
152 | $keys = array_keys($row); |
|||||||||||
153 | } |
|||||||||||
154 | ||||||||||||
155 | $arrayKeys = array_unique(array_merge($arrayKeys, $keys)); |
|||||||||||
156 | } |
|||||||||||
157 | ||||||||||||
158 | return $arrayKeys; |
|||||||||||
159 | } |
|||||||||||
160 | ||||||||||||
161 | /** |
|||||||||||
162 | * main and usually single method a custom parser must implement |
|||||||||||
163 | * |
|||||||||||
164 | * @param mixed $variable |
|||||||||||
165 | * |
|||||||||||
166 | * @return mixed [!!!] false is returned if the variable is not of current type |
|||||||||||
167 | */ |
|||||||||||
168 | abstract protected function _parse(&$variable); |
|||||||||||
169 | ||||||||||||
170 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
171 | /** |
|||||||||||
172 | * @param mixed $variable |
|||||||||||
173 | * @param KintVariableData $variableData |
|||||||||||
174 | * |
|||||||||||
175 | * @return bool|void |
|||||||||||
176 | */ |
|||||||||||
177 | 2 | private static function _parse_array(&$variable, KintVariableData $variableData) |
||||||||||
178 | { |
|||||||||||
179 | 2 | isset(self::$_marker) or self::$_marker = "\x00" . uniqid('kint', true); |
||||||||||
0 ignored issues
–
show
|
||||||||||||
180 | ||||||||||||
181 | # naturally, $GLOBALS variable is an intertwined recursion nightmare, use black magic |
|||||||||||
182 | 2 | $globalsDetector = false; |
||||||||||
183 | if ( |
|||||||||||
184 | 2 | isset($variable['GLOBALS']) |
||||||||||
185 | && |
|||||||||||
186 | 2 | is_array($variable['GLOBALS']) |
||||||||||
187 | ) { |
|||||||||||
188 | $globalsDetector = "\x01" . uniqid('kint', true); |
|||||||||||
189 | ||||||||||||
190 | $variable['GLOBALS'][$globalsDetector] = true; |
|||||||||||
191 | if (isset($variable[$globalsDetector])) { |
|||||||||||
192 | unset($variable[$globalsDetector]); |
|||||||||||
193 | self::$_dealingWithGlobals = true; |
|||||||||||
194 | } else { |
|||||||||||
195 | unset($variable['GLOBALS'][$globalsDetector]); |
|||||||||||
196 | $globalsDetector = false; |
|||||||||||
197 | } |
|||||||||||
198 | } |
|||||||||||
199 | ||||||||||||
200 | 2 | $variableData->type = 'array'; |
||||||||||
201 | 2 | $variableData->size = count($variable); |
||||||||||
202 | ||||||||||||
203 | 2 | if ($variableData->size === 0) { |
||||||||||
204 | /** @noinspection PhpInconsistentReturnPointsInspection */ |
|||||||||||
205 | return; |
|||||||||||
206 | } |
|||||||||||
207 | ||||||||||||
208 | 2 | if (isset($variable[self::$_marker])) { # recursion; TODO: mayhaps show from where |
||||||||||
209 | if (self::$_dealingWithGlobals) { |
|||||||||||
210 | $variableData->value = '*RECURSION*'; |
|||||||||||
211 | } else { |
|||||||||||
212 | unset($variable[self::$_marker]); |
|||||||||||
213 | $variableData->value = self::$_marker; |
|||||||||||
214 | } |
|||||||||||
215 | ||||||||||||
216 | return false; |
|||||||||||
217 | } |
|||||||||||
218 | 2 | if (self::_checkDepth()) { |
||||||||||
219 | $variableData->extendedValue = '*DEPTH TOO GREAT*'; |
|||||||||||
0 ignored issues
–
show
It seems like
'*DEPTH TOO GREAT*' of type string is incompatible with the declared type array<integer,object<kint\inc\KintVariableData>> of property $extendedValue .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
220 | ||||||||||||
221 | return false; |
|||||||||||
222 | } |
|||||||||||
223 | ||||||||||||
224 | 2 | $isSequential = self::_isSequential($variable); |
||||||||||
225 | ||||||||||||
226 | if ( |
|||||||||||
227 | 2 | $variableData->size > 1 |
||||||||||
228 | && |
|||||||||||
229 | 2 | ($arrayKeys = self::_isArrayTabular($variable)) !== false |
||||||||||
230 | ) { |
|||||||||||
231 | $variable[self::$_marker] = true; # this must be AFTER _isArrayTabular |
|||||||||||
232 | $firstRow = true; |
|||||||||||
233 | $extendedValue = '<table class="kint-report"><thead>'; |
|||||||||||
234 | ||||||||||||
235 | foreach ($variable as $rowIndex => &$row) { |
|||||||||||
236 | # display strings in their full length |
|||||||||||
237 | self::$_placeFullStringInValue = true; |
|||||||||||
238 | ||||||||||||
239 | if ($rowIndex === self::$_marker) { |
|||||||||||
240 | continue; |
|||||||||||
241 | } |
|||||||||||
242 | ||||||||||||
243 | if (isset($row[self::$_marker])) { |
|||||||||||
244 | $variableData->value = '*RECURSION*'; |
|||||||||||
245 | ||||||||||||
246 | return false; |
|||||||||||
247 | } |
|||||||||||
248 | ||||||||||||
249 | $extendedValue .= '<tr>'; |
|||||||||||
250 | if ($isSequential) { |
|||||||||||
251 | $output = '<td>' . '#' . ($rowIndex + 1) . '</td>'; |
|||||||||||
252 | } else { |
|||||||||||
253 | $output = self::_decorateCell(self::factory($rowIndex)); |
|||||||||||
254 | } |
|||||||||||
255 | if ($firstRow) { |
|||||||||||
256 | $extendedValue .= '<th> </th>'; |
|||||||||||
257 | } |
|||||||||||
258 | ||||||||||||
259 | # we iterate the known full set of keys from all rows in case some appeared at later rows, |
|||||||||||
260 | # as we only check the first two to assume |
|||||||||||
261 | foreach ($arrayKeys as $key) { |
|||||||||||
262 | if ($firstRow) { |
|||||||||||
263 | $extendedValue .= '<th>' . self::escape($key) . '</th>'; |
|||||||||||
264 | } |
|||||||||||
265 | ||||||||||||
266 | if (!isset($row[$key])) { |
|||||||||||
267 | $output .= '<td class="kint-empty"></td>'; |
|||||||||||
268 | continue; |
|||||||||||
269 | } |
|||||||||||
270 | ||||||||||||
271 | $var = self::factory($row[$key]); |
|||||||||||
272 | ||||||||||||
273 | if ($var->value === self::$_marker) { |
|||||||||||
274 | $variableData->value = '*RECURSION*'; |
|||||||||||
275 | ||||||||||||
276 | return false; |
|||||||||||
277 | } elseif ($var->value === '*RECURSION*') { |
|||||||||||
278 | $output .= '<td class="kint-empty"><u>*RECURSION*</u></td>'; |
|||||||||||
279 | } else { |
|||||||||||
280 | $output .= self::_decorateCell($var); |
|||||||||||
281 | } |
|||||||||||
282 | unset($var); |
|||||||||||
283 | } |
|||||||||||
284 | ||||||||||||
285 | if ($firstRow) { |
|||||||||||
286 | $extendedValue .= '</tr></thead><tr>'; |
|||||||||||
287 | $firstRow = false; |
|||||||||||
288 | } |
|||||||||||
289 | ||||||||||||
290 | $extendedValue .= $output . '</tr>'; |
|||||||||||
291 | } |
|||||||||||
292 | unset($row); |
|||||||||||
293 | self::$_placeFullStringInValue = false; |
|||||||||||
294 | ||||||||||||
295 | $variableData->extendedValue = $extendedValue . '</table>'; |
|||||||||||
0 ignored issues
–
show
It seems like
$extendedValue . '</table>' of type string is incompatible with the declared type array<integer,object<kint\inc\KintVariableData>> of property $extendedValue .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
296 | ||||||||||||
297 | } else { |
|||||||||||
298 | 2 | $variable[self::$_marker] = true; |
||||||||||
299 | 2 | $extendedValue = array(); |
||||||||||
300 | ||||||||||||
301 | 2 | foreach ($variable as $key => &$val) { |
||||||||||
302 | 2 | if ($key === self::$_marker) { |
||||||||||
303 | 2 | continue; |
||||||||||
304 | } |
|||||||||||
305 | ||||||||||||
306 | 2 | $output = self::factory($val); |
||||||||||
307 | 2 | if ($output->value === self::$_marker) { |
||||||||||
308 | $variableData->value = '*RECURSION*'; // recursion occurred on a higher level, thus $this is recursion |
|||||||||||
309 | return false; |
|||||||||||
310 | } |
|||||||||||
311 | 2 | if (!$isSequential) { |
||||||||||
312 | $output->operator = '=>'; |
|||||||||||
313 | } |
|||||||||||
314 | 2 | $output->name = $isSequential ? null : "'" . $key . "'"; |
||||||||||
315 | 2 | $extendedValue[] = $output; |
||||||||||
316 | } |
|||||||||||
317 | 2 | unset($val); |
||||||||||
318 | 2 | $variableData->extendedValue = $extendedValue; |
||||||||||
319 | } |
|||||||||||
320 | ||||||||||||
321 | 2 | if ($globalsDetector) { |
||||||||||
0 ignored issues
–
show
The expression
$globalsDetector of type string|false is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
||||||||||||
322 | self::$_dealingWithGlobals = false; |
|||||||||||
323 | } |
|||||||||||
324 | ||||||||||||
325 | 2 | unset($variable[self::$_marker]); |
||||||||||
326 | ||||||||||||
327 | 2 | return true; |
||||||||||
328 | } |
|||||||||||
329 | ||||||||||||
330 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
331 | /** |
|||||||||||
332 | * @param mixed $variable |
|||||||||||
333 | * @param KintVariableData $variableData |
|||||||||||
334 | */ |
|||||||||||
335 | private static function _parse_boolean(&$variable, KintVariableData $variableData) |
|||||||||||
336 | { |
|||||||||||
337 | $variableData->type = 'bool'; |
|||||||||||
338 | $variableData->value = $variable ? 'TRUE' : 'FALSE'; |
|||||||||||
339 | } |
|||||||||||
340 | ||||||||||||
341 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
342 | /** |
|||||||||||
343 | * @param mixed $variable |
|||||||||||
344 | * @param KintVariableData $variableData |
|||||||||||
345 | */ |
|||||||||||
346 | 2 | private static function _parse_double(&$variable, KintVariableData $variableData) |
||||||||||
347 | { |
|||||||||||
348 | 2 | $variableData->type = 'float'; |
||||||||||
349 | /** @noinspection ReferenceMismatchInspection */ |
|||||||||||
350 | 2 | $variableData->value = $variable; |
||||||||||
351 | 2 | } |
||||||||||
352 | ||||||||||||
353 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
354 | /** |
|||||||||||
355 | * @param mixed $variable |
|||||||||||
356 | * @param KintVariableData $variableData |
|||||||||||
357 | */ |
|||||||||||
358 | 2 | private static function _parse_integer(&$variable, KintVariableData $variableData) |
||||||||||
359 | { |
|||||||||||
360 | 2 | $variableData->type = 'integer'; |
||||||||||
361 | /** @noinspection ReferenceMismatchInspection */ |
|||||||||||
362 | 2 | $variableData->value = $variable; |
||||||||||
363 | 2 | } |
||||||||||
364 | ||||||||||||
365 | ||||||||||||
366 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
367 | /** |
|||||||||||
368 | * @param mixed $variable |
|||||||||||
369 | * @param KintVariableData $variableData |
|||||||||||
370 | */ |
|||||||||||
371 | 2 | private static function _parse_null(/** @noinspection PhpUnusedParameterInspection */ |
||||||||||
372 | &$variable, KintVariableData $variableData) |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
373 | { |
|||||||||||
374 | 2 | $variableData->type = 'NULL'; |
||||||||||
375 | 2 | } |
||||||||||
376 | ||||||||||||
377 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
378 | /** |
|||||||||||
379 | * @param mixed $variable |
|||||||||||
380 | * @param KintVariableData $variableData |
|||||||||||
381 | * |
|||||||||||
382 | * @return bool |
|||||||||||
383 | */ |
|||||||||||
384 | 2 | private static function _parse_object(&$variable, KintVariableData $variableData) |
||||||||||
385 | { |
|||||||||||
386 | 2 | if (function_exists('spl_object_hash')) { |
||||||||||
387 | 2 | $hash = spl_object_hash($variable); |
||||||||||
388 | } else { |
|||||||||||
389 | ob_start(); |
|||||||||||
390 | /** @noinspection ForgottenDebugOutputInspection */ |
|||||||||||
391 | /** @noinspection ReferenceMismatchInspection */ |
|||||||||||
392 | var_dump($variable); |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
393 | preg_match('[#(\d+)]', ob_get_clean(), $match); |
|||||||||||
394 | $hash = $match[1]; |
|||||||||||
395 | } |
|||||||||||
396 | ||||||||||||
397 | 2 | $castedArray = (array)$variable; |
||||||||||
398 | 2 | $variableData->type = get_class($variable); |
||||||||||
399 | 2 | $variableData->size = count($castedArray); |
||||||||||
400 | ||||||||||||
401 | 2 | if (isset(self::$_objects[$hash])) { |
||||||||||
402 | $variableData->value = '*RECURSION*'; |
|||||||||||
403 | ||||||||||||
404 | return false; |
|||||||||||
405 | } |
|||||||||||
406 | 2 | if (self::_checkDepth()) { |
||||||||||
407 | $variableData->extendedValue = '*DEPTH TOO GREAT*'; |
|||||||||||
0 ignored issues
–
show
It seems like
'*DEPTH TOO GREAT*' of type string is incompatible with the declared type array<integer,object<kint\inc\KintVariableData>> of property $extendedValue .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
408 | ||||||||||||
409 | return false; |
|||||||||||
410 | } |
|||||||||||
411 | ||||||||||||
412 | # ArrayObject (and maybe ArrayIterator, did not try yet) unsurprisingly consist of mainly dark magic. |
|||||||||||
413 | # What bothers me most, var_dump sees no problem with it, and ArrayObject also uses a custom, |
|||||||||||
414 | # undocumented serialize function, so you can see the properties in internal functions, but |
|||||||||||
415 | # can never iterate some of them if the flags are not STD_PROP_LIST. Fun stuff. |
|||||||||||
416 | if ( |
|||||||||||
417 | 2 | $variableData->type === 'ArrayObject' |
||||||||||
418 | || |
|||||||||||
419 | 2 | is_subclass_of($variable, 'ArrayObject') |
||||||||||
420 | ) { |
|||||||||||
421 | ||||||||||||
422 | /* @var $variable \ArrayObject */ |
|||||||||||
423 | ||||||||||||
424 | $arrayObjectFlags = $variable->getFlags(); |
|||||||||||
425 | $variable->setFlags(\ArrayObject::STD_PROP_LIST); |
|||||||||||
426 | } |
|||||||||||
427 | ||||||||||||
428 | 2 | self::$_objects[$hash] = true; // TODO: store reflectorObject here for alternatives cache |
||||||||||
429 | 2 | $reflector = new \ReflectionObject($variable); |
||||||||||
430 | ||||||||||||
431 | # add link to definition of user-land objects |
|||||||||||
432 | if ( |
|||||||||||
433 | 2 | Kint::$fileLinkFormat |
||||||||||
434 | && |
|||||||||||
435 | 2 | Kint::enabled() === Kint::MODE_RICH |
||||||||||
436 | && |
|||||||||||
437 | 2 | $reflector->isUserDefined() |
||||||||||
438 | ) { |
|||||||||||
439 | $url = Kint::getIdeLink($reflector->getFileName(), $reflector->getStartLine()); |
|||||||||||
440 | ||||||||||||
441 | $class = (strpos($url, 'http://') === 0) ? 'class="kint-ide-link" ' : ''; |
|||||||||||
442 | $variableData->type = "<a {$class}href=\"{$url}\">{$variableData->type}</a>"; |
|||||||||||
443 | } |
|||||||||||
444 | 2 | $variableData->size = 0; |
||||||||||
445 | ||||||||||||
446 | 2 | $extendedValue = array(); |
||||||||||
447 | 2 | $encountered = array(); |
||||||||||
448 | ||||||||||||
449 | # copy the object as an array as it provides more info than Reflection (depends) |
|||||||||||
450 | 2 | foreach ($castedArray as $key => $value) { |
||||||||||
451 | /* casting object to array: |
|||||||||||
452 | * integer properties are inaccessible; |
|||||||||||
453 | * private variables have the class name prepended to the variable name; |
|||||||||||
454 | * protected variables have a '*' prepended to the variable name. |
|||||||||||
455 | * These prepended values have null bytes on either side. |
|||||||||||
456 | * http://www.php.net/manual/en/language.types.array.php#language.types.array.casting |
|||||||||||
457 | */ |
|||||||||||
458 | if ($key[0] === "\x00") { |
|||||||||||
459 | ||||||||||||
460 | $access = $key[1] === '*' ? 'protected' : 'private'; |
|||||||||||
461 | ||||||||||||
462 | // Remove the access level from the variable name. |
|||||||||||
463 | $key = substr($key, strrpos($key, "\x00") + 1); |
|||||||||||
464 | } else { |
|||||||||||
465 | $access = 'public'; |
|||||||||||
466 | } |
|||||||||||
467 | ||||||||||||
468 | $encountered[$key] = true; |
|||||||||||
469 | ||||||||||||
470 | $output = self::factory($value, self::escape($key)); |
|||||||||||
471 | $output->access = $access; |
|||||||||||
472 | $output->operator = '->'; |
|||||||||||
473 | $extendedValue[] = $output; |
|||||||||||
474 | $variableData->size++; |
|||||||||||
475 | } |
|||||||||||
476 | ||||||||||||
477 | 2 | foreach ($reflector->getProperties() as $property) { |
||||||||||
478 | $name = $property->name; |
|||||||||||
479 | if ( |
|||||||||||
480 | isset($encountered[$name]) |
|||||||||||
481 | || |
|||||||||||
482 | $property->isStatic() |
|||||||||||
483 | ) { |
|||||||||||
484 | continue; |
|||||||||||
485 | } |
|||||||||||
486 | ||||||||||||
487 | View Code Duplication | if ($property->isProtected()) { |
||||||||||
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. ![]() |
||||||||||||
488 | $property->setAccessible(true); |
|||||||||||
489 | $access = 'protected'; |
|||||||||||
490 | } elseif ($property->isPrivate()) { |
|||||||||||
491 | $property->setAccessible(true); |
|||||||||||
492 | $access = 'private'; |
|||||||||||
493 | } else { |
|||||||||||
494 | $access = 'public'; |
|||||||||||
495 | } |
|||||||||||
496 | ||||||||||||
497 | $value = $property->getValue($variable); |
|||||||||||
498 | ||||||||||||
499 | $output = self::factory($value, self::escape($name)); |
|||||||||||
500 | $output->access = $access; |
|||||||||||
501 | $output->operator = '->'; |
|||||||||||
502 | $extendedValue[] = $output; |
|||||||||||
503 | $variableData->size++; |
|||||||||||
504 | } |
|||||||||||
505 | ||||||||||||
506 | 2 | if (isset($arrayObjectFlags)) { |
||||||||||
507 | $variable->setFlags($arrayObjectFlags); |
|||||||||||
508 | } |
|||||||||||
509 | ||||||||||||
510 | 2 | if ($variableData->size) { |
||||||||||
511 | $variableData->extendedValue = $extendedValue; |
|||||||||||
512 | } |
|||||||||||
513 | ||||||||||||
514 | 2 | return true; |
||||||||||
515 | } |
|||||||||||
516 | ||||||||||||
517 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
518 | /** |
|||||||||||
519 | * @param mixed $variable |
|||||||||||
520 | * @param KintVariableData $variableData |
|||||||||||
521 | */ |
|||||||||||
522 | private static function _parse_resource(&$variable, KintVariableData $variableData) |
|||||||||||
523 | { |
|||||||||||
524 | $resourceType = get_resource_type($variable); |
|||||||||||
525 | $variableData->type = "resource ({$resourceType})"; |
|||||||||||
526 | ||||||||||||
527 | if ( |
|||||||||||
528 | $resourceType === 'stream' |
|||||||||||
529 | && |
|||||||||||
530 | $meta = stream_get_meta_data($variable) |
|||||||||||
531 | ) { |
|||||||||||
532 | ||||||||||||
533 | /** @noinspection NestedPositiveIfStatementsInspection */ |
|||||||||||
534 | if (isset($meta['uri'])) { |
|||||||||||
535 | $file = $meta['uri']; |
|||||||||||
536 | ||||||||||||
537 | if (function_exists('stream_is_local')) { |
|||||||||||
538 | // Only exists on PHP >= 5.2.4 |
|||||||||||
539 | if (stream_is_local($file)) { |
|||||||||||
540 | $file = Kint::shortenPath($file); |
|||||||||||
541 | } |
|||||||||||
542 | } |
|||||||||||
543 | ||||||||||||
544 | $variableData->value = $file; |
|||||||||||
545 | } |
|||||||||||
546 | } |
|||||||||||
547 | } |
|||||||||||
548 | ||||||||||||
549 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
550 | /** |
|||||||||||
551 | * @param mixed $variable |
|||||||||||
552 | * @param KintVariableData $variableData |
|||||||||||
553 | */ |
|||||||||||
554 | 2 | private static function _parse_string(&$variable, KintVariableData $variableData) |
||||||||||
555 | { |
|||||||||||
556 | 2 | $variableData->type = 'string'; |
||||||||||
557 | ||||||||||||
558 | 2 | $encoding = self::_detectEncoding($variable); |
||||||||||
559 | 2 | if ($encoding) { |
||||||||||
0 ignored issues
–
show
The expression
$encoding of type false|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
||||||||||||
560 | 2 | $variableData->type .= ' [' . $encoding . ']'; |
||||||||||
561 | } |
|||||||||||
562 | ||||||||||||
563 | 2 | $variableData->size = UTF8::strlen($variable); |
||||||||||
564 | 2 | if (Kint::enabled() !== Kint::MODE_RICH) { |
||||||||||
565 | 1 | $variableData->value = '"' . self::escape($variable, $encoding) . '"'; |
||||||||||
566 | ||||||||||||
567 | 1 | return; |
||||||||||
568 | } |
|||||||||||
569 | ||||||||||||
570 | 1 | if (!self::$_placeFullStringInValue) { |
||||||||||
571 | ||||||||||||
572 | 1 | $strippedString = preg_replace('[\s+]', ' ', $variable); |
||||||||||
573 | if ( |
|||||||||||
574 | 1 | Kint::$maxStrLength |
||||||||||
575 | && |
|||||||||||
576 | 1 | $variableData->size > Kint::$maxStrLength |
||||||||||
577 | ) { |
|||||||||||
578 | ||||||||||||
579 | $tmpStrippedString = self::_substr($strippedString, 0, Kint::$maxStrLength, $encoding); |
|||||||||||
0 ignored issues
–
show
It seems like
$encoding defined by self::_detectEncoding($variable) on line 558 can also be of type false ; however, kint\inc\KintVariableData::_substr() does only seem to accept string|null , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
||||||||||||
580 | ||||||||||||
581 | // encode and truncate |
|||||||||||
582 | $variableData->value = '"' . self::escape($tmpStrippedString, $encoding) . '…"'; |
|||||||||||
583 | $variableData->extendedValue = self::escape($variable, $encoding); |
|||||||||||
0 ignored issues
–
show
It seems like
self::escape($variable, $encoding) of type string or null is incompatible with the declared type array<integer,object<kint\inc\KintVariableData>> of property $extendedValue .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
584 | ||||||||||||
585 | return; |
|||||||||||
586 | 1 | } elseif ($variable !== $strippedString) { // omit no data from display |
||||||||||
587 | ||||||||||||
588 | $variableData->value = '"' . self::escape($variable, $encoding) . '"'; |
|||||||||||
589 | $variableData->extendedValue = self::escape($variable, $encoding); |
|||||||||||
590 | ||||||||||||
591 | return; |
|||||||||||
592 | } |
|||||||||||
593 | } |
|||||||||||
594 | ||||||||||||
595 | 1 | $variableData->value = '"' . self::escape($variable, $encoding) . '"'; |
||||||||||
596 | 1 | } |
||||||||||
597 | ||||||||||||
598 | /** @noinspection PhpUnusedPrivateMethodInspection */ |
|||||||||||
599 | /** |
|||||||||||
600 | * @param mixed $variable |
|||||||||||
601 | * @param KintVariableData $variableData |
|||||||||||
602 | */ |
|||||||||||
603 | private static function _parse_unknown(&$variable, KintVariableData $variableData) |
|||||||||||
604 | { |
|||||||||||
605 | $type = gettype($variable); |
|||||||||||
606 | $variableData->type = 'UNKNOWN' . (!empty($type) ? " ({$type})" : ''); |
|||||||||||
607 | $variableData->value = var_export($variable, true); |
|||||||||||
608 | } |
|||||||||||
609 | ||||||||||||
610 | /** |
|||||||||||
611 | * @param mixed $value |
|||||||||||
612 | * @param null|false|string $encoding |
|||||||||||
613 | * |
|||||||||||
614 | * @return string|null |
|||||||||||
615 | */ |
|||||||||||
616 | 2 | public static function escape(&$value, $encoding = null) |
||||||||||
617 | { |
|||||||||||
618 | 2 | if (empty($value)) { |
||||||||||
619 | return $value; |
|||||||||||
620 | } |
|||||||||||
621 | ||||||||||||
622 | 2 | $kintEnabled = Kint::enabled(); |
||||||||||
623 | ||||||||||||
624 | 2 | if ($kintEnabled === Kint::MODE_CLI) { |
||||||||||
625 | 1 | $value = str_replace("\x1b", '\\x1b', $value); |
||||||||||
626 | } |
|||||||||||
627 | ||||||||||||
628 | if ( |
|||||||||||
629 | 2 | $kintEnabled === Kint::MODE_CLI |
||||||||||
630 | || |
|||||||||||
631 | 2 | $kintEnabled === Kint::MODE_WHITESPACE |
||||||||||
632 | ) { |
|||||||||||
633 | 1 | return $value; |
||||||||||
634 | } |
|||||||||||
635 | ||||||||||||
636 | 1 | if (!$encoding) { |
||||||||||
637 | $encoding = self::_detectEncoding($value); |
|||||||||||
638 | } |
|||||||||||
639 | ||||||||||||
640 | 1 | $value = htmlspecialchars($value, ENT_NOQUOTES, $encoding === 'ASCII' ? 'UTF-8' : $encoding); |
||||||||||
641 | ||||||||||||
642 | ||||||||||||
643 | // TODO: we could make the symbols hover-title show the code for the invisible symbol |
|||||||||||
644 | 1 | if ($encoding === 'UTF-8') { |
||||||||||
645 | # when possible force invisible characters to have some sort of display (experimental) |
|||||||||||
646 | 1 | $value = UTF8::remove_invisible_characters($value, false, '?'); |
||||||||||
647 | } |
|||||||||||
648 | ||||||||||||
649 | # this call converts all non-ASCII characters into html chars of format |
|||||||||||
650 | 1 | $value = UTF8::html_encode($value, true, $encoding); |
||||||||||
0 ignored issues
–
show
|
||||||||||||
651 | ||||||||||||
652 | 1 | return $value; |
||||||||||
653 | } |
|||||||||||
654 | ||||||||||||
655 | /** |
|||||||||||
656 | * the only public entry point to return a parsed representation of a variable |
|||||||||||
657 | * |
|||||||||||
658 | * @static |
|||||||||||
659 | * |
|||||||||||
660 | * @param mixed $variable |
|||||||||||
661 | * @param null|string $name |
|||||||||||
662 | * |
|||||||||||
663 | * @return KintParser |
|||||||||||
664 | */ |
|||||||||||
665 | 2 | final public static function factory(&$variable, $name = null) |
||||||||||
666 | { |
|||||||||||
667 | # save internal data to revert after dumping to properly handle recursions etc |
|||||||||||
668 | $revert = array( |
|||||||||||
669 | 2 | 'level' => self::$_level, |
||||||||||
670 | 2 | 'objects' => self::$_objects, |
||||||||||
671 | ); |
|||||||||||
672 | ||||||||||||
673 | 2 | self::$_level++; |
||||||||||
674 | ||||||||||||
675 | 2 | $varData = new KintVariableData(); |
||||||||||
676 | 2 | $varData->name = $name; |
||||||||||
677 | ||||||||||||
678 | # first parse the variable based on its type |
|||||||||||
679 | 2 | $varType = gettype($variable); |
||||||||||
680 | ||||||||||||
681 | 2 | if ($varType === 'unknown type') { |
||||||||||
682 | $varType = 'unknown'; # PHP 5.4 inconsistency |
|||||||||||
683 | } |
|||||||||||
684 | ||||||||||||
685 | 2 | $methodName = '_parse_' . $varType; |
||||||||||
686 | ||||||||||||
687 | # objects can be presented in a different way altogether, INSTEAD, not ALONGSIDE the generic parser |
|||||||||||
688 | 2 | if ($varType === 'object') { |
||||||||||
689 | 2 | foreach (self::$_objectParsers as $parserClass) { |
||||||||||
690 | 2 | $className = 'kint\parsers\objects\Kint_Objects_' . $parserClass; |
||||||||||
691 | ||||||||||||
692 | /** @var $object KintObject */ |
|||||||||||
693 | 2 | $object = new $className(); |
||||||||||
694 | 2 | if (($alternativeTabs = $object->parse($variable)) !== false) { |
||||||||||
695 | self::$_skipAlternatives = true; |
|||||||||||
696 | $alternativeDisplay = new KintVariableData(); |
|||||||||||
697 | $alternativeDisplay->type = $object->name; |
|||||||||||
698 | $alternativeDisplay->value = $object->value; |
|||||||||||
699 | $alternativeDisplay->name = $name; |
|||||||||||
700 | ||||||||||||
701 | foreach ($alternativeTabs as $nameInner => $values) { |
|||||||||||
702 | $alternative = self::factory($values); |
|||||||||||
703 | $alternative->type = $nameInner; |
|||||||||||
0 ignored issues
–
show
It seems like
$nameInner can also be of type integer . However, the property $type is declared as type string . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
||||||||||||
704 | if (Kint::enabled() === Kint::MODE_RICH) { |
|||||||||||
705 | empty($alternative->value) and $alternative->value = $alternative->extendedValue; |
|||||||||||
0 ignored issues
–
show
It seems like
$alternative->extendedValue of type array<integer,object<kint\inc\KintVariableData>> is incompatible with the declared type string of property $value .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
706 | $alternativeDisplay->_alternatives[] = $alternative; |
|||||||||||
707 | } else { |
|||||||||||
708 | $alternativeDisplay->extendedValue[] = $alternative; |
|||||||||||
709 | } |
|||||||||||
710 | } |
|||||||||||
711 | ||||||||||||
712 | self::$_skipAlternatives = false; |
|||||||||||
713 | self::$_level = $revert['level']; |
|||||||||||
714 | self::$_objects = $revert['objects']; |
|||||||||||
715 | ||||||||||||
716 | 2 | return $alternativeDisplay; |
||||||||||
717 | } |
|||||||||||
718 | } |
|||||||||||
719 | } |
|||||||||||
720 | ||||||||||||
721 | # base type parser returning false means "stop processing further": e.g. recursion |
|||||||||||
722 | 2 | if (self::$methodName($variable, $varData) === false) { |
||||||||||
723 | self::$_level--; |
|||||||||||
724 | ||||||||||||
725 | return $varData; |
|||||||||||
726 | } |
|||||||||||
727 | ||||||||||||
728 | if ( |
|||||||||||
729 | 2 | !self::$_skipAlternatives |
||||||||||
730 | && |
|||||||||||
731 | 2 | Kint::enabled() === Kint::MODE_RICH |
||||||||||
732 | ) { |
|||||||||||
733 | # if an alternative returns something that can be represented in an alternative way, don't :) |
|||||||||||
734 | 1 | self::$_skipAlternatives = true; |
||||||||||
735 | ||||||||||||
736 | # now check whether the variable can be represented in a different way |
|||||||||||
737 | 1 | foreach (self::$_customDataTypes as $parserClass) { |
||||||||||
738 | 1 | $className = 'kint\parsers\custom\Kint_Parsers_' . $parserClass; |
||||||||||
739 | ||||||||||||
740 | /** @var $parser KintParser */ |
|||||||||||
741 | ||||||||||||
742 | 1 | $parser = new $className(); |
||||||||||
743 | 1 | $parser->name = $name; # the parser may overwrite the name value, so set it first |
||||||||||
744 | ||||||||||||
745 | 1 | if ($parser->_parse($variable) !== false) { |
||||||||||
746 | 1 | $varData->_alternatives[] = $parser; |
||||||||||
747 | } |
|||||||||||
748 | } |
|||||||||||
749 | ||||||||||||
750 | # if alternatives exist, push extendedValue to their front and display it as one of alternatives |
|||||||||||
751 | 1 | if (!empty($varData->_alternatives) && isset($varData->extendedValue)) { |
||||||||||
752 | $_ = new KintVariableData(); |
|||||||||||
753 | ||||||||||||
754 | $_->value = $varData->extendedValue; |
|||||||||||
0 ignored issues
–
show
It seems like
$varData->extendedValue of type array<integer,object<kint\inc\KintVariableData>> is incompatible with the declared type string of property $value .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
755 | $_->type = 'contents'; |
|||||||||||
756 | $_->size = null; |
|||||||||||
757 | ||||||||||||
758 | array_unshift($varData->_alternatives, $_); |
|||||||||||
759 | $varData->extendedValue = null; |
|||||||||||
0 ignored issues
–
show
It seems like
null of type null is incompatible with the declared type array<integer,object<kint\inc\KintVariableData>> of property $extendedValue .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
760 | } |
|||||||||||
761 | ||||||||||||
762 | 1 | self::$_skipAlternatives = false; |
||||||||||
763 | } |
|||||||||||
764 | ||||||||||||
765 | 2 | self::$_level = $revert['level']; |
||||||||||
766 | 2 | self::$_objects = $revert['objects']; |
||||||||||
767 | ||||||||||||
768 | 2 | if (strlen($varData->name) > 80) { |
||||||||||
769 | $varData->name = |
|||||||||||
770 | self::_substr($varData->name, 0, 37) |
|||||||||||
771 | . '...' |
|||||||||||
772 | . self::_substr($varData->name, -38, null); |
|||||||||||
773 | } |
|||||||||||
774 | ||||||||||||
775 | 2 | return $varData; |
||||||||||
776 | } |
|||||||||||
777 | ||||||||||||
778 | /** |
|||||||||||
779 | * reset |
|||||||||||
780 | */ |
|||||||||||
781 | 2 | public static function reset() |
||||||||||
782 | { |
|||||||||||
783 | 2 | self::$_level = 0; |
||||||||||
784 | 2 | self::$_objects = self::$_marker = null; |
||||||||||
0 ignored issues
–
show
It seems like
self::$_marker = null of type null is incompatible with the declared type array of property $_objects .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
||||||||||||
785 | 2 | } |
||||||||||
786 | ||||||||||||
787 | } |
|||||||||||
788 |
PHP has two types of connecting operators (logical operators, and boolean operators):
and
&&
or
||
The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like
&&
, or||
.Let’s take a look at a few examples:
Logical Operators are used for Control-Flow
One case where you explicitly want to use logical operators is for control-flow such as this:
Since
die
introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined withthrow
at this point:These limitations lead to logical operators rarely being of use in current PHP code.