ppf-1.2.x-dev/src/PreprocessorFiles.php

src/PreprocessorFiles.php
<?php

namespace Drupal\ppf;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ThemeExtensionList;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Theme\ThemeManagerInterface;
use Symfony\Component\Finder\Finder;

/**
 * Provides a service for Preprocessor Files.
 */
final class PreprocessorFiles {
  use StringTranslationTrait;

  /**
   * Stores the name of the directory where preprocessor files are stored.
   *
   * @var string
   */
  public const PREPROCESSOR_FILES_DIRECTORY = 'preprocessors';

  /**
   * The ID of the main configuration for the module.
   *
   * @var string
   */
  public const CONFIG_ID = 'ppf.settings';

  /**
   * ID of the 'Preprocessor Files Extension' configuration.
   *
   * Allows specification of the directory to load preprocessor files from.
   *
   * e.g. By default, it searches for '*.preprocess.php' files.
   *
   * @var string
   */
  public const CONFIG__PREPROCESSOR_FILES_EXTENSION = 'preprocessor_files_extension';

  /**
   * Stores default value of the 'Preprocessor Files Extension' configuration.
   *
   * @var string
   */
  public const CONFIG__PREPROCESSOR_FILES_EXTENSION__DEFAULT = '.preprocess.php';

  /**
   * Use DI to inject Drupal's configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  public ConfigFactoryInterface $configFactory;

  /**
   * Drupal's Module Handler injected through DI.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  public ModuleHandlerInterface $moduleHandler;

  /**
   * Drupal's Theme Manager injected through DI.
   *
   * @var \Drupal\Core\Theme\ThemeManagerInterface
   */
  public ThemeManagerInterface $themeManager;

  /**
   * Drupal's Theme Extension List injected through DI.
   *
   * @var \Drupal\Core\Extension\ThemeExtensionList
   */
  public ThemeExtensionList $themeExtensionList;

  /**
   * Constructs the PreprocessorFiles service.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   Configuration Factory service injected through DI.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
   *   Module Handler service injected through DI.
   * @param \Drupal\Core\Theme\ThemeManagerInterface $themeManager
   *   Theme Manager service injected through DI.
   * @param \Drupal\Core\Extension\ThemeExtensionList $themeExtensionList
   *   Theme Extension List service injected through DI.
   */
  public function __construct(
    ConfigFactoryInterface $configFactory,
    ModuleHandlerInterface $moduleHandler,
    ThemeManagerInterface $themeManager,
    ThemeExtensionList $themeExtensionList,
  ) {
    $this->configFactory = $configFactory;
    $this->moduleHandler = $moduleHandler;
    $this->themeManager = $themeManager;
    $this->themeExtensionList = $themeExtensionList;
  }

  /**
   * Shortcut to obtain the PreprocessorFiles service from the global container.
   *
   * @return \Drupal\ppf\PreprocessorFiles
   *   The PreprocessorFiles service.
   */
  public static function service() : PreprocessorFiles {
    static $service;
    if (!empty($service)) {
      return $service;
    }
    $service = \Drupal::service('ppf');
    return $service;
  }

  /**
   * Get main configuration for the Preprocessor Files module.
   *
   * @return \Drupal\Core\Config\ImmutableConfig
   *   The immutable configuration object.
   */
  public function config() : ImmutableConfig {
    static $config = NULL;
    if (!empty($config)) {
      return $config;
    }
    $config = $this->configFactory->get(self::CONFIG_ID);
    return $config;
  }

  /**
   * Get the directory to search for preprocessor files in.
   *
   * @param string|null $theme
   *   Theme to obtain the directory path for.
   *
   * @return string
   *   Returns the path to the configured directory in the current active theme.
   */
  public function getPreprocessorFilesDirectoryForTheme(string|null $theme) : string {
    static $directory = [];
    if ($theme === NULL) {
      $theme = $this->themeManager->getActiveTheme()->getName();
    }
    if (!empty($directory[$theme])) {
      return $directory[$theme];
    }
    $themePath = $this->themeExtensionList->getPath($theme);
    $directory[$theme] = $themePath . '/' . self::PREPROCESSOR_FILES_DIRECTORY;
    return $directory[$theme];
  }

