Issue #3343198 by andy-blum, murilohp, smustgrave, safetypin: Improve documentation of hook_theme_suggestions_HOOK_alter()

merge-requests/3262/merge
Lauri Eskola 2023-03-03 10:20:46 +02:00
parent 22a39eb4bd
commit 0ac4b76303
No known key found for this signature in database
GPG Key ID: 382FC0F5B0DF53F8
4 changed files with 45 additions and 2 deletions

View File

@ -645,6 +645,8 @@ function hook_theme_suggestions_HOOK(array $variables) {
* hook_theme_suggestions_HOOK_alter(). So, for each module or theme, the more
* general hooks are called first followed by the more specific.
*
* New suggestions must begin with the value of HOOK, followed by two underscores to be discoverable.
*
* In the following example, we provide an alternative template suggestion to
* node and taxonomy term templates based on the user being logged in.
* @code
@ -690,11 +692,27 @@ function hook_theme_suggestions_alter(array &$suggestions, array $variables, $ho
* hook called (in this case 'node__article') is available in
* $variables['theme_hook_original'].
*
* New suggestions must begin with the value of HOOK, followed by two underscores to be discoverable.
* For example, consider the below suggestions from hook_theme_suggestions_node_alter:
* - node__article is valid
* - node__article__custom_template is valid
* - node--article is invalid
* - article__custom_template is invalid
*
* Implementations of this hook must be placed in *.module or *.theme files, or
* must otherwise make sure that the hook implementation is available at
* any given time.
*
* @todo Add @code sample.
* In the following example, we provide an alternative template suggestion to
* node templates based on the user being logged in.
* @code
* function MYMODULE_theme_suggestions_node_alter(array &$suggestions, array $variables) {
* if (\Drupal::currentUser()->isAuthenticated()) {
* $suggestions[] = 'node__logged_in';
* }
* }
*
* @endcode
*
* @param array $suggestions
* An array of theme suggestions.

View File

@ -55,6 +55,7 @@ class TwigDebugMarkupTest extends BrowserTestBase {
$this->assertStringContainsString("THEME HOOK: 'node'", $output, 'Theme call information found.');
$this->assertStringContainsString('* node--1--full' . $extension . PHP_EOL . ' x node--1' . $extension . PHP_EOL . ' * node--page--full' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' * node--full' . $extension . PHP_EOL . ' * node' . $extension, $output, 'Suggested template files found in order and node ID specific template shown as current template.');
$this->assertStringContainsString(Html::escape('node--<script type="text/javascript">alert(\'yo\');</script>'), (string) $output);
$this->assertStringContainsString('<!-- INVALID FILE NAME SUGGESTIONS:' . PHP_EOL . ' See https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_theme_suggestions_alter' . PHP_EOL . ' invalid_theme_suggestions' . PHP_EOL . '-->', $output, 'Twig debug markup found invalid suggestions.');
$template_filename = $templates['node__1']['path'] . '/' . $templates['node__1']['template'] . $extension;
$this->assertStringContainsString("BEGIN OUTPUT from '$template_filename'", $output, 'Full path to current template file found.');

View File

@ -68,6 +68,15 @@ function test_theme_theme_suggestions_theme_test_suggestions_alter(array &$sugge
array_unshift($suggestions, 'theme_test_suggestions__' . 'theme_override');
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function test_theme_theme_suggestions_node_alter(array &$suggestions, array $variables) {
// Add an invalid suggestion to be tested.
$suggestions[] = 'invalid_theme_suggestions';
\Drupal::messenger()->addStatus(__FUNCTION__ . '() executed.');
}
/**
* Implements hook_theme_registry_alter().
*/

View File

@ -93,12 +93,27 @@ function twig_render_template($template_file, array $variables) {
if (strpos($variables['theme_hook_original'], '__') === FALSE) {
$suggestions[] = $variables['theme_hook_original'];
}
foreach ($suggestions as &$suggestion) {
$invalid_suggestions = [];
$base_hook = $base_hook ?? $variables['theme_hook_original'];
foreach ($suggestions as $key => &$suggestion) {
// Valid suggestions are $base_hook, $base_hook__*, and contain no hyphens.
if (($suggestion !== $base_hook && !str_starts_with($suggestion, $base_hook . '__')) || str_contains($suggestion, '-')) {
$invalid_suggestions[] = $suggestion;
unset($suggestions[$key]);
continue;
}
$template = strtr($suggestion, '_', '-') . $extension;
$prefix = ($template == $current_template) ? 'x' : '*';
$suggestion = $prefix . ' ' . $template;
}
$output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n " . Html::escape(implode("\n ", $suggestions)) . "\n-->";
if (!empty($invalid_suggestions)) {
$output['debug_info'] .= "\n<!-- INVALID FILE NAME SUGGESTIONS:";
$output['debug_info'] .= "\n See https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_theme_suggestions_alter";
$output['debug_info'] .= "\n " . Html::escape(implode("\n ", $invalid_suggestions));
$output['debug_info'] .= "\n-->";
}
}
$output['debug_info'] .= "\n<!-- BEGIN OUTPUT from '" . Html::escape($template_file) . "' -->\n";
$output['debug_suffix'] .= "\n<!-- END OUTPUT from '" . Html::escape($template_file) . "' -->\n\n";