Last active
August 29, 2015 14:11
-
-
Save WinterSilence/8dd1b5d0aa284380202d to your computer and use it in GitHub Desktop.
Enso\Core\ShutdownHandler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Enso\Core; | |
/** | |
* Inline exception handler, displays the error message, source of the exception | |
* and the stack trace of the error. | |
* | |
* @package Enso\Core | |
* @copyright (c) 2014 WinterSilence | |
* @license MIT License | |
*/ | |
class ExceptionHandler | |
{ | |
// Text format to display | |
const FORMAT = '%s [%s]: %s ~ %s [%d]'; | |
/** | |
* @var \Exception | |
*/ | |
protected $exception; | |
/** | |
* @var string | |
*/ | |
protected $displayCache; | |
/** | |
* Create new instance. | |
* | |
* @param \Exception $exception | |
* @return void | |
*/ | |
public function __construct(\Exception $exception) | |
{ | |
$this->exception = $exception; | |
} | |
/** | |
* Text to display exception. | |
* | |
* @return string | |
*/ | |
public function display() | |
{ | |
if (empty($this->displayCache)) { | |
// Cache text | |
$this->displayCache = sprintf( | |
self::FORMAT, | |
get_class($this->exception), | |
$this->exception->getCode(), | |
strip_tags($this->exception->getMessage()), | |
$this->exception->getFile(), | |
$this->exception->getLine() | |
); | |
} | |
return $this->displayCache; | |
} | |
/** | |
* Text to display exception. | |
* | |
* @return string | |
*/ | |
public function __toString() | |
{ | |
return $this->display(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Enso\Core; | |
/** | |
* Shutdown handler - stack of callbacks. | |
* | |
* [!!] debug_backtrace() or debug_print_backtrace() will not work inside | |
* a shutdown function. If you call exit() within one registered shutdown | |
* function, processing will stop completely and no other registered shutdown | |
* functions will be called. | |
* | |
* @see http://php.net/function.register-shutdown-function | |
* | |
* @package Enso\Core | |
* @copyright (c) 2014 WinterSilence | |
* @license MIT License | |
*/ | |
class ShutdownHandler | |
{ | |
/** | |
* @var array Callbacks | |
*/ | |
protected $handlers = []; | |
/** | |
* @var array Types of errors to display at shutdown | |
*/ | |
protected $displayErrors = [E_PARSE, E_ERROR, E_USER_ERROR]; | |
/** | |
* Create instance and register as shutdown function. | |
* | |
* @param array $errors Shutdown errors | |
* @return void | |
*/ | |
public function __construct(array $errors = null) | |
{ | |
if ($errors) { | |
$this->displayErrors = $errors; | |
} | |
register_shutdown_function(array($this, 'execute')); | |
} | |
/** | |
* Add shutdown handler. | |
* | |
* @param callable $callback Callback (string, array, closure) | |
* @param array $arguments Callback`s arguments | |
* @param boolean $prepend Add prepend or append? | |
* @return ShutdownHandler | |
*/ | |
public function attach(callable $callback, array $arguments = [], $prepend = false) | |
{ | |
$handler = ['callback' => $callback, 'arguments' => $arguments]; | |
if (!in_array($handler, $this->handlers)) { | |
if ($prepend) { | |
array_unshift($this->handlers, $handler); | |
} else { | |
$this->handlers[] = $handler; | |
} | |
} | |
return $this; | |
} | |
/** | |
* Delete shutdown handler. | |
* | |
* @param callable $callback Callback (string, array, closure) | |
* @param array $arguments Callback`s arguments | |
* @return ShutdownHandler | |
*/ | |
public function detach(callable $callback, array $arguments = []) | |
{ | |
$handler = ['callback' => $callback, 'arguments' => $arguments]; | |
// Find handler | |
$key = array_search($handler, $this->handlers); | |
if ($key !== false) { | |
unset($this->handlers[$key]) | |
} | |
return $this; | |
} | |
/** | |
* Return all handlers. | |
* | |
* @return array | |
*/ | |
public function getHandlers() | |
{ | |
return $this->handlers; | |
} | |
/** | |
* Execute handlers. | |
* | |
* @return void | |
*/ | |
public function execute() | |
{ | |
try { | |
foreach ($this->handlers as $handler) { | |
call_user_func_array($handler['callback'], $handler['arguments']); | |
} | |
} catch (\Exception $exception) { | |
echo new ExceptionHandler($exception); | |
} | |
$error = error_get_last(); | |
if ($error && in_array($error['type'], $this->displayErrors)) | |
{ | |
if (ob_get_level()) { | |
// Clean the output buffer | |
ob_clean(); | |
} | |
// Fake an exception for nice debugging | |
$exception = new \ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']); | |
echo new ExceptionHandler($exception); | |
// Shutdown now to avoid a "death loop" | |
exit(1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment