You are here

function backtrace_error_handler in Devel 6

Same name and namespace in other branches
  1. 8.3 devel.module \backtrace_error_handler()
  2. 8 devel.module \backtrace_error_handler()
  3. 8.2 devel.module \backtrace_error_handler()
  4. 5 devel.module \backtrace_error_handler()
  5. 7 devel.module \backtrace_error_handler()
  6. 4.x devel.module \backtrace_error_handler()

Display backtrace showing the route of calls to the current error.

Parameters

$error_level: The level of the error raised.

$message: The error message.

$filename: The filename that the error was raised in.

$line: The line number the error was raised at.

$context: An array that points to the active symbol table at the point the error occurred.

1 string reference to 'backtrace_error_handler'
devel_set_handler in ./devel.module

File

./devel.module, line 484

Code

function backtrace_error_handler($error_level, $message, $filename, $line, $context) {

  // Don't respond to the error if it was suppressed with a '@'.
  if (error_reporting() == 0) {
    return;
  }

  // Don't respond to warning caused by ourselves.
  if (preg_match('#Cannot modify header information - headers already sent by \\([^\\)]*[/\\\\]devel[/\\\\]#', $message)) {
    return;
  }

  // We can't use the PHP E_* constants here as not all versions of PHP have all
  // the constants defined, so for consistency, we just use the numeric equivalent.
  $types = array(
    1 => array(
      'Error',
      WATCHDOG_ERROR,
    ),
    2 => array(
      'Warning',
      WATCHDOG_WARNING,
    ),
    4 => array(
      'Parse error',
      WATCHDOG_ERROR,
    ),
    8 => array(
      'Notice',
      WATCHDOG_NOTICE,
    ),
    16 => array(
      'Core error',
      WATCHDOG_ERROR,
    ),
    32 => array(
      'Core warning',
      WATCHDOG_WARNING,
    ),
    64 => array(
      'Compile error',
      WATCHDOG_ERROR,
    ),
    128 => array(
      'Compile warning',
      WATCHDOG_WARNING,
    ),
    256 => array(
      'User error',
      WATCHDOG_ERROR,
    ),
    512 => array(
      'User warning',
      WATCHDOG_WARNING,
    ),
    1024 => array(
      'User notice',
      WATCHDOG_NOTICE,
    ),
    2048 => array(
      'Strict warning',
      WATCHDOG_DEBUG,
    ),
    4096 => array(
      'Recoverable fatal error',
      WATCHDOG_ERROR,
    ),
    8192 => array(
      'Deprecated',
      WATCHDOG_WARNING,
    ),
    16384 => array(
      'User deprecated',
      WATCHDOG_WARNING,
    ),
  );
  $type = isset($types[$error_level]) ? $types[$error_level] : array(
    'Unknown error',
    WATCHDOG_ERROR,
  );

  // Hide stack trace and parameters from unqualified users.
  if (!user_access('access devel information')) {

    // Do what core does in common.inc.
    // (We need to duplicate the core code here rather than calling it
    // to avoid having the backtrace_error_handler() on top of the call stack.)
    if (function_exists('_drupal_get_last_caller') && function_exists('_drupal_log_error')) {

      // Use the functions in the D6-core-simpletest.patch.
      if ($error_level) {
        $caller = _drupal_get_last_caller(debug_backtrace());

        // We treat recoverable errors as fatal.
        _drupal_log_error(array(
          '%type' => $type[1],
          '%message' => $message,
          '%function' => $caller['function'],
          '%file' => $caller['file'],
          '%line' => $caller['line'],
        ), $error_level == E_RECOVERABLE_ERROR);
      }
    }
    else {

      // Duplicate the drupal_error_handler() code.
      $errno = $error_level;

      // If the @ error suppression operator was used, error_reporting will have
      // been temporarily set to 0.
      if (error_reporting() == 0) {
        return;
      }
      if ($errno & (E_ALL ^ E_DEPRECATED)) {
        $types = array(
          1 => 'error',
          2 => 'warning',
          4 => 'parse error',
          8 => 'notice',
          16 => 'core error',
          32 => 'core warning',
          64 => 'compile error',
          128 => 'compile warning',
          256 => 'user error',
          512 => 'user warning',
          1024 => 'user notice',
          2048 => 'strict warning',
          4096 => 'recoverable fatal error',
        );

        // For database errors, we want the line number/file name of the place that
        // the query was originally called, not _db_query().
        if (isset($context[DB_ERROR])) {
          $backtrace = array_reverse(debug_backtrace());

          // List of functions where SQL queries can originate.
          $query_functions = array(
            'db_query',
            'pager_query',
            'db_query_range',
            'db_query_temporary',
            'update_sql',
          );

          // Determine where query function was called, and adjust line/file
          // accordingly.
          foreach ($backtrace as $index => $function) {
            if (in_array($function['function'], $query_functions)) {
              $line = $backtrace[$index]['line'];
              $filename = $backtrace[$index]['file'];
              break;
            }
          }
        }

        // Try to use filter_xss(). If it's too early in the bootstrap process for
        // filter_xss() to be loaded, use check_plain() instead.
        $entry = check_plain($types[$errno]) . ': ' . (function_exists('filter_xss') ? filter_xss($message) : check_plain($message)) . ' in ' . check_plain($filename) . ' on line ' . check_plain($line) . '.';

        // Force display of error messages in update.php.
        if (variable_get('error_level', 1) == 1 || strstr($_SERVER['SCRIPT_NAME'], 'update.php')) {
          drupal_set_message($entry, 'error');
        }
        watchdog('php', '%message in %file on line %line.', array(
          '%error' => $types[$errno],
          '%message' => $message,
          '%file' => $filename,
          '%line' => $line,
        ), WATCHDOG_ERROR);
      }
    }
    return;
  }
  if ($error_level & (E_ALL ^ E_DEPRECATED)) {

    // Only write each distinct NOTICE message once, as repeats do not give any
    // further information and can choke the page output.
    if ($error_level == E_NOTICE) {
      static $written = array();
      if (!empty($written[$line][$filename][$message])) {
        return;
      }
      $written[$line][$filename][$message] = TRUE;
    }
    $backtrace = debug_backtrace();
    $variables = array(
      '%error' => $type[0],
      '%message' => $message,
      '%function' => $backtrace[1]['function'] . '()',
      '%file' => $filename,
      '%line' => $line,
    );
    if (variable_get('error_level', 1) == 1) {
      print t('%error: %message in %function (line %line of %file).', $variables) . " =>\n";
      ddebug_backtrace(1);

      // Also show the standard drupal message if this was requested via the admin option
      // for both backtrace and message.
      if (variable_get('devel_error_handler', DEVEL_ERROR_HANDLER_STANDARD) == DEVEL_ERROR_HANDLER_BACKTRACE_AND_MESSAGE) {
        drupal_set_message(t('%error: %message in %function (line %line of %file).', $variables), $type[1] <= WATCHDOG_ERROR ? 'error' : 'warning');
      }
    }
    watchdog('php', '%error: %message in %function (line %line of %file).', $variables, WATCHDOG_ERROR);
  }
}