Passed
Push — main ( 56297f...24dbbf )
by Sammy
02:55
created

Debugger::visualDump()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 4
rs 10
1
<?php
2
3
namespace HexMakina\Debugger
4
{
5
    class Debugger
6
    {
7
        public static function displayErrors($error_message = null)
8
        {
9
            $should_display = ini_get('display_errors') == '1';
10
11
            if ($should_display && !empty($error_message)) {
12
                echo self::toHTML($error_message);
13
            }
14
        }
15
16
        // -- dump on variable type (Throwables, array, anything else)
17
        public static function dump($var, $var_name = null, $full_backtrace = true)
18
        {
19
            if (is_object($var) && (is_subclass_of($var, 'Error') || is_subclass_of($var, 'Exception'))) {
20
                $backtrace = $var->getTrace();
21
                $full_backtrace = true;
22
                $var_dump  = self::formatThrowable($var);
23
            } else {
24
                $backtrace = debug_backtrace();
25
26
                ob_start();
27
                var_dump($var);
28
                $var_dump = ob_get_clean();
29
            }
30
31
            return PHP_EOL
32
            . "*******"
33
            . (empty($var_name) ? '' : " ($var_name) ")
34
            . "*******"
35
            . PHP_EOL
36
            . self::tracesToString($backtrace, $full_backtrace)
37
            . PHP_EOL
38
            . $var_dump;
39
        }
40
41
        // -- visual dump (depends on env)
42
        public static function visualDump($var, $var_name = null, $full_backtrace = false)
43
        {
44
            self::displayErrors(self::dump($var, $var_name, $full_backtrace));
45
            return $var;
46
        }
47
48
        // -- visual dump and DIE
49
        public static function visualDumpAndDie($var, $var_name = null, $full_backtrace = true)
50
        {
51
            self::vd($var, $var_name, $full_backtrace);
0 ignored issues
show
Bug introduced by
The method vd() does not exist on HexMakina\Debugger\Debugger. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
            self::/** @scrutinizer ignore-call */ 
52
                  vd($var, $var_name, $full_backtrace);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
52
            die;
1 ignored issue
show
Best Practice introduced by
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...
53
        }
54
55
56
      // -- formatting
57
58
      // -- formatting : first line of \Throwable-based error
59
        public static function formatThrowable(\Throwable $err)
60
        {
61
            return PHP_EOL . sprintf(
62
                '%s (%d) in file %s:%d' . PHP_EOL . '%s',
63
                get_class($err),
64
                $err->getCode(),
65
                self::formatFilename($err->getFile()),
66
                $err->getLine(),
67
                $err->getMessage()
68
            );
69
        }
70
71
        public static function formatFilename($file, $reduce_file_depth_to = 5)
72
        {
73
            return implode('/', array_slice(explode('/', $file), -$reduce_file_depth_to, $reduce_file_depth_to));
74
        }
75
76
      // -- formatting : nice backtrace
77
        public static function tracesToString($traces, $full_backtrace)
78
        {
79
            $formated_traces = [];
80
81
            foreach ($traces as $depth => $trace) {
82
                $function_name = $trace['function'] ?? '?';
83
                $class_name = $trace['class'] ?? '?';
84
85
                if (self::isInternalFunctionCall($class_name, $function_name)) {
86
                    continue;
87
                }
88
89
                if (!self::isShortcutCall($function_name) && isset($trace['args'])) {
90
                    $args = self::traceArgsToString($trace['args']);
91
                } else {
92
                    $args = microtime(true);
93
                }
94
95
                $call_file = isset($trace['file']) ? basename($trace['file']) : '?';
96
                $call_line = $trace['line'] ?? '?';
97
98
                $formated_traces [] = sprintf(
99
                    '[%-23.23s %3s]  %s%s(%s)',
100
                    $call_file,
101
                    $call_line,
102
                    "$class_name::",
103
                    $function_name,
104
                    $args
105
                );
106
107
                if ($full_backtrace === false) {
108
                    break;
109
                }
110
            }
111
112
            return implode(PHP_EOL, array_reverse($formated_traces));
113
        }
114
115
        private static function traceArgsToString($trace_args)
116
        {
117
            $ret = [];
118
            foreach ($trace_args as $arg) {
119
                if (is_null($arg)) {
120
                    $ret[] = 'NULL';
121
                } elseif (is_bool($arg)) {
122
                    $ret[] = 'bool:' . ((int)$arg);
123
                } elseif (is_scalar($arg)) {
124
                    $ret[] = $arg;
125
                } elseif (is_object($arg)) {
126
                    $ret[] = get_class($arg);
127
                } elseif (is_array($arg)) {
128
                    $ret[] = 'Array #' . count($arg);
129
                } else {
130
                    $ret[] = 'unknown type';
131
                }
132
            }
133
            $ret = implode(', ', $ret);
134
            return $ret;
135
        }
136
137
        private static function isInternalFunctionCall($class_name, $function_name): bool
138
        {
139
            return $class_name === __CLASS__ && in_array($function_name, ['dump', 'vd', 'dd']);
140
        }
141
142
        private static function isShortcutCall($function_name): bool
143
        {
144
            return in_array($function_name, ['vd', 'dd','vdt', 'ddt']);
145
        }
146
147
        private static function toHTML($message)
148
        {
149
            $css = [
150
            'text-align:left',
151
            'z-index:9999',
152
            'background-color:#FFF',
153
            'color:#000',
154
            'padding:0.5em',
155
            'font-size:0.7em',
156
            'margin:0 0 1em 0',
157
            'font-family:courier'
158
            ];
159
160
            return sprintf('<pre style="%s">%s</pre>', implode(';', $css), $message);
161
        }
162
    }
163
}
164
namespace
165
{
166
    if (!function_exists('vd')) {
167
        function vd($var, $var_name = null)
168
        {
169
            \HexMakina\Debugger\Debugger::visualDump($var, $var_name, false);
170
        }
171
    }
172
    if (!function_exists('dd')) {
173
        function dd($var, $var_name = null)
174
        {
175
            \HexMakina\Debugger\Debugger::visualDumpAndDie($var, $var_name, false);
176
        }
177
    }
178
    if (!function_exists('vdt')) {
179
        function vdt($var, $var_name = null)
180
        {
181
            \HexMakina\Debugger\Debugger::visual_dump($var, $var_name, true);
0 ignored issues
show
Bug introduced by
The method visual_dump() does not exist on HexMakina\Debugger\Debugger. Did you maybe mean visualDump()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
            \HexMakina\Debugger\Debugger::/** @scrutinizer ignore-call */ 
182
                                          visual_dump($var, $var_name, true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
182
        }
183
    }
184
    if (!function_exists('ddt')) {
185
        function ddt($var, $var_name = null)
186
        {
187
            \HexMakina\Debugger\Debugger::visualDumpAndDie($var, $var_name, true);
188
        }
189
    }
190
}
191