diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 1371ea07217d6c17539e779093fa1c9e710f4366..c7b2937684da87cfbaf87fe1d9cfed737675f6fa 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -316,7 +316,20 @@ function system_theme_suggestions_html(array $variables) { */ function system_theme_suggestions_page(array $variables) { $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/')); - return theme_get_suggestions($path_args, 'page'); + $suggestions = theme_get_suggestions($path_args, 'page'); + + $http_error_suggestions = [ + 'system.401' => 'page__401', + 'system.403' => 'page__403', + 'system.404' => 'page__404', + ]; + $route_name = \Drupal::routeMatch()->getRouteName(); + if (isset($http_error_suggestions[$route_name])) { + $suggestions[] = 'page__4xx'; + $suggestions[] = $http_error_suggestions[$route_name]; + } + + return $suggestions; } /** diff --git a/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php index ffbe543db7fd1409cb7370134a4533a97828b297..d0649ba110770f1e32cf18ac1819bdc8f2b79736 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php @@ -4,6 +4,7 @@ use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Path\PathMatcherInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Theme\Registry; use Drupal\Core\Utility\ThemeRegistry; use Drupal\KernelTests\KernelTestBase; @@ -192,6 +193,49 @@ public function testThemeSuggestions() { ], $suggestions, 'Found expected page node suggestions.'); } + /** + * Data provider for test40xThemeSuggestions(). + * + * @return array + * An associative array of 40x theme suggestions. + */ + public function provider40xThemeSuggestions() { + return [ + ['system.401', 'page__401'], + ['system.403', 'page__403'], + ['system.404', 'page__404'], + ]; + } + + /** + * Tests page theme suggestions for 40x responses. + * + * @dataProvider provider40xThemeSuggestions + */ + public function test40xThemeSuggestions($route, $suggestion) { + /** @var \Drupal\Core\Path\PathMatcherInterface $path_matcher */ + $path_matcher = $this->prophesize(PathMatcherInterface::class); + $path_matcher->isFrontPage()->willReturn(FALSE); + \Drupal::getContainer()->set('path.matcher', $path_matcher->reveal()); + /** @var \Drupal\Core\Path\CurrentPathStack $path_current */ + $path_current = $this->prophesize(CurrentPathStack::class); + $path_current->getPath()->willReturn('/node/123'); + \Drupal::getContainer()->set('path.current', $path_current->reveal()); + /** @var \Drupal\Core\Routing\RouteMatchInterface $route_matcher */ + $route_matcher = $this->prophesize(RouteMatchInterface::class); + $route_matcher->getRouteName()->willReturn($route); + \Drupal::getContainer()->set('current_route_match', $route_matcher->reveal()); + + $suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_page', [[]]); + $this->assertSame([ + 'page__node', + 'page__node__%', + 'page__node__123', + 'page__4xx', + $suggestion, + ], $suggestions); + } + /** * Tests theme-provided templates that are registered by modules. */