function ModuleInstaller::install

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
  2. 11.x core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
  3. 10 core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
  4. 10 core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
  5. 9 core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
  6. 9 core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
  7. 8.9.x core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
  8. 8.9.x core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()

Installs a given list of modules.

Order of events:

  • Gather and add module dependencies to $module_list (if applicable).
  • For each module that is being installed:
  • Invoke hook_modules_installed().

To install test modules add

$settings['extension_discovery_scan_tests'] = TRUE;

to your settings.php.

Parameters

string[] $module_list: An array of module names.

bool $enable_dependencies: (optional) If TRUE, dependencies will automatically be installed in the correct order. This incurs a significant performance cost, so use FALSE if you know $module_list is already complete.

Return value

bool TRUE if the modules were successfully installed.

Overrides ModuleInstallerInterface::install

File

core/lib/Drupal/Core/Extension/ModuleInstaller.php, line 162

Class

ModuleInstaller
Default implementation of the module installer.

Namespace

Drupal\Core\Extension

Code

public function install(array $module_list, $enable_dependencies = TRUE) {
  $extension_config = \Drupal::configFactory()->getEditable('core.extension');
  $installed_modules = $extension_config->get('module') ?: [];
  // The modules the caller explicitly asked for that are not yet installed.
  // Dependency resolution happens in ::getModulesToInstall() below; the
  // deprecation notice is intentionally only emitted for these requested
  // modules and not for dependencies pulled in automatically.
  $requested_modules = array_diff($module_list, array_keys($installed_modules));
  // Resolve the full, dependency-sorted list of modules to install. This
  // also validates that the modules exist and are compatible.
  $module_list = $this->getModulesToInstall($module_list, $enable_dependencies);
  if (empty($module_list)) {
    // Nothing to do. All modules already installed.
    return TRUE;
  }
  // ::getModulesToInstall() reset the extension list, so reuse it here
  // without paying the cost of another scan.
  $module_data = \Drupal::service('extension.list.module')->getList();
  foreach ($requested_modules as $module) {
    if (isset($module_data[$module]) && $module_data[$module]->info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER] === ExtensionLifecycle::DEPRECATED) {
      // phpcs:ignore Drupal.Semantics.FunctionTriggerError
      @trigger_error("The module '{$module}' is deprecated. See " . $module_data[$module]->info['lifecycle_link'], E_USER_DEPRECATED);
    }
  }
  // Required for module installation checks.
  include_once $this->root . '/core/includes/install.inc';
  /** @var \Drupal\Core\Config\ConfigInstaller $config_installer */
  $config_installer = \Drupal::service('config.installer');
  $sync_status = $config_installer->isSyncing();
  foreach ($module_list as $module) {
    // Throw an exception if the module name is too long.
    if (strlen($module) > DRUPAL_EXTENSION_NAME_MAX_LENGTH) {
      throw new ExtensionNameLengthException("Module name '{$module}' is over the maximum allowed length of " . DRUPAL_EXTENSION_NAME_MAX_LENGTH . ' characters');
    }
    // Throw an exception if a theme with the same name is enabled.
    $installed_themes = $extension_config->get('theme') ?: [];
    if (isset($installed_themes[$module])) {
      throw new ExtensionNameReservedException("Module name {$module} is already in use by an installed theme.");
    }
  }
  // Check the validity of the default configuration. This will throw
  // exceptions if the configuration is not valid.
  $config_installer->checkConfigurationToInstall('module', $module_list);
  // Some modules require a container rebuild before and after install.
  // Group modules such that as many are installed together as possible until
  // one needs a container rebuild.
  $module_groups = [];
  $index = 0;
  foreach ($module_list as $module) {
    // Ensure the container is rebuilt both before and after a module that
    // requires a container rebuild is installed.
    $container_rebuild_required = !empty($module_data[$module]->info['container_rebuild_required']);
    if ($container_rebuild_required && !empty($module_groups[$index])) {
      $index++;
    }
    $module_groups[$index][] = $module;
    if ($container_rebuild_required) {
      $index++;
    }
  }
  foreach ($module_groups as $modules) {
    $this->doInstall($modules, $installed_modules, $sync_status);
    // Refresh the installed modules list from configuration to preserve
    // module weight.
    $extension_config = \Drupal::configFactory()->getEditable('core.extension');
    $installed_modules = $extension_config->get('module') ?: [];
  }
  if (!InstallerKernel::installationAttempted()) {
    // If the container was rebuilt during hook_install() it might not have
    // the 'router.route_provider.old' service.
    if (\Drupal::hasService('router.route_provider.old')) {
      \Drupal::getContainer()->set('router.route_provider', \Drupal::service('router.route_provider.old'));
    }
    if (!\Drupal::service('router.route_provider.lazy_builder')->hasRebuilt()) {
      // Rebuild routes after installing module. This is done here on top of
      // \Drupal\Core\Routing\RouteBuilder::destruct to not run into errors on
      // fastCGI which executes ::destruct() after the module installation
      // page was sent already.
      \Drupal::service('router.builder')->rebuild();
    }
    else {
      // Rebuild the router immediately if it is marked as needing a rebuild.
      // @todo Work this through a bit more. This fixes
      //   \Drupal\Tests\standard\Functional\StandardTest::testStandard()
      //   after separately out the optional configuration install.
      \Drupal::service('router.builder')->rebuildIfNeeded();
    }
  }
  $this->moduleHandler
    ->invokeAll('modules_installed', [
    $module_list,
    $sync_status,
  ]);
  return TRUE;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.