Follow-up to #2362517: Improve default 403/404 exception HTML subscriber: don't duplicate the page render pipeline, use the routing system — add system.403 and system.404 routes

Problem/Motivation

#2362517: Improve default 403/404 exception HTML subscriber: don't duplicate the page render pipeline, use the routing system — add system.403 and system.404 routes adds a Http4xxController for returning 403 and 404 page markup.
In comment #12 @dawehner noted it would be good if these had their own theme functions to allow simple changes to the markup - e.g. #theme => 'page__403' or #theme => 'page__404'.

Proposed resolution

Add them

Remaining tasks

Wait for #2362517: Improve default 403/404 exception HTML subscriber: don't duplicate the page render pipeline, use the routing system — add system.403 and system.404 routes
Write patch.
Add tests.
Review.

User interface changes

None.

API changes

None.

CommentFileSizeAuthor
#59 2363987-54-59.txt547 bytesKrzysztof Domański
#59 2363987-59.patch3.21 KBKrzysztof Domański
#54 interdiff_50_54.txt729 bytespandaski
#54 2363987-54-40x-theme-suggestion.patch3.27 KBpandaski
#50 interdiff_47_50.txt960 bytespandaski
#50 2363987-50-40x-theme-suggestion.patch3.29 KBpandaski
#47 2363987-47-40x-theme-suggestion.patch3.24 KBpandaski
#47 interdiff_42_47.txt797 bytespandaski
#46 2363987-46-40x-theme-suggestion.patch3.24 KBpandaski
#46 interdiff_42_46.txt797 bytespandaski
#42 2363987-42-40x-theme-suggestion.patch3.13 KBmr.baileys
#42 interdiff-40-42.txt1.18 KBmr.baileys
#40 2363987-40-40x-theme-suggestion.patch3.04 KBmr.baileys
#40 interdiff.txt1.52 KBmr.baileys
#36 2363987-36-40x-theme-suggestion.patch3.02 KBmr.baileys
#36 2363987-36-40x-theme-suggestion-test-only.patch2.14 KBmr.baileys
#11 40x_error_theme_sugggestions-2363987-11.patch889 bytesacrosman
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

catch’s picture

Status: Postponed » Active
DuaelFr’s picture

Is it still necessary?
With a Vanilla Drupal 8, templates suggestions follow the path so you can use html__system__40x or page__system__40x.

Crell’s picture

I'd much rather have a formal template defined than rely on magic path template naming. Path-based templating is a cludge anyway. :-) Not a priority but definitely open to someone working on this. I think this would also be 8.1 safe, probably?

dawehner’s picture

Yeah, I think there would be no problem in making that an opt IN feature.

Wim Leers’s picture

Issue tags: +TX (Themer Experience)

This is just a matter of updating \Drupal\system\Controller\Http4xxController AFAICT.

dawehner’s picture

Yeah, you can also easily deal with it in a contrib module, if you like.

Crell’s picture

So yes, consider this approved to work on whenever. :-)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Component: request processing system » theme system

I think this component is a better match.

IRONFELIX’s picture

Very strange, I tried to use the patch #11, but drupal continue to ignore file "page--404.html.twig"

Chi’s picture

Status: Active » Needs review

@IRONFELIX, I just checked it against the latest 8.4.x code. The patch is still valid. Make sure you clear caches and template name is spelled correctly.

IRONFELIX’s picture

I use Drupal 8.3.1 and when I go to the wrong url, this line in code

$route_name = Drupal::routeMatch()->getRouteName();

returns value "entity.node.canonical" and next if doesn't work, of course.

Chi’s picture

entity.node.canonical means that valid route was found for the requested URL.
Can you check how this works on fresh Drupal installation?

IRONFELIX’s picture

@Chi, to tell the truth, I decided to select more easy way and set hook in my theme without touching any system files::

function mytheme_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  $http_error_suggestions = [
     'system.401' => 'page__401',
     'system.403' => 'page__403',
     'system.404' => 'page__404',
  ];
  $node = \Drupal::request()->attributes->get('node');
  if ($node) {
     if ($node->id() == 49 ) {  // this is the node id linked to the 404 page
        $suggestions[] = $http_error_suggestions['system.404'];
     }
  }
}
Chi’s picture

