1 | <?php /** @noinspection PhpUnnecessaryCurlyVarSyntaxInspection */ |
||
2 | |||
3 | /* |
||
4 | * debug.php :: Clase Debug, maneja reporte de eventos |
||
5 | * |
||
6 | * V4.0 copyright 2010-2011 by Gorlum for http://supernova.ws |
||
7 | * [!] Merged `errors` to `logs` |
||
8 | * [+] Now debugger can work with database detached. All messages would be dumped to page |
||
9 | * [+] Now `logs` has both human-readable and machine-readable fields |
||
10 | * |
||
11 | * V3.0 copyright 2010 by Gorlum for http://supernova.ws |
||
12 | * [+] Full rewrtie & optimize |
||
13 | * [*] Now there is fallback procedure if no link to db detected |
||
14 | * |
||
15 | * V2.0 copyright 2010 by Gorlum for http://supernova.ws |
||
16 | * [*] Now error also contains backtrace - to see exact way problem comes |
||
17 | * [*] New method 'warning' sends message to dedicated SQL-table for non-errors |
||
18 | * |
||
19 | * V1.0 Created by Perberos. All rights reversed (C) 2006 |
||
20 | * |
||
21 | * Experiment code!!! |
||
22 | * |
||
23 | * vamos a experimentar >:) |
||
24 | * le veo futuro a las classes, ayudaria mucho a tener un codigo mas ordenado... |
||
25 | * que esperabas!!! soy newbie!!! D':< |
||
26 | */ |
||
27 | |||
28 | use DBAL\db_mysql; |
||
29 | |||
30 | if (!defined('INSIDE')) { |
||
31 | die("attemp hacking"); |
||
32 | } |
||
33 | |||
34 | class debug { |
||
35 | protected $log; |
||
36 | protected $numqueries; |
||
37 | protected $log_array; |
||
38 | |||
39 | public function log_file($message, $ident_change = 0) { |
||
40 | if (!defined('SN_DEBUG_LOG') || !SN_DEBUG_LOG) { |
||
41 | return; |
||
42 | } |
||
43 | |||
44 | static $ident = 0; |
||
45 | static $logFileName; |
||
46 | |||
47 | if (!$logFileName) { |
||
48 | $logFileName = SN_ROOT_PHYSICAL . '/.logs/supernova.log'; |
||
49 | file_put_contents($logFileName, "\r\n\r\n", FILE_APPEND); |
||
50 | } |
||
51 | if ($ident_change < 0) { |
||
52 | $ident += $ident_change * 2; |
||
53 | } |
||
54 | file_put_contents($logFileName, date(FMT_DATE_TIME_SQL, time()) . str_repeat(' ', $ident + 1) . $message . "\r\n", FILE_APPEND); |
||
55 | if ($ident_change > 0) { |
||
56 | $ident += $ident_change * 2; |
||
57 | } |
||
58 | } |
||
59 | |||
60 | public function log_sql($message, $ident_change = 0) { |
||
61 | static $ident = 0; |
||
62 | static $logFileName; |
||
63 | static $mt_rand; |
||
64 | |||
65 | if (!$mt_rand) { |
||
66 | $mt_rand = mt_rand(); |
||
67 | } |
||
68 | |||
69 | if (!$logFileName) { |
||
70 | $dbName = SN::$db->dbName; |
||
71 | $logFileName = SN_ROOT_PHYSICAL . "/.logs/{$dbName}.mysql." . date('Y-m-d-H-i-s.') . sprintf("%06d", gettimeofday()["usec"]) . ".log"; |
||
72 | } |
||
73 | if ($ident_change < 0) { |
||
74 | $ident += $ident_change * 2; |
||
75 | } |
||
76 | file_put_contents($logFileName, str_repeat(' ', $ident) . $message . "\n\n", FILE_APPEND); |
||
77 | if ($ident_change > 0) { |
||
78 | $ident += $ident_change * 2; |
||
79 | } |
||
80 | } |
||
81 | |||
82 | public function __construct() { |
||
83 | $this->log = ''; |
||
84 | $this->numqueries = 0; |
||
85 | } |
||
86 | |||
87 | function add($mes) { |
||
88 | $this->log .= $mes; |
||
89 | $this->numqueries++; |
||
90 | } |
||
91 | |||
92 | function add_to_array($mes) { |
||
93 | $this->log_array[] = $mes; |
||
94 | } |
||
95 | |||
96 | function echo_log() { |
||
97 | echo '<br><table><tr><td class=k colspan=4><a href="' . SN_ROOT_PHYSICAL . "admin/settings.php\">Debug Log</a>:</td></tr>{$this->log}</table>"; |
||
98 | die(); |
||
0 ignored issues
–
show
|
|||
99 | } |
||
100 | |||
101 | public function compact_backtrace($backtrace, $long_comment = false, $onlyLastX = null) { |
||
102 | static $exclude_functions = array( |
||
103 | // Caller not needed |
||
104 | 'comment_query', |
||
105 | // Excluding includes/requires |
||
106 | 'include', 'include_once', 'require_once', 'require', |
||
107 | // Excluding query calls/DB wrap functions |
||
108 | 'doquery', |
||
109 | 'db_get_record_list', // 'db_user_by_id', 'db_get_user_by_id', |
||
110 | 'doSelect', 'doSelectFetch', |
||
111 | 'db_query_update', |
||
112 | 'selectValue', |
||
113 | // classPersistent |
||
114 | '__get', 'db_loadItem', '__set', 'db_saveItem', |
||
115 | // Constructors ?! Why not... |
||
116 | '__construct', |
||
117 | // Hook handlers |
||
118 | 'sn_function_call', |
||
119 | // Chat |
||
120 | 'db_chat_player_list_online', |
||
121 | // Transaction-related functions |
||
122 | 'db_transaction_commit', 'transactionCommit', 'transactionStart', 'db_transaction_start', 'db_transaction_rollback', 'transactionRollback', |
||
123 | ); |
||
124 | |||
125 | $raw = []; |
||
126 | $filtered = []; |
||
127 | foreach ($backtrace as $a_trace) { |
||
128 | $function = |
||
129 | (!empty($a_trace['type']) |
||
130 | ? ($a_trace['type'] == '->' |
||
131 | ? "({$a_trace['class']})" . get_class($a_trace['object']) |
||
132 | : $a_trace['class'] |
||
133 | ) . $a_trace['type'] |
||
134 | : '' |
||
135 | ) . $a_trace['function'] . '()'; |
||
136 | |||
137 | $file = str_replace(SN_ROOT_PHYSICAL, '', str_replace('\\', '/', !empty($a_trace['file']) ? $a_trace['file'] : '')); |
||
138 | |||
139 | $line = !empty($a_trace['line']) ? '@' . $a_trace['line'] : ''; |
||
140 | $raw[] = "{$function} - '{$file}'{$line}"; |
||
141 | |||
142 | if (!in_array($a_trace['function'], $exclude_functions)) { |
||
143 | $filtered[] = &$raw[count($raw) - 1]; |
||
144 | } |
||
145 | |||
146 | if (!$long_comment) { |
||
147 | break; |
||
148 | } |
||
149 | } |
||
150 | |||
151 | $raw = array_reverse($raw); |
||
152 | $filtered = array_reverse($filtered); |
||
153 | |||
154 | if ($onlyLastX) { |
||
155 | $raw = array_slice($raw, -$onlyLastX); |
||
156 | $filtered = array_slice($filtered, -$onlyLastX); |
||
157 | } |
||
158 | |||
159 | return [$raw, $filtered,]; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * @param array $backtrace |
||
164 | * @param string $sql |
||
165 | * |
||
166 | * @return string |
||
167 | */ |
||
168 | public function comment_query($backtrace, $sql) { |
||
169 | list($raw, $filtered,) = $this->compact_backtrace($backtrace, defined('DEBUG_SQL_COMMENT_LONG')); |
||
170 | |||
171 | $sql_commented = [ |
||
172 | "/* ", |
||
173 | 'date' => date("s.") . sprintf("%06d", gettimeofday()["usec"]), |
||
174 | !empty($filtered) ? "\n" . implode("\n", $filtered) . " \n" : '', |
||
175 | "*/\n", |
||
176 | // SQL itself with removed double spaces |
||
177 | preg_replace("/\s+/", ' ', $sql), |
||
178 | ]; |
||
179 | |||
180 | if (defined('DEBUG_SQL_FILE_LOG') && !empty(DEBUG_SQL_FILE_LOG)) { |
||
181 | $this->log_sql(implode('', $sql_commented)); |
||
182 | } |
||
183 | |||
184 | // $sql_commented = '/* ' . implode("<br />", $sql_comment) . '<br /> */ ' . preg_replace("/\s+/", ' ', $sql); |
||
185 | // $isSelect = strpos(strtoupper($query), 'SELECT') !== false ? 'true' : 'false'; |
||
186 | $sql_commented['date'] = date('Y-m-d H:i:') . $sql_commented['date']; |
||
187 | |||
188 | // if(strpos($sql_comment, 'compact_backtrace') === false) { |
||
189 | // $transaction_id = SN::db_transaction_check(false) ? SN::$transaction_id : SN::$transaction_id++; |
||
190 | // $result[] = "tID {$transaction_id}"; |
||
191 | // } |
||
192 | |||
193 | if (defined('DEBUG_SQL_ERROR')) { |
||
194 | array_unshift($raw, preg_replace("/\s+/", ' ', $sql)); |
||
195 | array_unshift($raw, $sql_commented['date']); |
||
196 | $this->add_to_array($raw); |
||
197 | } |
||
198 | |||
199 | $sql = implode('', $sql_commented); |
||
200 | |||
201 | return $sql; |
||
202 | } |
||
203 | |||
204 | |||
205 | function dump($dump = false, $force_base = false, $deadlock = false) { |
||
206 | if ($dump === false) { |
||
207 | return []; |
||
208 | } |
||
209 | |||
210 | $error_backtrace = array(); |
||
211 | $base_dump = false; |
||
212 | |||
213 | if ($force_base === true) { |
||
214 | $base_dump = true; |
||
215 | } |
||
216 | |||
217 | if ($dump === true) { |
||
218 | $base_dump = true; |
||
219 | } else { |
||
220 | if (!is_array($dump)) { |
||
221 | $dump = array('var' => $dump); |
||
222 | } |
||
223 | |||
224 | foreach ($dump as $dump_var_name => $dump_var) { |
||
225 | if ($dump_var_name == 'base_dump') { |
||
226 | $base_dump = $dump_var; |
||
227 | } else { |
||
228 | $error_backtrace[$dump_var_name] = $dump_var; |
||
229 | } |
||
230 | } |
||
231 | } |
||
232 | |||
233 | if ($deadlock && ($q = SN::$db->mysql_get_innodb_status())) { |
||
234 | $error_backtrace['deadlock'] = explode("\n", $q['Status']); |
||
235 | foreach ($error_backtrace['cSN_data'] as &$location) { |
||
236 | foreach ($location as $location_id => &$location_data) // $location_data = $location_id; |
||
237 | { |
||
238 | $location_data = isset($location_data['username']) ? $location_data['username'] : |
||
239 | (isset($location_data['name']) ? $location_data['name'] : $location_id); |
||
240 | } |
||
241 | } |
||
242 | } |
||
243 | |||
244 | if ($base_dump) { |
||
245 | if (!is_array($this->log_array) || empty($this->log_array)) { |
||
246 | $this->log_array = []; |
||
247 | } else { |
||
248 | foreach ($this->log_array as $log) { |
||
249 | $error_backtrace['queries'][] = $log; |
||
250 | } |
||
251 | } |
||
252 | |||
253 | $error_backtrace['backtrace'] = debug_backtrace(); |
||
254 | unset($error_backtrace['backtrace'][1]); |
||
255 | unset($error_backtrace['backtrace'][0]); |
||
256 | |||
257 | // Converting object instances to object names |
||
258 | |||
259 | foreach ($error_backtrace['backtrace'] as &$backtrace) { |
||
260 | if (!empty($backtrace['object']) && is_object($backtrace['object'])) { |
||
261 | $backtrace['object'] = get_class($backtrace['object']); |
||
262 | } |
||
263 | |||
264 | if (empty($backtrace['args'])) { |
||
265 | continue; |
||
266 | } |
||
267 | |||
268 | // Doing same conversion for backtrace params |
||
269 | foreach ($backtrace['args'] as &$arg) { |
||
270 | if (is_object($arg)) { |
||
271 | $arg = 'object::' . get_class($arg); |
||
272 | } |
||
273 | } |
||
274 | } |
||
275 | |||
276 | // $error_backtrace['query_log'] = "\r\n\r\nQuery log\r\n<table><tr><th>Number</th><th>Query</th><th>Page</th><th>Table</th><th>Rows</th></tr>{$this->log}</table>\r\n"; |
||
277 | $error_backtrace['$_GET'] = $_GET; |
||
278 | $error_backtrace['$_POST'] = $_POST; |
||
279 | $error_backtrace['$_REQUEST'] = $_REQUEST; |
||
280 | $error_backtrace['$_COOKIE'] = $_COOKIE; |
||
281 | $error_backtrace['$_SESSION'] = empty($_SESSION) ? [] : $_SESSION; |
||
282 | $error_backtrace['$_SERVER'] = $_SERVER; |
||
283 | global $user, $planetrow; |
||
284 | $error_backtrace['user'] = $user; |
||
285 | $error_backtrace['planetrow'] = $planetrow; |
||
286 | } |
||
287 | |||
288 | return $error_backtrace; |
||
289 | } |
||
290 | |||
291 | function error_fatal($die_message, $details = 'There is a fatal error on page') { |
||
292 | // TODO - Записывать детали ошибки в лог-файл |
||
293 | die($die_message); |
||
294 | } |
||
295 | |||
296 | public function error($message = 'There is a error on page', $title = 'Internal Error', $httpCode = 500, $dump = true) { |
||
297 | global $config, $sys_stop_log_hit, $lang, $sys_log_disabled, $user; |
||
298 | |||
299 | if (empty(SN::$db->connected)) { |
||
300 | // TODO - писать ошибку в файл |
||
301 | die('SQL server currently unavailable. Please contact Administration...'); |
||
302 | } |
||
303 | |||
304 | db_mysql::db_transaction_rollback(); |
||
305 | |||
306 | if (SN::$config->debug == 1) { |
||
307 | /** @noinspection HtmlDeprecatedTag */ |
||
308 | /** @noinspection XmlDeprecatedElement */ |
||
309 | /** @noinspection HtmlDeprecatedAttribute */ |
||
310 | echo "<h2>{$title}</h2><br><font color=red>" . htmlspecialchars($message) . "</font><br><hr>"; |
||
311 | echo "<table>{$this->log}</table>"; |
||
312 | } |
||
313 | |||
314 | $fatal_error = 'Fatal error: cannot write to `logs` table. Please contact Administration...'; |
||
315 | |||
316 | $error_text = SN::$db->db_escape($message); |
||
317 | $error_backtrace = $this->dump($dump, true, strpos($message, 'Deadlock') !== false); |
||
318 | |||
319 | if (!$sys_log_disabled) { |
||
320 | $this->_writeLogMessage($httpCode, $user, $title, $message, $error_backtrace, $fatal_error); |
||
321 | |||
322 | $message = "Пожалуйста, свяжитесь с админом, если ошибка повторится. Ошибка №: <b>" . SN::$db->db_insert_id() . "</b>"; |
||
323 | |||
324 | $sys_stop_log_hit = true; |
||
325 | $sys_log_disabled = true; |
||
326 | !function_exists('messageBox') ? die($message) : SnTemplate::messageBox($message, 'Ошибка', '', 0, false); |
||
327 | } else { |
||
328 | // // TODO Здесь надо писать в файло |
||
329 | ob_start(); |
||
330 | print("<hr>User ID {$user['id']} raised error code {$httpCode} titled '{$title}' with text '{$error_text}' on page {$_SERVER['SCRIPT_NAME']}"); |
||
331 | |||
332 | foreach ($error_backtrace as $name => $value) { |
||
333 | print('<hr>'); |
||
334 | pdump($value, $name); |
||
335 | } |
||
336 | ob_end_flush(); |
||
337 | die(); |
||
338 | } |
||
339 | } |
||
340 | |||
341 | function warning($message, $title = 'System Message', $httpCode = 300, $dump = false) { |
||
342 | global $user, $lang, $sys_log_disabled; |
||
343 | |||
344 | if (empty(SN::$db->connected)) { |
||
345 | // TODO - писать ошибку в файл |
||
346 | die('SQL server currently unavailable. Please contact Administration...'); |
||
347 | } |
||
348 | |||
349 | $fatal_error = 'Fatal error: cannot write to `logs` table. Please contact Administration...'; |
||
350 | |||
351 | $error_backtrace = $this->dump($dump, false); |
||
352 | |||
353 | if (empty($sys_log_disabled)) { |
||
354 | $this->_writeLogMessage($httpCode, $user, $title, $message, $error_backtrace, $fatal_error); |
||
355 | } else { |
||
356 | // // TODO Здесь надо писать в файло |
||
357 | $id = !empty($user['id']) ? $user['id'] : 0; |
||
358 | print("<hr>User ID {$id} made log entry with code {$httpCode} titled '{$title}' with text '{$message}' on page {$_SERVER['SCRIPT_NAME']}"); |
||
359 | } |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * @param $httpCode |
||
364 | * @param $user |
||
365 | * @param $title |
||
366 | * @param $message |
||
367 | * @param array $error_backtrace |
||
368 | * @param $fatal_error |
||
369 | * |
||
370 | * @return void |
||
371 | */ |
||
372 | function _writeLogMessage($httpCode, $user, $title, $message, array $error_backtrace, $fatal_error) { |
||
373 | /** @noinspection SqlResolve */ |
||
374 | $query = "INSERT INTO `{{logs}}` SET |
||
375 | `log_time` = '" . time() . "', `log_code` = '" . SN::$db->db_escape($httpCode) . "', " . |
||
376 | "`log_sender` = '" . (!empty($user['id']) ? SN::$db->db_escape($user['id']) : 0) . "', " . |
||
377 | "`log_username` = '" . SN::$db->db_escape(!empty($user['user_name']) ? $user['user_name'] : '') . "', " . |
||
378 | "`log_title` = '" . SN::$db->db_escape($title) . "', `log_text` = '" . SN::$db->db_escape($message) . "', " . |
||
379 | "`log_page` = '" . SN::$db->db_escape(strpos($_SERVER['SCRIPT_NAME'], SN_ROOT_RELATIVE) === false ? $_SERVER['SCRIPT_NAME'] : substr($_SERVER['SCRIPT_NAME'], strlen(SN_ROOT_RELATIVE))) . "'" . ", " . |
||
380 | "`log_dump` = '" . ($error_backtrace ? SN::$db->db_escape(json_encode($error_backtrace)) : '') . "'" . ";"; |
||
381 | |||
382 | doquery($query, '', false, true) or die($fatal_error . SN::$db->db_error()); |
||
383 | } |
||
384 | } |
||
385 | |||
386 | // Copyright (c) 2009-2010 Gorlum for http://supernova.ws |
||
387 | // Dump variables nicer then var_dump() |
||
388 | |||
389 | function dump($value, $varname = null, $level = 0, $dumper = '') { |
||
390 | if (isset($varname)) { |
||
391 | $varname .= " = "; |
||
392 | } |
||
393 | |||
394 | if ($level == -1) { |
||
395 | $trans[' '] = '∴'; |
||
396 | $trans["\t"] = '⇒'; |
||
397 | $trans["\n"] = '¶;'; |
||
398 | $trans["\r"] = '⇐'; |
||
399 | $trans["\0"] = '⊕'; |
||
400 | |||
401 | return strtr(htmlspecialchars($value), $trans); |
||
402 | } |
||
403 | if ($level == 0) { |
||
404 | // $dumper = '<pre>' . mt_rand(10, 99) . '|' . $varname; |
||
405 | $dumper = mt_rand(10, 99) . '|' . $varname; |
||
406 | } |
||
407 | |||
408 | $type = gettype($value); |
||
409 | $dumper .= $type; |
||
410 | |||
411 | if ($type == 'string') { |
||
412 | $dumper .= '(' . strlen($value) . ')'; |
||
413 | $value = dump($value, '', -1); |
||
414 | } elseif ($type == 'boolean') { |
||
415 | $value = ($value ? 'true' : 'false'); |
||
416 | } elseif ($type == 'object') { |
||
417 | $props = get_class_vars(get_class($value)); |
||
418 | $dumper .= '(' . count($props) . ') <u>' . get_class($value) . '</u>'; |
||
419 | foreach ($props as $key => $val) { |
||
420 | $dumper .= "\n" . str_repeat("\t", $level + 1) . $key . ' => '; |
||
421 | $dumper .= dump($value->$key, '', $level + 1); |
||
422 | } |
||
423 | $value = ''; |
||
424 | } elseif ($type == 'array') { |
||
425 | $dumper .= '(' . count($value) . ')'; |
||
426 | foreach ($value as $key => $val) { |
||
427 | $dumper .= "\n" . str_repeat("\t", $level + 1) . dump($key, '', -1) . ' => '; |
||
428 | $dumper .= dump($val, '', $level + 1); |
||
429 | } |
||
430 | $value = ''; |
||
431 | } |
||
432 | $dumper .= " <b>$value</b>"; |
||
433 | // if($level == 0) { |
||
434 | // $dumper .= '</pre>'; |
||
435 | // } |
||
436 | |||
437 | return $dumper; |
||
438 | } |
||
439 | |||
440 | function pdump($value, $varname = null) { |
||
441 | $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); |
||
442 | // print_rr($backtrace); |
||
443 | // $backtrace = $backtrace[1]; |
||
444 | |||
445 | $caller = ''; |
||
446 | if (defined('SN_DEBUG_PDUMP_CALLER') && SN_DEBUG_PDUMP_CALLER) { |
||
447 | $caller = (!empty($backtrace[1]['class']) ? $backtrace[1]['class'] : '') . |
||
448 | (!empty($backtrace[1]['type']) ? $backtrace[1]['type'] : '') . |
||
449 | $backtrace[1]['function'] . |
||
450 | (!empty($backtrace[0]['file']) |
||
451 | ? ( |
||
452 | ' (' . substr($backtrace[0]['file'], SN_ROOT_PHYSICAL_STR_LEN) . |
||
453 | (!empty($backtrace[0]['line']) ? ':' . $backtrace[0]['line'] : '') . |
||
454 | ')' |
||
455 | ) |
||
456 | : '' |
||
457 | ); |
||
458 | $caller = "\r\n" . $caller; |
||
459 | } |
||
460 | |||
461 | if (php_sapi_name() == "cli") { |
||
462 | print("\n" . |
||
463 | dump($value, $varname) . |
||
464 | $caller . |
||
465 | "\n\n" |
||
466 | ); |
||
467 | } else { |
||
468 | print('<pre style="text-align: left; background-color: #111111; color: #0A0; font-family: Courier, monospace !important; padding: 1em 0; font-weight: 800; font-size: 14px;">' . |
||
469 | dump($value, $varname) . |
||
470 | $caller . |
||
471 | '</pre>' |
||
472 | ); |
||
473 | } |
||
474 | } |
||
475 | |||
476 | function debug($value, $varname = null) { |
||
477 | pdump($value, $varname); |
||
478 | } |
||
479 | |||
480 | function pr($prePrint = false) { |
||
481 | if ($prePrint) { |
||
482 | print("<br>"); |
||
483 | } |
||
484 | print(mt_rand() . "<br>"); |
||
485 | } |
||
486 | |||
487 | function pc($prePrint = false) { |
||
488 | global $_PRINT_COUNT_VALUE; |
||
489 | $_PRINT_COUNT_VALUE++; |
||
490 | |||
491 | if ($prePrint) { |
||
492 | print("<br>"); |
||
493 | } |
||
494 | print($_PRINT_COUNT_VALUE . "<br>"); |
||
495 | } |
||
496 | |||
497 | function prep($message) { |
||
498 | print('<pre>' . $message . '</pre>'); |
||
499 | } |
||
500 | |||
501 | function backtrace_no_arg() { |
||
502 | $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); |
||
503 | array_shift($trace); |
||
504 | |||
505 | return $trace; |
||
506 | } |
||
507 | |||
508 | if (!function_exists('pre')) { |
||
509 | define('START', microtime(true)); // SHOULD NEVER BE REMOVED! |
||
510 | |||
511 | /** |
||
512 | * @param mixed $value <p> |
||
513 | * The variable you want to export. |
||
514 | * </p> |
||
515 | * @param mixed ...$values [optional] |
||
516 | * |
||
517 | * @return void |
||
518 | */ |
||
519 | function pre() { |
||
520 | if (func_num_args() <= 0) { |
||
521 | return; |
||
522 | } |
||
523 | |||
524 | foreach (func_get_args() ?: [] as $var) { |
||
525 | print "<pre>"; |
||
526 | print_r( |
||
527 | $var === null ? 'null' : |
||
528 | (($type = gettype($var)) == 'object' || $type == 'array' |
||
529 | ? $var : |
||
530 | ($type === 'string' |
||
531 | ? $type . '(' . strlen($var) . ') `' . $var . '`' : |
||
532 | ($type == 'boolean' |
||
533 | ? ($var ? 'true' : 'false') |
||
534 | : $type . ' ' . print_r($var, true) |
||
535 | ) |
||
536 | ) |
||
537 | ) |
||
538 | ); |
||
539 | print "</pre>"; |
||
540 | } |
||
541 | |||
542 | $trace = debug_backtrace(); |
||
543 | |||
544 | $p = $trace[1]['function'] == 'pred' ? $trace[1] : $trace[0]; |
||
545 | // print("\n{$p['file']}@{$p['line']}<br />\n" . (is_string($die) ? 'Die message: ' . $die . "<br />\n" : '')); |
||
546 | print("\n{$p['file']}@{$p['line']}<br />\n"); |
||
547 | } |
||
548 | |||
549 | function pred() { |
||
550 | call_user_func_array('pre', func_get_args()); |
||
551 | die(); |
||
552 | } |
||
553 | } |
||
554 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.