This change helps fix critical issues with Drupal themeing by defining and determining theme suggestions before running preprocess functions.
Whereas modules and themes previously altered $variables['theme_hook_suggestion']
and $variables['theme_hook_suggestions']
in preprocess functions to introduce theme suggestions, modules and themes now define and alter theme suggestions in their own dedicated hooks.
API changes:
Removed the ability to change template suggestions in preprocess functions by altering $variables['theme_hook_suggestion']
and $variables['theme_hook_suggestions']
.
New hooks introduced:
hook_theme_suggestions_HOOK(array $variables)
hook_theme_suggestions_alter(array &$suggestions, array $variables, $hook)
hook_theme_suggestions_HOOK_alter(array &$suggestions, array $variables)
Code that altered suggestions in preprocess needs to be moved to suggestion hooks.
Examples:
From the module that is providing the theme hook (implementing hook_theme()
):
Suggestions code is moved from template_preprocess_HOOK()
to hook_theme_suggestions_HOOK()
.
Before:
/**
* Prepares variables for search results templates.
*/
function template_preprocess_search_results(&$variables) {
$variables['theme_hook_suggestions'][] = 'search_results__' . $variables['plugin_id'];
}
After:
/**
* Implements hook_theme_suggestions_HOOK().
*/
function search_theme_suggestions_search_results(array $variables) {
return array('search_results__' . $variables['plugin_id']);
}
Any other module or theme:
Suggestions code is moved from HOOK_preprocess_HOOK()
to manipulating the suggestions array in hook_theme_suggestions_HOOK_alter()
.
Before:
/**
* Implements hook_preprocess_HOOK() for node templates.
*/
function MYTHEME_preprocess_node(&$variables) {
$variables['theme_hook_suggestions'][] = 'node__' . 'my_first_suggestion';
$variables['theme_hook_suggestions'][] = 'node__' . 'my_second_suggestion';
}
After:
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) {
$suggestions[] = 'node__' . 'my_first_suggestion';
$suggestions[] = 'node__' . 'my_second_suggestion';
}
Altering $variables['theme_hook_suggestion']
(singular) is now just a matter of adding the suggestion to the end of the suggestions array in hook_theme_suggestions_HOOK_alter(). If you need to ensure that your suggestion is at the end, implement hook_module_implements_alter().
Before:
/**
* Implements hook_preprocess_HOOK() for node templates.
*/
function MYTHEME_preprocess_node(&$variables) {
$variables['theme_hook_suggestion'] = 'node__' . 'my_suggestion';
}
After:
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) {
$suggestions[] = 'node__' . 'my_suggestion';
}
Generic alter hook (to alter/add suggestions for multiple theme hooks):
There is also a generic suggestions alter hook that is invoked for all theme hooks.
Suggestions code is moved from HOOK_preprocess()
to manipulating the suggestions array in hook_theme_suggestions_alter()
.
Before:
/**
* Implements hook_preprocess().
*/
function MYMODULE_preprocess(&$variables, $hook) {
if (in_array($hook, array('node', 'taxonomy_term'))) {
$variables['theme_hook_suggestions'][] = $hook . '__' . 'my_first_suggestion';
$variables['theme_hook_suggestions'][] = $hook . '__' . 'my_second_suggestion';
}
}
After:
/**
* Implements hook_theme_suggestions_alter().
*/
function MYMODULE_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
if (in_array($hook, array('node', 'taxonomy_term'))) {
$suggestions[] = $hook . '__' . 'my_first_suggestion';
$suggestions[] = $hook . '__' . 'my_second_suggestion';
}
}