Passed
Push — main ( d9bdc0...52d4eb )
by Sammy
05:12 queued 03:31
created

Debugger.php (1 issue)

Severity
1
<?php
2
3
namespace HexMakina\Debugger
4
{
5
    trait Debugger
6
    {
7
        public function __debugInfo() : array
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="text-align:left; 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
26
      // -- visual dump (depends on env)
27
        public static function vd($var, $var_name = null, $full_backtrace = false)
28
        {
29
            self::display_errors(self::dump($var, $var_name, $full_backtrace));
30
        }
31
32
      // -- visual dump and DIE
33
        public static function dd($var, $var_name = null, $full_backtrace = true)
34
        {
35
            self::vd($var, $var_name, $full_backtrace);
36
            die;
1 ignored issue
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
37
        }
38
39
      // -- dump on variable type (Throwables, array, anything else)
40
        public static function dump($var, $var_name = null, $full_backtrace = true)
41
        {
42
            if (is_object($var) && (is_subclass_of($var, 'Error') || is_subclass_of($var, 'Exception'))) {
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
            } else {
47
                $backtrace = debug_backtrace();
48
49
                ob_start();
50
                var_dump($var);
51
                $var_dump = ob_get_clean();
52
            }
53
54
            return PHP_EOL."*******".(empty($var_name) ? '' : " ($var_name) ")."*******".PHP_EOL.self::format_trace($backtrace, $full_backtrace).PHP_EOL.$var_dump;
55
        }
56
57
      // -- formatting
58
59
      // -- formatting : first line of \Throwable-based error
60
        public static function format_throwable_message($class, $code, $file, $line, $message)
61
        {
62
            return sprintf(PHP_EOL.'%s (%d) in file %s:%d'.PHP_EOL.'%s', $class, $code, self::format_file($file), $line, $message);
63
        }
64
65
      // -- formatting : shorten file path to [self::REDUCE_FILE_PATH_DEPTH_TO] elements
66
        public static function format_file($file, $reduce_file_depth_to = 5)
67
        {
68
            return implode('/', array_slice(explode('/', $file), -$reduce_file_depth_to, $reduce_file_depth_to));
69
        }
70
71
      // -- formatting : nice backtrace
72
        public static function format_trace($traces, $full_backtrace)
73
        {
74
            $formated_traces = [];
75
76
            foreach ($traces as $depth => $trace) {
77
                $function_name = $trace['function'] ?? '?';
78
                $class_name = $trace['class'] ?? '?';
79
80
                if (self::is_debugger_function($class_name, $function_name)) {
81
                    continue;
82
                }
83
84
                if (!self::is_debugger_call($function_name) && isset($trace['args'])) {
85
                    $args = self::trace_args_to_string($trace['args']);
86
                } else {
87
                    $args = microtime(true);
88
                }
89
90
                $call_file = isset($trace['file']) ? basename($trace['file']) : '?';
91
                $call_line = $trace['line'] ?? '?';
92
93
                $formated_traces []= sprintf('[%-23.23s %3s] %'.($depth*3).'s%s%s(%s)', $call_file, $call_line, ' ', "$class_name::", $function_name, $args);
94
95
                if ($full_backtrace === false) {
96
                    break;
97
                }
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
                if (is_null($arg)) {
108
                    $ret[]= 'NULL';
109
                } elseif (is_bool($arg)) {
110
                    $ret[]= 'bool:'.((int)$arg);
111
                } elseif (is_scalar($arg)) {
112
                    $ret[]= $arg;
113
                } elseif (is_object($arg)) {
114
                    $ret[]= get_class($arg);
115
                } elseif (is_array($arg)) {
116
                    $ret[]= 'Array #'.count($arg);
117
                } else {
118
                    $ret[] = 'unknown type';
119
                }
120
            }
121
            $ret = implode(', ', $ret);
122
            return $ret;
123
        }
124
125
        private static function is_debugger_function($class_name, $function_name)
126
        {
127
            return $class_name === __CLASS__ && in_array($function_name, ['dump', 'vd', 'dd']);
128
        }
129
130
        private static function is_debugger_call($function_name)
131
        {
132
            return in_array($function_name, ['vd', 'dd','vdt', 'ddt']);
133
        }
134
    }
135
}
136
137
namespace
138
{
139
    if (!function_exists('vd')) {
140
        function vd($var, $var_name = null)
141
        {
142
            \HexMakina\Debugger\Debugger::vd($var, $var_name, false);
143
        }
144
    }
145
    if (!function_exists('dd')) {
146
        function dd($var, $var_name = null)
147
        {
148
            \HexMakina\Debugger\Debugger::dd($var, $var_name, false);
149
        }
150
    }
151
    if (!function_exists('vdt')) {
152
        function vdt($var, $var_name = null)
153
        {
154
            \HexMakina\Debugger\Debugger::vd($var, $var_name, true);
155
        }
156
    }
157
    if (!function_exists('ddt')) {
158
        function ddt($var, $var_name = null)
159
        {
160
            \HexMakina\Debugger\Debugger::dd($var, $var_name, true);
161
        }
162
    }
163
}
164