diff --git a/core/includes/errors.inc b/core/includes/errors.inc old mode 100644 new mode 100755 index 40e2903..33298ac --- a/core/includes/errors.inc +++ b/core/includes/errors.inc @@ -265,6 +265,12 @@ function _drupal_log_error($error, $fatal = FALSE) { exit; } + $html = Error::renderFatalError(['title' => 'Service unavailable', 'message' => $message]); + if (!empty($html)) { + $message = $html; + $response->headers->set('Content-Type', 'text/html'); + } + $response->setContent($message); $response->setStatusCode(500, '500 Service unavailable (with message)'); diff --git a/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php old mode 100644 new mode 100755 index 4317ff0..313d573 --- a/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php @@ -125,7 +125,15 @@ public function onException(GetResponseForExceptionEvent $event) { $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']); + $type = 'text/plain'; + + $html = Error::renderFatalError(['title' => $this->t('Service unavailable'), 'message' => $content]); + if (!empty($html)) { + $content = $html; + $type = 'text/html'; + } + + $response = new Response($content, 500, ['Content-Type' => $type]); if ($exception instanceof HttpExceptionInterface) { $response->setStatusCode($exception->getStatusCode()); diff --git a/core/lib/Drupal/Core/Utility/Error.php b/core/lib/Drupal/Core/Utility/Error.php old mode 100644 new mode 100755 index eb452c2..8dd8de5 --- a/core/lib/Drupal/Core/Utility/Error.php +++ b/core/lib/Drupal/Core/Utility/Error.php @@ -5,6 +5,8 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Xss; use Drupal\Core\Database\DatabaseExceptionWrapper; +use Twig_Environment; +use Twig_Loader_Array; /** * Drupal error utility class. @@ -101,6 +103,45 @@ public static function renderExceptionSafe($exception) { } /** + * Renders fatal error page from twig template using Symfony twig engine. + * + * @param array $context + * Variables to be passed to twig template. + * + * @return string + * An html code with rendered fatal error page. + */ + public static function renderFatalError(array $context) { + $content = ''; + + // Try to get the current theme. If this fails, + // for example if the database connection is not there, use bartik. + try { + $theme = \Drupal::service('theme.manager')->getActiveTheme()->getName(); + $path = DRUPAL_ROOT . '/' . drupal_get_path('theme', $theme) . '/templates/fatal-error-page.html.twig'; + } + catch (\Exception $e) { + $path = DRUPAL_ROOT . '/core/themes/bartik/templates/fatal-error-page.html.twig'; + } + + if (file_exists($path)) { + // Directly use Symfony twig engine without Drupal wrapper to minimize + // possibility of nested exception. + $environment = new Twig_Environment(); + $template = file_get_contents($path); + $loader = new Twig_Loader_Array(['fatal_error' => $template]); + $environment->setLoader($loader); + + $context = array_map(function ($v) { + return trim(strip_tags($v)); + }, $context); + $content = $environment->render('fatal_error', $context); + } + + return $content; + } + + /** * Gets the last caller from a backtrace. * * @param array $backtrace diff --git a/core/themes/bartik/templates/fatal-error-page.html.twig b/core/themes/bartik/templates/fatal-error-page.html.twig new file mode 100755 index 0000000..50a30c8 --- /dev/null +++ b/core/themes/bartik/templates/fatal-error-page.html.twig @@ -0,0 +1,41 @@ +{# +/** + * @file + * Bartik's theme implementation to display a fatal error page. + * + */ + #} + + +
+