diff --git a/core/lib/Drupal/Core/ExceptionController.php b/core/lib/Drupal/Core/ExceptionController.php index 92d4454..7d73c84 100644 --- a/core/lib/Drupal/Core/ExceptionController.php +++ b/core/lib/Drupal/Core/ExceptionController.php @@ -225,8 +225,12 @@ public function on404Html(FlattenException $exception, Request $request) { public function on500Html(FlattenException $exception, Request $request) { $error = $this->decodeException($exception); - // Because the kernel doesn't run until full bootstrap, we know that - // most subsystems are already initialized. + // Backtrace array is not a valid replacement value for t(). + $backtrace = array(); + if (isset($error['backtrace'])) { + $backtrace = $error['backtrace']; + unset($error['backtrace']); + } $headers = array(); @@ -258,13 +262,35 @@ public function on500Html(FlattenException $exception, Request $request) { $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); + // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path + // in the message. This does not happen for (false) security. + $root_length = strlen(DRUPAL_ROOT); + if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { + $error['%file'] = substr($error['%file'], $root_length + 1); + } + // Should not translate the string to avoid errors producing more errors. + $message = format_string('%type: !message in %function (line %line of %file).', $error); + + // Check if verbose error reporting is on. + $error_level = config('system.logging')->get('error_level'); + + if ($error_level == ERROR_REPORTING_DISPLAY_VERBOSE) { + // First trace is the error itself, already contained in the message. + // While the second trace is the error source and also contained in the + // message, the message doesn't contain argument values, so we output it + // once more in the backtrace. + array_shift($backtrace); + // Generate a backtrace containing only scalar argument values. + $message .= '
' . format_backtrace($backtrace) . '
'; + } + drupal_set_message($message, $class, TRUE); } drupal_set_title(t('Error')); @@ -369,6 +395,7 @@ protected function decodeException(FlattenException $exception) { '%file' => $caller['file'], '%line' => $caller['line'], 'severity_level' => WATCHDOG_ERROR, + 'backtrace' => $backtrace, ); } @@ -380,12 +407,12 @@ protected function decodeException(FlattenException $exception) { * and not one of our debug functions. * * @param $backtrace - * A standard PHP backtrace. + * A standard PHP backtrace. Passed by reference. * * @return * An associative array with keys 'file', 'line' and 'function'. */ - protected function getLastCaller($backtrace) { + protected function getLastCaller(&$backtrace) { // Ignore black listed error handling functions. $blacklist = array('debug', '_drupal_error_handler', '_drupal_exception_handler'); diff --git a/core/modules/system/lib/Drupal/system/Tests/System/ErrorHandlerTest.php b/core/modules/system/lib/Drupal/system/Tests/System/ErrorHandlerTest.php index 11d1356..18160db 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/ErrorHandlerTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/ErrorHandlerTest.php @@ -54,7 +54,7 @@ function testErrorHandler() { ); // Set error reporting to display verbose notices. - config('system.logging')->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save(); + $config->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save(); $this->drupalGet('error-test/generate-warnings'); $this->assertResponse(200, 'Received expected HTTP status code.'); $this->assertErrorMessage($error_notice); @@ -94,6 +94,7 @@ function testErrorHandler() { * Test the exception handler. */ function testExceptionHandler() { + $config = config('system.logging'); $error_exception = array( '%type' => 'Exception', '!message' => 'Drupal is awesome', @@ -112,6 +113,7 @@ function testExceptionHandler() { $this->drupalGet('error-test/trigger-exception'); $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.'); $this->assertErrorMessage($error_exception); + $this->assertNoRaw('
', 'Did not find pre element with backtrace class.');
 
     $this->drupalGet('error-test/trigger-pdo-exception');
     $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.');
@@ -121,6 +123,24 @@ function testExceptionHandler() {
     $this->assertText($error_pdo_exception['!message'], format_string('Found !message in error page.', $error_pdo_exception));
     $error_details = format_string('in %function (line ', $error_pdo_exception);
     $this->assertRaw($error_details, format_string("Found '!message' in error page.", array('!message' => $error_details)));
+    $this->assertNoRaw('
', 'Did not find pre element with backtrace class.');
+
+    // Set error reporting to display verbose notices.
+    $config->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save();
+    $this->drupalGet('error-test/trigger-exception');
+    $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.');
+    $this->assertErrorMessage($error_exception);
+    $this->assertRaw('
', 'Found pre element with backtrace class.');
+
+    $this->drupalGet('error-test/trigger-pdo-exception');
+    $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.');
+    // We cannot use assertErrorMessage() since the extact error reported
+    // varies from database to database. Check that the SQL string is displayed.
+    $this->assertText($error_pdo_exception['%type'], format_string('Found %type in error page.', $error_pdo_exception));
+    $this->assertText($error_pdo_exception['!message'], format_string('Found !message in error page.', $error_pdo_exception));
+    $error_details = format_string('in %function (line ', $error_pdo_exception);
+    $this->assertRaw($error_details, format_string("Found '!message' in error page.", array('!message' => $error_details)));
+    $this->assertRaw('
', 'Found pre element with backtrace class.');
   }
 
   /**