From 80ff1898cf99ec3e1a72e51a81e49ec5ccd6721d Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Tue, 18 Oct 2022 17:53:04 +0300 Subject: [PATCH] Fix to Bug When Code Execution Stopped By Another Handler The bug causes other handlers to not execute. --- src/webfiori/error/AbstractHandler.php | 25 +++++++++++++++++++++++++ src/webfiori/error/Handler.php | 23 +++++++++++++---------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/webfiori/error/AbstractHandler.php b/src/webfiori/error/AbstractHandler.php index 178c318..5a9f995 100644 --- a/src/webfiori/error/AbstractHandler.php +++ b/src/webfiori/error/AbstractHandler.php @@ -12,6 +12,7 @@ abstract class AbstractHandler { private $traceArr; private $name; private $isCalled; + private $isExecuting; /** * Creates new instance of the class. */ @@ -19,6 +20,7 @@ public function __construct() { $this->traceArr = []; $this->name = 'New Handler'; $this->isCalled = false; + $this->isExecuting = false; } /** * Sets the handler as executed. @@ -134,6 +136,29 @@ public function setException(Throwable $ex) { $this->exception = $ex; $this->setTrace(); } + /** + * Sets the value that tells if the handler is begin executed or not. + * + * This method is used internally by the library to set status of the + * handler. + * + * @param bool $isExec True to set the handler as begin executed. False + * to not. + */ + public function setIsExecuting(bool $isExec) { + $this->isExecuting = $isExec; + } + /** + * Check if the handler is in execution stage or not. + * + * This method is used to indicate if execution + * scope is inside the method AbstractHandler::handle() or not. + * + * @return bool True if the handler is executing. False if not. + */ + public function isExecuting() : bool { + return $this->isExecuting; + } private function setTrace() { $ex = $this->getException(); diff --git a/src/webfiori/error/Handler.php b/src/webfiori/error/Handler.php index 9f00552..b6feaf9 100644 --- a/src/webfiori/error/Handler.php +++ b/src/webfiori/error/Handler.php @@ -81,7 +81,12 @@ class Handler { * * @var AbstractHandler */ - private $handler; + private $isErrOccured; + /** + * + * @var Throwable|null + */ + private $lastException; /** * * @var Handler @@ -91,6 +96,7 @@ private function __construct() { ini_set('display_startup_errors', 1); ini_set('display_errors', 1); error_reporting(-1); + $this->isErrOccured = false; set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) { $errClass = TraceEntry::extractClassName($errfile); @@ -100,30 +106,27 @@ private function __construct() { }); set_exception_handler(function (Throwable $ex) { + $this->lastException = $ex; foreach (Handler::get()->handlersPool as $h) { if ($h->isActive()) { $h->setException($ex); + $h->setIsExecuting(true); $h->handle(); + $h->setIsExecuting(false); $h->setIsExecuted(true); } } }); register_shutdown_function(function () { - $lastErr = error_get_last(); - - if ($lastErr !== null) { + if ($this->lastException !== null) { if (ob_get_length()) { ob_clean(); } - $errClass = TraceEntry::extractClassName($lastErr['file']); - $errType = Handler::ERR_TYPES[$lastErr['type']]; - $message = $errType['description'].': '.$lastErr['message'].' At '.$errClass.' Line '.$lastErr['line']; - $ex = new ErrorHandlerException($message, $lastErr['type'], $lastErr['file']); foreach (Handler::get()->handlersPool as $h) { - if ($h->isActive() && $h->isShutdownHandler() && !$h->isExecuted()) { - $h->setException($ex); + if ($h->isActive() && $h->isShutdownHandler() && !$h->isExecuted() && !$h->isExecuting()) { + $h->setException($this->lastException); $h->handle(); $h->setIsExecuted(true); }