1 | <?php |
||
2 | |||
3 | namespace HexMakina\Debugger |
||
4 | { |
||
5 | trait Debugger |
||
6 | { |
||
7 | public function __debugInfo() |
||
8 | { |
||
9 | return [json_encode(get_object_vars($this))]; |
||
10 | } |
||
11 | |||
12 | public static function init() |
||
13 | { |
||
14 | // just to load the class, required to get the shortcuts defined in namespace \ |
||
15 | } |
||
16 | |||
17 | public static function display_errors($error_message=null) |
||
18 | { |
||
19 | $should_display = ini_get('display_errors') == '1'; |
||
20 | |||
21 | if($should_display && !empty($error_message)) |
||
22 | echo('<pre style="z-index:9999; background-color:#FFF; color:#000; padding:0.5em; font-size:0.7em; margin:0 0 1em 0; font-family:courier;">'.$error_message.'</pre>'); |
||
23 | } |
||
24 | |||
25 | // ----------------------------------------------------------- visual dump (depends on env) |
||
26 | public static function vd($var, $var_name = null, $full_backtrace = false) |
||
27 | { |
||
28 | self::display_errors(self::dump($var, $var_name, $full_backtrace)); |
||
29 | } |
||
30 | |||
31 | // ----------------------------------------------------------- visual dump and DIE |
||
32 | public static function dd($var, $var_name = null, $full_backtrace = true) |
||
33 | { |
||
34 | self::vd($var, $var_name, $full_backtrace); |
||
35 | die; |
||
36 | } |
||
37 | |||
38 | // ----------------------------------------------------------- dump on variable type (Throwables, array, anything else) |
||
39 | public static function dump($var, $var_name = null, $full_backtrace = true) |
||
40 | { |
||
41 | if(is_object($var) && (is_subclass_of($var, 'Error') || is_subclass_of($var, 'Exception'))) |
||
42 | { |
||
43 | $backtrace = $var->getTrace(); |
||
44 | $full_backtrace = true; |
||
45 | $var_dump = self::format_throwable_message(get_class($var), $var->getCode(), $var->getFile(), $var->getLine(), $var->getMessage()); |
||
46 | } |
||
47 | else |
||
48 | { |
||
49 | $backtrace = debug_backtrace(); |
||
50 | |||
51 | ob_start(); |
||
52 | var_dump($var); |
||
53 | $var_dump = ob_get_clean(); |
||
54 | } |
||
55 | |||
56 | return PHP_EOL."*******".(empty($var_name) ? '' : " ($var_name) ")."*******".PHP_EOL.self::format_trace($backtrace, $full_backtrace).PHP_EOL.$var_dump; |
||
57 | } |
||
58 | |||
59 | // ----------------------------------------------------------- formatting |
||
60 | |||
61 | // ----------------------------------------------------------- formatting : first line of \Throwable-based error |
||
62 | public static function format_throwable_message($class, $code, $file, $line, $message) |
||
63 | { |
||
64 | return sprintf(PHP_EOL.'%s (%d) in file %s:%d'.PHP_EOL.'%s', $class, $code, self::format_file($file), $line, $message); |
||
65 | } |
||
66 | |||
67 | // ----------------------------------------------------------- formatting : shorten file path to [self::REDUCE_FILE_PATH_DEPTH_TO] elements |
||
68 | public static function format_file($file,$reduce_file_depth_to = 5) |
||
69 | { |
||
70 | return implode('/', array_slice(explode('/', $file), -$reduce_file_depth_to, $reduce_file_depth_to)); |
||
71 | } |
||
72 | |||
73 | // ----------------------------------------------------------- formatting : nice backtrace |
||
74 | public static function format_trace($traces, $full_backtrace) |
||
75 | { |
||
76 | $formated_traces = []; |
||
77 | |||
78 | foreach($traces as $depth => $trace) |
||
79 | { |
||
80 | $function_name = $trace['function'] ?? '?'; |
||
81 | $class_name = $trace['class'] ?? '?'; |
||
82 | |||
83 | if(self::is_debugger_function($class_name, $function_name)) |
||
84 | continue; |
||
85 | |||
86 | if(!self::is_debugger_call($function_name) && isset($trace['args'])) |
||
87 | { |
||
88 | $args = []; |
||
89 | foreach($trace['args'] as $arg) |
||
90 | { |
||
91 | if(is_null($arg)) |
||
92 | $args[]= 'null'; |
||
93 | elseif(is_bool($arg)) |
||
94 | $args[]= $arg === true ? 'bool:true' : 'bool:false'; |
||
95 | elseif(is_string($arg) || is_numeric($arg)) |
||
96 | $args[]= $arg; |
||
97 | elseif(is_object($arg)) |
||
98 | $args[]= get_class($arg); |
||
99 | elseif(is_array($arg)) |
||
100 | $args[]= 'Array #'.count($arg); |
||
101 | else |
||
102 | { |
||
103 | var_dump($arg); |
||
104 | $args[] = '!!OTHER!!'; |
||
105 | } |
||
106 | } |
||
107 | $args = implode(', ', $args); |
||
108 | } |
||
109 | else |
||
110 | $args = microtime(true); |
||
111 | |||
112 | $call_file = isset($trace['file']) ? basename($trace['file']) : '?'; |
||
113 | $call_line = $trace['line'] ?? '?'; |
||
114 | |||
115 | $formated_traces []= sprintf('[%-23.23s %3s] %'.($depth*3).'s%s%s(%s)', $call_file, $call_line,' ', "$class_name::", $function_name, $args); |
||
116 | |||
117 | if($full_backtrace === false) |
||
118 | break; |
||
119 | } |
||
120 | |||
121 | return implode(PHP_EOL, array_reverse($formated_traces)); |
||
122 | } |
||
123 | |||
124 | private static function is_debugger_function($class_name, $function_name) |
||
125 | { |
||
126 | return $class_name === __CLASS__ && in_array($function_name, ['dump', 'vd', 'dd']); |
||
127 | } |
||
128 | |||
129 | private static function is_debugger_call($function_name) |
||
130 | { |
||
131 | return in_array($function_name, ['vd', 'dd','vdt', 'ddt']); |
||
132 | } |
||
133 | } |
||
134 | } |
||
135 | |||
136 | namespace |
||
137 | { |
||
138 | if(!function_exists('vd')) { |
||
139 | function vd($var, $var_name=null){ return \HexMakina\Debugger\Debugger::vd($var, $var_name, false);} |
||
0 ignored issues
–
show
|
|||
140 | } |
||
141 | if(!function_exists('dd')) { |
||
142 | function dd($var, $var_name=null){ return \HexMakina\Debugger\Debugger::dd($var, $var_name, false);} |
||
0 ignored issues
–
show
Are you sure the usage of
HexMakina\Debugger\Debug...$var, $var_name, false) targeting HexMakina\Debugger\Debugger::dd() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
143 | } |
||
144 | if(!function_exists('vdt')) { |
||
145 | function vdt($var, $var_name=null){ return \HexMakina\Debugger\Debugger::vd($var, $var_name, true);} |
||
0 ignored issues
–
show
Are you sure the usage of
HexMakina\Debugger\Debug...($var, $var_name, true) targeting HexMakina\Debugger\Debugger::vd() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
146 | } |
||
147 | if(!function_exists('ddt')) { |
||
148 | function ddt($var, $var_name=null){ return \HexMakina\Debugger\Debugger::dd($var, $var_name, true);} |
||
0 ignored issues
–
show
Are you sure the usage of
HexMakina\Debugger\Debug...($var, $var_name, true) targeting HexMakina\Debugger\Debugger::dd() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
149 | } |
||
150 | } |
||
151 |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.