diff --git a/core/lib/Drupal/Core/Theme/ThemeManager.php b/core/lib/Drupal/Core/Theme/ThemeManager.php index 1a0b908..9f541db 100644 --- a/core/lib/Drupal/Core/Theme/ThemeManager.php +++ b/core/lib/Drupal/Core/Theme/ThemeManager.php @@ -153,22 +153,12 @@ protected function theme($hook, $variables = array()) { $theme_registry = $this->themeRegistry->getRuntime(); $theme_hooks = (array) $hook; - $hook_pattern = array_pop($theme_hooks); - $derived_hooks = array(); - - // Add all variants for directly called suggestions like - // '#theme' => 'comment__node__article'. - while ($pos = strrpos($hook_pattern, '__')) { - $derived_hooks[] = $hook_pattern; - $hook_pattern = substr($hook_pattern, 0, $pos); - } - $theme_hooks = array_merge($theme_hooks, array_reverse($derived_hooks)); - + $hook_found = FALSE; // If an array of hook candidates were passed, use the first one that has an // implementation. if (is_array($hook)) { foreach ($hook as $candidate) { - if ($theme_registry->has($candidate)) { + if ($hook_found = $theme_registry->has($candidate)) { break; } } @@ -178,32 +168,33 @@ protected function theme($hook, $variables = array()) { // preprocess callbacks. $original_hook = $hook; - // If there's no implementation, check for more generic fallbacks. + // Get all the more generic fallbacks and check for them if there's no + // implementation yet. // If there's still no implementation, log an error and return an empty // string. - if (!$theme_registry->has($hook)) { - // Iteratively strip everything after the last '__' delimiter, until an - // implementation is found. - while ($pos = strrpos($hook, '__')) { - $hook = substr($hook, 0, $pos); - if ($theme_registry->has($hook)) { - break; - } + $hook_pattern = array_pop($theme_hooks); + $derived_hooks = []; + while ($pos = strrpos($hook_pattern, '__')) { + $derived_hooks[] = $hook_pattern; + $hook_pattern = substr($hook_pattern, 0, $pos); + if (!$hook_found && $hook_found = $theme_registry->has($hook_pattern)) { + $hook = $hook_pattern; } - if (!$theme_registry->has($hook)) { - // Only log a message when not trying theme suggestions ($hook being an - // array). - if (!isset($candidate)) { - \Drupal::logger('theme')->warning('Theme hook %hook not found.', array('%hook' => $hook)); - } - // There is no theme implementation for the hook passed. Return FALSE so - // the function calling _theme() can differentiate between a hook that - // exists and renders an empty string and a hook that is not - // implemented. - return FALSE; + } + if (!$theme_registry->has($hook)) { + // Only log a message when not trying theme suggestions ($hook being an + // array). + if (!isset($candidate)) { + \Drupal::logger('theme')->warning('Theme hook %hook not found.', array('%hook' => $hook)); } + // There is no theme implementation for the hook passed. Return FALSE so + // the function calling _theme() can differentiate between a hook that + // exists and renders an empty string and a hook that is not + // implemented. + return FALSE; } + $theme_hooks = array_merge($theme_hooks, $derived_hooks); $info = $theme_registry->get($hook); // If a renderable array is passed as $variables, then set $variables to @@ -253,7 +244,7 @@ protected function theme($hook, $variables = array()) { // If _theme() was invoked with a direct theme suggestion like // '#theme' => 'node__article', add it to the suggestions array before // invoking suggestion alter hooks. - $suggestions = array_merge($suggestions, $theme_hooks); + $suggestions = array_merge($suggestions, array_reverse($theme_hooks)); // Invoke hook_theme_suggestions_alter() and // hook_theme_suggestions_HOOK_alter(). diff --git a/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php b/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php index 777dffa..cd2e2fd 100644 --- a/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php +++ b/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php @@ -99,7 +99,7 @@ public function testArraySuggestionsTwigDebugMarkup() { $this->drupalGet('theme-test/array-suggestions'); $this->assertTrue(strpos($this->getRawContent(), "THEME HOOK: 'theme_test_array_suggestions'") !== FALSE, 'Theme call information found.'); - $this->assertTrue(strpos($this->getRawContent(), '') !== FALSE, 'Suggested template files found in order and correct suggestion shown as current template.'); + $this->assertTrue(strpos($this->getRawContent(), '') !== FALSE, 'Suggested template files found in order and correct suggestion shown as current template.'); } /** diff --git a/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php b/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php index aacdfbd..191102d 100644 --- a/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php +++ b/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php @@ -143,7 +143,12 @@ function suggestionAlterInclude() { * Menu callback for testing suggestion hooks with an array of theme hooks. */ public function arraySuggestions() { - return array('#theme' => array('theme_test_array_suggestions__not_implemented', 'theme_test_array_suggestions')); + return array( + '#theme' => array( + 'theme_test_array_suggestions__not_implemented', + 'theme_test_array_suggestions__not_implemented_2', + 'theme_test_array_suggestions'), + ); } /**