preprocessors-8.x-1.0-beta8/preprocessors.module

preprocessors.module
<?php

/**
 * @file
 * Module file for the Preprocessors module.
 *
 * Allows Drupal to load preprocessor plugins. These act like an OOP alternative
 * to preprocess hooks that you would place in your .theme or .module files.
 */

use Drupal\preprocessors\Preprocessors;

/**
 * Implements hook_help().
 *
 * @noinspection PhpUnused
 */
function preprocessors_help(string $route_name) : ?string {
  switch ($route_name) {
    case 'help.page.preprocessors':
      $output = '<p><strong>' . t('Refer to the official <a href="https://git.drupalcode.org/project/preprocessors">README</a> for more detailed documentation!') . '</strong></p>';
      $output .= '<p>' . t('The Preprocessors module allows you to create dedicated plugins to preprocess template variables instead of hooks.') . '</p>';
      $output .= '<h2>' . t('Main Functionality') . '</h2>';
      $output .= '<p>' . t('This behaviour is similar to <a href="https://www.drupal.org/docs/8/theming-drupal-8/modifying-attributes-in-a-theme-file">Preprocess Functions</a>. Understanding how they work is crucial to the use of this module.') . '</p>';
      $output .= '<p>' . t('Additionally, understanding the <a href="https://www.drupal.org/docs/drupal-apis/plugin-api">Plugin API</a> is essentially to the usage of this module.') . '</p>';
      return $output;
  }

  return NULL;
}

/**
 * Implements hook_theme_registry_alter().
 */
function preprocessors_theme_registry_alter(&$theme_registry) : void {
  // Load our Preprocessor Plugins first. If there are none, we can stop here.
  $plugins = Preprocessors::service()->getPreprocessorPlugins();
  if (empty($plugins)) {
    return;
  }

  // Sort our plugins.
  // This is a way to make sure base hooks execute before subhooks.
  // Our plugins are keyed by the hook they are to act on.
  uksort($plugins, function ($a, $b) {
    return strcmp($a, $b);
  });

  // Loop in our plugins and set some parameters in the registry.
  foreach ($plugins as $hook => $collections) {
    // If the hook isn't in the registry, we try to find a base hook, so we
    // can instantiate it.
    if (!isset($theme_registry[$hook])) {
      // This aims to emulate the same functionality as preprocess functions.
      // e.g. If node--article.html.twig doesn't exist, but a
      // HOOK_preprocess_node__article() function exists, a registry entry is
      // created for the 'node__article' hook. We need to cover the case where
      // a preprocessor plugin exists, but no template or hook exists.
      $baseHookCandidate = explode("__", $hook)[0];

      // If no base hook exists, we simply stop here.
      if (!isset($theme_registry[$baseHookCandidate])) {
        continue;
      }

      // Now we know a base hook exists.
      // We simply want to copy the implementation of the base hook into a new
      // entry for our subhook.
      $theme_registry[$hook] = $theme_registry[$baseHookCandidate];

      // Adjust the data for our subhook.
      $theme_registry[$hook]['base hook'] = $baseHookCandidate;
    }

    _preprocessors_insert_hook_preprocess_function($theme_registry, $hook);

    // Entries with base hooks should inherit any preprocessor plugins.
    if (
      isset($theme_registry[$hook]['base hook'])
      && isset($theme_registry[$theme_registry[$hook]['base hook']]['preprocessors']['preprocess plugins'])
    ) {
      $theme_registry[$hook]['preprocessors']['base preprocess plugins'] = $theme_registry[$theme_registry[$hook]['base hook']]['preprocessors']['preprocess plugins'];
    }

    // Add our preprocessor plugins to the list of plugins.
    foreach ($collections['module'] ?? [] as $preprocessor) {
      $theme_registry[$hook]['preprocessors']['preprocess plugins']['module'][] = $preprocessor->getId();
    }
    foreach ($collections['theme'] ?? [] as $preprocessor) {
      $theme_registry[$hook]['preprocessors']['preprocess plugins']['theme'][] = $preprocessor->getId();
    }
  }
}

/**
 * Add custom functions to the 'preprocess functions' entry in the registry.
 *
 * @param array $theme_registry
 *   The Drupal theme registry.
 * @param string $hook
 *   The hook to add our custom function to.
 * @param bool $base
 *   Set to TRUE if processing the base hook of the hook.
 */
