/** * = Options = * * All options are optional, and so is passing in an options item. * You don't have to supply any, it's up to you. * * Note that if 'php_error.force_disable' is true, then this object * will try to look like it works, but won't actually do anything. * * All options can also be passed in from 'php.ini'. You do this * by setting it with 'php_error.' prefix. For example: * * php_error.catch_ajax_errors = On * php_error.error_reporting_on = E_ALL | E_STRICT * * Includes: * = Types of errors this will catch = * - catch_ajax_errors When on, this will inject JS Ajax wrapping code, to allow this to catch any future JSON errors. Defaults to true. * - catch_supressed_errors The @ supresses errors. If set to true, then they are still reported anyway, but respected when false. Defaults to false. * - catch_class_not_found When true, loading a class that does not exist will be caught. This defaults to true. * * = Error reporting level = * - error_reporting_on value for when errors are on, defaults to all errors * - error_reporting_off value for when errors are off, defaults to php.ini's error_reporting. * * = Setup Details = * - application_root When it's working out hte stack trace, this is the root folder of the application, to use as it's base. * Defaults to the servers root directory. * * A relative path can be given, but lets be honest, an explicit path is the way to guarantee that you * will get the path you want. My relative might not be the same as your relative. * * - snippet_num_lines The number of lines to display in the code snippet. * That includes the line being reported. * * - server_name The name for this server, defaults to "$_SERVER['SERVER_NAME']" * * - ignore_folders This is allows you to highlight non-framework code in a stack trace. * An array of folders to ignore, when working out the stack trace. * This is folder prefixes in relation to the application_root, whatever that might be. * They are only ignored if there is a file found outside of them. * If you still don't get what this does, don't worry, it's here cos I use it. * * - application_folders Just like ignore, but anything found in these folders takes precedence * over anything else. * * - background_text The text that appeares in the background. By default this is blank. * Why? You can replace this with the name of your framework, for extra customization spice. * * - html_only By default, PHP Error only runs on ajax and HTML pages. * If this is false, then it will also run when on non-HTML * pages too, such as replying with images of JavaScript * from your PHP. Defaults to true. * * - throw_errors By default, PHP Error will stop execution on trigerred errors. * You can enabled it to throw errors instead. * - error_page Error page to show if display_errors is disabled. * Should be an absolute path to .html or .php file * * - error_log Defines where to log messages. * FALSE - disables logging * 0 - logs to the syslog, equivalent of php's error_log($message, 0) (default) * absolute path - logs to the provided file path, equivalent of php's error_log($message, 3, $path) * email - sends an email, equivalent of php's error_log($message, 1, $email) * * - error_log_format Format of log messages with printf() directives. * %1$s - timestamp (empty if error_log is set to 0, because syslog is using it's own timestamp) * %2$s - error message * %3$s - file * %4$s - line * %5$s - stack trace (starts on the newline and is indented) * Defaults to "%s%s\n %s, %s %s" * * - error_log_time_format Format of log's timestamp compatible with strftime() * Defaults to "[%c] " * * @param options Optional, an array of values to customize this handler. * @throws Exception This is raised if given an options that does *not* exist (so you know that option is meaningless). */ public function __construct($options = null) { // there can only be one to rule them all global $_php_error_global_handler; if ($_php_error_global_handler !== null) { $this->lastGlobalErrorHandler = $_php_error_global_handler; } else { $this->lastGlobalErrorHandler = null; } $_php_error_global_handler = $this; $this->cachedFiles = array(); $this->isShutdownRegistered = false; $this->isOn = false; /* * Deal with the options. * * They are removed one by one, and any left, will raise an error. */ $ignoreFolders = ErrorHandler::optionsPop($options, 'ignore_folders', null); $appFolders = ErrorHandler::optionsPop($options, 'application_folders', null); if ($ignoreFolders !== null) { ErrorHandler::setFolders($this->ignoreFolders, $this->ignoreFoldersLongest, $ignoreFolders); } if ($appFolders !== null) { ErrorHandler::setFolders($this->applicationFolders, $this->applicationFoldersLongest, $appFolders); } $this->defaultErrorReportingOn = ErrorHandler::optionsPop($options, 'error_reporting_on', -1); $this->defaultErrorReportingOff = ErrorHandler::optionsPop($options, 'error_reporting_off', error_reporting()); $this->applicationRoot = ErrorHandler::optionsPop($options, 'application_root', $_SERVER['DOCUMENT_ROOT']); $this->serverName = ErrorHandler::optionsPop($options, 'server_name', isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : null); /* * Relative paths might be given for document root, * so we make it explicit. */ $dir = @realpath($this->applicationRoot); if (!is_string($dir)) { throw new Exception("Document root not found: " . $this->applicationRoot); } else { $this->applicationRoot = str_replace('\\', '/', $dir); } $this->catchClassNotFound = !!ErrorHandler::optionsPop($options, 'catch_class_not_found', true); $this->catchSurpressedErrors = !!ErrorHandler::optionsPop($options, 'catch_supressed_errors', false); $this->catchAjaxErrors = !!ErrorHandler::optionsPop($options, 'catch_ajax_errors', true); $this->backgroundText = ErrorHandler::optionsPop($options, 'background_text', ''); $this->numLines = ErrorHandler::optionsPop($options, 'snippet_num_lines', ErrorHandler::NUM_FILE_LINES); $this->displayLineNumber = ErrorHandler::optionsPop($options, 'display_line_numbers', false); $this->htmlOnly = !!ErrorHandler::optionsPop($options, 'html_only', true); $this->throwErrors = !!ErrorHandler::optionsPop($options, 'throw_errors', false); $this->errorPage = ErrorHandler::optionsPop($options, 'error_page', false); $this->errorLog = ErrorHandler::optionsPop($options, 'error_log', 0); $this->errorLogFormat = ErrorHandler::optionsPop($options, 'error_log_format', "%s%s\n %s, %s %s"); $this->errorLogTimeFormat = ErrorHandler::optionsPop($options, 'error_log_time_format', '[%c] '); $this->classNotFoundException = null; $wordpress = ErrorHandler::optionsPop($options, 'wordpress', false); if ($wordpress) { // php doesn't like | in constants and privates, so just set it directly : ( $this->defaultErrorReportingOn = E_ERROR | E_WARNING | E_PARSE | E_USER_DEPRECATED & ~E_DEPRECATED & ~E_STRICT; } if ($options) { foreach ($options as $key => $val) { throw new InvalidArgumentException("Unknown option given {$key}"); } } $this->isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest' || isset($_REQUEST['php_error_is_ajax']); $this->isBufferSetup = false; $this->startBuffer(); }