You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.9 KiB
106 lines
3.9 KiB
<?php |
|
|
|
namespace Twister; |
|
|
|
/** |
|
* Custom Exception Handler |
|
*/ |
|
class ExceptionHandler |
|
{ |
|
function __construct() |
|
{ |
|
set_exception_handler(function ($e) |
|
{ |
|
$dump = null; |
|
|
|
switch (get_class($e)) |
|
{ |
|
case 'mysqli_sql_exception': |
|
|
|
$backtrace = $e->getTrace(); |
|
$sql = null; |
|
foreach ($backtrace as $trace) |
|
{ |
|
switch ($trace['function']) |
|
{ // Find MySQLi query if there was one! |
|
case 'query': |
|
case 'real_query': |
|
if ( ! isset($trace['class']) || $trace['class'] !== 'mysqli') break; |
|
$sql = $trace['args'][0]; // 1st arg in object style (mysqli::query()) |
|
break; |
|
case 'mysqli_query': |
|
case 'mysqli_real_query': |
|
$sql = $trace['args'][1]; // 2nd arg in procedural style (mysqli_query()) |
|
} |
|
} |
|
if (isset($sql)) |
|
{ |
|
$backtrace = array_reverse($backtrace); // reverse the array, it feels a bit more natural to see the stack trace in call order! |
|
$dump .= '<hr />' . PHP_EOL . '<b>SQL Query Dump:</b><br />' . PHP_EOL . '<font color="gray">' . htmlentities($sql) . '</font><br />' . PHP_EOL; |
|
} |
|
break; |
|
} |
|
|
|
$backtrace = $e->getTrace(); |
|
$max_file_length = 0; |
|
$max_line_length = 0; |
|
$internal_function = '[internal function]'; |
|
foreach($backtrace as $trace) |
|
{ |
|
if (isset($trace['file'])) |
|
{ |
|
$max_file_length = max($max_file_length, strlen($trace['file'])); |
|
$max_line_length = max($max_line_length, strlen($trace['line'])); |
|
} |
|
else |
|
$max_file_length = strlen($internal_function); |
|
} |
|
$backtrace = array_reverse($backtrace); // reverse the array, it feels a bit more natural to see the stack trace in call order! |
|
$dump .= PHP_EOL . PHP_EOL . 'Stack trace:<pre>' . PHP_EOL; |
|
foreach ($backtrace as $index => $trace) |
|
{ |
|
$args = null; |
|
$comma = null; |
|
foreach ($trace['args'] as $arg) |
|
{ |
|
if (is_string($arg)) $args .= $comma . (strpos($arg,'\'')===false?'\'':'"') . (strlen($arg) > 40 ? substr($arg, 0, 40) . ' ...' : $arg) . (strpos($arg,'\'')===false?'\'':'"'); |
|
else if (is_numeric($arg)) $args .= $comma . $arg; |
|
else if (is_bool($arg)) $args .= $comma . $arg; // ($arg ? 'true' : 'false') |
|
else if (is_null($arg)) $args .= $comma . 'null'; |
|
else if (is_array($arg)) $args .= $comma . 'array'; |
|
else if (is_object($arg)) $args .= $comma . '(object) ' . get_class($arg); |
|
else if (is_callable($arg)) $args .= $comma . 'callable'; |
|
else if (is_resource($arg)) $args .= $comma . 'resource'; |
|
$comma = ', '; |
|
} |
|
$dump .= str_pad('#' . ($index + 1), 4) . |
|
(isset($trace['file']) ? (str_pad($trace['file'], $max_file_length) . ' (line: ' . $trace['line'] . ')' . str_repeat(' ', $max_line_length - strlen($trace['line']))) : str_pad($internal_function, $max_file_length + $max_line_length + 9)) . ' <b>' . |
|
(isset($trace['class']) ? $trace['class'] . $trace['type'] : null) . |
|
$trace['function'] . '</b>(' . $args . ')' . PHP_EOL; |
|
} |
|
$dump .= '</pre>'; |
|
|
|
// Detect Content-Type |
|
$headers = headers_list(); |
|
$html = true; |
|
$found_content_type = false; |
|
foreach ($headers as $header) |
|
{ |
|
if (strpos($header, 'Content-Type:') !== false || strpos($header, 'Content-type:') !== false) |
|
{ |
|
$found_content_type = true; |
|
$html = strpos($header, 'text/html') !== false; |
|
} |
|
} |
|
if ( ! $found_content_type && headers_sent() === false) |
|
header('Content-Type: text/html; charset=utf-8'); |
|
|
|
$dump = '<br />' . PHP_EOL . |
|
'<b>Fatal error</b>: Uncaught <span style="color:red">' . get_class($e) . '</span>: ' . htmlentities($e->getMessage()) . ' thrown in <b>' . $e->getFile() . '</b> on line <b>' . $e->getLine() . '</b><br /><br />' . PHP_EOL . |
|
$dump . PHP_EOL; |
|
|
|
echo $html ? $dump : html_entity_decode(strip_tags($dump)); |
|
exit; |
|
}); |
|
} |
|
}
|
|
|