class CachedModuleHandler

Class that manages enabled modules in a Drupal installation.

Hierarchy

Expanded class hierarchy of CachedModuleHandler

File

drupal/core/lib/Drupal/Core/Extension/CachedModuleHandler.php, line 16
Contains Drupal\Core\Extension\CachedModuleHandler.

Namespace

Drupal\Core\Extension
View source
class CachedModuleHandler extends ModuleHandler implements CachedModuleHandlerInterface {

  /**
   * State key/value store.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
   */
  protected $state;

  /**
   * Cache backend for storing enabled modules.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $bootstrapCache;

  /**
   * Whether the cache needs to be written.
   *
   * @var boolean
   */
  protected $cacheNeedsWriting = FALSE;

  /**
   * Constructs a new CachedModuleHandler object.
   */
  public function __construct(array $module_list = array(), KeyValueStoreInterface $state, CacheBackendInterface $bootstrap_cache) {
    parent::__construct($module_list);
    $this->state = $state;
    $this->bootstrapCache = $bootstrap_cache;
  }

  /**
   * Implements \Drupal\Core\Extension\ModuleHandlerInterface::getBootstrapModules().
   */
  public function getBootstrapModules() {
    if (isset($this->bootstrapModules)) {
      return $this->bootstrapModules;
    }
    if ($cached = $this->bootstrapCache
      ->get('bootstrap_modules')) {
      $bootstrap_list = $cached->data;
    }
    else {
      $bootstrap_list = $this->state
        ->get('system.module.bootstrap') ?: array();
      $this->bootstrapCache
        ->set('bootstrap_modules', $bootstrap_list);
    }
    $this->bootstrapModules = array_keys($bootstrap_list);
    return $this->bootstrapModules;
  }

  /**
   * Overrides \Drupal\Core\Extension\ModuleHandler::getHookInfo().
   */
  public function getHookInfo() {

    // When this function is indirectly invoked from bootstrap_invoke_all() prior
    // to all modules being loaded, we do not want to cache an incomplete
    // hook_hookInfo() result, so instead return an empty array. This requires
    // bootstrap hook implementations to reside in the .module file, which is
    // optimal for performance anyway.
    if (!$this->loaded) {
      return array();
    }
    if (!isset($this->hookInfo)) {
      if ($cache = $this->bootstrapCache
        ->get('hook_info')) {
        $this->hookInfo = $cache->data;
      }
      else {
        $this->hookInfo = parent::getHookInfo();
        $this->bootstrapCache
          ->set('hook_info', $this->hookInfo);
      }
    }
    return $this->hookInfo;
  }

  /**
   * Implements \Drupal\Core\Extension\ModuleHandlerInterface::resetImplementations().
   */
  public function resetImplementations() {

    // We maintain a persistent cache of hook implementations in addition to the
    // static cache to avoid looping through every module and every hook on each
    // request. Benchmarks show that the benefit of this caching outweighs the
    // additional database hit even when using the default database caching
    // backend and only a small number of modules are enabled. The cost of the
    // $this->bootstrapCache->get() is more or less constant and reduced further when
    // non-database caching backends are used, so there will be more significant
    // gains when a large number of modules are installed or hooks invoked, since
    // this can quickly lead to module_hook() being called several thousand times
    // per request.
    parent::resetImplementations();
    $this->bootstrapCache
      ->set('module_implements', array());
    $this->bootstrapCache
      ->delete('hook_info');
  }

  /**
   * Implements \Drupal\Core\Extension\CachedModuleHandlerInterface::writeCache().
   */
  public function writeCache() {
    if ($this->cacheNeedsWriting) {
      $this->bootstrapCache
        ->set('module_implements', $this->implementations);
      $this->cacheNeedsWriting = FALSE;
    }
  }

  /**
   * Overrides \Drupal\Core\Extension\ModuleHandler::getImplementationInfo().
   */
  protected function getImplementationInfo($hook) {
    if (!isset($this->implementations)) {
      $this->implementations = $this
        ->getCachedImplementationInfo();
    }
    if (!isset($this->implementations[$hook])) {

      // The hook is not cached, so ensure that whether or not it has
      // implementations, the cache is updated at the end of the request.
      $this->cacheNeedsWriting = TRUE;
      $this->implementations[$hook] = parent::getImplementationInfo($hook);
    }
    else {
      foreach ($this->implementations[$hook] as $module => $group) {

        // If this hook implementation is stored in a lazy-loaded file, include
        // that file first.
        if ($group) {
          $this
            ->loadInclude($module, 'inc', "{$module}.{$group}");
        }

        // It is possible that a module removed a hook implementation without the
        // implementations cache being rebuilt yet, so we check whether the
        // function exists on each request to avoid undefined function errors.
        // Since module_hook() may needlessly try to load the include file again,
        // function_exists() is used directly here.
        if (!function_exists($module . '_' . $hook)) {

          // Clear out the stale implementation from the cache and force a cache
          // refresh to forget about no longer existing hook implementations.
          unset($this->implementations[$hook][$module]);
          $this->cacheNeedsWriting = TRUE;
        }
      }
    }
    return $this->implementations[$hook];
  }

