You are here

protected function Registry::postProcessExtension in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Theme/Registry.php \Drupal\Core\Theme\Registry::postProcessExtension()

Completes the theme registry adding discovered functions and hooks.

Parameters

array $cache: The theme registry as documented in \Drupal\Core\Theme\Registry::processExtension().

\Drupal\Core\Theme\ActiveTheme $theme: Current active theme.

See also

::processExtension()

1 call to Registry::postProcessExtension()
Registry::build in core/lib/Drupal/Core/Theme/Registry.php
Builds the theme registry cache.

File

core/lib/Drupal/Core/Theme/Registry.php, line 706

Class

Registry
Defines the theme registry service.

Namespace

Drupal\Core\Theme

Code

protected function postProcessExtension(array &$cache, ActiveTheme $theme) {

  // Gather prefixes. This will be used to limit the found functions to the
  // expected naming conventions.
  $prefixes = array_keys((array) $this->moduleHandler
    ->getModuleList());
  foreach (array_reverse($theme
    ->getBaseThemeExtensions()) as $base) {
    $prefixes[] = $base
      ->getName();
  }
  if ($theme
    ->getEngine()) {
    $prefixes[] = $theme
      ->getEngine() . '_engine';
  }
  $prefixes[] = $theme
    ->getName();
  $grouped_functions = $this
    ->getPrefixGroupedUserFunctions($prefixes);

  // Collect all variable preprocess functions in the correct order.
  $suggestion_level = [];
  $matches = [];

  // Look for functions named according to the pattern and add them if they
  // have matching hooks in the registry.
  foreach ($prefixes as $prefix) {

    // Grep only the functions which are within the prefix group.
    list($first_prefix, ) = explode('_', $prefix, 2);
    if (!isset($grouped_functions[$first_prefix])) {
      continue;
    }

    // Add the function and the name of the associated theme hook to the list
    // of preprocess functions grouped by suggestion specificity if a matching
    // base hook is found.
    foreach ($grouped_functions[$first_prefix] as $candidate) {
      if (preg_match("/^{$prefix}_preprocess_(((?:[^_]++|_(?!_))+)__.*)/", $candidate, $matches)) {
        if (isset($cache[$matches[2]])) {
          $level = substr_count($matches[1], '__');
          $suggestion_level[$level][$candidate] = $matches[1];
        }
      }
    }
  }

  // Add missing variable preprocessors. This is needed for modules that do
  // not explicitly register the hook. For example, when a theme contains a
  // variable preprocess function but it does not implement a template, it
  // will go missing. This will add the expected function. It also allows
  // modules or themes to have a variable process function based on a pattern
  // even if the hook does not exist.
  ksort($suggestion_level);
  foreach ($suggestion_level as $level => $item) {
    foreach ($item as $preprocessor => $hook) {
      if (isset($cache[$hook]['preprocess functions']) && !in_array($hook, $cache[$hook]['preprocess functions'])) {

        // Add missing preprocessor to existing hook.
        $cache[$hook]['preprocess functions'][] = $preprocessor;
      }
      elseif (!isset($cache[$hook]) && strpos($hook, '__')) {

        // Process non-existing hook and register it.
        // Look for a previously defined hook that is either a less specific
        // suggestion hook or the base hook.
        $this
          ->completeSuggestion($hook, $cache);
        $cache[$hook]['preprocess functions'][] = $preprocessor;
      }
    }
  }

  // Inherit all base hook variable preprocess functions into suggestion
  // hooks. This ensures that derivative hooks have a complete set of variable
  // preprocess functions.
  foreach ($cache as $hook => $info) {

    // The 'base hook' is only applied to derivative hooks already registered
    // from a pattern. This is typically set from
    // drupal_find_theme_functions() and drupal_find_theme_templates().
    if (isset($info['incomplete preprocess functions'])) {
      $this
        ->completeSuggestion($hook, $cache);
      unset($cache[$hook]['incomplete preprocess functions']);
    }

    // Optimize the registry.
    if (isset($cache[$hook]['preprocess functions']) && empty($cache[$hook]['preprocess functions'])) {
      unset($cache[$hook]['preprocess functions']);
    }

    // Ensure uniqueness.
    if (isset($cache[$hook]['preprocess functions'])) {
      $cache[$hook]['preprocess functions'] = array_unique($cache[$hook]['preprocess functions']);
    }
  }
}