function ModuleInstaller::install
Same name in this branch
- 11.x core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
Same name in other branches
- 9 core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
- 9 core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
- 8.9.x core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
- 8.9.x core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
- 10 core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php \Drupal\Core\ProxyClass\Extension\ModuleInstaller::install()
- 10 core/lib/Drupal/Core/Extension/ModuleInstaller.php \Drupal\Core\Extension\ModuleInstaller::install()
Overrides ModuleInstallerInterface::install
File
-
core/
lib/ Drupal/ Core/ Extension/ ModuleInstaller.php, line 122
Class
- ModuleInstaller
- Default implementation of the module installer.
Namespace
Drupal\Core\ExtensionCode
public function install(array $module_list, $enable_dependencies = TRUE) {
$extension_config = \Drupal::configFactory()->getEditable('core.extension');
// Remove any modules that are already installed.
$installed_modules = $extension_config->get('module') ?: [];
// Only process currently uninstalled modules.
$module_list = array_diff($module_list, array_keys($installed_modules));
if (empty($module_list)) {
// Nothing to do. All modules already installed.
return TRUE;
}
// Get all module data so we can find dependencies and sort and find the
// core requirements. The module list needs to be reset so that it can
// re-scan and include any new modules that may have been added directly
// into the filesystem.
$module_data = \Drupal::service('extension.list.module')->reset()
->getList();
foreach ($module_list as $module) {
if (!empty($module_data[$module]->info['core_incompatible'])) {
throw new MissingDependencyException("Unable to install modules: module '{$module}' is incompatible with this version of Drupal core.");
}
if ($module_data[$module]->info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER] === ExtensionLifecycle::OBSOLETE) {
throw new ObsoleteExtensionException("Unable to install modules: module '{$module}' is obsolete.");
}
if ($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);
}
}
if ($enable_dependencies) {
$module_list = $module_list ? array_combine($module_list, $module_list) : [];
if ($missing_modules = array_diff_key($module_list, $module_data)) {
// One or more of the given modules doesn't exist.
throw new MissingDependencyException(sprintf('Unable to install modules %s due to missing modules %s.', implode(', ', $module_list), implode(', ', $missing_modules)));
}
// Add dependencies to the list. The new modules will be processed as
// the foreach loop continues.
foreach ($module_list as $module => $value) {
foreach (array_keys($module_data[$module]->requires) as $dependency) {
if (!isset($module_data[$dependency])) {
// The dependency does not exist.
throw new MissingDependencyException("Unable to install modules: module '{$module}' is missing its dependency module {$dependency}.");
}
// Skip already installed modules.
if (!isset($module_list[$dependency]) && !isset($installed_modules[$dependency])) {
if ($module_data[$dependency]->info['core_incompatible']) {
throw new MissingDependencyException("Unable to install modules: module '{$module}'. Its dependency module '{$dependency}' is incompatible with this version of Drupal core.");
}
$module_list[$dependency] = $dependency;
}
}
}
// Set the actual module weights.
$module_list = array_map(function ($module) use ($module_data) {
return $module_data[$module]->sort;
}, $module_list);
// Sort the module list by their weights (reverse).
arsort($module_list);
$module_list = array_keys($module_list);
}
// 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.