Skip to content

Instantly share code, notes, and snippets.

@ircmaxell
Created July 27, 2011 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ircmaxell/ef12f5779c32cd02b9e8 to your computer and use it in GitHub Desktop.
Save ircmaxell/ef12f5779c32cd02b9e8 to your computer and use it in GitHub Desktop.
ErrorExceptions
<?php
use ErrorExceptions\ErrorExceptions;
class ConfigurationException extends LogicException {}
class DisabledFeatureException extends ConfigurationException {}
class OpenBaseDirException extends DisabledFeatureException {}
class SafeModeException extends DisabledFeatureException {}
class URLFileAccessDisabledException extends ConfigurationException {}
ErrorExceptions::addMultipleCoreExceptions(array(
E_WARNING => array(
'/function is disabled/' => 'DisabledFeatureException',
'/has been disabled for security reasons/' => '',
'/open(_|\s)basedir/i' => 'OpenBaseDirException',
'/safe(_|\s)mode/i' => 'SafeModeException',
'/Unable to access .*/' => 'SafeModeException',
),
));
<?php
use ErrorExceptions\ErrorExceptions;
class ConflictException extends LogicException {}
class DeprecatedException extends LogicException {}
class InvalidCallbackException extends LogicException {}
class InvalidClassException extends LogicException {}
class InvalidImplementationException extends LogicException {}
class InvalidInputException extends RuntimeException {}
class InvalidReturnValueException extends LogicException {}
class InvalidScopeException extends LogicException {}
class InvalidValueException extends LogicException {}
class OutOfMemoryException extends RuntimeException {}
class NotSupportedException extends RuntimeException {}
class OutputException extends RuntimeException {}
class ParseException extends LogicException {}
class PHPCoreException extends LogicException {}
class ReferenceException extends LogicException {}
class StrictException extends LogicException {}
class TypeConversionException extends LogicException {}
class UndefinedConstantException extends LogicException {}
class UndefinedVariableException extends LogicException {}
class UnknownErrorException extends RuntimeException {}
class WTFException extends LogicException {}
ErrorExceptions::addMultipleCoreExceptions(array(
E_DEPRECATED => array(
'/./' => 'DeprecatedException',
),
E_NOTICE => array(
'/Constant .* already defined/' => 'LogicException',
'/Exceptions must be derived from the Exception/' => 'InvalidClassException',
'/failed to (flush|delete|delete and flush) buffer/' => 'OutputException',
'/(modify|assign|get) property of non-object/' => 'LogicException',
'/(Illegal|Corrupt) member variable name/' => 'ParseException',
'/Indirect modification of overloaded property/' => 'LogicException',
'/(Object|Array) .* to string conversion/' => 'TypeConversionException',
'/Object of class .* could not be converted to/' => 'TypeConversionException',
'/undefined constant/i' => 'UndefinedConstantException',
'/undefined (property|variable)/i' => 'UndefinedVariableException',
'/Undefined offset/' => 'OutOfBoundsException',
'/Uninitialized string offset/' => 'OutOfBoundsException',
),
E_RECOVERABLE_ERROR => array(
'/__toString\(\) must return a string/' => 'InvalidReturnValueException',
'/Argument \d+ passed to .* must/' => 'InvalidArgumentException',
'/Cannot get arguments for calling closure/' => 'LogicException',
'/Closure object cannot have properties/' => 'LogicException',
'/Instantiation of .* is not allowed/' => 'LogicException',
'/Object of class .* could not be converted to/' => 'TypeConversionException',
),
E_STRICT => array(
'/Accessing static property .* as non static/' => 'StrictException',
'/Creating default object from empty value/' => 'UndefinedVariableException',
'/Non-static method .* be called statically/' => 'StrictException',
'/Redefining already defined constructor/' => 'ParseException',
'/Resource .* used as offset/' => 'TypeConversionException',
'/Static function .* should not be abstract/' => 'ParseException',
),
E_WARNING => array(
'/__toString\(\) must return a string/' => 'InvalidReturnValueException',
'/a COM object/i' => 'com_exception',
'/Argument \d+ not passed to function/' => 'OutOfBoundsException',
'/bad type specified while parsing parameters/' => 'PHPCoreException',
'/called from outside a class/' => 'InvalidScopeException',
'/Can only handle single dimension variant arrays/' => 'com_exception',
'/Cannot add element to the array/' => 'RuntimeException',
'/Cannot add (user|internal) functions to return value/' => 'PHPCoreException',
'/Cannot convert to (real|ordinal) value/' => 'TypeConversionException',
'/Cannot (read|write) property of object - .* handler defined/' => 'PHPCoreException',
'/Cannot redeclare class/' => 'InvalidClassException',
'/Cannot unset offset in a non-array variable/' => 'LogicException',
'/Cannot use a scalar value as an array/' => 'TypeConversionException',
'/class .* is undefined/' => 'InvalidClassException',
'/Class .* not found/' => 'InvalidClassException',
'/Class constants cannot be defined/' => 'LogicException',
'/Clone method does not require arguments/' => 'ParseException',
'/Constants may only evaluate to scalar values/' => 'InvalidValueException',
'/converting from PHP array to VARIANT/' => 'TypeConversionException',
'/Could not convert string to unicode/i' => 'InvalidInputException',
'/Could not execute/' => 'LogicException',
'/Could not find a factory/' => 'PHPCoreException',
'/could not obtain parameters for parsing/' => 'PHPCoreException',
'/expected to be a reference/' => 'ReferenceException',
'/expects the argument .* to be a valid callback/' => 'InvalidCallbackException',
'/expects parameter \d+ to be a valid callback/' => 'InvalidCallbackException',
'/failed allocating/i' => 'OutOfMemoryException',
'/failed to allocate/i' => 'OutOfMemoryException',
'/first parameter has to be/i' => 'InvalidArgumentException',
'/First parameter must either be/' => 'InvalidArgumentException',
'/function is not supported/' => 'BadFunctionCallException',
'/handler .* did not return a/' => 'LogicException',
'/Illegal offset type/' => 'LogicException',
'/Illegal string offset/' => 'OutOfBoundsException',
'/Illegal type returned from/' => 'InvalidReturnValueException',
'/Indirect modification of overloaded element/' => 'LogicException',
'/Input variable nesting level exceeded/' => 'InvalidInputException',
'/invalid .* ID/i' => 'InvalidArgumentException',
'/Invalid callback/' => 'InvalidCallbackException',
'/invalid date/' => 'InvalidArgumentException',
'/Invalid error type specified/' => 'DomainException',
'/Illegal offset type/' => 'DomainException',
'/invalid parameter given for/i' => 'DomainException',
'/Invalid scanner mode/' => 'DomainException',
'/is no longer supported/' => 'DeprecatedException',
'/is not a valid mode for/' => 'DomainException',
'/is not a valid .* resource/' => 'DomainException',
'/is not implemented/' => 'InvalidImplementationException',
'/is only valid for years between/i' => 'OutOfRangeException',
'/is too long for/' => 'DomainException',
'/may not be negative/i' => 'OutOfRangeException',
'/(modify|assign|get) property of non-object/' => 'LogicException',
'/must be a name of .* class/' => 'InvalidClassException',
'/must be greather than/' => 'RangeException',
'/must not return itself/' => 'InvalidReturnValueException',
'/must return a/' => 'InvalidReturnValueException',
'/no .* resource supplied/' => 'InvalidArgumentException',
'/no function context/' => 'LogicException',
'/not a dispatchable interface/' => 'BadMethodCallException',
'/not supported on this platform/' => 'NotSupportedException',
'/Nothing returned from/' => 'InvalidReturnValueException',
'/object doesn\'t support property references/' => 'ReferenceException',
'/only one varargs specifier/' => 'PHPCoreException',
'/output handler .* conflicts with/' => 'ConflictException',
'/Parameter wasn\'t passed by reference/' => 'ReferenceException',
'/POST Content-Length of/' => 'InvalidInputException',
'/POST length does not match Content-Length/' => 'InvalidInputException',
'/request_startup.* failed/' => 'PHPCoreException',
'/should be >/' => 'RangeException',
'/The magic method .* must have public/' => 'ParseException',
'/The use statement with non-compound name/' => 'ParseException',
'/this code not yet written/i' => 'WTFException',
'/timestamp value must be a positive value/i' => 'InvalidArgumentException',
'/type library constant .* already defined/i' => 'LogicException',
'/Unable to find typeinfo using/i' => 'RuntimeException',
'/Unknown .* list entry type in/' => 'PHPCoreException',
'/Unspecified error/' => 'UnknownErrorException',
'/Variable passed to .* is not an/' => 'DomainException',
'/variant is not an/' => 'InvalidArgumentException',
'/variant: failed to copy from/' => 'TypeConversionException',
'/Wrong parameter count for/' => 'InvalidArgumentException',
'/year out of range/i' => 'OutOfRangeException',
'/zval: conversion from/' => 'TypeConversionException',
),
));
<?php
namespace ErrorExceptions;
use ErrorException;
require_once 'ConfigurationExceptions.php';
require_once 'CoreExceptions.php';
require_once 'IOExceptions.php';
require_once 'MathExceptions.php';
class ErrorExceptions {
protected $callbacks = array();
protected $errors = E_ALL;
protected static $coreExceptions = array();
protected $exceptions = array();
protected $failureCallbacks = array();
protected $lastError = array();
protected $registered = false;
public static function addMultipleCoreExceptions(array $exceptions) {
static::$coreExceptions = array_merge_recursive_correct(
$exceptions, static::$coreExceptions
);
}
public function __construct($errorLevel = E_ALL) {
$this->errors = $errorLevel;
$this->exceptions = static::$coreExceptions;
}
public function addCallback($callback) {
if (is_callable($callback)) {
$this->callbacks[] = $callback;
}
}
public function addFailureCallback($callback) {
if (is_callable($callback)) {
$this->failureCallbacks[] = $callback;
}
}
public function addException($errNo, $regex, $exception) {
if (!isset($this->exceptions[$errNo])) {
$this->exceptions[$errNo] = array();
}
$this->exceptions[$errNo][$regex] = $exception;
}
public function addMultipleExceptions(array $exceptions) {
$this->exceptions = array_merge_recursive_correct(
$exceptions, $this->exceptions
);
}
public function handleError($errNo, $errStr, $errFile, $errLine) {
if (!$this->registered) {
return true;
}
$this->lastError = array(
'type' => $errNo,
'message' => $errStr,
'file' => $errFile,
'line' => $errLine
);
$exception = $this->lookupError($errNo, $errStr, $errFile, $errLine);
if ($exception && class_exists($exception)) {
$previous = new ErrorException(
$errStr,
0,
$errNo,
$errFile,
$errLine
);
throw new $exception($errStr, $errNo, $previous);
}
return $exception;
}
public function handleShutdown() {
if (!$this->registered) {
return true;
}
$error = error_get_last();
if (!is_null($error) && $error != $this->lastError) {
$this->callFailedCallbacks(
$error['type'], $error['message'], $error['file'], $error['line']
);
}
}
public function register() {
set_error_handler(
array($this, 'handleError'), $this->errors
);
register_shutdown_function(array($this, 'handleShutdown'));
$this->registered = true;
}
public function unregister() {
restore_error_handler();
$this->registered = false;
}
protected function callFailedCallbacks($errNo, $errStr, $errFile, $errLine) {
foreach ($this->failureCallbacks as $callback) {
if (call_user_func($callback, $errNo, $errStr, $errFile, $errLine)) {
return true;
}
}
return false;
}
protected function lookupError($errNo, $errStr, $errFile, $errLine) {
foreach ($this->callbacks as $callback) {
$exception = call_user_func($callback, $errNo, $errStr);
if ($exception && class_exists($exception)) {
return $exception;
}
}
if (!isset($this->exceptions[$errNo])) {
return false;
}
foreach ($this->exceptions[$errNo] as $regex => $exception) {
if (preg_match($regex, $errStr)) {
return $exception;
}
}
return $this->callFailedCallbacks($errNo, $errStr, $errFile, $errLine);
}
}
function array_merge_recursive_correct(array $array1, array $array2) {
foreach ($array2 as $key => $value) {
if (isset($array1[$key]) && is_array($array1[$key]) && is_array($value)) {
$array1[$key] = array_merge_recursive_correct($array1[$key],
$array2[$key]);
} else {
$array1[$key] = $value;
}
}
return $array1;
}
<?php
use ErrorExceptions\ErrorExceptions;
class CurlException extends LogicException {}
class DNSException extends IOException {}
class FileNotFoundException extends IOException {}
class IOException extends RuntimeException {}
class InvalidFileNameException extends InvalidPathException {}
class InvalidLockException extends IOException {}
class InvalidNetworkAddressException extends InvalidPathException {}
class InvalidPathException extends IOException {}
class InvalidProtocolException extends InvalidURLException {}
class InvalidStreamException extends IOException {}
class InvalidURLException extends InvalidPathException {}
class NotReadableException extends IOException {}
class NotWritableException extends IOException {}
class PartialWriteException extends WriteFailureException {}
class ReadFailureException extends IOException {}
class SSLException extends IOException {}
class StatException extends IOException {}
class StreamFilterException extends IOException {}
class StreamWrapperException extends IOException {}
class WriteFailureException extends IOException {}
ErrorExceptions::addMultipleCoreExceptions(array(
E_NOTICE => array(
'/:\/\/ was never changed, nothing to restore/' => 'StreamWrapperException',
'/path was truncated to/' => 'InvalidPathException',
'/send of \d+ bytes failed/' => 'WriteFailureException',
),
E_WARNING => array(
'/:\/\/ never existed, nothing to restore/' => 'StreamWrapperException',
'/Attempt to close cURL handle from a callback/' => 'CurlException',
'/bytes more data than requested/' => 'OverflowException',
'/call the CURL/i' => 'CurlException',
'/cannot peek or fetch OOB data/' => 'ReadFailureException',
'/cannot read from a stream opened in/' => 'InvalidStreamException',
'/cannot seek/' => 'IOException',
'/cannot use stream opened in mode/' => 'InvalidStreamException',
'/cannot write OOB data/' => 'WriteFailureException',
'/Could not build curl_slist/' => 'CurlException',
'/could not extract hash key from/' => 'SSLException',
'/could not read .* data from stream/' => 'IOException',
'/cURL handle/' => 'CurlException',
'/CURLOPT/' => 'InvalidArgumentException',
'/Failed opening .* for (inclusion|highlighting)/' => 'NotReadableException',
'/failed to bind to/' => 'IOException',
'/Failed to resolve/' => 'DNSException',
'/filename cannot be empty/' => 'InvalidFileNameException',
'/file handle is not writable/' => 'NotWritableException',
'/File name is longer than the maximum/' => 'InvalidFileNameException',
'/getaddrinfo failed/' => 'DNSException',
'/gethostbyname failed/' => 'DNSException',
'/Invalud curl configuration option/' => 'CurlException',
'/Invalid IP address/' => 'InvalidNetworkAddressException',
'/invalid URL/' => 'InvalidURLException',
'/No such file or directory/' => 'FileNotFoundException',
'/protocol .* disabled in curl/i' => 'InvalidProtocolException',
'/Protocol .* already defined/' => 'StreamWrapperException',
'/There was an error mcode=/' => 'CurlException',
'/this stream does not support SSL/' => 'SSLException',
'/unable to allocate stream/' => 'IOException',
'/Unable to find the wrapper/' => 'StreamWrapperException',
'/Unable to include uri/' => 'IOException',
'/Unable to include .* (URI|request)/' => 'IOException',
'/Unable to register wrapper/' => 'StreamWrapperException',
'/Unable to restore original .* wrapper/' => 'StreamWrapperException',
'/Unable to unregister protocol/' => 'StreamWrapperException',
'/URI lookup failed/' => 'DNSException',
),
));
<?php
use ErrorExceptions\ErrorExceptions;
class ZeroDivisionException extends MathException {}
class MathException extends LogicException {}
ErrorExceptions::addMultipleCoreExceptions(array(
E_WARNING => array(
'/Division by zero/' => 'ZeroDivisionException',
'/Square root of a negative number/' => 'MathException',
),
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment