diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 6e9636f..4b21b6c 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -9,11 +9,11 @@
use Drupal\Core\DrupalKernel;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\DatabaseExceptionWrapper;
+use Drupal\Core\Extension\InfoParser;
use Drupal\Core\Form\FormState;
use Drupal\Core\Installer\Exception\AlreadyInstalledException;
use Drupal\Core\Installer\Exception\InstallerException;
use Drupal\Core\Installer\Exception\NoProfilesException;
-use Drupal\Core\Installer\Exception\TooManyDistributionsException;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
@@ -1214,14 +1214,20 @@ function _install_select_profile(&$install_state) {
}
}
// Check for a distribution. If the site has more than one distribution force
- // the user to choose which will ensure that settings.php has to be written.
- try {
- if ($distribution = \Drupal::service('kernel')->getDistribution()) {
- return $distribution;
+ // the user to choose.
+ $listing = new ExtensionDiscovery(\Drupal::root());
+ $listing->setProfileDirectories([]);
+ $info_parser = new InfoParser();
+ $distributions = [];
+ foreach ($listing->scan('profile') as $profile) {
+ $info = $info_parser->parse($profile->getPathname());
+ if (!empty($info['distribution'])) {
+ $distributions[] = $profile->getName();
}
}
- catch (TooManyDistributionsException $e) {
- // The user must choose.
+ // If there is only one distribution then use it.
+ if (count($distributions) === 1) {
+ return reset($distributions);
}
// Get all visible (not hidden) profiles.
@@ -2174,34 +2180,20 @@ function install_display_requirements($install_state, $requirements) {
}
/**
- * Installation task; writes profile to settings.php (absent a distribution).
+ * Installation task; writes profile to settings.php if possible.
*
* @param array $install_state
* An array of information about the current installation state.
*
* @see _install_select_profile()
+ *
+ * @deprecated in Drupal 8.3.0 and will be removed before Drupal 9.0.0. The
+ * install profile is written to core.extension.
*/
function install_write_profile($install_state) {
- $settings_value = Settings::get('install_profile');
- // We need to write to settings.php if the value in settings.php does not
- // equal the selected profile.
- $need_to_write = $settings_value !== $install_state['parameters']['profile'];
- // However, if we're dealing with a distribution and the profile is not
- // writable do not write the value to settings.php if the current value is not
- // set.
- $distribution = FALSE;
- try {
- $distribution = \Drupal::service('kernel')->getDistribution();
- }
- catch (TooManyDistributionsException $e) {
- // The user will have chosen.
- }
-
- if ($settings_value == '' && $distribution && !is_writable(\Drupal::service('site.path') . '/settings.php')) {
- $need_to_write = FALSE;
- }
-
- if ($need_to_write) {
+ // Only need to write to settings.php if it is possible. The primary storage
+ // for the install profile is the core.extension configuration.
+ if (is_writable(\Drupal::service('site.path') . '/settings.php')) {
// Remember the profile which was used.
$settings['settings']['install_profile'] = (object) array(
'value' => $install_state['parameters']['profile'],
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index b7865b3..9670d78 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -190,12 +190,13 @@ public static function root() {
*/
public static function installProfile() {
if (static::hasContainer()) {
- return static::getContainer()->getParameter('install_profile');
+ $profile = static::getContainer()->getParameter('install_profile');
}
else {
$config_storage = BootstrapConfigStorageFactory::getDatabaseStorage();
- return $config_storage->read('core.extension')['profile'];
+ $profile = $config_storage->read('core.extension')['profile'];
}
+ return empty($profile) ? NULL : $profile;
}
/**
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index f1fc596..92e5181 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -14,10 +14,8 @@
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Drupal\Core\DependencyInjection\YamlFileLoader;
use Drupal\Core\Extension\ExtensionDiscovery;
-use Drupal\Core\Extension\InfoParser;
use Drupal\Core\File\MimeType\MimeTypeGuesser;
use Drupal\Core\Http\TrustedHostsRequestFactory;
-use Drupal\Core\Installer\Exception\TooManyDistributionsException;
use Drupal\Core\Language\Language;
use Drupal\Core\Site\Settings;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@@ -1513,56 +1511,16 @@ protected function addServiceFiles(array $service_yamls) {
* The name of the any active install profile or distribution.
*/
protected function getInstallProfile() {
- $install_profile = Settings::get('install_profile');
+ $config = $this->getConfigStorage()->read('core.extension');
+ // Ensure empty strings are NULLs.
+ $install_profile = empty($config['profile']) ? NULL : $config['profile'];
- if (empty($install_profile) && ($config = $this->getConfigStorage()->read('core.extension')) && isset($config['profile'])) {
- $install_profile = $config['profile'];
+ // If system_update_8300() has not yet run fallback to using settings.
+ if (empty($install_profile)) {
+ $install_profile = Settings::get('install_profile');
}
- elseif (empty($install_profile)) {
- $install_profile = $this->getDistribution();
- }
- return $install_profile;
- }
- /**
- * Get the name of any discovered profile that is a distribution.
- *
- * Scans the filesystem looking for all installation profiles. Returns the one
- * that has a 'distribution' entry in its info.yml file. If multiple profiles
- * are distributions, an exception will be thrown.
- *
- * This is used in two places:
- * 1) During installation, if there is a single distribution, then
- * the installer will not write the installation profile name
- * to settings.php.
- * 2) Whenever DrupalKernel::getInstallProfile() is called, if there
- * is no installation profile name noted in settings.php, then
- * it will call this function to determine the distribution
- * to use.
- *
- * @return string|FALSE
- * The machine name of any discovered distribution. FALSE if there are no
- * distributions.
- *
- * @throws \Drupal\Core\Installer\Exception\TooManyDistributionsException
- * Thrown when a site has more than one distribution installation profile.
- */
- protected function getDistribution() {
- $listing = new ExtensionDiscovery($this->root);
- $listing->setProfileDirectories([]);
- $info_parser = new InfoParser();
- $distributions = [];
- foreach ($listing->scan('profile') as $profile) {
- $info = $info_parser->parse($profile->getPathname());
- if (!empty($info['distribution'])) {
- $distributions[] = $profile->getName();
- }
- }
- // There can be only one.
- if (count($distributions) > 1) {
- throw new TooManyDistributionsException('A site can only have one distribution, multiple installation profiles discovered: ' . implode(', ', $distributions));
- }
- return reset($distributions);
+ return $install_profile;
}
}
diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
index ad2eb5e..24b4c70 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
@@ -8,7 +8,6 @@
use Drupal\Core\Config\ConfigImportValidateEventSubscriberBase;
use Drupal\Core\Config\ConfigNameException;
use Drupal\Core\Extension\ThemeHandlerInterface;
-use Drupal\Core\Site\Settings;
/**
* Config import subscriber for config import events.
@@ -112,9 +111,10 @@ protected function validateModules(ConfigImporter $config_importer) {
}
}
- // Settings is safe to use because settings.php is written before any module
- // is installed.
- $install_profile = Settings::get('install_profile');
+ // Get the install profile from the site's configuration.
+ $current_core_extension = $config_importer->getStorageComparer()->getTargetStorage()->read('core.extension');
+ $install_profile = isset($current_core_extension['profile']) ? $current_core_extension['profile'] : NULL;
+
// Ensure that all modules being uninstalled are not required by modules
// that will be installed after the import.
$uninstalls = $config_importer->getExtensionChangelist('module', 'uninstall');
@@ -129,10 +129,15 @@ protected function validateModules(ConfigImporter $config_importer) {
}
// Ensure that the install profile is not being uninstalled.
- if (in_array($install_profile, $uninstalls)) {
+ if (in_array($install_profile, $uninstalls, TRUE)) {
$profile_name = $module_data[$install_profile]->info['name'];
$config_importer->logError($this->t('Unable to uninstall the %profile profile since it is the install profile.', array('%profile' => $profile_name)));
}
+
+ // Ensure the profile is not changing.
+ if ($install_profile !== $core_extension['profile']) {
+ $config_importer->logError($this->t('Cannot change the install profile from %new_profile to %profile once Drupal is installed.', array('%profile' => $install_profile, '%new_profile' => $core_extension['profile'])));
+ }
}
/**
diff --git a/core/lib/Drupal/Core/Installer/InstallerKernel.php b/core/lib/Drupal/Core/Installer/InstallerKernel.php
index 55e8af6..adeb5c5 100644
--- a/core/lib/Drupal/Core/Installer/InstallerKernel.php
+++ b/core/lib/Drupal/Core/Installer/InstallerKernel.php
@@ -66,11 +66,4 @@ public function getInstallProfile() {
return $profile;
}
- /**
- * {@inheritdoc}
- */
- public function getDistribution() {
- return parent::getDistribution();
- }
-
}
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index 96c5cf6..4a50c43 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -231,7 +231,7 @@ protected function setUp() {
// \Drupal\Core\Config\ConfigInstaller::installDefaultConfig() to work.
// Write directly to active storage to avoid early instantiation of
// the event dispatcher which can prevent modules from registering events.
- \Drupal::service('config.storage')->write('core.extension', array('module' => array(), 'theme' => array()));
+ \Drupal::service('config.storage')->write('core.extension', array('module' => array(), 'theme' => array(), 'profile' => ''));
// Collect and set a fixed module list.
$class = get_class($this);
diff --git a/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php b/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php
index bb73472..2fe5d4f 100644
--- a/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php
+++ b/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php
@@ -5,8 +5,6 @@
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel;
-use Drupal\Core\Extension\ExtensionDiscovery;
-use Drupal\Core\Installer\Exception\TooManyDistributionsException;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
use Symfony\Component\HttpFoundation\Request;
@@ -124,44 +122,11 @@ public function testInstalled() {
// Confirm that Drupal recognizes this distribution as the current profile.
$this->assertEqual(\Drupal::installProfile(), 'mydistro');
$this->assertNull(Settings::get('install_profile'), 'The install profile has not been written to settings.php.');
+ $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.');
$this->rebuildContainer();
$this->pass('Container can be rebuilt even though distribution is not written to settings.php.');
-
- // Create another installation profile which is a distribution.
- $info = [
- 'type' => 'profile',
- 'core' => \Drupal::CORE_COMPATIBILITY,
- 'name' => 'Distribution profile 2',
- 'distribution' => [
- 'name' => 'My Distribution 2',
- 'install' => [
- 'theme' => 'bartik',
- ],
- ],
- ];
- // File API functions are not available yet.
- $path = $this->siteDirectory . '/profiles/mydistro2';
- mkdir($path, 0777, TRUE);
- file_put_contents("$path/mydistro2.info.yml", Yaml::encode($info));
-
- // Ensure that no install profile is configured yet.
- \Drupal::configFactory()->getEditable('core.extension')
- ->set('profile', NULL)
- ->save();
-
- // Test that a site will multiple distributions will get an exception when
- // rebuilding the container. In order to do this we need to reset the
- // discovered files in ExtensionDiscovery.
- try {
- ExtensionDiscovery::reset();
- $this->rebuildContainer();
- $this->fail('TooManyDistributionsException exception thrown.');
- }
- catch (TooManyDistributionsException $e) {
- $this->pass('TooManyDistributionsException exception thrown.');
- $this->assertEqual('A site can only have one distribution, multiple installation profiles discovered: mydistro, mydistro2', $e->getMessage());
- }
+ $this->assertEqual(\Drupal::installProfile(), 'mydistro');
}
}
diff --git a/core/modules/system/src/Tests/Installer/DistributionProfileTest.php b/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
index 01e25e6..569fe36 100644
--- a/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
+++ b/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
@@ -73,6 +73,7 @@ public function testInstalled() {
// Confirm that Drupal recognizes this distribution as the current profile.
$this->assertEqual(\Drupal::installProfile(), 'mydistro');
$this->assertEqual(Settings::get('install_profile'), 'mydistro', 'The install profile has been written to settings.php.');
+ $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.');
}
}
diff --git a/core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php b/core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php
index 4ac889e..0dab57f 100644
--- a/core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php
+++ b/core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php
@@ -3,8 +3,6 @@
namespace Drupal\system\Tests\Installer;
use Drupal\Component\Serialization\Yaml;
-use Drupal\Core\Extension\ExtensionDiscovery;
-use Drupal\Core\Installer\Exception\TooManyDistributionsException;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
@@ -83,27 +81,11 @@ public function testInstalled() {
// Confirm that Drupal recognizes this distribution as the current profile.
$this->assertEqual(\Drupal::installProfile(), 'distribution_one');
$this->assertEqual(Settings::get('install_profile'), 'distribution_one', 'The install profile has been written to settings.php.');
+ $this->assertEqual($this->config('core.extension')->get('profile'), 'distribution_one', 'The install profile has been written to core.extension configuration.');
- // Test that a site will multiple distributions will get an exception when
- // calling \Drupal\Core\DrupalKernel::getDistribution().
- try {
- $kernel = $this->container->get('kernel');
- // getDistribution() is protected in the DrupalKernel class.
- // Call setAccessible(TRUE) so that we can call it to test its behavior.
- $getDistributionMethod = new \ReflectionMethod($kernel, 'getDistribution');
- $getDistributionMethod->setAccessible(TRUE);
- $getDistributionMethod->invokeArgs($kernel, array());
- $this->fail('TooManyDistributionsException exception thrown.');
- }
- catch (TooManyDistributionsException $e) {
- $this->pass('TooManyDistributionsException exception thrown.');
- }
- // To mirror the test in DistributionProfileExistingSettingsTest we reset
- // the discovered files in ExtensionDiscovery.
- // @see \Drupal\system\Tests\Installer\DistributionProfileExistingSettingsTest::testInstalled()
- ExtensionDiscovery::reset();
$this->rebuildContainer();
- $this->pass('Container can be rebuilt as distribution is written to settings.php.');
+ $this->pass('Container can be rebuilt as distribution is written to configuration.');
+ $this->assertEqual(\Drupal::installProfile(), 'distribution_one');
}
}
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
index 945e994..bde5644 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
@@ -669,6 +669,34 @@ public function testInstallProfile() {
}
/**
+ * Tests install profile validation during configuration import.
+ *
+ * @see \Drupal\Core\EventSubscriber\ConfigImportSubscriber
+ */
+ public function testInstallProfileMisMatch() {
+ $sync = $this->container->get('config.storage.sync');
+
+ $extensions = $sync->read('core.extension');
+ // Change the install profile.
+ $extensions['profile'] = 'this_will_not_work';
+ $sync->write('core.extension', $extensions);
+
+ try {
+ $this->configImporter->reset()->import();
+ $this->fail('ConfigImporterException not thrown; an invalid import was not stopped due to missing dependencies.');
+ }
+ catch (ConfigImporterException $e) {
+ $this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
+ $error_log = $this->configImporter->getErrors();
+ // Install profiles can not be changed. Note that KernelTestBase currently
+ // does not use an install profile. This situation should be impossible
+ // to get in but site's can removed the install profile setting from
+ // settings.php so the test is valid.
+ $this->assertEqual(['Cannot change the install profile from this_will_not_work to once Drupal is installed.'], $error_log);
+ }
+ }
+
+ /**
* Tests config_get_config_directory().
*/
public function testConfigGetConfigDirectory() {
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 94a1e04..ffcaaba 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -270,6 +270,11 @@
* by the user.
*
* @see install_select_profile()
+ *
+ * @deprecated in Drupal 8.3.0 and will be removed before Drupal 9.0.0. The
+ * install profile is written to the core.extension confoguration. If a
+ * service requires the install profile use the 'install_profile' container
+ * parameter. Functional code can use \Drupal::installProfile().
*/
# $settings['install_profile'] = '';