Problem/Motivation

Currently, the ThemeManager::render() function starts the theme suggestions process. It looks at the #theme property and builds a list of theme suggestions to see which suggestion is actually implemented in the theme registry. It then takes that one match and passes it to theme suggestions alter hooks, leaving all the other related suggestions hidden to the rest of Drupal.

Here's an example.

If #theme is set to hedhog__brown__spiney, then ThemeManager::render() will search through the following list of hooks:

  1. hedhog__brown__spiney
  2. hedhog__brown
  3. hedhog

Case 1: If neither hedhog__brown__spiney or hedhog__brown is currently implemented, then ThemeManager::render() completely ignores them. ThemeManager::render() then grabs a new list of suggestions from hook_theme_suggestions_hedhog() and that new list is passed to hook_theme_suggestions_alter() and hook_theme_suggestions_hedhog_alter(). In this case, both hedhog__brown__spiney and hedhog__brown are invisible to the rest of the system.

Case 2: If a module or theme later implements hedhog__brown then ThemeManager::render() will add the implemented suggestion to the end of the hook_theme_suggestions_hedhog() suggestion list before passing it to alter hooks. This means the hedhog__brown suggestions was actually more specific than all the suggestions in hook_theme_suggestions_hedhog(). And, so is hedhog__brown__spiney, but that suggestion is still hidden.

Steps to reproduce

Render anything with #theme suggestion more complex than a simple base hook.

Proposed resolution

Instead of conditionally appending suggestions from #theme on to the end of the hook_theme_suggestions_HOOK(), we should always append those suggestions so that hook_theme_suggestions_alter() and hook_theme_suggestions_HOOK_alter() can see them.

Remaining tasks

  • Create an MR
  • Review and try to think of a possible hook_theme_suggestions_HOOK_alter scenario where this MR would fail. (If you can find one, postpone this for 10.x.)

API changes

The theme suggestions from #theme will always be added to the end of the hook_theme_suggestions_HOOK() list of suggestions before sending them to hook_theme_suggestions_alter() and hook_theme_suggestions_HOOK_alter().

Release notes snippet

Previously, theme suggestions from #theme (like views_exposed_form__content__page) were only sometimes added to the $suggestions variable passed to hook_theme_suggestions_alter() and hook_theme_suggestions_HOOK_alter(). Now those suggestions are always passed to alter hooks.

Issue fork drupal-3187010

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

JohnAlbin created an issue. See original summary.

johnalbin’s picture

Issue summary: View changes
Status: Active » Needs review

Ok. So I'm not sure if this change is appropriate for 9.2.x or needs to wait for 10.0.x. This is a big change. It's definitely a major oversight in the API. One could argue it's a long-standing bug since 8.0.x or one could argue that it's now baked-in as "works as designed" and fixing the oversight is basically a feature request now. Also, the MR is highly tested, but it is still adding 52 and deleting 41 lines of code in a critical ThemeManager::render() function.

In regards to the actual code in the MR…

I refactored all the theme suggestions tests in #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme to account for a boatload of edge cases. So I just copied them over to this MR and tweaked them slightly since I'm not fixing either the Twig debug comment bug or #2752443: Incorrect order and duplicate theme hook suggestions which affects the test output as I originally wrote them for the other issue.

As I looked at doing the minimum amount of changes to ThemeManager::render() function, I had to create a full list of suggestions which Drupal used to break; out of before completing. When I rewrote that loop, it was clear that there were a few other loops that could be combined to make the code clearer and possibly run faster, so I went ahead and changed them.

johnalbin’s picture

Decide if this is a 10.0.x change or 9.2.x change.

Adding "Needs frontend framework manager review" tag.

FYI, this bugfix will make the code needed to fix #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme much simpler.

johnalbin’s picture

This MR now also fixes #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme at the same time. If you were to look at previous versions of the MR, you'll see that the tests were a little peculiar because they had to ignore parts of the Twig debug comment output in order for the tests to pass while #2118743 was still broken.

If you look at the MR for #2118743, you'll see the code is complicated, ugly, and ~48 lines long. But when trying to fix that issue in this issue's MR, it becomes really simple to fix. I've added comments to this MR to show the 13 lines of code added to ThemeManager.php needed to create the 2 new Twig variables and the 11 lines of code removed from twig.engine so it doesn't try to calculate theme suggestions itself. So, basically, fixing #2118743 in this issue's MR is just 2 extra lines of code.

johnalbin’s picture

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

johnalbin’s picture

Issue summary: View changes
johnalbin’s picture

Issue summary: View changes

This is a big change. It's definitely a major oversight in the API. One could argue it's a long-standing bug since 8.0.x or one could argue that it's now baked-in as "works as designed" and fixing the oversight is basically a feature request now.

I'm been thinking about this for a bit now.

So while it could be argued this change is a feature request and not a bug fix, in order to properly test this change I had to fix #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme. And, #2118743 is definitely a bug.

Also, feature requests can be implemented in 9.3.0 as long as they don't break existing APIs.

So the question of whether this should go into 9.3.0 or 10.0.0 is whether this change would break any existing hook_theme_suggestions_HOOK(), hook_theme_suggestions_alter() or hook_theme_suggestions_HOOK_alter() implementations. I'd argue it won't break any of those and I've added extensive tests to show this. To prove I'm wrong on this point, we'd need to write a test that fails with this patch, but passes without the patch.

johnalbin’s picture

Status: Needs review » Closed (duplicate)

The previous bugfix for #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme was too awful to consider to be committed. The cleanest code that fixes that issue is the code for this issue, so I'm closing this issue and moving the patch over.