diff --git a/includes/errors.inc b/includes/errors.inc index 3a97b6d..4dc8cfe 100644 --- a/includes/errors.inc +++ b/includes/errors.inc @@ -67,7 +67,8 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c if ($error_level & error_reporting()) { $types = drupal_error_levels(); list($severity_msg, $severity_level) = $types[$error_level]; - $caller = _drupal_get_last_caller(debug_backtrace()); + $backtrace = debug_backtrace(); + $caller = _drupal_get_last_caller($backtrace); if (!function_exists('filter_xss_admin')) { require_once DRUPAL_ROOT . '/includes/common.inc'; @@ -83,6 +84,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c '%file' => $caller['file'], '%line' => $caller['line'], 'severity_level' => $severity_level, + 'backtrace' => $backtrace, ), $error_level == E_RECOVERABLE_ERROR); } } @@ -189,6 +191,10 @@ function _drupal_log_error($error, $fatal = FALSE) { drupal_maintenance_theme(); } + // Backtrace array is not a valid replacement value for t(). + $backtrace = $error['backtrace']; + unset($error['backtrace']); + // When running inside the testing framework, we relay the errors // to the tested site by the way of HTTP headers. $test_info = &$GLOBALS['drupal_test_info']; @@ -237,13 +243,43 @@ function _drupal_log_error($error, $fatal = FALSE) { $class = 'error'; // If error type is 'User notice' then treat it as debug information - // instead of an error message, see dd(). + // instead of an error message. + // @see debug() if ($error['%type'] == 'User notice') { $error['%type'] = 'Debug'; $class = 'status'; } - drupal_set_message(t('%type: !message in %function (line %line of %file).', $error), $class); + $message = t('%type: !message in %function (line %line of %file).', $error); + // First trace is the error itself, already contained in the message. + array_shift($backtrace); + // Second trace is the error source, already contained in the message. + array_shift($backtrace); + // Generate a simple backtrace string with simplified arguments. + $message .= '
'; + foreach ($backtrace as $trace) { + $call = array('function' => '', 'args' => array()); + if (isset($trace['class'])) { + $call['function'] = $trace['class'] . $trace['type'] . $trace['function']; + } + elseif (isset($trace['function'])) { + $call['function'] = $trace['function']; + } + else { + $call['function'] = 'main'; + } + foreach ($trace['args'] as $arg) { + if (is_scalar($arg)) { + $call['args'][] = is_string($arg) ? "'$arg'" : $arg; + } + else { + $call['args'][] = ucfirst(gettype($arg)); + } + } + $message .= $call['function'] . '(' . implode(', ', $call['args']) . ")\n"; + } + $message .= ''; + drupal_set_message($message, $class); } if ($fatal) { @@ -260,11 +296,11 @@ function _drupal_log_error($error, $fatal = FALSE) { * Gets the last caller from a backtrace. * * @param $backtrace - * A standard PHP backtrace. + * A standard PHP backtrace. Passed by reference. * @return * An associative array with keys 'file', 'line' and 'function'. */ -function _drupal_get_last_caller($backtrace) { +function _drupal_get_last_caller(&$backtrace) { // Errors that occur inside PHP internal functions do not generate // information about file and line. Ignore black listed functions. $blacklist = array('debug', '_drupal_error_handler', '_drupal_exception_handler'); diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module index 89c605c..d92c104 100644 --- a/modules/field/modules/text/text.module +++ b/modules/field/modules/text/text.module @@ -9,6 +9,7 @@ * Implements hook_help(). */ function text_help($path, $arg) { + $foo = $bar; switch ($path) { case 'admin/help#text': $output = '';