From d1f0e4360fcd978e865d72661138262411986360 Mon Sep 17 00:00:00 2001 From: Visman Date: Tue, 21 Aug 2018 21:12:17 +0700 Subject: [PATCH] Added error handler --- app/Core/ErrorHandler.php | 191 ++++++++++++++++++++++++++++++++++++++ app/bootstrap.php | 12 +-- app/config/install.php | 4 + app/config/main.dist.php | 5 + 4 files changed, 205 insertions(+), 7 deletions(-) create mode 100644 app/Core/ErrorHandler.php diff --git a/app/Core/ErrorHandler.php b/app/Core/ErrorHandler.php new file mode 100644 index 00000000..c5e4a631 --- /dev/null +++ b/app/Core/ErrorHandler.php @@ -0,0 +1,191 @@ + 'OTHER_ERROR', + \E_ERROR => 'E_ERROR', + \E_WARNING => 'E_WARNING', + \E_PARSE => 'E_PARSE', + \E_NOTICE => 'E_NOTICE', + \E_CORE_ERROR => 'E_CORE_ERROR', + \E_CORE_WARNING => 'E_CORE_WARNING', + \E_COMPILE_ERROR => 'E_COMPILE_ERROR', + \E_COMPILE_WARNING => 'E_COMPILE_WARNING', + \E_USER_ERROR => 'E_USER_ERROR', + \E_USER_WARNING => 'E_USER_WARNING', + \E_USER_NOTICE => 'E_USER_NOTICE', + \E_STRICT => 'E_STRICT', + \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', + \E_DEPRECATED => 'E_DEPRECATED', + \E_USER_DEPRECATED => 'E_USER_DEPRECATED', + ]; + + /** + * Конструктор + */ + public function __construct() + { + \set_error_handler([$this, 'errorHandler']); + \set_exception_handler([$this, 'exceptionHandler']); + \register_shutdown_function([$this, 'shutdownHandler']); + + \ob_start(); + $this->obLevel = \ob_get_level(); + } + + /** + * Деструктор + */ + public function __destruct() + { + \restore_error_handler(); + \restore_exception_handler(); + + //???? + } + + /** + * Обрабатыет перехватываемые ошибки + * + * @param int $type + * @param string $message + * @param string $file + * @param string $line + * + * @return bool + */ + public function errorHandler($type, $message, $file, $line) + { + $error = [ + 'type' => $type, + 'message' => $message, + 'file' => $file, + 'line' => $line, + ]; + $this->log($error); + + if ($type & \error_reporting()) { + $this->error = $error; + exit(1); + } + + $this->logged = false; + return true; + } + + /** + * Обрабатывает не перехваченные исключения + * + * @param Exception|Throwable $e + */ + public function exceptionHandler($e) + { + $this->error = [ + 'type' => 0, //???? + 'message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + ]; + } + + /** + * Окончательно обрабатывает ошибки (в том числе фатальные) и исключения + */ + public function shutdownHandler() + { + if (isset($this->error['type'])) { + $show = true; + } else { + $show = false; + $this->error = \error_get_last(); + + if (isset($this->error['type'])) { + switch ($this->error['type']) { + case \E_ERROR: + case \E_PARSE: + case \E_CORE_ERROR: + case \E_CORE_WARNING: + case \E_COMPILE_ERROR: + case \E_COMPILE_WARNING: + $show = true; + break; + } + } + } + + if (isset($this->error['type']) && ! $this->logged) { + $this->log($this->error); + } + + while (\ob_get_level() > $this->obLevel) { + \ob_end_clean(); + } + if (\ob_get_level() === $this->obLevel) { + if ($show) { + \ob_end_clean(); + + $this->show($this->error); + } else { + \ob_end_flush(); + } + } + } + + /** + * Отправляет сообщение в лог + * + * @param array $error + */ + protected function log(array $error) + { + $this->logged = true; + $type = isset($this->type[$error['type']]) ? $this->type[$error['type']] : $this->type[0]; + $message = "PHP {$type}: \"{$error['message']}\" in {$error['file']}:[{$error['line']}]"; + $message = \preg_replace('%[\x00-\x1F]%', ' ', $message); + + \error_log($message); + } + + /** + * Выводит сообщение об ошибке + * + * @param array $error + */ + protected function show(array $error) + { + \header('HTTP/1.1 500 Internal Server Error'); + + if (1 == \ini_get('display_errors')) { + $type = isset($this->type[$error['type']]) ? $this->type[$error['type']] : $this->type[0]; + + echo "PHP {$type}: \"{$error['message']}\" in {$error['file']}:[{$error['line']}]"; + } else { + echo 'Oops'; + } + } +} diff --git a/app/bootstrap.php b/app/bootstrap.php index 44ac2eaf..de2227a0 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -3,16 +3,12 @@ namespace ForkBB; use ForkBB\Core\Container; +use ForkBB\Core\ErrorHandler; use ForkBB\Models\Page; use RuntimeException; -// боевой -#\error_reporting(E_ALL); -#\ini_set('display_errors', 0); -#\ini_set('log_errors', 1); -// разраб -\error_reporting(E_ALL); -\ini_set('display_errors', 1); +\error_reporting(\E_ALL ^ \E_NOTICE); +\ini_set('display_errors', 0); \ini_set('log_errors', 1); \mb_language('uni'); @@ -21,6 +17,8 @@ use RuntimeException; require __DIR__ . '/../vendor/autoload.php'; +$errorHandler = new ErrorHandler(); + if (\is_file(__DIR__ . '/config/main.php')) { $c = new Container(include __DIR__ . '/config/main.php'); } elseif (\is_file(__DIR__ . '/config/install.php')) { diff --git a/app/config/install.php b/app/config/install.php index a9634e89..e97bb791 100644 --- a/app/config/install.php +++ b/app/config/install.php @@ -1,5 +1,9 @@ 'http://forkbb.local', 'DEBUG' => 0, diff --git a/app/config/main.dist.php b/app/config/main.dist.php index d4d169f8..0ea7a78c 100644 --- a/app/config/main.dist.php +++ b/app/config/main.dist.php @@ -1,5 +1,10 @@ '_BASE_URL_', 'EOL' => PHP_EOL, // Define line breaks in mail headers; possible values can be PHP_EOL, "\r\n", "\n" or "\r"