You are here

public function FinalExceptionSubscriber::onException in Drupal 8

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php \Drupal\Core\EventSubscriber\FinalExceptionSubscriber::onException()

Handles exceptions for this subscriber.

Parameters

\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event: The event to process.

File

core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php, line 79

Class

FinalExceptionSubscriber
Last-chance handler for exceptions: the final exception subscriber.

Namespace

Drupal\Core\EventSubscriber

Code

public function onException(GetResponseForExceptionEvent $event) {
  $exception = $event
    ->getException();
  $error = Error::decodeException($exception);

  // Display the message if the current error reporting level allows this type
  // of message to be displayed, and unconditionally in update.php.
  $message = '';
  if ($this
    ->isErrorDisplayable($error)) {

    // If error type is 'User notice' then treat it as debug information
    // instead of an error message.
    // @see debug()
    if ($error['%type'] == 'User notice') {
      $error['%type'] = 'Debug';
    }
    $error = $this
      ->simplifyFileInError($error);
    unset($error['backtrace']);
    if (!$this
      ->isErrorLevelVerbose()) {

      // Without verbose logging, use a simple message.
      // We use \Drupal\Component\Render\FormattableMarkup directly here,
      // rather than use t() since we are in the middle of error handling, and
      // we don't want t() to cause further errors.
      $message = new FormattableMarkup('%type: @message in %function (line %line of %file).', $error);
    }
    else {

      // With verbose logging, we will also include a backtrace.
      $backtrace_exception = $exception;
      while ($backtrace_exception
        ->getPrevious()) {
        $backtrace_exception = $backtrace_exception
          ->getPrevious();
      }
      $backtrace = $backtrace_exception
        ->getTrace();

      // 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.
      $error['@backtrace'] = Error::formatBacktrace($backtrace);
      $message = new FormattableMarkup('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error);
    }
  }
  $content_type = $event
    ->getRequest()
    ->getRequestFormat() == 'html' ? 'text/html' : 'text/plain';
  $content = $this
    ->t('The website encountered an unexpected error. Please try again later.');
  $content .= $message ? '</br></br>' . $message : '';
  $response = new Response($content, 500, [
    'Content-Type' => $content_type,
  ]);
  if ($exception instanceof HttpExceptionInterface) {
    $response
      ->setStatusCode($exception
      ->getStatusCode());
    $response->headers
      ->add($exception
      ->getHeaders());
  }
  else {
    $response
      ->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)');
  }
  $event
    ->setResponse($response);
}