@IRONFELIX, I suppose you have configured /node/49 path as default 404 page. That's why the patch did not work for you.

acrosman’s picture

Version: 8.3.x-dev » 8.4.x-dev
acrosman’s picture

Issue tags: +Needs tests
Pascal-’s picture

Works perfectly.

  1. Install patch
  2. Remove default error settings in: admin/config/system/site-information
  3. Create a page--404.html.twig (and/or 401, 403)
  4. Clear cache
Ruslan Piskarov’s picture

Hello @IRONFELIX.
Just try the following code together with page--404.html.twig:

/**
 * Implements hook_theme_suggestions_page_alter() to set 40x template suggestions.
 *
 * @param array $suggestions
 * @param array $variables
 */
function mytheme_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));
  $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[] = $http_error_suggestions[$route_name];
  }
}
kovtunos’s picture

#22 Works for me. Tested on several sites (Drupal 8.3.5).

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

pingwin4eg’s picture

Status: Needs review » Reviewed & tested by the community

Patch from #2363987-11: Add theme support for content of 401/403/404 responses works perfectly already on 2 client's projects. Both - Drupal 8.4.x.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record

We still need tests and a change record.

pawel_r’s picture

I had to slightly change #22 answer to use another hook (hook_theme_suggestions_HOOK_alter):

function MYTHEME_theme_suggestions_page_alter(array &$suggestions, array $variables){
  $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));

  $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[] = $http_error_suggestions[$route_name];
  }
  
  return $suggestions;
}
acrosman’s picture

Issue tags: -Needs change record

Added a draft change record: https://www.drupal.org/node/2960810

kovtunos’s picture

$path_args variable is never used in #28. Here's updated code:

function MYTHEME_theme_suggestions_page_alter(array &$suggestions, array $variables){
  $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[] = $http_error_suggestions[$route_name];
  }
  
  return $suggestions;
}
karenann’s picture

For those of us that want to keep the config items as an option, what do you all think of this as an option?

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MYTHEME_theme_suggestions_page_alter(array &$suggestions, array $variables){

  // Define what we are handling.
  $http_error_suggestions = [
    '401' => 'page__4xx',
    '403' => 'page__4xx',
    '404' => 'page__4xx',
    'system.401' => 'page__4xx',
    'system.403' => 'page__4xx',
    'system.404' => 'page__4xx',
  ];

  // Determine if we have defined config vars.
  $site_403 = \Drupal::config('system.site')->get('page.403');
  $site_404 = \Drupal::config('system.site')->get('page.404');

  // If we do not have config vars, we can use route names.
  // Returns value "entity.node.canonical" when config vars are set.
  if (empty($site_403) && empty($site_404)) {
    $route_name = \Drupal::routeMatch()->getRouteName();
    if (isset($http_error_suggestions[$route_name])) {
      $suggestions[] = $http_error_suggestions[$route_name];
    }
  }
  else {
    $status = \Drupal::requestStack()->getCurrentRequest()->attributes->get('exception');
    if ($status) {
      $code = $status->getStatusCode();
      if (in_array($code, [401, 403, 404])) {
        $suggestions[] = $http_error_suggestions[$code];
      }
    }
  }

  return $suggestions;
}

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

sankarprakash’s picture

#17 - gives me a solution

Anonymous’s picture

Got a working solution with #30

Thanks for that!

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mr.baileys’s picture

andypost’s picture

