Problem/Motivation
In system_theme_suggestions_maintenance_page(), a template suggestion is provided for maintenance-page--offline.html.twig:
if ($offline) {
$suggestions[] = 'maintenance_page__offline';
}
However, this template is not picked up when the system is offline. This results in a generic, unstyled exception page (i.e. a WSOD), creating a poor user experience. This is functionality that did exist and work in Drupal 7, and an attempt was made to have this functionality ported to Drupal 8, but appears to not have been completed/successful.
This is a major issue because it has no workaround and is a regression from Drupal 7.
Cause a significant admin- or developer-facing bug with no workaround.
Steps to reproduce
Scenario A (when core/includes/errors.inc is used):
- Set correct database credentials in settings.php
- Clear cache: drush cr
- Set $config['system.logging']['error_level'] = 'hide' in settings.php
- Set $settings['maintenance_theme'] = 'bartik' in settings.php
- Set incorrect database credentials in settings.php (for example invalid username)
- Refresh the page.
- There is a plain text message: "The website encountered an unexpected error. Please try again later."
Scenario B (when \Drupal\Core\EventSubscriber\FinalExceptionSubscriber is used):
- Make sure that $settings['hash_salt'] in set in settings.php
- Clear cache: drush cr
- Set $config['system.logging']['error_level'] = 'hide' in settings.php
- Set $settings['maintenance_theme'] = 'bartik' in settings.php
- Comment out $settings['hash_salt'] in settings file
- Refresh the page.
- There is a plain text message: "The website encountered an unexpected error. Please try again later."
Proposed resolution
Adds a way to render a template when in a fatal error context first by trying to get the maintenance theme in settings and then by the slower extension discovery if the that fails. Finally it falls back to a WSOD like fatal message.
Scenario A is addressed by calling the new static method in errors.inc.
Scenario B is addressed by calling the new static method in FinalExceptionSubscriber.
These scenarios are addressed in a new browser test.
Remaining tasks
User interface changes
Fatal errors will be attempted to be rendered using the maintenance theme "offline" template. This would cause previously displaying a WSOD to potentially show a themed page instead.
API changes
- New public method Drupal\Core\Utility\Error::renderFatalError
Data model changes
N/A
Release notes snippet
This is a patch (bugfix) for a regression due to incomplete porting of functionality from Drupal 7 to Drupal 8 (and now Drupal 9). Drupal 7 allowed for the implementation of
maintenance-page--offline.tpl.php โ
, a template that to be shown when the site was offline and unable to connect to the database. The porting of this functionality to Drupal 8 and 9 was incomplete, and the equivalent Twig template, maintenance-page--ofline.html.twig
, was not picked up, resulting in a generic, unstyled exception page (i.e. a WSOD) with a poor user experience. This but has now been fixed, and site themers can implement maintenance-page--ofline.html.twig
on Drupal 8 and 9 sites.
Who this affects
This bugfix affects Drupal theme developers. Theme developers will now be able to create a template page to be displayed when Drupal is unable to reach the database, providing an improved user experience.
How to Implement
- Copy core/modules/system/templates/maintenance-page.html.twig to the theme to be used when your site is offline.
- (Optional) Edit the template to provide the HTML you would like visitors to see when the site is offline
- Edit settings.php, uncomment the line
$settings['maintenance_theme'] = 'bartik';
, and change the value from bartik
to the machine name of the theme you chose in step one above.
- Clear your registry
How to test the template
After performing the steps above, the way to test that the template is working is to force a fatal error on your site. Warning: it is strongly advised to not test this on a production server. Fatal errors can be forced as follows:
- Set
$config['system.logging']['error_level'] = 'hide';
in settings.php
- Set incorrect database credentials in settings.php (for example invalid username)
- Refresh the page
- Confirm that the template has been picked up