  /**
   * Get the configured preprocessor files extension.
   *
   * @return string
   *   Returns the file extension that is configured.
   */
  public function getPreprocessorFilesExtension() : string {
    static $extension;
    if ($extension !== NULL) {
      return $extension;
    }
    $extension = $this->config()->get(self::CONFIG__PREPROCESSOR_FILES_EXTENSION) ?? self::CONFIG__PREPROCESSOR_FILES_EXTENSION__DEFAULT;
    return $extension;
  }

  /**
   * Check if preprocessor files exist in the currently active theme.
   *
   * @param string|null $theme
   *   Theme to check for.
   *
   * @return bool
   *   Returns TRUE if files exists. Returns FALSE otherwise.
   */
  public function preprocessorFilesDirectoryExistsInTheme(string|null $theme = NULL) : bool {
    static $exists = [];
    if ($theme === NULL) {
      $theme = $this->themeManager->getActiveTheme()->getName();
    }
    if (!empty($exists[$theme])) {
      return $exists[$theme];
    }
    $directory = self::getPreprocessorFilesDirectoryForTheme($theme);
    $exists[$theme] = file_exists($directory);
    return $exists[$theme];
  }

  /**
   * Get preprocessor files for a given theme.
   *
   * Will get files for the active theme if no theme is provided.
   *
   * @param string|null $theme
   *   Theme to obtain preprocessor files for.
   *
   * @return array
   *   Array of file paths.
   */
  public static function getPreprocessorFilesForTheme(string|null $theme = NULL) : array {
    // Store files in a static variable. Only fetch them once.
    static $files = [];

    // Get active theme if theme is null.
    if ($theme === NULL) {
      $theme = self::service()->themeManager->getActiveTheme()->getName();
    }

    // If files are set, get them.
    if (isset($files[$theme])) {
      return $files[$theme];
    }

    // If the directory doesn't exist for the theme, we stop here.
    if (!self::service()->preprocessorFilesDirectoryExistsInTheme($theme)) {
      $files[$theme] = [];
      return $files[$theme];
    }

    // Get base theme files if this is the active theme.
    if ($theme === self::service()->themeManager->getActiveTheme()->getName()) {
      /** @var ThemeExtensionList $themeExtension */
      $baseThemes = array_reverse(self::service()->themeManager->getActiveTheme()->getBaseThemeExtensions());
      foreach ($baseThemes as $baseThemeName => $extension) {
        $files[$theme] = array_merge_recursive($files[$theme] ?? [], self::getPreprocessorFilesForTheme($baseThemeName));
      }
    }

    // Get the directory and load files for it.
    $directory = self::service()->getPreprocessorFilesDirectoryForTheme($theme);
    $files[$theme] = array_merge_recursive($files[$theme] ?? [], self::getPreprocessorFiles($directory));

    return $files[$theme];
  }

  /**
   * Get preprocessor files for active modules.
   *
   * @return array
   *   Array of file paths.
   */
  public static function getPreprocessorFilesForActiveModules() : array {
    static $files = [];
    if (!empty($files)) {
      return $files;
    }

    $moduleList = self::service()->moduleHandler->getModuleList();
    foreach ($moduleList as $module) {
      $moduleDirectory = $module->getPath();
      $files = array_merge_recursive($files, self::getPreprocessorFiles($moduleDirectory));
    }

    return $files;
  }

  /**
   * Get array of preprocessor files from a given directory.
   *
   * @param string $directory
   *   The directory to search in.
   *
   * @return array
   *   Array of files that were found.
   */
  private static function getPreprocessorFiles(string $directory) : array {
    static $files;
    if (isset($files[$directory])) {
      return $files[$directory];
    }

    // Get file extension.
    $extension = self::service()->getPreprocessorFilesExtension();

    // Initialize a Symfony Finder component to aid us here. Very handy!
    // We try to load all preprocessor files here.
    $finder = new Finder();
    $finder->in($directory);
    $finder->name("*$extension");
    $finder->files();

    // If we have no results, we can stop here.
    if (!$finder->hasResults()) {
      return [];
    }

    // We do a quick first loop to simply get all found files and set hooks.
    foreach ($finder as $file) {
      $files[$directory][str_replace('-', '_', explode(".", $file->getFilename())[0])][] = $file->getPathname();
    }

    // Sort our hooks.
    // This is a way to make sure base hooks execute before subhooks.
    uksort($files[$directory], function ($a, $b) {
      return strcmp($a, $b);
    });

    return $files[$directory];
  }

}

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

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