X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FEventSubscriber%2FFinalExceptionSubscriber.php;fp=web%2Fcore%2Flib%2FDrupal%2FCore%2FEventSubscriber%2FFinalExceptionSubscriber.php;h=4317ff08cb387556992b58d1b630093334e44379;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hp=0000000000000000000000000000000000000000;hpb=aea91e65e895364e460983b890e295aa5d5540a5;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php b/web/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php new file mode 100644 index 000000000..4317ff08c --- /dev/null +++ b/web/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php @@ -0,0 +1,195 @@ +configFactory = $config_factory; + } + + /** + * Gets the configured error level. + * + * @return string + */ + protected function getErrorLevel() { + if (!isset($this->errorLevel)) { + $this->errorLevel = $this->configFactory->get('system.logging')->get('error_level'); + } + return $this->errorLevel; + } + + /** + * Handles exceptions for this subscriber. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + 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 call SafeMarkup::format 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 = SafeMarkup::format('%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 = SafeMarkup::format('%type: @message in %function (line %line of %file).
@backtrace
', $error); + } + } + + $content = $this->t('The website encountered an unexpected error. Please try again later.'); + $content .= $message ? '

' . $message : ''; + $response = new Response($content, 500, ['Content-Type' => 'text/plain']); + + 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); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + // Run as the final (very late) KernelEvents::EXCEPTION subscriber. + $events[KernelEvents::EXCEPTION][] = ['onException', -256]; + return $events; + } + + /** + * Checks whether the error level is verbose or not. + * + * @return bool + */ + protected function isErrorLevelVerbose() { + return $this->getErrorLevel() === ERROR_REPORTING_DISPLAY_VERBOSE; + } + + /** + * Wrapper for error_displayable(). + * + * @param $error + * Optional error to examine for ERROR_REPORTING_DISPLAY_SOME. + * + * @return bool + * + * @see \error_displayable + */ + protected function isErrorDisplayable($error) { + return error_displayable($error); + } + + /** + * Attempts to reduce error verbosity in the error message's file path. + * + * Attempts to reduce verbosity by removing DRUPAL_ROOT from the file path in + * the message. This does not happen for (false) security. + * + * @param $error + * Optional error to examine for ERROR_REPORTING_DISPLAY_SOME. + * + * @return + * The updated $error. + */ + protected function simplifyFileInError($error) { + // 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); + } + return $error; + } + +}