Updated: Comment #N
Problem/Motivation
In D7 you had access to $variables['theme_hook_suggestions']
in preprocess functions. This was good because you could see the available theme hook suggestions, but you could also change the current suggestion at any point during the preprocess stage by altering this variable and/or $variables['theme_hook_suggestion']
. This ability to change the theme hook suggestions via preprocess made it so that checking the value of these variables in a preprocess function could not be relied on if you wanted to perform specific alterations for a certain theme hook suggestion or set of theme hook suggestions.
In Drupal 8 we've removed 'theme_hook_suggestions' and 'theme_hook_suggestion' from preprocess. Altering the theme hook suggestions happens in the theme suggestion stage before any preprocess hooks are invoked - see #1751194: Introduce hook_theme_suggestions[_HOOK]() and hook_theme_suggestions[_HOOK]_alter() and its change record.
We still want to find a way to solve the use case brought up in #939462: Specific preprocess functions for theme hook suggestions are not invoked and pave the way for template consolidation (#1804614: [meta] Consolidate theme functions and properly use theme suggestions in core).
Proposed resolution
Heavily inspired by @effulgentsia's post at #939462-6: Specific preprocess functions for theme hook suggestions are not invoked
Pass the complete array of theme hook suggestions to preprocess functions so that variable preprocessing can be done conditionally based on theme suggestions. Also, when an array of hooks is given, treat them as suggestions and pass them through accordingly in _theme().
Now that suggestions are immutable during the preprocess stage, we can check the second parameter passed to preprocess functions, $hook, to see which template is being used. What preprocess is missing is the complete array of theme hook suggestions to cover more use cases.
My suggestion at this time is to add this array to the $info array (the third parameter that is passed to preprocess functions). To my knowledge $info is currently made up of information coming from the theme registry and we would be adding non-theme registry data to this array, but I find this preferable to adding a fourth parameter to preprocess functions for this use case and it maintains backwards compatibility by not changing the function signature of preprocess.
See #1885714-16: Remove theme_install_page() for a basic proof of concept of how this could work, or read on for a more detailed explanation.
Preprocess functions can examine the theme hook suggestion data and have complete flexibility as to how they want to act. When working with theme suggestions these are the 2 most prominent ways that this data would likely be used (note that either of these can be used by both modules and themes):
1. Logic based on a suggestion actually being used (e.g. node--article.html.twig template exists in the currently active theme).
<?php
function MYTHEME_preprocess_node(&$variables, $hook) {
if ($hook == 'node__article') {
$variables['article_template'] = TRUE;
}
}
?>
2. Logic based on a suggestion simply being in the list of $suggestions, whether or not node--article.html.twig exists within the theme or not.
<?php
function MYTHEME_preprocess_node(&$variables, $hook, $info) {
// We would add ‘theme suggestions’ to the $info array in theme().
if (in_array('node__article', $info['suggestions'])) {
$variables['article_suggestion'] = TRUE;
}
}
?>
If there is a large amount of preprocessing needed for a certain theme suggestion, that logic can always be moved out into a "helper" function and this function can even be named after the theme hook suggestion but it will not be invoked automatically. For example:
<?php
function MYTHEME_preprocess_node(&$variables, $hook, $info) {
// We would add ‘theme suggestions’ to the $info array in theme().
if (in_array('node__article', $info['suggestions'])) {
MYTHEME_preprocess_node__article($variables);
}
}
function MYTHEME_preprocess_node__article(&$variables) {
...
}
?>
Remaining tasks
- Write patch
- Write tests
- Review patch
User interface changes
n/a
API changes
An API addition of being able to access the full suggestion data in preprocess functions.