diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigDebugMarkupTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigDebugMarkupTest.php index 32a1362..7045195 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigDebugMarkupTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigDebugMarkupTest.php @@ -51,8 +51,7 @@ function testTwigDebugMarkup() { $output = _theme('node', node_view($node)); $this->assertTrue(strpos($output, '') !== FALSE, 'Twig debug markup found in theme output when debug is enabled.'); $this->assertTrue(strpos($output, "CALL: _theme('node')") !== FALSE, 'Theme call information found.'); - $this->assertTrue(strpos($output, 'x node--1' . $extension) !== FALSE, 'Node ID specific template shown as current template.'); - $this->assertTrue(strpos($output, '* node' . $extension) !== FALSE, 'Base template file found.'); + $this->assertTrue(strpos($output, 'x node--1' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' * node' . $extension) !== FALSE, 'Suggested template files found in order and node ID specific template shown as current template.'); $template_filename = $templates['node__1']['path'] . '/' . $templates['node__1']['template'] . $extension; $this->assertTrue(strpos($output, "BEGIN OUTPUT from '$template_filename'") !== FALSE, 'Full path to current template file found.'); @@ -60,8 +59,14 @@ function testTwigDebugMarkup() { // debug markup are correct. $node2 = $this->drupalCreateNode(); $output = _theme('node', node_view($node2)); - $this->assertTrue(strpos($output, '* node--2' . $extension) !== FALSE, 'Node ID specific template suggestion found.'); - $this->assertTrue(strpos($output, 'x node' . $extension) !== FALSE, 'Base template file shown as current template.'); + $this->assertTrue(strpos($output, '* node--2' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' x node' . $extension) !== FALSE, 'Suggested template files found in order and base template shown as current template.'); + + // Create another node and make sure the template suggestions shown in the + // debug markup are correct. + $node3 = $this->drupalCreateNode(); + $output = theme('node__foo__bar', node_view($node3)); + $this->assertTrue(strpos($output, "CALL: theme('node__foo__bar')") !== FALSE, 'Theme call information found.'); + $this->assertTrue(strpos($output, '* node--foo--bar' . $extension . PHP_EOL . ' * node--foo' . $extension . PHP_EOL . ' * node--3' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' x node' . $extension) !== FALSE, 'Suggested template files found in order and base template shown as current template.'); // Disable debug, rebuild the service container, and clear all caches. $this->settingsSet('twig_debug', FALSE); diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index a317124..dd8442e 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -57,11 +57,34 @@ function twig_render_template($template_file, $variables) { if (settings()->get('twig_debug', FALSE)) { $output['debug_prefix'] .= "\n\n"; $output['debug_prefix'] .= "\n"; + // If there are theme suggestions, reverse the array so more specific + // suggestions are shown first. + if (!empty($variables['theme_hook_suggestions'])) { + $variables['theme_hook_suggestions'] = array_reverse($variables['theme_hook_suggestions']); + } + // Add debug output for directly called suggestions like + // '#theme' => 'comment__node__article'. + if (strpos($variables['theme_hook_original'], '__') !== FALSE) { + $derived_suggestions[] = $hook = $variables['theme_hook_original']; + while ($pos = strrpos($hook, '__')) { + $hook = substr($hook, 0, $pos); + $derived_suggestions[] = $hook; + } + // Get the value of the base hook (last derived suggestion) and append it + // to the end of all theme suggestions. + $base_hook = array_pop($derived_suggestions); + $variables['theme_hook_suggestions'] = array_merge($derived_suggestions, $variables['theme_hook_suggestions']); + $variables['theme_hook_suggestions'][] = $base_hook; + } if (!empty($variables['theme_hook_suggestions'])) { $extension = twig_extension(); $current_template = basename($template_file); $suggestions = $variables['theme_hook_suggestions']; - $suggestions[] = $variables['theme_hook_original']; + // Only add the original theme hook if it wasn't a directly called + // suggestion. + if (strpos($variables['theme_hook_original'], '__') === FALSE) { + $suggestions[] = $variables['theme_hook_original']; + } foreach ($suggestions as &$suggestion) { $template = strtr($suggestion, '_', '-') . $extension; $prefix = ($template == $current_template) ? 'x' : '*';