class UpdateModuleHandler

Deals with module enables and throws exception if hooks fired during updates.

This is necessary for a reliable and testable update environment.

Hierarchy

Expanded class hierarchy of UpdateModuleHandler

File

drupal/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php, line 18
Contains \Drupal\Core\Extension\UpdateModuleHandler.

Namespace

Drupal\Core\Extension
View source
class UpdateModuleHandler extends ModuleHandler {

  /**
   * {@inheritdoc}
   */
  public function getImplementations($hook) {
    if (substr($hook, -6) === '_alter') {
      return array();
    }
    switch ($hook) {

      // hook_requirements is necessary for updates to work.
      case 'requirements':

      // Allow logging.
      case 'watchdog':
        return parent::getImplementations($hook);

      // Forms and pages do not render without the basic elements defined in
      // system_element_info().
      case 'element_info':

      // Forms do not render without the basic elements in
      // drupal_common_theme() called from system_theme().
      case 'theme':

      // user_update_8011() uses public:// to create the image style directory.
      case 'stream_wrappers':
        return array(
          'system',
        );

      // This is called during rebuild to find testing themes.
      case 'system_theme_info':
        return array();

      // t() in system_stream_wrappers() needs this. Other schema calls aren't
      // supported.
      case 'schema':
        return array(
          'locale',
        );
      default:
        throw new \LogicException("Invoking hooks {$hook} is not supported during updates");
    }
  }

  /**
   * {@inheritdoc}
   */
  public function enable($module_list, $enable_dependencies = TRUE) {
    $schema_store = \Drupal::keyValue('system.schema');
    $old_schema = array();
    foreach ($module_list as $module) {

      // Check for initial schema and install it. The schema version of a newly
      // installed module is always 0. Using 8000 here would be inconsistent
      // since $module_update_8000() may involve a schema change, and we want
      // to install the schema as it was before any updates were added.
      module_load_install($module);
      $function = $module . '_schema_0';
      if (function_exists($function)) {
        $schema = $function();
        foreach ($schema as $table => $spec) {
          db_create_table($table, $spec);
        }
      }

      // Enable the module with a weight of 0.
      $module_config = config('system.module');
      $module_config
        ->set("enabled.{$module}", 0)
        ->set('enabled', module_config_sort($module_config
        ->get('enabled')))
        ->save();

      // Ensure the module is not contained in disabled modules.
      config('system.module.disabled')
        ->clear($module)
        ->save();
      $current_schema = $schema_store
        ->get($module);

      // Set the schema version if the module was not just disabled before.
      if ($current_schema === NULL || $current_schema === SCHEMA_UNINSTALLED) {

        // Change the schema version to the given value (defaults to 0), so any
        // module updates since the module's inception are executed in a core
        // upgrade.
        $schema_store
          ->set($module, 0);
        $old_schema[$module] = SCHEMA_UNINSTALLED;
      }
      else {
        $old_schema[$module] = $current_schema;
      }

      // Copy the default configuration of the module into the active storage.
      // The default configuration is not altered in any way, and since the module
      // is just being installed, none of its configuration can exist already, so
      // this is a plain copy operation from one storage to another.
      $module_config_path = drupal_get_path('module', $module) . '/config';
      if (is_dir($module_config_path)) {
        $module_filestorage = new FileStorage($module_config_path);
        $config_storage = drupal_container()
          ->get('config.storage');
        foreach ($module_filestorage
          ->listAll() as $config_name) {

          // If this file already exists, something in the upgrade path went
          // completely wrong and we want to know.
          if ($config_storage
            ->exists($config_name)) {
            throw new ConfigException(format_string('Default configuration file @name of @module module unexpectedly exists already before the module was installed.', array(
              '@module' => $module,
              '@name' => $config_name,
            )));
          }
          $config_storage
            ->write($config_name, $module_filestorage
            ->read($config_name));
        }
      }

      // system_list_reset() is in module.inc but that would only be available
      // once the variable bootstrap is done.
      require_once DRUPAL_ROOT . '/core/includes/module.inc';
      system_list_reset();
      $this->moduleList[$module] = drupal_get_filename('module', $module);
      $this
        ->load($module);
      drupal_classloader_register($module, dirname($this->moduleList[$module]));

      // @todo Figure out what to do about hook_install() and hook_enable().
    }
    return $old_schema;
  }

  /**
   * {@inheritdoc}
   */
  public function disable($module_list, $disable_dependents = TRUE) {
    throw new \LogicException('Disabling modules is not supported during updates');
  }

  /**
   * {@inheritdoc}
   */
  public function uninstall($module_list = array(), $uninstall_dependents = TRUE) {
    throw new \LogicException('Uninstalling modules is not supported during updates');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
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::getBootstrapModules public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getBootstrapModules(). Overrides ModuleHandlerInterface::getBootstrapModules 1
ModuleHandler::getHookInfo public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getHookInfo(). Overrides ModuleHandlerInterface::getHookInfo 1
ModuleHandler::getImplementationInfo protected function Provides information about modules' implementations of a hook. 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::resetImplementations public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::resetImplementations(). Overrides ModuleHandlerInterface::resetImplementations 1
ModuleHandler::setModuleList public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::setModuleList(). Overrides ModuleHandlerInterface::setModuleList
ModuleHandler::__construct public function Constructs a ModuleHandler object. 1
UpdateModuleHandler::disable public function Disables a given set of modules. Overrides ModuleHandler::disable
UpdateModuleHandler::enable public function Enables or installs a given list of modules. Overrides ModuleHandler::enable
UpdateModuleHandler::getImplementations public function Implements \Drupal\Core\Extension\ModuleHandlerInterface::getImplementations(). Overrides ModuleHandler::getImplementations
UpdateModuleHandler::uninstall public function Uninstalls a given list of disabled modules. Overrides ModuleHandler::uninstall