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
|
|
|
$args = self::trace_args_to_string($trace['args']); |
88
|
|
|
else |
89
|
|
|
$args = microtime(true); |
90
|
|
|
|
91
|
|
|
$call_file = isset($trace['file']) ? basename($trace['file']) : '?'; |
92
|
|
|
$call_line = $trace['line'] ?? '?'; |
93
|
|
|
|
94
|
|
|
$formated_traces []= sprintf('[%-23.23s %3s] %'.($depth*3).'s%s%s(%s)', $call_file, $call_line,' ', "$class_name::", $function_name, $args); |
95
|
|
|
|
96
|
|
|
if($full_backtrace === false) |
97
|
|
|
break; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
return implode(PHP_EOL, array_reverse($formated_traces)); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
private static function trace_args_to_string($trace_args) |
104
|
|
|
{ |
105
|
|
|
$ret = []; |
106
|
|
|
foreach($trace_args as $arg) |
107
|
|
|
{ |
108
|
|
|
if(is_null($arg)) |
109
|
|
|
$ret[]= 'null'; |
110
|
|
|
elseif(is_bool($arg)) |
111
|
|
|
$ret[]= $arg === true ? 'bool:true' : 'bool:false'; |
112
|
|
|
elseif(is_string($arg) || is_numeric($arg)) |
113
|
|
|
$ret[]= $arg; |
114
|
|
|
elseif(is_object($arg)) |
115
|
|
|
$ret[]= get_class($arg); |
116
|
|
|
elseif(is_array($arg)) |
117
|
|
|
$ret[]= 'Array #'.count($arg); |
118
|
|
|
else |
119
|
|
|
{ |
120
|
|
|
var_dump($arg); |
121
|
|
|
$ret[] = '!!OTHER!!'; |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
$ret = implode(', ', $ret); |
125
|
|
|
return $ret; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
private static function is_debugger_function($class_name, $function_name) |
129
|
|
|
{ |
130
|
|
|
return $class_name === __CLASS__ && in_array($function_name, ['dump', 'vd', 'dd']); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
private static function is_debugger_call($function_name) |
134
|
|
|
{ |
135
|
|
|
return in_array($function_name, ['vd', 'dd','vdt', 'ddt']); |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
namespace |
141
|
|
|
{ |
142
|
|
|
if(!function_exists('vd')) { |
143
|
|
|
function vd($var, $var_name=null){ return \HexMakina\Debugger\Debugger::vd($var, $var_name, false);} |
|
|
|
|
144
|
|
|
} |
145
|
|
|
if(!function_exists('dd')) { |
146
|
|
|
function dd($var, $var_name=null){ return \HexMakina\Debugger\Debugger::dd($var, $var_name, false);} |
|
|
|
|
147
|
|
|
} |
148
|
|
|
if(!function_exists('vdt')) { |
149
|
|
|
function vdt($var, $var_name=null){ return \HexMakina\Debugger\Debugger::vd($var, $var_name, true);} |
|
|
|
|
150
|
|
|
} |
151
|
|
|
if(!function_exists('ddt')) { |
152
|
|
|
function ddt($var, $var_name=null){ return \HexMakina\Debugger\Debugger::dd($var, $var_name, true);} |
|
|
|
|
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
|
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.