  /**
   * Retrieves hook implementation info from the cache.
   */
  protected function getCachedImplementationInfo() {
    if ($cache = $this->bootstrapCache
      ->get('module_implements')) {
      return $cache->data;
    }
    else {
      return array();
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CachedModuleHandler::$bootstrapCache protected property Cache backend for storing enabled modules.
CachedModuleHandler::$cacheNeedsWriting protected property Whether the cache needs to be written.
CachedModuleHandler::$state protected property State key/value store.
CachedModuleHandler::getBootstrapModules public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getBootstrapModules(). Overrides ModuleHandler::getBootstrapModules
CachedModuleHandler::getCachedImplementationInfo protected function Retrieves hook implementation info from the cache.
CachedModuleHandler::getHookInfo public function Overrides \Drupal\Core\Extension\ModuleHandler::getHookInfo(). Overrides ModuleHandler::getHookInfo
CachedModuleHandler::getImplementationInfo protected function Overrides \Drupal\Core\Extension\ModuleHandler::getImplementationInfo(). Overrides ModuleHandler::getImplementationInfo
CachedModuleHandler::resetImplementations public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::resetImplementations(). Overrides ModuleHandler::resetImplementations
CachedModuleHandler::writeCache public function Implements \Drupal\Core\Extension\CachedModuleHandlerInterface::writeCache(). Overrides CachedModuleHandlerInterface::writeCache
CachedModuleHandler::__construct public function Constructs a new CachedModuleHandler object. Overrides ModuleHandler::__construct
ModuleHandler::$alterFunctions protected property List of alter hook implementations keyed by hook name(s).
ModuleHandler::$bootstrapModules protected property List of enabled bootstrap modules.
ModuleHandler::$hookInfo protected property Information returned by hook_hook_info() implementations.
ModuleHandler::$implementations protected property List of hook implementations keyed by hook name.
ModuleHandler::$loaded protected property Boolean indicating whether modules have been loaded.
ModuleHandler::$loadedFiles protected property List of loaded files.
ModuleHandler::$moduleList protected property List of enabled modules.
ModuleHandler::alter public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::alter(). Overrides ModuleHandlerInterface::alter
ModuleHandler::buildModuleDependencies public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::buildModuleDependencies(). Overrides ModuleHandlerInterface::buildModuleDependencies
ModuleHandler::disable function Disables a given set of modules. Overrides ModuleHandlerInterface::disable 1
ModuleHandler::enable public function Enables or installs a given list of modules. Overrides ModuleHandlerInterface::enable 1
ModuleHandler::getImplementations public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getImplementations(). Overrides ModuleHandlerInterface::getImplementations 1
ModuleHandler::getModuleList public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getModuleList(). Overrides ModuleHandlerInterface::getModuleList
ModuleHandler::implementsHook public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::implementsHook(). Overrides ModuleHandlerInterface::implementsHook
ModuleHandler::invoke public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::invoke(). Overrides ModuleHandlerInterface::invoke
ModuleHandler::invokeAll public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::invokeAll(). Overrides ModuleHandlerInterface::invokeAll
ModuleHandler::isLoaded public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::isLoaded(). Overrides ModuleHandlerInterface::isLoaded
ModuleHandler::load public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::load(). Overrides ModuleHandlerInterface::load
ModuleHandler::loadAll public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::loadAll(). Overrides ModuleHandlerInterface::loadAll
ModuleHandler::loadAllIncludes public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::loadAllIncludes(). Overrides ModuleHandlerInterface::loadAllIncludes
ModuleHandler::loadBootstrapModules public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::loadBootstrapModules(). Overrides ModuleHandlerInterface::loadBootstrapModules
ModuleHandler::loadInclude public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::loadInclude(). Overrides ModuleHandlerInterface::loadInclude
ModuleHandler::moduleExists public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::moduleExists(). Overrides ModuleHandlerInterface::moduleExists
ModuleHandler::parseDependency protected function Parses a dependency for comparison by drupal_check_incompatibility().
ModuleHandler::reload public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::reload(). Overrides ModuleHandlerInterface::reload
ModuleHandler::setModuleList public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::setModuleList(). Overrides ModuleHandlerInterface::setModuleList
ModuleHandler::uninstall public function Uninstalls a given list of disabled modules. Overrides ModuleHandlerInterface::uninstall 1