<commit_before><?php
/**
 * Lithium: the most rad php framework
 *
 * @copyright     Copyright 2009, Union of RAD (http://union-of-rad.org)
 * @license       http://opensource.org/licenses/bsd-license.php The BSD License
 */

namespace lithium\core;

use Exception;
use ErrorException;
use lithium\util\collection\Filters;

/**
 * The `ErrorHandler` class allows PHP errors and exceptions to be handled in a uniform way. Using
 * the `ErrorHandler`'s configuration, it is possible to have very broad but very tight control
 * over error handling in your application.
 *
 * {{{ embed:lithium\tests\cases\core\ErrorHandlerTest::testExceptionCatching(2-7) }}}
 *
 * Using a series of cascading rules and handlers, it is possible to capture and handle very
 * specific errors and exceptions.
 */
class ErrorHandler extends \lithium\core\StaticObject {

	/**
	 * Configuration parameters.
	 *
	 * @var array Config params
	 */
	protected static $_config = array();

	/**
	 * Error/exception handlers.
	 *
	 * @var array An array of closures that represent all invokable error/exception handlers.
	 */
	protected static $_handlers = array();

	/**
	 * Types of checks available for sorting & parsing errors/exceptions.
	 * Default checks are for `code`, `stack` and `message`.
	 *
	 * @var array Array of checks represented as closures, indexed by name.
	 */
	protected static $_checks = array();

	/**
	 * Currently registered exception handler.
	 *
	 * @var closure Closure representing exception handler.
	 */
	protected static $_exceptionHandler = null;

	/**
	 * State of error/exception handling.
	 *
	 * @var boolean True if custom error/exception handlers have been registered, false
	 *      otherwise.
	 */
	protected static $_isRunning = false;

	/**
	 * Setup basic error handling checks/types, as well as register the error and exception
	 * hanlders.
	 *
	 * Called on static class initialization (i.e. when first loaded).
	 *
	 * @return void
	 */
	public static function __init() {
		static::$_checks = array(
			'type'  => function($config, $info) {
				return (
					$config['type'] == $info['type'] ||
					is_subclass_of($info['type'], $config['type'])
				);
			},
			'code' => function($config, $info) {
				return ($config['code'] & $info['code']);
			},
			'stack' => function($config, $info) {
				foreach ((array) $config['stack'] as $frame) {
					if (in_array($frame, $info['stack'])) {
						return true;
					}
				}
				return false;
			},
			'message' => function($config, $info) {
				return preg_match($config['message'], $info['message']);
			}
		);
		$self = get_called_class();

		static::$_exceptionHandler = function($exception, $return = false) use ($self) {
			$info = array('type' => get_class($exception)) + compact('exception');

			foreach (array('message', 'file', 'line', 'trace') as $key) {
				$method = 'get' . ucfirst($key);
				$info[$key] = $exception->{$method}();
			}
			if ($return) {
				return $info;
			}<commit_msg>Enabling `ErrorHandler` exception-type checking to catch sub-classes of the type given, and simplifying call stack checks to allow any stack frame intersection.<commit_after><?php
/**
 * Lithium: the most rad php framework
 *
 * @copyright     Copyright 2009, Union of RAD (http://union-of-rad.org)
 * @license       http://opensource.org/licenses/bsd-license.php The BSD License
 */

namespace lithium\core;

use Exception;
use ErrorException;
use lithium\util\collection\Filters;

/**
 * The `ErrorHandler` class allows PHP errors and exceptions to be handled in a uniform way. Using
 * the `ErrorHandler`'s configuration, it is possible to have very broad but very tight control
 * over error handling in your application.
 *
 * {{{ embed:lithium\tests\cases\core\ErrorHandlerTest::testExceptionCatching(2-7) }}}
 *
 * Using a series of cascading rules and handlers, it is possible to capture and handle very
 * specific errors and exceptions.
 */
class ErrorHandler extends \lithium\core\StaticObject {

	/**
	 * Configuration parameters.
	 *
	 * @var array Config params
	 */
	protected static $_config = array();

	/**
	 * Error/exception handlers.
	 *
	 * @var array An array of closures that represent all invokable error/exception handlers.
	 */
	protected static $_handlers = array();

	/**
	 * Types of checks available for sorting & parsing errors/exceptions.
	 * Default checks are for `code`, `stack` and `message`.
	 *
	 * @var array Array of checks represented as closures, indexed by name.
	 */
	protected static $_checks = array();

	/**
	 * Currently registered exception handler.
	 *
	 * @var closure Closure representing exception handler.
	 */
	protected static $_exceptionHandler = null;

	/**
	 * State of error/exception handling.
	 *
	 * @var boolean True if custom error/exception handlers have been registered, false
	 *      otherwise.
	 */
	protected static $_isRunning = false;

	/**
	 * Setup basic error handling checks/types, as well as register the error and exception
	 * hanlders.
	 *
	 * Called on static class initialization (i.e. when first loaded).
	 *
	 * @return void
	 */
	public static function __init() {
		static::$_checks = array(
			'type'  => function($config, $info) {
				return (boolean) array_filter((array) $config['type'], function($type) use ($info) {
					return $type == $info['type'] || is_subclass_of($info['type'], $type);
				});
			},
			'code' => function($config, $info) {
				return ($config['code'] & $info['code']);
			},
			'stack' => function($config, $info) {
				return (boolean) array_intersect((array) $config['stack'], $info['stack']);
			},
			'message' => function($config, $info) {
				return preg_match($config['message'], $info['message']);
			}
		);
		$self = get_called_class();

		static::$_exceptionHandler = function($exception, $return = false) use ($self) {
			$info = array('type' => get_class($exception)) + compact('exception');

			foreach (array('message', 'file', 'line', 'trace') as $key) {
				$method = 'get' . ucfirst($key);
				$info[$key] = $exception->{$method}();
			}
			if ($return) {
				return $info;
			}
{'fraction_non_alphanumeric': 0.14076632132872882, 'fraction_numerical': 0.001973359644795264, 'mean_word_length': 3.628614916286149, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5381609', 'n_tokens_mistral': 1960, 'n_tokens_neox': 1695, 'n_words': 571}