Passed
Push — main ( e7ed47...9aaa9d )
by Sammy
02:30
created

Debugger   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 83
c 3
b 0
f 0
dl 0
loc 165
rs 9.84
wmc 32

13 Methods

Rating   Name   Duplication   Size   Complexity  
A isInternalFunctionCall() 0 3 2
A dd() 0 4 1
A vd() 0 3 1
A init() 0 2 1
A __debugInfo() 0 3 1
A formatThrowable() 0 9 1
A toHTML() 0 14 1
B tracesToString() 0 36 7
B traceArgsToString() 0 20 7
A formatFilename() 0 3 1
A isShortcutCall() 0 3 1
A displayErrors() 0 6 3
A dump() 0 22 5
1
<?php
2
3
namespace HexMakina\Debugger
4
{
5
    trait Debugger
6
    {
7
8
        public function __debugInfo(): array
9
        {
10
            return [json_encode(get_object_vars($this))];
11
        }
12
13
        public static function init()
14
        {
15
          // just to load the class, required to get the shortcuts defined in namespace \
16
        }
17
18
        public static function displayErrors($error_message = null)
19
        {
20
            $should_display = ini_get('display_errors') == '1';
21
22
            if ($should_display && !empty($error_message)) {
23
                echo self::toHTML($error_message);
24
            }
25
        }
26
27
      // -- visual dump (depends on env)
28
        public static function vd($var, $var_name = null, $full_backtrace = false)
29
        {
30
            self::displayErrors(self::dump($var, $var_name, $full_backtrace));
31
        }
32
33
      // -- visual dump and DIE
34
        public static function dd($var, $var_name = null, $full_backtrace = true)
35
        {
36
            self::vd($var, $var_name, $full_backtrace);
37
            die;
38
        }
39
40
      // -- dump on variable type (Throwables, array, anything else)
41
        public static function dump($var, $var_name = null, $full_backtrace = true)
42
        {
43
            if (is_object($var) && (is_subclass_of($var, 'Error') || is_subclass_of($var, 'Exception'))) {
44
                $backtrace = $var->getTrace();
45
                $full_backtrace = true;
46
                $var_dump  = self::formatThrowable($var);
47
            } else {
48
                $backtrace = debug_backtrace();
49
50
                ob_start();
51
                var_dump($var);
52
                $var_dump = ob_get_clean();
53
            }
54
55
            return PHP_EOL
56
            . "*******"
57
            . (empty($var_name) ? '' : " ($var_name) ")
58
            . "*******"
59
            . PHP_EOL
60
            . self::tracesToString($backtrace, $full_backtrace)
61
            . PHP_EOL
62
            . $var_dump;
63
        }
64
65
      // -- formatting
66
67
      // -- formatting : first line of \Throwable-based error
68
        public static function formatThrowable(\Throwable $err)
69
        {
70
            return PHP_EOL . sprintf(
71
                '%s (%d) in file %s:%d' . PHP_EOL . '%s',
72
                get_class($err),
73
                $err->getCode(),
74
                self::formatFilename($err->getFile()),
75
                $err->getLine(),
76
                $err->getMessage()
77
            );
78
        }
79
80
        private static function formatFilename($file, $reduce_file_depth_to = 5)
81
        {
82
            return implode('/', array_slice(explode('/', $file), -$reduce_file_depth_to, $reduce_file_depth_to));
83
        }
84
85
      // -- formatting : nice backtrace
86
        public static function tracesToString($traces, $full_backtrace)
87
        {
88
            $formated_traces = [];
89
90
            foreach ($traces as $depth => $trace) {
91
                $function_name = $trace['function'] ?? '?';
92
                $class_name = $trace['class'] ?? '?';
93
94
                if (self::isInternalFunctionCall($class_name, $function_name)) {
95
                    continue;
96
                }
97
98
                if (!self::isShortcutCall($function_name) && isset($trace['args'])) {
99
                    $args = self::traceArgsToString($trace['args']);
100
                } else {
101
                    $args = microtime(true);
102
                }
103
104
                $call_file = isset($trace['file']) ? basename($trace['file']) : '?';
105
                $call_line = $trace['line'] ?? '?';
106
107
                $formated_traces [] = sprintf(
108
                    '[%-23.23s %3s]  %s%s(%s)',
109
                    $call_file,
110
                    $call_line,
111
                    "$class_name::",
112
                    $function_name,
113
                    $args
114
                );
115
116
                if ($full_backtrace === false) {
117
                    break;
118
                }
119
            }
120
121
            return implode(PHP_EOL, array_reverse($formated_traces));
122
        }
123
124
        private static function traceArgsToString($trace_args)
125
        {
126
            $ret = [];
127
            foreach ($trace_args as $arg) {
128
                if (is_null($arg)) {
129
                    $ret[] = 'NULL';
130
                } elseif (is_bool($arg)) {
131
                    $ret[] = 'bool:' . ((int)$arg);
132
                } elseif (is_scalar($arg)) {
133
                    $ret[] = $arg;
134
                } elseif (is_object($arg)) {
135
                    $ret[] = get_class($arg);
136
                } elseif (is_array($arg)) {
137
                    $ret[] = 'Array #' . count($arg);
138
                } else {
139
                    $ret[] = 'unknown type';
140
                }
141
            }
142
            $ret = implode(', ', $ret);
143
            return $ret;
144
        }
145
146
        private static function isInternalFunctionCall($class_name, $function_name): bool
147
        {
148
            return $class_name === __CLASS__ && in_array($function_name, ['dump', 'vd', 'dd']);
149
        }
150
151
        private static function isShortcutCall($function_name): bool
152
        {
153
            return in_array($function_name, ['vd', 'dd','vdt', 'ddt']);
154
        }
155
156
        private static function toHTML($message)
157
        {
158
            $css = [
159
            'text-align:left',
160
            'z-index:9999',
161
            'background-color:#FFF',
162
            'color:#000',
163
            'padding:0.5em',
164
            'font-size:0.7em',
165
            'margin:0 0 1em 0',
166
            'font-family:courier'
167
            ];
168
169
            return sprintf('<pre style="%s">%s</pre>', implode(';', $css), $message);
170
        }
171
    }
172
}
173
namespace
174
{
175
    if (!function_exists('vd')) {
176
        function vd($var, $var_name = null)
177
        {
178
            \HexMakina\Debugger\Debugger::vd($var, $var_name, false);
179
        }
180
    }
181
    if (!function_exists('dd')) {
182
        function dd($var, $var_name = null)
183
        {
184
            \HexMakina\Debugger\Debugger::dd($var, $var_name, false);
185
        }
186
    }
187
    if (!function_exists('vdt')) {
188
        function vdt($var, $var_name = null)
189
        {
190
            \HexMakina\Debugger\Debugger::vd($var, $var_name, true);
191
        }
192
    }
193
    if (!function_exists('ddt')) {
194
        function ddt($var, $var_name = null)
195
        {
196
            \HexMakina\Debugger\Debugger::dd($var, $var_name, true);
197
        }
198
    }
199
}
200