예제 #1
0
 private function runEnableErrors()
 {
     global $_php_error_is_ini_enabled;
     if ($_php_error_is_ini_enabled) {
         $catchSurpressedErrors =& $this->catchSurpressedErrors;
         $self = $this;
         // all errors \o/ !
         error_reporting($this->defaultErrorReportingOn);
         if (ErrorHandler::isIIS()) {
             @ini_set('log_errors', false);
         }
         set_error_handler(function ($code, $message, $file, $line, $context) use($self, &$catchSurpressedErrors) {
             /*
              * DO NOT! log the error.
              * 
              * Either it's thrown as an exception, and so logged by the exception handler,
              * or we return false, and it's logged by PHP.
              * 
              * Also DO NOT! throw an exception, instead report it.
              * This is because if an operation raises both a user AND
              * fatal error (such as require), then the exception is
              * silently ignored.
              */
             if ($self->isOn()) {
                 /*
                  * Turning off 'html_errors' at this point avoids interference 
                  * with xDebugs 'var_dump()'-overload, thus preserving prettyfied dumps
                  */
                 @ini_set('html_errors', false);
                 /*
                  * When using an @, the error reporting drops to 0.
                  */
                 if (error_reporting() !== 0 || $catchSurpressedErrors) {
                     $ex = new ErrorException($message, $code, $code, $file, $line);
                     if ($self->throwErrors) {
                         throw $ex;
                     } else {
                         $self->reportException($ex);
                     }
                 }
             } else {
                 return false;
             }
         }, $this->defaultErrorReportingOn);
         set_exception_handler(function ($ex) use($self) {
             if ($self->isOn()) {
                 /*
                  * Turning off 'html_errors' at this point avoids interference 
                  * with xDebugs 'var_dump()'-overload, thus preserving prettyfied dumps
                  */
                 @ini_set('html_errors', false);
                 $self->reportException($ex);
             } else {
                 return false;
             }
         });
         if (!$self->isShutdownRegistered) {
             if ($self->catchClassNotFound) {
                 $classException =& $self->classNotFoundException;
                 $autoloaderFuns = ErrorHandler::$SAFE_AUTOLOADER_FUNCTIONS;
                 /*
                  * When this is called, the key point is that we don't error!
                  *
                  * Instead we record that an error has occurred,
                  * if we believe one has, and then let PHP error as normal.
                  * The stack trace we record is then used later.
                  *
                  * This is done for two reasons:
                  *  - functions like 'class_exists' will run the autoloader, and we shouldn't error on them
                  *  - on PHP 5.3.0, the class loader registered functions does *not* return closure objects, so we can't do anything clever.
                  * 
                  * So we watch, but don't touch.
                  */
                 spl_autoload_register(function ($className) use($self, &$classException, &$autoloaderFuns) {
                     if ($self->isOn()) {
                         $classException = null;
                         // search the stack first, to check if we are running from 'class_exists' before we error
                         if (defined('DEBUG_BACKTRACE_IGNORE_ARGS')) {
                             $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
                         } else {
                             $trace = debug_backtrace();
                         }
                         $error = true;
                         foreach ($trace as $row) {
                             if (isset($row['function'])) {
                                 $function = $row['function'];
                                 // they are just checking, so don't error
                                 if (in_array($function, $autoloaderFuns, true)) {
                                     $error = false;
                                     break;
                                     // not us, and not the autoloader, so error!
                                 } else {
                                     if ($function !== '__autoload' && $function !== 'spl_autoload_call' && strpos($function, 'php_error\\') === false) {
                                         break;
                                     }
                                 }
                             }
                         }
                         if ($error) {
                             $classException = new ErrorException("Class '{$className}' not found", E_ERROR, E_ERROR, __FILE__, __LINE__);
                         }
                     }
                 });
             }
             $self->isShutdownRegistered = true;
         }
     }
 }