Completed
Push — master ( a66420...6394df )
by Steevan
08:32
created

DebugBacktraceHtml   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 226
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 1
dl 0
loc 226
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A dump() 0 4 1
A eDump() 0 5 1
B getDump() 0 26 2
B getStyles() 0 39 1
A getJavascript() 0 11 1
C getBacktraceDump() 0 69 12
A getCallerDump() 0 17 4
B getCodePreview() 0 19 6
1
<?php
2
3
class DebugBacktraceHtml extends \DebugBacktrace
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
{
5
    /**
6
     * @param int $offset
7
     * @param int|null $limit
8
     */
9
    public static function dump($offset = 0, $limit = null)
10
    {
11
        echo static::getDump(static::getBacktraces($offset + 1, $limit));
12
    }
13
14
    /**
15
     * @param int $offset
16
     * @param int|null $limit
17
     */
18
    public static function eDump($offset = 0, $limit = null)
19
    {
20
        static::dump($offset + 1, $limit);
21
        exit();
22
    }
23
24
    /**
25
     * @param array $backtraces
26
     * @return string
27
     */
28
    public static function getDump(array $backtraces)
29
    {
30
        $return = static::getStyles();
31
        $return .= static::getJavascript();
32
33
        $return .= '<div class="steevanb-backtrace-container">';
34
        $return .= static::getCallerDump();
35
36
        $return .= '
37
            <table class="table-backtrace">
38
                <tr>
39
                    <th>#</th>
40
                    <th>File#Line</th>
41
                    <th>Call</th>
42
                </tr>
43
        ';
44
        $previewPrefix = uniqid('steevanb_backtrace_preview');
45
        foreach ($backtraces as $index => $backtrace) {
46
            $return .= static::getBacktraceDump($backtrace, $index, $previewPrefix);
47
        }
48
        $return .= '</table>';
49
50
        $return .= '</div>';
51
52
        return $return;
53
    }
54
55
    /** @return string */
56
    protected static function getStyles()
57
    {
58
        return '
59
            <style type="text/css">
60
                .steevanb-backtrace-container {
61
                    padding: 3px;
62
                    border: solid 2px #9e9e9e;
63
                    background-color: #F5F5F5;
64
                    cursor: default;
65
                    font-family: monospace;
66
                }
67
                .steevanb-backtrace-container table {
68
                    border-collapse: collapse;
69
                }
70
                .steevanb-backtrace-container table.table-backtrace tr.dark {
71
                    background-color: #e5e5e5;
72
                }
73
                .steevanb-backtrace-container table.table-backtrace td {
74
                    padding: 2px !important;
75
                }
76
                .steevanb-backtrace-container table.table-backtrace td a,
77
                .steevanb-backtrace-container table.table-backtrace td a:hover,
78
                .steevanb-backtrace-container table.table-backtrace td a:visited
79
                {
80
                    color: #4e7ca9 !important;
81
                    text-decoration: none !important;
82
                    cursor: pointer !important;
83
                }
84
                .steevanb-backtrace-container table.table-backtrace td a:hover {
85
                    text-decoration: underline !important;
86
                }
87
                .steevanb-backtrace-caller {
88
                    padding: 3px;
89
                    background-color: #78a1c9;
90
                    color: white;
91
                    font-weight: bold;
92
                }
93
            </style>';
94
    }
95
96
    /** @return string */
97
    protected static function getJavascript()
98
    {
99
        return '
100
            <script type="text/javascript">
101
                function steevanb_dev_showCodePreview(id)
102
                {
103
                    var element = document.getElementById(id);
104
                    element.style.display = (element.style.display === "none") ? "" : "none";
105
                }
106
            </script>';
107
    }
108
109
    /**
110
     * @param array $backtrace
111
     * @param int $index
112
     * @param string $previewPrefix
113
     * @return string
114
     */
115
    protected static function getBacktraceDump(array $backtrace, $index, $previewPrefix)
116
    {
117
        $filePath = null;
118
        $line = null;
119
        $previewId = $previewPrefix . '_' . $index;
120
121
        if ($backtrace['file'] !== null) {
122
            if (file_exists($backtrace['file'])) {
123
                $filePath = $backtrace['file'];
124
                $fileFound = true;
125
126
                if ($backtrace['line'] !== null) {
127
                    $line = $backtrace['line'];
128
                    $lineFound = true;
129
                } else {
130
                    $lineFound = false;
131
                }
132
            } elseif (substr($backtrace['file'], -16) === ' : eval()\'d code') {
133
                $fileAndLine = substr($backtrace['file'], 0, -16);
134
                $filePath = substr($fileAndLine, 0, strrpos($fileAndLine, '('));
135
                if (file_exists($filePath)) {
136
                    $line = substr($fileAndLine, strrpos($fileAndLine, '(') + 1, -1);
137
                    $fileFound = true;
138
                    $lineFound = true;
139
                } else {
140
                    $fileFound = false;
141
                    $lineFound = false;
142
                }
143
            } else {
144
                $fileFound = false;
145
                $lineFound = false;
146
            }
147
        } else {
148
            $fileFound = false;
149
            $lineFound = false;
150
        }
151
152
        if ($fileFound === false && $lineFound === false) {
153
            $fileLineHtml = '\Closure';
154
            $codePreview = null;
155
        } else {
156
            $codePreview = static::getCodePreview($filePath, $line);
157
            $fileLineHtml = '
158
                <a
159
                    title="' . static::getFilePath($filePath) . '"
160
                    onclick="steevanb_dev_showCodePreview(\'' . $previewId . '\')"
161
                >
162
                    ' . basename($filePath) . '#' . $line . '
163
                </a>
164
            ';
165
        }
166
167
        $html = '
168
            <tr' . ($index % 2 ? null : ' class="dark"') . '>
169
                <td>' . ($index + 1) . '</td>
170
                <td>' . $fileLineHtml . '</td>
171
                <td>' . $backtrace['call'] . '</td>
172
            </tr>
173
        ';
174
        if ($fileFound && $lineFound) {
175
            $html .= '
176
                <tr' . ($index % 2 ? null : ' class="dark"') . ' id="' . $previewId . '" style="display: none">
177
                    <td colspan="3"><pre>' . $codePreview . '</pre></td>
178
                </tr>
179
            ';
180
        }
181
182
        return $html;
183
    }
184
185
    /** @return string */
186
    protected static function getCallerDump()
187
    {
188
        $caller = static::getCaller();
189
190
        $return = '<div class="steevanb-backtrace-caller">';
191
        $header = null;
192
        if (is_array($caller)) {
193
            $header .= isset($caller['file']) ? static::getFilePath($caller['file']) : '(Unknow file)';
194
            $header .= isset($caller['line']) ? '#' . $caller['line'] : '::(Unknow line)';
195
        } else {
196
            $header= 'Unkonw caller';
197
        }
198
        $return .= $header;
199
        $return .= '</div>';
200
201
        return $return;
202
    }
203
204
    /**
205
     * @param string $file
206
     * @param int $line
207
     * @return string
208
     */
209
    protected static function getCodePreview($file, $line)
210
    {
211
        $preview = [];
212
        $lineMin = $line - 6;
213
        $lineMax = $line + 4;
214
        foreach (file($file) as $index => $codeLine) {
215
            if ($index >= $lineMin && $index <= $lineMax) {
216
                if ($index === $line - 1) {
217
                    $preview[] = '<span style="background-color: #7fd189">' . rtrim($codeLine) . '</span>';
218
                } else {
219
                    $preview[] = rtrim($codeLine);
220
                }
221
            } elseif ($index > $lineMax) {
222
                break;
223
            }
224
        }
225
226
        return implode('<br />', $preview);
227
    }
228
}
229