Using magic preprocess hooks messes up template suggestions order

Created on 29 April 2020, almost 5 years ago
Updated 16 May 2023, almost 2 years ago

Problem/Motivation

If you create a magic preprocess suggestion like:

function MYMODULE_preprocess_node__event(&$variables) {}

Yet you do not have a template `node--event.html.twig`, `node__event` is still added to the registry in `Drupal\Core\Theme\Registry`, but the cached data in the build method sets it to the default 'node.html.twig'.

This becomes a problem if you then subsequently want to template a view mode in your theme, eg, `node--teaser.html.twig`. `node__teaser` is a valid suggestion with higher priority according to the comments

FILE NAME SUGGESTIONS:
   * node--1--teaser.html.twig
   * node--1.html.twig
   * node--event--teaser.html.twig
   * node--event.html.twig
   * node--teaser.html.twig
   x node.html.twig

However, `node.html.twig` will still be selected because the result of `Drupal\Core\Theme\Registry::build()` will contain a key `node__event` pointing at `node.html.twig` at a higher specificity than `node--teaser.html.twig`

Proposed resolution

Prevent automatically adding to theme registry build if no template matches the specificity of the preprocess hook.

Remaining tasks

Determine how to approach this.

User interface changes

None

API changes

None

Data model changes

None

Release notes snippet

Fix an edge case theme registry issue when using magic template preprocess suggestions

🐛 Bug report
Status

Closed: works as designed

Version

9.5

Component
Theme 

Last updated about 4 hours ago

Created by

🇬🇧United Kingdom scott_euser

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

Comments & Activities

Not all content is available!

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

  • 🇺🇸United States Amber Himes Matz Portland, OR USA

    Thanks for reporting this issue. We rely on issue reports like this one to resolve bugs and improve Drupal core. This issue is being triaged as part of the Bug Smash Initiative.

    I don’t think you’re “magically” creating a new template suggestion by implementing function MYMODULE_preprocess_node__event(&$variables) {}. You’re implementing a hook that is covered by the core node module, which provides default template suggestions, including dynamic ones based on the machine name of the content type (aka “bundle”).

    See core/modules/node/node.module (“bundle” is the machine name of the content type):

    /**
     * Implements hook_theme_suggestions_HOOK().
     */
    function node_theme_suggestions_node(array $variables) {
      $suggestions = [];
      $node = $variables['elements']['#node'];
      $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
    
      $suggestions[] = 'node__' . $sanitized_view_mode;
      $suggestions[] = 'node__' . $node->bundle();
      $suggestions[] = 'node__' . $node->bundle() . '__' . $sanitized_view_mode;
      $suggestions[] = 'node__' . $node->id();
      $suggestions[] = 'node__' . $node->id() . '__' . $sanitized_view_mode;
    
      return $suggestions;
    }
    

    The way to create a new template suggestion, or to alter the suggestions provided by another module or theme, is to implement HOOK_theme_suggestions_alter() or HOOK_theme_suggestions_HOOK_alter(). You can use either of these hooks to add/remove suggestions from the list or reorder the list by making changes to the $suggestions array.

    I see a couple of problems with the original report that makes me think that maybe this is more of a misunderstanding of how the system is designed to work, rather than a bug with the system:

    1) Implementing a specific hook for a template and then not creating that template seems counterproductive.
    2) There is already a hook in Drupal’s API to reorder theme hook suggestions provided by any module or theme and that’s hook_theme_suggestions_alter() or it’s more specific counterpart, hook_theme_suggestions_HOOK_alter()

    I could be totally wrong about this, so feel free to re-open and provide more information or context.

Production build 0.71.5 2024