+++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -193,6 +194,42 @@ public function testThemeSuggestions() {
+    $this->container->set('path.current', $path_current->reveal());
...
+    $suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_page', [[]]);

instead of $this->container better \Drupal::getContainer()

The last submitted patch, 36: 2363987-36-40x-theme-suggestion-test-only.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 36: 2363987-36-40x-theme-suggestion.patch, failed testing. View results

mr.baileys’s picture

Status: Needs work » Needs review
FileSize
1.52 KB
3.04 KB

Thanks @andypost, updated the test. Not sure why the test in #36 is failing, but seems unrelated to this change.

pandaski’s picture

Better using

$route_name = \Drupal::routeMatch()->getRouteName();

instead of

$route_name = Drupal::routeMatch()->getRouteName();

Also, another theme suggestion for `system.4xx` could be helpful as well.

mr.baileys’s picture

Updated the patch, taking into account the feedback from #41.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

Now ready!

pandaski’s picture

RTBC +1

lauriii’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -193,6 +194,43 @@ public function testThemeSuggestions() {
+    $this->assertContains($suggestion, $suggestions);
+    $this->assertContains('page__4xx', $suggestions);

Could we add an assertion for the order of the suggestions as well? It would be good to ensure that the specific error codes override the generic one.

pandaski’s picture

Check the suggestions

    $this->assertSame([
      'page__node',
      'page__node__%',
      'page__node__123',
      'page__4xx',
      $suggestion,
    ], $suggestions, 'Found expected suggestions for 401, 403 and 404 responses.');
pandaski’s picture

Status: Needs work » Needs review
Krzysztof Domański’s picture

Status: Needs review » Needs work

1. Description for the @return value is missing.

/**
 * Data provider for test40xThemeSuggestions().
 *
 * @return array
 */
 public function provider40xThemeSuggestions() {

2. Two spaces.

diff --git a/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -212,7 +212,7 @@ public function provider40xThemeSuggestions() {
    * @dataProvider provider40xThemeSuggestions
    */
   public function test40xThemeSuggestions($route, $suggestion) {
-    /** @var  Drupal\Core\Path\PathMatcherInterface $path_matcher */
+    /** @var Drupal\Core\Path\PathMatcherInterface $path_matcher */
pandaski’s picture

Status: Needs work » Needs review
FileSize
3.29 KB
960 bytes

reroll the patch with the comment from #49

Anonymous’s picture

Status: Needs review » Reviewed & tested by the community
catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -192,6 +193,49 @@ public function testThemeSuggestions() {
+    ], $suggestions, 'Found expected suggestions for 401, 403 and 404 responses.');

This is using a data provider, so only one code is getting tested per method run. We could use a variable in the assertion message maybe? Or just remove the assertion message.

andypost’s picture

pandaski’s picture

Status: Needs work » Needs review
FileSize
3.27 KB
729 bytes

Thanks @catch

Attached patch contains the following changes:

  • modify the assertion message to a generic message
Anonymous’s picture

Status: Needs review » Reviewed & tested by the community
larowlan’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -192,6 +193,49 @@ public function testThemeSuggestions() {
+    ], $suggestions, 'Found expected suggestions for 40x responses.');

I think what @catch was asking here was for it to say "Found expected suggestions for $route" so it was more explicit

Other than that, this looks good to go

larowlan’s picture

+++ b/core/tests/Drupal/KernelTests/Core/Theme/RegistryTest.php
@@ -192,6 +193,49 @@ public function testThemeSuggestions() {
+    ], $suggestions, 'Found expected suggestions for 40x responses.');

Actually, on second thoughts, lets just remove the message altogether.

The default provided by phpunit for arrays is far superior to anything we can come up with here.

larowlan’s picture

Feel free to put it back to RTBC if the patch comes back green with that change

Krzysztof Domański’s picture

Title: Add theme page__403 page__404 for theming content of 403 and 404 responses » Add theme support for content of 401/403/404 responses
Status: Needs work » Reviewed & tested by the community
FileSize
3.21 KB
547 bytes

Changes according to #57.

larowlan’s picture

larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed ad5a6a6 and pushed to 8.8.x. Thanks!

Published change record

  • larowlan committed ad5a6a6 on 8.8.x
    Issue #2363987 by Joseph Zhao, mr.baileys, Krzysztof Domański, acrosman...
Wim Leers’s picture

Oh, wow! I'd swear this was done years ago, but clearly I was wrong!

andypost’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

OCTOGONE.dev’s picture

#22 Works for me.