diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index 65466a2d65..59b12d2bcb 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -300,7 +300,12 @@ public function install(array $module_list, $enable_dependencies = TRUE) { \Drupal::service('theme_handler')->refreshInfo(); // Allow the module to perform install tasks. - $this->moduleHandler->invoke($module, 'install'); + if (!$sync_status || $this->moduleHandler->getModule($module)->getType() !== "profile") { + // Invoke the extensions install hook if we are not syncing config + // or if the extension is not the profile. Profiles install hook is + // only invoked when installing it with the normal installer. + $this->moduleHandler->invoke($module, 'install'); + } // Record the fact that it was installed. \Drupal::logger('system')->info('%module module installed.', ['%module' => $module]); diff --git a/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php index 185a27be3c..adb040ad3d 100644 --- a/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php @@ -93,31 +93,25 @@ public function buildForm(array $form, FormStateInterface $form_state, $install_ $extensions = $sync->read('core.extension'); $site = $sync->read('system.site'); if (isset($site['name']) && isset($extensions['profile']) && in_array($extensions['profile'], array_keys($names), TRUE)) { - // Ensure the the profile can be installed from configuration. Install - // profile's which implement hook_INSTALL() are not supported. - // @todo https://www.drupal.org/project/drupal/issues/2982052 Remove - // this restriction. - module_load_install($extensions['profile']); - if (!function_exists($extensions['profile'] . '_install')) { - $form['profile']['#options'][static::CONFIG_INSTALL_PROFILE_KEY] = $this->t('Use existing configuration'); - $form['profile'][static::CONFIG_INSTALL_PROFILE_KEY]['#description'] = [ - 'description' => [ - '#markup' => $this->t('Install %name using existing configuration.', ['%name' => $site['name']]), + // Add the option to install the site from configuration. + $form['profile']['#options'][static::CONFIG_INSTALL_PROFILE_KEY] = $this->t('Use existing configuration'); + $form['profile'][static::CONFIG_INSTALL_PROFILE_KEY]['#description'] = [ + 'description' => [ + '#markup' => $this->t('Install %name using existing configuration.', ['%name' => $site['name']]), + ], + 'info' => [ + '#type' => 'item', + '#markup' => $this->t('The configuration from the directory %sync_directory will be used.', ['%sync_directory' => $config_directories[CONFIG_SYNC_DIRECTORY]]), + '#wrapper_attributes' => [ + 'class' => ['messages', 'messages--status'], ], - 'info' => [ - '#type' => 'item', - '#markup' => $this->t('The configuration from the directory %sync_directory will be used.', ['%sync_directory' => $config_directories[CONFIG_SYNC_DIRECTORY]]), - '#wrapper_attributes' => [ - 'class' => ['messages', 'messages--status'], - ], - '#states' => [ - 'visible' => [ - ':input[name="profile"]' => ['value' => static::CONFIG_INSTALL_PROFILE_KEY], - ], + '#states' => [ + 'visible' => [ + ':input[name="profile"]' => ['value' => static::CONFIG_INSTALL_PROFILE_KEY], ], ], - ]; - } + ], + ]; } } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 2cddcbfff9..8eacf50fe8 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -1001,20 +1001,6 @@ function system_requirements($phase) { ]; } - // During installs from configuration don't support install profiles that - // implement hook_install. - if ($phase == 'install' && !empty($install_state['config_install_path'])) { - $install_hook = $install_state['parameters']['profile'] . '_install'; - if (function_exists($install_hook)) { - $requirements['config_install'] = [ - 'title' => t('Configuration install'), - 'value' => $install_state['parameters']['profile'], - 'description' => t('The selected profile has a hook_install() implementation and therefore can not be installed from configuration.'), - 'severity' => REQUIREMENT_ERROR, - ]; - } - } - if ($phase === 'runtime') { $settings = Settings::getAll(); if (array_key_exists('install_profile', $settings)) { diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigProfileHookInstall.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigProfileHookInstall.php deleted file mode 100644 index 2d9d6cdfc1..0000000000 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigProfileHookInstall.php +++ /dev/null @@ -1,64 +0,0 @@ -siteDirectory . '/profiles/' . $this->profile; - $contents = <<profile}.install", $contents); - parent::visitInstaller(); - } - - /** - * Installer step: Configure settings. - */ - protected function setUpSettings() { - // There are errors therefore there is nothing to do here. - return; - } - - /** - * Final installer step: Configure site. - */ - protected function setUpSite() { - // There are errors therefore there is nothing to do here. - return; - } - - /** - * {@inheritdoc} - */ - protected function getConfigTarball() { - // We're not going to get to the config import stage so this does not - // matter. - return __DIR__ . '/../../../fixtures/config_install/testing_config_install_no_config.tar.gz'; - } - - /** - * Confirms the installation has failed and the expected error is displayed. - */ - public function testConfigSync() { - $this->assertTitle('Requirements problem | Drupal'); - $this->assertText($this->profile); - $this->assertText('The selected profile has a hook_install() implementation and therefore can not be installed from configuration.'); - } - -} diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryMultilingualTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryMultilingualTest.php index e223998ed7..c94b72ecaa 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryMultilingualTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryMultilingualTest.php @@ -29,6 +29,23 @@ protected function setUpProfile() { return parent::setUpProfile(); } + /** + * {@inheritdoc} + */ + protected function visitInstaller() { + // Create an .install file with a hook_install() implementation. + $path = $this->siteDirectory . '/profiles/' . $this->profile; + $contents = <<profile}.install", $contents); + parent::visitInstaller(); + } + /** * {@inheritdoc} */ diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryProfileHookInstall.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryProfileHookInstall.php index 63aea303de..b2ee7a3475 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryProfileHookInstall.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigSyncDirectoryProfileHookInstall.php @@ -76,16 +76,9 @@ protected function getConfigTarball() { } /** - * Tests installing from config is not available due to hook_INSTALL(). + * Tests installing from config is available even with to hook_INSTALL(). */ public function testConfigSync() { - $this->assertSession()->titleEquals('Select an installation profile | Drupal'); - $this->assertSession()->responseNotContains('Use existing configuration'); - - // Remove the install hook and the option to install from existing - // configuration will be available. - unlink("{$this->siteDirectory}/profiles/{$this->profile}/{$this->profile}.install"); - $this->getSession()->reload(); $this->assertSession()->titleEquals('Select an installation profile | Drupal'); $this->assertSession()->responseContains('Use existing configuration'); }