diff --git a/.gitignore b/.gitignore index 187adb2..e4217b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/nbproject/ \ No newline at end of file +/nbproject/ +/vendor/ \ No newline at end of file diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php index a43a8ac..4cadfe1 100644 --- a/src/ErrorHandler.php +++ b/src/ErrorHandler.php @@ -7,80 +7,78 @@ * * @author Rafael M. Salvioni */ -class ErrorHandler +abstract class ErrorHandler { /** - * Count opened instances + * Stack of started handlers * - * @var int + * @var array */ - private static $opened = 0; + private static $stack = []; + /** - * Stores the instances' config + * Checks if the ErrorHandler is started. * - * @var array + * @return bool */ - private static $config = []; - + public static function isStarted() + { + return !empty(static::$stack); + } + /** - * Start the error's handler engine. + * Starting the ErrorHandler. * - * @param bool $useSuppress Consider use of error operator? - * @param bool $useErrorLevel Consider current error reporting level? - * @param bool $errorTypes Custom error types to consider + * @param int $level */ - public static function start( - $useSuppress = false, $useErrorLevel = false, $errorTypes = \E_ALL - ) { - if (self::$opened++ == 0) { - \set_error_handler([__CLASS__, 'handle'], $errorTypes); - } - self::$config[] = [(bool)$useSuppress, (bool)$useErrorLevel]; + public static function start($level = \E_ALL) + { + static::$stack[] = null; + \set_error_handler([__CLASS__, 'handle'], $level); } /** - * Stop handler engine. + * Stop the current ErrorHandler. * + * @param bool $throw Throws a eventual exception? + * @return \ErrorException */ - public static function stop() + public static function stop($throw = true) { - if (self::$opened > 0) { - \array_pop(self::$config); - - if (--self::$opened == 0) { - \restore_error_handler(); + if (static::isStarted()) { + $exception = \array_pop(static::$stack); + \restore_error_handler(); + + if (($exception instanceof \ErrorException) && $throw) { + throw $exception; } + return $exception; } + return null; } /** - * Error's handler. + * Stop all handlers. * - * If a exceptions was fired, the engine will be stopped automatically. + */ + public static function clean() + { + while (!empty(static::$stack)) { + static::stop(false); + } + } + + /** + * Error handler callback. * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline - * @throws \ErrorException */ public static function handle($errno, $errstr, $errfile, $errline) { - if (self::$opened > 0) { - $config =& self::$config[self::$opened - 1]; - $errorReporting = \error_reporting(); - - if ($errorReporting == 0) { - $throws = !$config[0]; - } - else { - $throws = !$config[1] || ($errorReporting & $errno) > 0; - } - - if ($throws) { - self::stop(); - throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); - } - } + $stack =& static::$stack[\count(static::$stack) - 1]; + $stack = new \ErrorException($errstr, 0, $errno, $errfile, $errline); } } diff --git a/test/ErrorHandlerTest.php b/test/ErrorHandlerTest.php index 739848b..7f41c7f 100644 --- a/test/ErrorHandlerTest.php +++ b/test/ErrorHandlerTest.php @@ -13,98 +13,61 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase /** * @test */ - public function startTest() + public function startStopTest() { try { ErrorHandler::start(); \trigger_error("UserError", \E_USER_ERROR); + ErrorHandler::stop(); $this->assertTrue(false); } - catch (\ErrorException $ex) { - $this->assertEquals($ex->getMessage(), "UserError"); - } - ErrorHandler::stop(); - - try { - ErrorHandler::start(true); - @\trigger_error("UserError", \E_USER_ERROR); - $this->assertTrue(true); - } - catch (\ErrorException $ex) { - $this->assertTrue(false); + catch (\Exception $ex) { + $this->assertEquals("UserError", $ex->getMessage()); } - ErrorHandler::stop(); try { - ErrorHandler::start(false, true); - \error_reporting(E_USER_WARNING); - \trigger_error("UserError", \E_USER_ERROR); + ErrorHandler::start(\E_USER_WARNING); + \trigger_error("UserError", \E_USER_NOTICE); + ErrorHandler::stop(); $this->assertTrue(true); } - catch (\ErrorException $ex) { + catch (\Exception $ex) { $this->assertTrue(false); } - ErrorHandler::stop(); - - try { - ErrorHandler::start(false, false, \E_USER_WARNING); - \trigger_error("UserError", \E_USER_WARNING); - $this->assertTrue(false); - } - catch (\ErrorException $ex) { - $this->assertTrue(true); - } - ErrorHandler::stop(); } /** * @test - * @depends startTest + * @depends startStopTest */ - public function stopTest() + public function startedTest() { - $called = false; - \set_error_handler(function ($errno, $errmsg) use (&$called) { - $called = true; - }); - ErrorHandler::start(); + $this->assertTrue(ErrorHandler::isStarted()); ErrorHandler::stop(); - - @\trigger_error('Notice', \E_USER_NOTICE); - $this->assertTrue($called); - } - - /** - * @test - * @depends stopTest - */ - public function multipleStartTest() - { - $called = false; - \set_error_handler(function ($errno, $errmsg) use (&$called) { - $called = true; - }); - - $n = \mt_rand(5, 15); + $this->assertFalse(ErrorHandler::isStarted()); + } + + /** + * @test + * @depends startedTest + */ + public function cleanTest() + { + $n = \mt_rand(1, 20); for ($i = 0; $i < $n; $i++) { ErrorHandler::start(); } + ErrorHandler::clean(); + $this->assertFalse(ErrorHandler::isStarted()); - ErrorHandler::stop(); try { - @\trigger_error('Notice', \E_USER_NOTICE); - $this->assertFalse(true); - } - catch (\ErrorException $ex) { - $this->assertFalse($called); - } - - $n -= 2; - for ($i = 0; $i < $n; $i++) { + \trigger_error("UserError", \E_USER_NOTICE); ErrorHandler::stop(); + $this->assertTrue(false); + } + catch (\PHPUnit_Framework_Error_Notice $ex) { + $this->assertTrue(true); } - @\trigger_error('Notice', \E_USER_NOTICE); - $this->assertTrue($called); - } + } }