function _preprocessors_insert_hook_preprocess_function(array &$theme_registry, string $hook, bool $base = FALSE) : void {
  // Add our custom preprocess function to the registry entry.
  if (!$base && isset($theme_registry[$hook]['base hook']) && !in_array('_preprocessors_load_base_hook_plugins', $theme_registry[$hook]['preprocess functions'])) {
    _preprocessors_insert_hook_preprocess_function($theme_registry, $hook, TRUE);
  }

  $implementation = '_preprocessors_load_hook_plugins';
  $check = $hook;
  if ($base) {
    $implementation = '_preprocessors_load_base_hook_plugins';
    $check = $theme_registry[$hook]['base hook'];
  }

  // Add our custom preprocess function to the registry entry.
  if (!in_array($implementation, $theme_registry[$hook]['preprocess functions'])) {
    // We want our custom function to run after all other module hooks,
    // but before theme hooks.
    // We'll do some shenanigans here to accomplish this.
    $moduleList = Preprocessors::service()->getModuleList();

    // Here we want to find the last module preprocess function.
    $lastModulePreprocess = NULL;
    foreach ($moduleList as $moduleName => $extension) {
      $foundModulePreprocess = array_filter($theme_registry[$hook]['preprocess functions'], function ($entry) use ($moduleName, $check) {
        return str_starts_with($entry, $moduleName . '_preprocess') && str_ends_with($entry, 'preprocess_' . $check);
      });
      if (!empty($foundModulePreprocess)) {
        $lastModulePreprocess = end($foundModulePreprocess);
      }
    }

    // Place plugin preprocessing right before theme preprocessing.
    // Otherwise, we try something different.
    if ($lastModulePreprocess !== NULL) {
      array_splice($theme_registry[$hook]['preprocess functions'], array_search($lastModulePreprocess, $theme_registry[$hook]['preprocess functions']) + 1, 0, $implementation);
    }
    else {
      // If a module preprocess could not be located, we try to place it
      // after the traditional 'template_preprocess'.
      // We go further than that if 'template_preprocess_HOOK' exists.
      $templatePreprocessKey = array_search('template_preprocess', $theme_registry[$hook]['preprocess functions']);
      $templatePreprocessHookKey = array_search('template_preprocess_' . $hook, $theme_registry[$hook]['preprocess functions']);
      $templatePreprocessBaseHookKey = FALSE;
      if (isset($theme_registry[$hook]['base hook'])) {
        $templatePreprocessBaseHookKey = array_search('template_preprocess_' . $hook, $theme_registry[$hook]['preprocess functions']);
      }

      if ($templatePreprocessHookKey !== FALSE) {
        array_splice($theme_registry[$hook]['preprocess functions'], $templatePreprocessHookKey + 1, 0, $implementation);
      }
      elseif (isset($theme_registry[$hook]['base hook']) && $templatePreprocessBaseHookKey !== FALSE) {
        array_splice($theme_registry[$hook]['preprocess functions'], $templatePreprocessBaseHookKey + 1, 0, $implementation);
      }
      else {
        array_splice($theme_registry[$hook]['preprocess functions'], $templatePreprocessKey + 1, 0, $implementation);
      }
    }
  }
}

/**
 * Handle loading of relevant preprocessor file for a given template.
 *
 * @param array $variables
 *   The array of variables passed to the Twig template.
 * @param string $hook
 *   The theme hook.
 * @param array $info
 *   The theme info.
 */
function _preprocessors_load_hook_plugins(array &$variables, string $hook, array $info) : void {
  // Preprocess with plugins.
  Preprocessors::preprocess($info['preprocessors']['preprocess plugins'], $variables, $hook, $info);
}

/**
 * Handle loading of relevant preprocessor file for a given template.
 *
 * @param array $variables
 *   The array of variables passed to the Twig template.
 * @param string $hook
 *   The theme hook.
 * @param array $info
 *   The theme info.
 */
function _preprocessors_load_base_hook_plugins(array &$variables, string $hook, array $info) : void {
  // Preprocess with base hook plugins first.
  if (isset($info['preprocessors']['base preprocess plugins'])) {
    Preprocessors::preprocess($info['preprocessors']['base preprocess plugins'], $variables, $hook, $info);
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc