1 <?php
2
3 namespace Alo;
4
5 use Exception;
6
7 if (!defined('GEN_START')) {
8 http_response_code(404);
9 } else {
10
11 /**
12 * Handles autoloading, errors and exceptions
13 *
14 * @author Art <a.molcanovas@gmail.com>
15 */
16 abstract class Handler {
17
18 /**
19 * Whether CSS has been injected yet
20 *
21 * @var bool
22 */
23 protected static $cssInjected = false;
24
25 /**
26 * Injects CSS into the page to preffity our output
27 *
28 * @author Art <a.molcanovas@gmail.com>
29 */
30 protected static function injectCss() {
31 if (!self::$cssInjected) {
32 self::$cssInjected = true;
33 echo '<style>';
34 include DIR_SYS . 'core' . DIRECTORY_SEPARATOR . 'error.css';
35 echo '</style>';
36 }
37 }
38
39 /**
40 * The error handler
41 *
42 * @author Art <a.molcanovas@gmail.com>
43 *
44 * @param int $errno The level of the error raised
45 * @param string $errstr The error message
46 * @param string $errfile The filename that the error was raised in
47 * @param int $errline The line number the error was raised at
48 */
49 static function error($errno, $errstr, $errfile, $errline) {
50 self::injectCss();
51 $type = $errno;
52 $label = 'warning';
53
54 switch ($errno) {
55 case E_NOTICE:
56 case E_USER_NOTICE:
57 $type = 'NOTICE';
58 $label = 'info';
59 break;
60 case E_ERROR:
61 case E_USER_ERROR:
62 case E_COMPILE_ERROR:
63 case E_RECOVERABLE_ERROR:
64 case E_CORE_ERROR:
65 $type = 'ERROR';
66 $label = 'danger';
67 break;
68 case E_DEPRECATED:
69 case E_USER_DEPRECATED:
70 $type = 'DEPRECATED';
71 break;
72 case E_WARNING:
73 case E_USER_WARNING:
74 case E_CORE_WARNING:
75 $type = 'WARNING';
76 break;
77 }
78
79 $f = explode(DIR_INDEX, $errfile);
80 $f = isset($f[1]) ? $f[1] : $f[0];
81
82 echo '<div class="text-center">' //BEGIN outer container
83 . '<div class="alo-err alert alert-' . $label . '">' //BEGIN inner container
84 . '<div>' //BEGIN header
85 . '<span
86 class="alo-bold">' . $type . ': ' . '</span><span>' . $errstr . '</span></div>'//END header
87 . '<div><span class="alo-bold">Raised in </span>' . '<span class="alo-uline">' . $f . '</span>';
88
89 if ($errline) {
90 echo '<span> @ line </span><span class="alo-uline">' . $errline . '</span>';
91 }
92
93 echo '</div><span class="alo-bold">Backtrace:</span>';
94
95 $trace = array_reverse(debug_backtrace());
96 array_pop($trace);
97
98 self::echoTrace($trace);
99
100 echo '</div>'//END inner
101 . '</div>'; //END outer
102
103 $trace = \debug_backtrace();
104 array_shift($trace);
105 \Log::error($errstr, $trace);
106 }
107
108 /**
109 * Used to automatically load class,interface and trait files
110 *
111 * @author Art <a.molcanovas@gmail.com>
112 *
113 * @param string $name Class name
114 */
115 static function autoloader($name) {
116 $name = ltrim(strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $name)), '/') . '.php';
117 $locations = [DIR_APP . 'class',
118 DIR_SYS . 'class',
119 DIR_APP . 'interface',
120 DIR_APP . 'traits'];
121
122 foreach ($locations as $l) {
123 if (file_exists($l . DIRECTORY_SEPARATOR . $name)) {
124 include_once $l . DIRECTORY_SEPARATOR . $name;
125 break;
126 }
127 }
128 }
129
130 /**
131 * Echoes previous exceptions if applicable
132 *
133 * @author Art <a.molcanovas@gmail.com>
134 *
135 * @param null|\Exception $e The previous exception
136 */
137 protected static function echoPreviousExceptions($e) {
138 if ($e instanceof Exception) {
139 echo '<div><span class="alo-bold">Preceded by </span><span>[' . $e->getCode() . ']: ' .
140 $e->getMessage() . ' @ <span class="alo-uline">' . $e->getFile() . '</span>\'s line ' .
141 $e->getLine() . '.</span></div>';
142
143 self::echoPreviousExceptions($e->getPrevious());
144 }
145 }
146
147 /**
148 * Echoes the debug backtrace
149 *
150 * @author Art <a.molcanovas@gmail.com>
151 *
152 * @param array $trace The backtrace
153 */
154 protected static function echoTrace($trace) {
155 echo '<table class="table" border="1">'//BEGIN table
156 . '<thead>'//BEGIN head
157 . '<tr>'//BEGIN head row
158 . '<th>#</th>'//Trace number
159 . '<th>Method</th>'//Method used
160 . '<th>Args</th>'//Method args
161 . '<th>Location</th>'//File
162 . '<th>Line</th>'//Line of code
163 . '</tr>'//END head row
164 . '</thead>'//END head
165 . '<tbody>'; //BEGIN table
166
167 foreach ($trace as $k => $v) {
168 $func = $loc = $line = '';
169
170 if (isset($v['class'])) {
171 $func = $v['class'];
172 }
173 if (isset($v['type'])) {
174 $func .= $v['type'];
175 }
176 if (isset($v['function'])) {
177 $func .= $v['function'] . '()';
178 }
179 if (!$func) {
180 $func = '[unknown]';
181 }
182
183 if (isset($v['file'])) {
184 $loc = get(explode(DIR_INDEX, $v['file'])[1]);
185 }
186 if (isset($v['line'])) {
187 $line .= $v['line'];
188 }
189
190 echo '<tr>' //BEGIN row
191 . '<td>' . $k . '</td>' //Trace #
192 . '<td>' . $func . '</td>' //Method used
193 . '<td>' . //BEGIN args
194 (get($v['args']) ? debugLite($v['args']) : '<span class="label label-default">NONE</span>') .
195 '</td>' //END args
196 . '<td>' //BEGIN location
197 . ($loc ? $loc : '<span class="label label-default">???</span>') . '</td>'//END location
198 . '<td>'//BEGIN line
199 . ($line || $line == '0' ? $line : '<span class="label label-default">???</span>') . '</td>'
200 //END line
201 . '</tr>';
202 }
203
204 echo '</tbody>' . '</table>';
205 }
206
207 /**
208 * Exception handler
209 *
210 * @author Art <a.molcanovas@gmail.com>
211 *
212 * @param \Exception $e The exception
213 */
214 static function ecxeption(\Exception $e) {
215 self::injectCss();
216
217 echo '<div class="text-center">' //BEGIN outer container
218 . '<div class="alo-err alert alert-danger">'//BEGIN inner container
219 . '<div>'//BEGIN header
220 . '<span class="alo-bold">Uncaught exception: </span><span>' . $e->getMessage() . '</span></div>'
221 //END header
222 //BEGIN raised
223 . '<div><span class="alo-bold">Raised in </span><span class="alo-uline">' . $e->getFile() .
224 '</span> @ line ' . $e->getLine() . '</div>' . '<div><span class="alo-bold">Code: </span><span>' .
225 $e->getCode() . '</span></div>';
226
227 self::echoPreviousExceptions($e->getPrevious());
228
229 echo '<span class="alo-bold">Backtrace:</span>';
230
231 self::echoTrace($e->getTrace());
232
233 echo '</div></div>'; //END inner/outer
234 }
235 }
236 }
237