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 | namespace Xicrow\PhpDebug; |
||
3 | |||
4 | /** |
||
5 | * Class Timer |
||
6 | * |
||
7 | * @package Xicrow\PhpDebug |
||
8 | */ |
||
9 | class Timer |
||
10 | { |
||
11 | /** |
||
12 | * @var array |
||
13 | */ |
||
14 | public static $collection = []; |
||
15 | |||
16 | /** |
||
17 | * @var boolean|string |
||
18 | */ |
||
19 | public static $currentItem = false; |
||
20 | |||
21 | /** |
||
22 | * @var array |
||
23 | */ |
||
24 | public static $runningItems = []; |
||
25 | |||
26 | /** |
||
27 | * Force the unit to display elapsed times in (MS|S|M|H|D|W) |
||
28 | * |
||
29 | * @var null|string |
||
30 | */ |
||
31 | public static $forceDisplayUnit = null; |
||
32 | |||
33 | /** |
||
34 | * Color threshold for output (5 => 'red', all items with values of 5 or higher will be red) |
||
35 | * |
||
36 | * @var array |
||
37 | */ |
||
38 | public static $colorThreshold = []; |
||
39 | |||
40 | /** |
||
41 | * @var bool |
||
42 | */ |
||
43 | public static $output = true; |
||
44 | |||
45 | /** |
||
46 | * @var array |
||
47 | */ |
||
48 | public static $style = [ |
||
49 | 'output_format' => '<pre style="margin-top: 0; padding: 5px; font-family: Menlo, Monaco, Consolas, monospace; font-weight: bold; font-size: 12px; background-color: #18171B; border: none; color: #FF8400; display: block; z-index: 1000;">%s</pre>', |
||
50 | 'called_from_format' => '<pre style="margin-bottom: 0; padding: 5px; font-family: Menlo, Monaco, Consolas, monospace; font-weight: normal; font-size: 12px; background-color: #18171B; border: none; color: #AAAAAA; display: block; z-index: 1000;">%s</pre>', |
||
51 | 'hover_style' => 'background-color: #333333;', |
||
52 | ]; |
||
53 | |||
54 | /** |
||
55 | * @param string $data |
||
56 | * |
||
57 | * @codeCoverageIgnore |
||
58 | */ |
||
59 | public static function output($data) |
||
60 | { |
||
61 | if (!self::$output || !is_string($data)) { |
||
62 | return; |
||
63 | } |
||
64 | |||
65 | if (php_sapi_name() != 'cli') { |
||
66 | echo sprintf(self::$style['called_from_format'], Debugger::getCalledFrom(2)); |
||
67 | echo sprintf(self::$style['output_format'], $data); |
||
68 | echo '<style type="text/css">.xicrow-php-debug-timer:hover{ ' . self::$style['hover_style'] . ' }</style>'; |
||
69 | } else { |
||
70 | echo Debugger::getCalledFrom(2); |
||
71 | echo "\n"; |
||
72 | echo $data; |
||
73 | } |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * |
||
78 | */ |
||
79 | 6 | public static function reset() |
|
80 | { |
||
81 | 6 | self::$collection = []; |
|
82 | 6 | self::$currentItem = false; |
|
83 | 6 | self::$runningItems = []; |
|
84 | 6 | } |
|
85 | |||
86 | /** |
||
87 | * @param string|null $key |
||
88 | * @param array $data |
||
89 | * |
||
90 | * @return string |
||
91 | */ |
||
92 | 6 | public static function add($key = null, $data = []) |
|
93 | { |
||
94 | // If no key is given |
||
95 | 6 | if (is_null($key)) { |
|
96 | // Set key to file and line |
||
97 | $key = Debugger::getCalledFrom(2); |
||
98 | } |
||
99 | |||
100 | // If key is allready in use |
||
101 | 6 | if (isset(self::$collection[$key])) { |
|
102 | // Get original item |
||
103 | 1 | $item = self::$collection[$key]; |
|
104 | |||
105 | // Set new item count |
||
106 | 1 | $itemCount = (isset($item['count']) ? ($item['count'] + 1) : 2); |
|
107 | |||
108 | // Set correct key for the original item |
||
109 | 1 | if (strpos($item['key'], '#') === false) { |
|
110 | 1 | self::$collection[$key] = array_merge($item, [ |
|
111 | 1 | 'key' => $key . ' #1', |
|
112 | 1 | 'count' => $itemCount, |
|
113 | ]); |
||
114 | } else { |
||
115 | self::$collection[$key] = array_merge($item, [ |
||
116 | 'count' => $itemCount, |
||
117 | ]); |
||
118 | } |
||
119 | |||
120 | // Set new key |
||
121 | 1 | $key = $key . ' #' . $itemCount; |
|
122 | } |
||
123 | |||
124 | // Make sure various options are set |
||
125 | 6 | if (!isset($data['key'])) { |
|
126 | 6 | $data['key'] = $key; |
|
127 | } |
||
128 | 6 | if (!isset($data['parent'])) { |
|
129 | 6 | $data['parent'] = self::$currentItem; |
|
130 | } |
||
131 | 6 | if (!isset($data['level'])) { |
|
132 | 6 | $data['level'] = 0; |
|
133 | 6 | if (isset($data['parent']) && isset(self::$collection[$data['parent']])) { |
|
134 | 1 | $data['level'] = (self::$collection[$data['parent']]['level'] + 1); |
|
135 | } |
||
136 | } |
||
137 | |||
138 | // Add item to collection |
||
139 | 6 | self::$collection[$key] = $data; |
|
140 | |||
141 | 6 | return $key; |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * @param string|null $key |
||
146 | * |
||
147 | * @return string |
||
148 | */ |
||
149 | 3 | public static function start($key = null) |
|
150 | { |
||
151 | // Add new item |
||
152 | 3 | $key = self::add($key, [ |
|
153 | 3 | 'start' => microtime(true), |
|
154 | ]); |
||
155 | |||
156 | // Set current item |
||
157 | 3 | self::$currentItem = $key; |
|
158 | |||
159 | // Add to running items |
||
160 | 3 | self::$runningItems[$key] = true; |
|
161 | |||
162 | 3 | return $key; |
|
163 | } |
||
164 | |||
165 | /** |
||
166 | * @param string|null $key |
||
167 | * |
||
168 | * @return string |
||
169 | */ |
||
170 | 2 | public static function stop($key = null) |
|
171 | { |
||
172 | // If no key is given |
||
173 | 2 | if (is_null($key)) { |
|
174 | // Get key of the last started item |
||
175 | 1 | end(self::$runningItems); |
|
176 | 1 | $key = key(self::$runningItems); |
|
177 | } |
||
178 | |||
179 | // Check for key duplicates, and find the last one not stopped |
||
180 | 2 | if (isset(self::$collection[$key]) && isset(self::$collection[$key . ' #2'])) { |
|
181 | 1 | $lastNotStopped = false; |
|
182 | 1 | $currentKey = $key; |
|
183 | 1 | $currentIndex = 1; |
|
184 | 1 | while (isset(self::$collection[$currentKey])) { |
|
185 | 1 | if (!isset(self::$collection[$currentKey]['stop'])) { |
|
186 | 1 | $lastNotStopped = $currentKey; |
|
187 | } |
||
188 | |||
189 | 1 | $currentIndex++; |
|
190 | 1 | $currentKey = $key . ' #' . $currentIndex; |
|
191 | } |
||
192 | |||
193 | 1 | if ($lastNotStopped) { |
|
194 | 1 | $key = $lastNotStopped; |
|
195 | } |
||
196 | } |
||
197 | |||
198 | // If item exists in collection |
||
199 | 2 | if (isset(self::$collection[$key])) { |
|
200 | // Update the item |
||
201 | 2 | self::$collection[$key]['stop'] = microtime(true); |
|
202 | |||
203 | 2 | self::$currentItem = self::$collection[$key]['parent']; |
|
204 | } |
||
205 | |||
206 | 2 | if (isset(self::$runningItems[$key])) { |
|
207 | 2 | unset(self::$runningItems[$key]); |
|
208 | } |
||
209 | |||
210 | 2 | return $key; |
|
211 | } |
||
212 | |||
213 | /** |
||
214 | * @param string|null $key |
||
215 | * @param int|float|null $start |
||
216 | * @param int|float|null $stop |
||
217 | * |
||
218 | * @return string |
||
219 | */ |
||
220 | 2 | public static function custom($key = null, $start = null, $stop = null) |
|
221 | { |
||
222 | // Add new item |
||
223 | 2 | self::add($key, [ |
|
224 | 2 | 'start' => $start, |
|
225 | 2 | 'stop' => $stop, |
|
226 | ]); |
||
227 | |||
228 | // If no stop value is given |
||
229 | 2 | if (is_null($stop)) { |
|
230 | // Set current item |
||
231 | 1 | self::$currentItem = $key; |
|
232 | |||
233 | // Add to running items |
||
234 | 1 | self::$runningItems[$key] = true; |
|
235 | } |
||
236 | |||
237 | 2 | return $key; |
|
238 | } |
||
239 | |||
240 | /** |
||
241 | * @param string|null $key |
||
242 | * @param string|array|\Closure $callback |
||
243 | * |
||
244 | * @return mixed |
||
245 | */ |
||
246 | 1 | public static function callback($key = null, $callback) |
|
247 | { |
||
248 | // Get parameters for callback |
||
249 | 1 | $callbackParams = func_get_args(); |
|
250 | 1 | unset($callbackParams[0], $callbackParams[1]); |
|
251 | 1 | $callbackParams = array_values($callbackParams); |
|
252 | |||
253 | // Get key if no key is given |
||
254 | 1 | if (is_null($key)) { |
|
255 | 1 | if (is_string($callback)) { |
|
256 | 1 | $key = $callback; |
|
257 | 1 | } elseif (is_array($callback)) { |
|
258 | 1 | $keyArr = []; |
|
259 | 1 | foreach ($callback as $k => $v) { |
|
260 | 1 | if (is_string($v)) { |
|
261 | 1 | $keyArr[] = $v; |
|
262 | 1 | } elseif (is_object($v)) { |
|
263 | 1 | $keyArr[] = get_class($v); |
|
264 | } |
||
265 | } |
||
266 | |||
267 | 1 | $key = implode('', $keyArr); |
|
268 | 1 | if (count($keyArr) > 1) { |
|
269 | 1 | $method = array_pop($keyArr); |
|
270 | 1 | $key = implode('/', $keyArr); |
|
271 | 1 | $key .= '::' . $method; |
|
272 | } |
||
273 | |||
274 | 1 | unset($keyArr, $method); |
|
275 | 1 | } elseif (is_object($callback) && $callback instanceof \Closure) { |
|
276 | 1 | $key = 'closure'; |
|
277 | } |
||
278 | 1 | $key = 'callback: ' . $key; |
|
279 | } |
||
280 | |||
281 | // Set default return value |
||
282 | 1 | $returnValue = true; |
|
283 | |||
284 | // Set error handler, to convert errors to exceptions |
||
285 | 1 | set_error_handler(function ($errno, $errstr, $errfile, $errline, array $errcontext) { |
|
0 ignored issues
–
show
|
|||
286 | 1 | throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); |
|
287 | 1 | }); |
|
288 | |||
289 | try { |
||
290 | // Start output buffer to capture any output |
||
291 | 1 | ob_start(); |
|
292 | |||
293 | // Start profiler |
||
294 | 1 | self::start($key); |
|
295 | |||
296 | // Execute callback, and get result |
||
297 | 1 | $callbackResult = call_user_func_array($callback, $callbackParams); |
|
298 | |||
299 | // Stop profiler |
||
300 | 1 | self::stop($key); |
|
301 | |||
302 | // Get and clean output buffer |
||
303 | 1 | $callbackOutput = ob_get_clean(); |
|
304 | 1 | } catch (\ErrorException $callbackException) { |
|
0 ignored issues
–
show
The class
ErrorException does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
305 | // Stop and clean output buffer |
||
306 | 1 | ob_end_clean(); |
|
307 | |||
308 | // Show error message |
||
309 | 1 | self::output('Invalid callback sent to Timer::callback: ' . str_replace('callback: ', '', $key)); |
|
310 | |||
311 | // Clear the item from the collection |
||
312 | 1 | unset(self::$collection[$key]); |
|
313 | |||
314 | // Clear callback result and output |
||
315 | 1 | unset($callbackResult, $callbackOutput); |
|
316 | |||
317 | // Set return value to false |
||
318 | 1 | $returnValue = false; |
|
319 | } |
||
320 | |||
321 | // Restore error handler |
||
322 | 1 | restore_error_handler(); |
|
323 | |||
324 | // Return result, output or true |
||
325 | 1 | return (isset($callbackResult) ? $callbackResult : (!empty($callbackOutput) ? $callbackOutput : $returnValue)); |
|
326 | } |
||
327 | |||
328 | /** |
||
329 | * @param string|null $key |
||
330 | * @param array $options |
||
331 | * |
||
332 | * @codeCoverageIgnore |
||
333 | */ |
||
334 | public static function show($key = null, $options = []) |
||
335 | { |
||
336 | $output = self::getStats($key, $options); |
||
337 | |||
338 | if (!empty($output)) { |
||
339 | self::output($output); |
||
340 | } |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * @param array $options |
||
345 | * |
||
346 | * @codeCoverageIgnore |
||
347 | */ |
||
348 | public static function showAll($options = []) |
||
349 | { |
||
350 | // Stop started items |
||
351 | if (count(self::$runningItems)) { |
||
352 | foreach (self::$runningItems as $key => $value) { |
||
353 | self::stop($key); |
||
354 | } |
||
355 | } |
||
356 | |||
357 | // Output items |
||
358 | $output = ''; |
||
359 | $itemCount = 1; |
||
360 | foreach (self::$collection as $key => $item) { |
||
361 | $stats = self::getStats($key, $options); |
||
362 | |||
363 | if (php_sapi_name() == 'cli') { |
||
364 | $output .= (!empty($output) ? "\n" : '') . $stats; |
||
365 | } else { |
||
366 | $output .= '<div class="xicrow-php-debug-timer">'; |
||
367 | $output .= $stats; |
||
368 | $output .= '</div>'; |
||
369 | } |
||
370 | |||
371 | $itemCount++; |
||
372 | |||
373 | unset($stats); |
||
374 | } |
||
375 | unset($itemCount); |
||
376 | |||
377 | self::output($output); |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * @param string|null $key |
||
382 | * @param array $options |
||
383 | * |
||
384 | * @return string |
||
385 | */ |
||
386 | 1 | public static function getStats($key, $options = []) |
|
387 | { |
||
388 | // Merge options with default options |
||
389 | 1 | $options = array_merge([ |
|
390 | // Show nested (boolean) |
||
391 | 1 | 'nested' => true, |
|
392 | // Prefix for nested items (string) |
||
393 | 'nested_prefix' => '|-- ', |
||
394 | // Max key length (int) |
||
395 | 'max_key_length' => 100, |
||
396 | 1 | ], $options); |
|
397 | |||
398 | // If item does not exist |
||
399 | 1 | if (!isset(self::$collection[$key])) { |
|
400 | 1 | return 'Unknow item in with key: ' . $key; |
|
401 | } |
||
402 | |||
403 | // Get item |
||
404 | 1 | $item = self::$collection[$key]; |
|
405 | |||
406 | // Get item result |
||
407 | 1 | $itemResult = 'N/A'; |
|
408 | 1 | $itemResultFormatted = 'N/A'; |
|
409 | 1 | if (isset($item['start']) && isset($item['stop'])) { |
|
410 | 1 | $itemResult = (($item['stop'] - $item['start']) * 1000); |
|
411 | 1 | $itemResultFormatted = self::formatMiliseconds($itemResult, 4, self::$forceDisplayUnit); |
|
412 | } |
||
413 | |||
414 | // Variable for output |
||
415 | 1 | $output = ''; |
|
416 | |||
417 | // Prep key for output |
||
418 | 1 | $outputName = ''; |
|
419 | 1 | $outputName .= ($options['nested'] ? str_repeat($options['nested_prefix'], $item['level']) : ''); |
|
420 | 1 | $outputName .= $item['key']; |
|
421 | 1 | if (mb_strlen($outputName) > $options['max_key_length']) { |
|
422 | 1 | $outputName = '~' . mb_substr($item['key'], -($options['max_key_length'] - 1)); |
|
423 | } |
||
424 | |||
425 | // Add item stats |
||
426 | 1 | $output .= str_pad($outputName, ($options['max_key_length'] + (strlen($outputName) - mb_strlen($outputName))), ' '); |
|
427 | 1 | $output .= ' | '; |
|
428 | 1 | $output .= str_pad($itemResultFormatted, 20, ' ', ($itemResult == 'N/A' ? STR_PAD_RIGHT : STR_PAD_LEFT)); |
|
429 | |||
430 | 1 | if (php_sapi_name() != 'cli' && is_array(self::$colorThreshold) && count(self::$colorThreshold)) { |
|
431 | krsort(self::$colorThreshold); |
||
432 | foreach (self::$colorThreshold as $value => $color) { |
||
433 | if (is_numeric($itemResult) && $itemResult >= $value) { |
||
434 | $output = '<span style="color: ' . $color . ';">' . $output . '</span>'; |
||
435 | } |
||
436 | } |
||
437 | } |
||
438 | |||
439 | 1 | return $output; |
|
440 | } |
||
441 | |||
442 | /** |
||
443 | * @param int|float $number |
||
444 | * @param int $precision |
||
445 | * @param null|string $forceUnit |
||
446 | * |
||
447 | * @return string |
||
448 | */ |
||
449 | 1 | public static function formatMiliseconds($number = 0, $precision = 2, $forceUnit = null) |
|
450 | { |
||
451 | $units = [ |
||
452 | 1 | 'MS' => 1, |
|
453 | 'S' => 1000, |
||
454 | 'M' => 60, |
||
455 | 'H' => 60, |
||
456 | 'D' => 24, |
||
457 | 'W' => 7, |
||
458 | ]; |
||
459 | |||
460 | 1 | if (is_null($forceUnit)) { |
|
461 | 1 | $forceUnit = self::$forceDisplayUnit; |
|
462 | } |
||
463 | |||
464 | 1 | $value = $number; |
|
465 | 1 | if (!empty($forceUnit) && array_key_exists($forceUnit, $units)) { |
|
466 | 1 | $unit = $forceUnit; |
|
467 | 1 | foreach ($units as $k => $v) { |
|
468 | 1 | $value = ($value / $v); |
|
469 | 1 | if ($k == $unit) { |
|
470 | 1 | break; |
|
471 | } |
||
472 | } |
||
473 | } else { |
||
474 | 1 | $unit = ''; |
|
475 | 1 | foreach ($units as $k => $v) { |
|
476 | 1 | if (empty($unit) || ($value / $v) > 1) { |
|
477 | 1 | $value = ($value / $v); |
|
478 | 1 | $unit = $k; |
|
479 | } else { |
||
480 | 1 | break; |
|
481 | } |
||
482 | } |
||
483 | } |
||
484 | |||
485 | 1 | return sprintf('%0.' . $precision . 'f', $value) . ' ' . str_pad($unit, 2, ' ', STR_PAD_RIGHT); |
|
486 | } |
||
487 | } |
||
488 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.