8 * Exception and error handler
10 class ExceptionHandler
13 * @var \http\Env\Response
18 * Set up error/exception/shutdown handler
20 public function __construct(\http\Env\Response
$r) {
22 set_exception_handler($this);
23 set_error_handler($this);
24 register_shutdown_function($this);
27 private static function cleanBuffers() {
28 while (ob_get_level()) {
29 if (!@ob_end_clean
()) {
36 * The exception/error/shutdown handler callback
38 public function __invoke($e = null, $msg = null) {
39 if ($e instanceof \Exception ||
$e instanceof \Throwable
) {
42 echo static::htmlException($e);
43 } catch (\Exception
$ignore) {
44 headers_sent() or HTTP
::setResponseCode(500);
45 die("FATAL ERROR:\n$e\n$ignore");
47 } elseif (isset($e, $msg)) {
48 throw new \
Exception($msg, $e);
49 } elseif (($error = error_get_last())) {
50 switch ($error["type"]) {
57 $message = sprintf("%s in %s at line %d",
58 $error["message"], $error["file"], $error["line"]);
59 echo static::htmlError("Application Error", $message, 500, "");
66 * Format an exception as HTML and send appropriate exception info as HTTP headers
68 * @param array $title_tag
69 * @param array $message_tag
70 * @param array $trace_tag
73 public static function htmlException(/*\Throwable*/ $e, array $title_tag = ["h1"], array $message_tag = ["p"], array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) {
74 if ($e instanceof Exception
) {
75 $code = $e->getCode() ?
: 500;
80 for ($html = ""; $e; $e = $e->getPrevious()) {
81 $html .= static::htmlError(HTTP
::getResponseStatusForCode($code),
82 $e->getMessage(), $code, $e->getTraceAsString(),
83 $title_tag, $message_tag, $trace_tag);
89 * Format an error as HTML
90 * @param string $title
91 * @param string $message
93 * @param string $trace
94 * @param array $title_tag
95 * @param array $message_tag
96 * @param array $trace_tag
99 public static function htmlError($title, $message, $code, $trace = null, array $title_tag = ["h1"], array $message_tag = ["p"], array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) {
100 HTTP
::setResponseCode($code);
102 $html = sprintf("<%s>%s</%s>\n<%s>%s</%s>\n",
103 implode(" ", $title_tag), $title, $title_tag[0],
104 implode(" ", $message_tag), $message, $message_tag[0]);
106 if (!isset($trace)) {
108 debug_print_backtrace();
109 $trace = ob_get_clean();
111 if (!empty($trace)) {
112 $html .= sprintf("<%s>%s</%s>\n",
113 implode(" ", $trace_tag), $trace, $trace_tag[0]);