diff --git a/src/RaspAP/Exceptions/HtmlErrorRenderer.php b/src/RaspAP/Exceptions/HtmlErrorRenderer.php new file mode 100755 index 00000000..5abbe2a9 --- /dev/null +++ b/src/RaspAP/Exceptions/HtmlErrorRenderer.php @@ -0,0 +1,107 @@ + + * @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE + * @see + */ + +declare(strict_types=1); + +namespace RaspAP\Exceptions; + +class HtmlErrorRenderer +{ + + public function __construct() + { + $this->charset = 'UTF-8'; + $this->projectDir = $_SERVER['DOCUMENT_ROOT']; + $this->template = '/templates/exception.php'; + $this->debug = true; + } + + public function render($exception) + { + $message = $exception->getMessage(); + $code = $exception->getCode(); + $file = $exception->getFile(); + $line = $exception->getLine(); + $trace = $this->getExceptionTraceAsString($exception); + + header('Content-Type: text/html; charset='.$this->charset); + if ($this->debug) { + header('X-Debug-Exception: '. rawurlencode($message)); + header('X-Debug-Exception-File: '. rawurlencode($file).':'.$line); + } + + $__template_data = compact( + "message", + "code", + "file", + "line", + "trace" + ); + if (is_array($__template_data)) { + extract($__template_data); + } + $file = $this->projectDir . $this->template; + ob_start(); + include $file; + echo ob_get_clean(); + } + + /** + * Improved exception trace + * @param object $e : exception + * @param array $seen : passed to recursive calls to accumulate trace lines already seen + * @return array of strings, one entry per trace line + * @see https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c + */ + public function getExceptionTraceAsString($e, $seen = null) { + + $starter = $seen ? 'Thrown by: ' : ''; + $result = array(); + if (!$seen) $seen = array(); + $trace = $e->getTrace(); + $prev = $e->getPrevious(); + $result[] = sprintf('%s%s: %s', $starter, get_class($e), $e->getMessage()); + $file = $e->getFile(); + $line = $e->getLine(); + + while (true) { + $current = "$file:$line"; + if (is_array($seen) && in_array($current, $seen)) { + $result[] = sprintf(' ... %d more', count($trace)+1); + break; + } + $result[] = sprintf(' at %s%s%s(%s%s%s)', + count($trace) && array_key_exists('class', $trace[0]) ? str_replace('\\', '.', $trace[0]['class']) : '', + count($trace) && array_key_exists('class', $trace[0]) && array_key_exists('function', $trace[0]) ? '.' : '', + count($trace) && array_key_exists('function', $trace[0]) ? str_replace('\\', '.', $trace[0]['function']) : '(main)', + $line === null ? $file : basename($file), + $line === null ? '' : ':', + $line === null ? '' : $line); + + if (is_array($seen)) { + $seen[] = "$file:$line"; + } + if (!count($trace)) { + break; + } + $file = array_key_exists('file', $trace[0]) ? $trace[0]['file'] : 'Unknown Source'; + $line = array_key_exists('file', $trace[0]) && array_key_exists('line', $trace[0]) && $trace[0]['line'] ? $trace[0]['line'] : null; + array_shift($trace); + } + $result = join(PHP_EOL, $result); + if ($prev) { + $result .= PHP_EOL . getExceptionTraceAsString($prev, $seen); + } + return $result; + } + +} + diff --git a/templates/exception.php b/templates/exception.php new file mode 100755 index 00000000..9602f296 --- /dev/null +++ b/templates/exception.php @@ -0,0 +1,17 @@ + + +
+ + + + + +