Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme

Created on 23 October 2013, over 10 years ago
Updated 6 June 2024, 20 days ago

Updated: Comment #206

Problem/Motivation

Twig debugging output is supposed to show all template suggestions. Currently, the debug output does not show all the template suggestions that the Drupal render system knows about.

Here are a few examples where this feature fails:

  • Views (a core feature used in many places) templates do not show any template suggestions. For example, go to /admin/content and look at the Filter form at the top of the page; Twig debug shows: 'views_exposed_form', but Drupal's theme system is given this list of suggestions: ['views_exposed_form__content__page_1', 'views_exposed_form__page_1', 'views_exposed_form__default', 'views_exposed_form__content__page', 'views_exposed_form__page', 'views_exposed_form__content', 'views_exposed_form'] (defined in Drupal\views\Form\ViewsExposedForm::buildForm()).
  • Using the default Bartik theme, use Drupal's search and look at the list of search results. Twig debug shows: x item-list--search-results.html.twig, x item-list--search-results.html.twig, * item-list.html.twig, but Drupal's theme system is given this list of suggestions: ['item_list__search_results__node_search', 'item_list__search_results'] (defined in Drupal\search\Controller\SearchController::view()).

The underlying cause of this issue is when #theme is set as an array of suggestions. The twig_debug output only works* when #theme is a string or when suggestions are added via suggestions_alter hooks.

* where "works" is defined as super buggy output, showing duplicates and out-of-order suggestions. See 🐛 Incorrect order and duplicate theme hook suggestions Needs work

When #theme is set as an array of suggestions, Drupal\Core\Theme\ThemeManager::render() will call the theme suggestions alter hooks with the base hook and will conditionally add an entry from the #theme array if that entry is actually implemented in the system. If none of #theme array suggestion entries are implemented, only the base hook is sent to the theme suggestions alter hooks and the code handling the twig debug comments code.

Here's a specific example of what Drupal core does now:

  1. #theme is set to ['item_list__search_results__node_search', 'item_list__search_results'] in Drupal\search\Controller\SearchController::view()
  2. Drupal\Core\Theme\ThemeManager::render() will look for implementations of the theme suggestions in the #theme entry.
    • If the only implemented Twig template is item-list.html.twig (like in the Stable themes), the theme suggestion alter hooks will be passed this list of suggestions: item_list, [list of suggestions from hook_theme_suggestions_item_list() (if this function existed)]
    • If the item-list--search-results.html.twig Twig template is implemented (like most core themes), the theme suggestion alter hooks will be passed this list of suggestions: item_list, [list of suggestions from hook_theme_suggestions_item_list()], item_list__search_results
  3. The twig_render_template() generates the Twig debugging comments by looking at the list of theme suggestions returned by the theme suggestion alter hooks (passed in $variables['theme_hook_suggestions']). But it doesn't know about the item_list__search_results__node_search suggestion in Step 1, so the list is wrong.

Proposed resolution

Theoretically, we could fix this by #2923506: Deprecate and discourage use of the "array of theme hooks" feature , but that is a loooong road of deprecations that is completely stalled. And since the "array of theme hooks" feature has been in core since 6.x and has been used frequently in contrib and in core 9.1.x and earlier, we need to fix the bug now.

OMG. No. This is technically possible, but a "proper list of theme suggestions" requires super ugly code if we're not going to modify existing lines of code. See comment #204 for proof in the form of a patch that implements this option.

Instead of conditionally appending suggestions from #theme on to the end of the suggestions from 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.

Extending the example above, no matter what item_list Twig templates are implemented, the theme suggestion alter hooks will be passed this list of suggestions: item_list, [list of suggestions from hook_theme_suggestions_item_list()], item_list__search_results, item_list__search_results__node_search

This will make it easy to output an accurate suggestion list in twig debugging comments.

We will need to add extensive tests to make sure we aren't breaking anything.

This solution also fixes 🐛 Incorrect order and duplicate theme hook suggestions Needs work .

Remaining tasks

  1. Final polishing and reviews
  2. Commit

User interface changes

Twig debug output will display all templates suggestions, no matter the source of those suggestions.

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.

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Theme 

Last updated 44 minutes ago

Created by

🇨🇦Canada Cottser

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024