Verified Commit d21fd5d2 authored by Dave Long's avatar Dave Long
Browse files

Issue #2953921 by andypost, donquixote, borisson_, effulgentsia: Refactor out...

Issue #2953921 by andypost, donquixote, borisson_, effulgentsia: Refactor out theme hook suggestion building from ThemeManager::render() into a separate function
parent 61edc1b1
Loading
Loading
Loading
Loading
+48 −28
Original line number Diff line number Diff line
@@ -214,34 +214,7 @@ public function render($hook, array $variables) {
      'theme_hook_original' => $original_hook,
    ];

    // Set base hook for later use. For example if '#theme' => 'node__article'
    // is called, we run hook_theme_suggestions_node_alter() rather than
    // hook_theme_suggestions_node__article_alter(), and also pass in the base
    // hook as the last parameter to the suggestions alter hooks.
    if (isset($info['base hook'])) {
      $base_theme_hook = $info['base hook'];
    }
    else {
      $base_theme_hook = $hook;
    }

    // Invoke hook_theme_suggestions_HOOK().
    $suggestions = $this->moduleHandler->invokeAll('theme_suggestions_' . $base_theme_hook, [$variables]);
    // If the theme implementation was invoked with a direct theme suggestion
    // like '#theme' => 'node__article', add it to the suggestions array before
    // invoking suggestion alter hooks.
    if (isset($info['base hook'])) {
      $suggestions[] = $hook;
    }

    // Invoke hook_theme_suggestions_alter() and
    // hook_theme_suggestions_HOOK_alter().
    $hooks = [
      'theme_suggestions',
      'theme_suggestions_' . $base_theme_hook,
    ];
    $this->moduleHandler->alter($hooks, $suggestions, $variables, $base_theme_hook);
    $this->alter($hooks, $suggestions, $variables, $base_theme_hook);
    $suggestions = $this->buildThemeHookSuggestions($hook, $info['base hook'] ?? '', $variables);

    // Check if each suggestion exists in the theme registry, and if so,
    // use it instead of the base hook. For example, a function may use
@@ -373,6 +346,53 @@ public function render($hook, array $variables) {
    return ($output instanceof MarkupInterface) ? $output : (string) $output;
  }

  /**
   * Builds theme hook suggestions for a theme hook with variables.
   *
   * @param string $hook
   *   Theme hook that was called.
   * @param string $info_base_hook
   *   Theme registry info for $hook['base hook'] key or empty string.
   * @param array $variables
   *   Theme variables that were passed along with the call.
   *
   * @return string[]
   *   Suggested theme hook names to use instead of $hook, in the order of
   *   ascending specificity.
   *   The caller will pick the last of those suggestions that has a known theme
   *   registry entry.
   *
   * @internal
   *   This method may change at any time. It is not for use outside this class.
   */
  protected function buildThemeHookSuggestions(string $hook, string $info_base_hook, array $variables): array {
    // Set base hook for later use. For example if '#theme' => 'node__article'
    // is called, we run hook_theme_suggestions_node_alter() rather than
    // hook_theme_suggestions_node__article_alter(), and also pass in the base
    // hook as the last parameter to the suggestions alter hooks.
    $base_theme_hook = $info_base_hook ?: $hook;

    // Invoke hook_theme_suggestions_HOOK().
    $suggestions = $this->moduleHandler->invokeAll('theme_suggestions_' . $base_theme_hook, [$variables]);
    // If the theme implementation was invoked with a direct theme suggestion
    // like '#theme' => 'node__article', add it to the suggestions array before
    // invoking suggestion alter hooks.
    if ($info_base_hook) {
      $suggestions[] = $hook;
    }

    // Invoke hook_theme_suggestions_alter() and
    // hook_theme_suggestions_HOOK_alter().
    $hooks = [
      'theme_suggestions',
      'theme_suggestions_' . $base_theme_hook,
    ];
    $this->moduleHandler->alter($hooks, $suggestions, $variables, $base_theme_hook);
    $this->alter($hooks, $suggestions, $variables, $base_theme_hook);

    return $suggestions;
  }

  /**
   * Initializes the active theme for a given route match.
   *