diff --git a/core/globals.api.php b/core/globals.api.php index 1487b1942c..0f60ad5585 100644 --- a/core/globals.api.php +++ b/core/globals.api.php @@ -62,7 +62,10 @@ /** * The location of file system directories used for site configuration data. * - * @see drupal_install_config_directories() + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use + * \Drupal\Core\Site\Settings::get('config_sync_directory') instead. + * + * @see https://www.drupal.org/node/3018145 */ global $config_directories; diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 69544ba76c..ef9090c8d3 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -13,6 +13,7 @@ use Drupal\Core\Logger\RfcLogLevel; use Drupal\Core\Test\TestDatabase; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Site\Settings; use Drupal\Core\Utility\Error; use Drupal\Core\StringTranslation\TranslatableMarkup; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; @@ -158,7 +159,10 @@ /** * $config_directories key for sync directory. * - * @see config_get_config_directory() + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use + * \Drupal\Core\Site\Settings::get('config_sync_directory') instead. + * + * @see https://www.drupal.org/node/3018145 */ const CONFIG_SYNC_DIRECTORY = 'sync'; @@ -196,10 +200,19 @@ * The configuration directory path. * * @throws \Exception + * + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use + * \Drupal\Core\Site\Settings::get('config_sync_directory') instead. + * + * @see https://www.drupal.org/node/3018145 */ function config_get_config_directory($type) { global $config_directories; - + @trigger_error('config_get_config_directory() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\Core\Site\Settings::get(\'config_sync_directory\') instead. See https://www.drupal.org/node/3018145', E_USER_DEPRECATED); + $config_sync_directory = Settings::get('config_sync_directory', FALSE); + if ($config_sync_directory) { + $config_directories[CONFIG_SYNC_DIRECTORY] = $config_sync_directory; + } // @todo Remove fallback in Drupal 9. https://www.drupal.org/node/2574943 if ($type == CONFIG_SYNC_DIRECTORY && !isset($config_directories[CONFIG_SYNC_DIRECTORY]) && isset($config_directories[CONFIG_STAGING_DIRECTORY])) { $type = CONFIG_STAGING_DIRECTORY; diff --git a/core/includes/file.inc b/core/includes/file.inc index 6356a3f4b7..5327a38035 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -336,15 +336,7 @@ function file_ensure_htaccess() { } file_save_htaccess('temporary://', TRUE); - // If a staging directory exists then it should contain a .htaccess file. - // @todo https://www.drupal.org/node/2696103 catch a more specific exception - // and simplify this code. - try { - $staging = config_get_config_directory(CONFIG_SYNC_DIRECTORY); - } - catch (\Exception $e) { - $staging = FALSE; - } + $staging = Settings::get('config_sync_directory', FALSE); if ($staging) { // Note that we log an error here if we can't write the .htaccess file. This // can occur if the staging directory is read-only. If it is then it is the diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 5258b5d19b..d788288a3a 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -380,7 +380,7 @@ function install_begin_request($class_loader, &$install_state) { // Determine whether base system services are ready to operate. try { - $sync_directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $sync_directory = Settings::get('config_sync_directory', FALSE); $install_state['config_verified'] = file_exists($sync_directory); } catch (Exception $e) { @@ -1532,13 +1532,13 @@ function _install_get_version_info($version) { * profile information will be added here. */ function install_load_profile(&$install_state) { - global $config_directories; $profile = $install_state['parameters']['profile']; $install_state['profiles'][$profile]->load(); $install_state['profile_info'] = install_profile_info($profile, isset($install_state['parameters']['langcode']) ? $install_state['parameters']['langcode'] : 'en'); - if (!empty($install_state['parameters']['existing_config']) && !empty($config_directories[CONFIG_SYNC_DIRECTORY])) { - $install_state['config_install_path'] = $config_directories[CONFIG_SYNC_DIRECTORY]; + $sync_directory = Settings::get('config_sync_directory'); + if (!empty($install_state['parameters']['existing_config']) && !empty($sync_directory)) { + $install_state['config_install_path'] = $sync_directory; } // If the profile has a config/sync directory copy the information to the // install_state global. diff --git a/core/includes/install.inc b/core/includes/install.inc index 7ac7f3c602..97ef16ca5c 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -204,16 +204,14 @@ function drupal_get_database_types() { * are dumped up to a stdClass object. The object can have value, required * and comment properties. * @code - * $settings['config_directories'] = array( - * CONFIG_SYNC_DIRECTORY => (object) array( - * 'value' => 'config_hash/sync', - * 'required' => TRUE, - * ), + * $settings['settings']['config_sync_directory'] = (object) array( + * 'value' => 'config_hash/sync', + * 'required' => TRUE, * ); * @endcode * gets dumped as: * @code - * $config_directories['sync'] = 'config_hash/sync' + * $settings['config_sync_directory'] = 'config_hash/sync' * @endcode */ function drupal_rewrite_settings($settings = [], $settings_file = NULL) { @@ -479,10 +477,13 @@ function _drupal_rewrite_settings_dump_one(\stdClass $variable, $prefix = '', $s /** * Creates the config directory and ensures it is operational. * - * @see install_settings_form_submit() - * @see update_prepare_d8_bootstrap() + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. + * There is no replacement. + * + * @see https://www.drupal.org/node/3018145 */ function drupal_install_config_directories() { + @trigger_error('drupal_install_config_directories() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. There is no replacement. See https://www.drupal.org/node/3018145.', E_USER_DEPRECATED); global $config_directories, $install_state; // If settings.php does not contain a config sync directory name we need to diff --git a/core/lib/Drupal/Core/Config/FileStorageFactory.php b/core/lib/Drupal/Core/Config/FileStorageFactory.php index 9e324975f9..c597db5b3c 100644 --- a/core/lib/Drupal/Core/Config/FileStorageFactory.php +++ b/core/lib/Drupal/Core/Config/FileStorageFactory.php @@ -2,6 +2,8 @@ namespace Drupal\Core\Config; +use Drupal\Core\Site\Settings; + /** * Provides a factory for creating config file storage objects. */ @@ -23,9 +25,19 @@ public static function getActive() { * Returns a FileStorage object working with the sync config directory. * * @return \Drupal\Core\Config\FileStorage FileStorage + * + * @throws \Exception + * In case the sync directory does not exist or is not defined in + * $settings['config_sync_directory'] */ public static function getSync() { - return new FileStorage(config_get_config_directory(CONFIG_SYNC_DIRECTORY)); + $directory = Settings::get('config_sync_directory', FALSE); + if ($directory === FALSE) { + // @todo: throw a more specific exception. + // @see https://www.drupal.org/node/2696103 + throw new \Exception('In case the sync directory does not exist or is not defined in $settings["config_sync_directory"]'); + } + return new FileStorage($directory); } } diff --git a/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php index 185a27be3c..b0b72f6a99 100644 --- a/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php @@ -5,6 +5,7 @@ use Drupal\Core\Config\FileStorage; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Site\Settings; /** * Provides the profile selection form. @@ -31,7 +32,6 @@ public function getFormId() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, $install_state = NULL) { - global $config_directories; $form['#title'] = $this->t('Select an installation profile'); $profiles = []; @@ -88,8 +88,9 @@ public function buildForm(array $form, FormStateInterface $form_state, $install_ } } - if (!empty($config_directories[CONFIG_SYNC_DIRECTORY])) { - $sync = new FileStorage($config_directories[CONFIG_SYNC_DIRECTORY]); + $config_sync_directory = Settings::get('config_sync_directory'); + if (!empty($config_sync_directory)) { + $sync = new FileStorage($config_sync_directory); $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)) { @@ -106,7 +107,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $install_ ], 'info' => [ '#type' => 'item', - '#markup' => $this->t('The configuration from the directory %sync_directory will be used.', ['%sync_directory' => $config_directories[CONFIG_SYNC_DIRECTORY]]), + '#markup' => $this->t('The configuration from the directory %sync_directory will be used.', ['%sync_directory' => $config_sync_directory]), '#wrapper_attributes' => [ 'class' => ['messages', 'messages--status'], ], @@ -134,10 +135,10 @@ public function buildForm(array $form, FormStateInterface $form_state, $install_ * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - global $install_state, $config_directories; + global $install_state; $profile = $form_state->getValue('profile'); if ($profile === static::CONFIG_INSTALL_PROFILE_KEY) { - $sync = new FileStorage($config_directories[CONFIG_SYNC_DIRECTORY]); + $sync = new FileStorage(Settings::get('config_sync_directory')); $profile = $sync->read('core.extension')['profile']; $install_state['parameters']['existing_config'] = TRUE; } diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index b82bb01ae1..75099a2a35 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -4,9 +4,11 @@ use Drupal\Component\Utility\Crypt; use Drupal\Core\Database\Database; +use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\RendererInterface; +use Drupal\Core\Site\Settings; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -225,12 +227,26 @@ public function submitForm(array &$form, FormStateInterface $form_state) { 'value' => Crypt::randomBytesBase64(55), 'required' => TRUE, ]; + // If settings.php does not contain a config sync directory name we need to + // configure one. + if (empty(Settings::get('config_sync_directory'))) { + if (empty($install_state['config_install_path'])) { + // Add a randomized config directory name to settings.php + $config_sync_directory = $this->createRandomConfigDirectory(); + } + else { + // Install profiles can contain a config sync directory. If they do, + // 'config_install_path' is a path to the directory. + $config_sync_directory = $install_state['config_install_path']; + } + $settings['settings']['config_sync_directory'] = (object) [ + 'value' => $config_sync_directory, + 'required' => TRUE, + ]; + } drupal_rewrite_settings($settings); - // Add the config directories to settings.php. - drupal_install_config_directories(); - // Indicate that the settings file has been verified, and check the database // for the last completed task, now that we have a valid connection. This // last step is important since we want to trigger an error if the new @@ -241,4 +257,26 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $install_state['completed_task'] = install_verify_completed_task(); } + /** + * Create a random config sync directory. + * + * @return string + * The path to the generated config sync directory. + */ + protected function createRandomConfigDirectory() { + $config_sync_directory = \Drupal::service('site.path') . '/files/config_' . Crypt::randomBytesBase64(55) . '/sync'; + // This should never fail, it is created here inside the public files + // directory, which has already been verified to be writable itself. + if (\Drupal::service('file_system')->prepareDirectory($config_sync_directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) { + // Put a README.txt into the sync config directory. This is required so + // that they can later be added to git. Since this directory is + // auto-created, we have to write out the README rather than just adding + // it to the drupal core repo. + $text = 'This directory contains configuration to be imported into your Drupal site. To make this configuration active, visit admin/config/development/configuration/sync.' . ' For information about deploying configuration between servers, see https://www.drupal.org/documentation/administer/config'; + file_put_contents($config_sync_directory . '/README.txt', $text); + } + + return $config_sync_directory; + } + } diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php index c6fbed659f..ad8713a752 100644 --- a/core/lib/Drupal/Core/Site/Settings.php +++ b/core/lib/Drupal/Core/Site/Settings.php @@ -128,6 +128,16 @@ public static function initialize($app_root, $site_path, &$class_loader) { // Initialize Database. Database::setMultipleConnectionInfo($databases); + // For BC ensure the $config_directories global is set both in the global + // and settings. + if (!isset($settings['config_sync_directory']) && !empty($config_directories['sync'])) { + @trigger_error('$config_directories[\'sync\'] has moved to $settings[\'config_sync_directory\']. See https://www.drupal.org/node/3018145.', E_USER_DEPRECATED); + $settings['config_sync_directory'] = $config_directories['sync']; + } + elseif (isset($settings['config_sync_directory'])) { + $config_directories['sync'] = $settings['config_sync_directory']; + } + // Initialize Settings. new Settings($settings); } diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 46fea2f830..de4f9ab2cf 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -43,6 +43,11 @@ /** * The config directories used in this test. + * + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use + * \Drupal\Core\Site\Settings::get('config_sync_directory') instead. + * + * @see https://www.drupal.org/node/3018145 */ protected $configDirectories = []; @@ -293,9 +298,7 @@ protected function doInstall() { */ protected function initSettings() { Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $this->classLoader); - foreach ($GLOBALS['config_directories'] as $type => $path) { - $this->configDirectories[$type] = $path; - } + $this->configDirectories['sync'] = Settings::get('config_sync_directory'); // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write diff --git a/core/modules/config/src/Form/ConfigImportForm.php b/core/modules/config/src/Form/ConfigImportForm.php index 4911d98c68..7632e18408 100644 --- a/core/modules/config/src/Form/ConfigImportForm.php +++ b/core/modules/config/src/Form/ConfigImportForm.php @@ -7,6 +7,7 @@ use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Site\Settings; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -30,6 +31,13 @@ class ConfigImportForm extends FormBase { */ protected $fileSystem; + /** + * The settings object. + * + * @var \Drupal\Core\Site\Settings + */ + protected $settings; + /** * Constructs a new ConfigImportForm. * @@ -37,14 +45,21 @@ class ConfigImportForm extends FormBase { * The configuration storage. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system service. + * @param \Drupal\Core\Site\Settings $settings + * The settings object. */ - public function __construct(StorageInterface $config_storage, FileSystemInterface $file_system = NULL) { + public function __construct(StorageInterface $config_storage, FileSystemInterface $file_system = NULL, Settings $settings = NULL) { $this->configStorage = $config_storage; if (!isset($file_system)) { @trigger_error('The $file_system parameter was added in Drupal 8.8.0 and will be required in 9.0.0. See https://www.drupal.org/node/3021434.', E_USER_DEPRECATED); $file_system = \Drupal::service('file_system'); } $this->fileSystem = $file_system; + if (!isset($settings)) { + @trigger_error('The $settings parameter was added in Drupal 8.8.0 and will be required in 9.0.0. See https://www.drupal.org/node/2980712.', E_USER_DEPRECATED); + $settings = \Drupal::service('settings'); + } + $this->settings = $settings; } /** @@ -53,7 +68,8 @@ public function __construct(StorageInterface $config_storage, FileSystemInterfac public static function create(ContainerInterface $container) { return new static( $container->get('config.storage.sync'), - $container->get('file_system') + $container->get('file_system'), + $container->get('settings') ); } @@ -68,7 +84,7 @@ public function getFormId() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { - $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $directory = $this->settings->get('config_sync_directory'); $directory_is_writable = is_writable($directory); if (!$directory_is_writable) { $this->messenger()->addError($this->t('The directory %directory is not writable.', ['%directory' => $directory])); @@ -115,7 +131,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { foreach ($archiver->listContent() as $file) { $files[] = $file['filename']; } - $archiver->extractList($files, config_get_config_directory(CONFIG_SYNC_DIRECTORY)); + $archiver->extractList($files, $this->settings->get('config_sync_directory')); $this->messenger()->addStatus($this->t('Your configuration files were successfully uploaded and are ready for import.')); $form_state->setRedirect('config.sync'); } diff --git a/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php b/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php index 6f6659d743..bc4dc7c5c3 100644 --- a/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php +++ b/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\config\Functional; +use Drupal\Core\Site\Settings; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\TestFileCreationTrait; @@ -50,7 +51,7 @@ public function testImport() { $this->assertText(t('Could not extract the contents of the tar file')); // Make the sync directory read-only. - $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $directory = Settings::get('config_sync_directory'); \Drupal::service('file_system')->chmod($directory, 0555); $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertRaw(t('The directory %directory is not writable.', ['%directory' => $directory])); diff --git a/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php b/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php index 15dc91e0f2..92aae4c913 100644 --- a/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php +++ b/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php @@ -5,6 +5,7 @@ use Drupal\Core\Config\PreExistingConfigException; use Drupal\Core\Config\StorageInterface; use Drupal\Core\File\Exception\FileException; +use Drupal\Core\Site\Settings; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\BrowserTestBase; @@ -201,7 +202,7 @@ public function testConfigModuleRequirements() { $this->drupalLogin($this->adminUser); $this->drupalPostForm('admin/modules', ['modules[config][enable]' => TRUE], t('Install')); - $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $directory = Settings::get('config_sync_directory'); try { \Drupal::service('file_system')->deleteRecursive($directory); } diff --git a/core/modules/field/tests/src/Kernel/FieldImportCreateTest.php b/core/modules/field/tests/src/Kernel/FieldImportCreateTest.php index 8d5112ef16..e889905ba8 100644 --- a/core/modules/field/tests/src/Kernel/FieldImportCreateTest.php +++ b/core/modules/field/tests/src/Kernel/FieldImportCreateTest.php @@ -2,8 +2,8 @@ namespace Drupal\Tests\field\Kernel; +use Drupal\Core\Site\Settings; use Drupal\field\Entity\FieldConfig; - use Drupal\field\Entity\FieldStorageConfig; /** @@ -93,7 +93,7 @@ public function testImportCreate() { // Add the new files to the sync directory. $src_dir = __DIR__ . '/../../modules/field_test_config/sync'; - $target_dir = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $target_dir = Settings::get('config_sync_directory'); /** @var \Drupal\Core\File\FileSystemInterface $file_system */ $file_system = \Drupal::service('file_system'); $this->assertTrue($file_system->copy("$src_dir/$field_storage_config_name.yml", "$target_dir/$field_storage_config_name.yml")); diff --git a/core/modules/node/tests/src/Kernel/Config/NodeImportCreateTest.php b/core/modules/node/tests/src/Kernel/Config/NodeImportCreateTest.php index 4df9719065..66b41db354 100644 --- a/core/modules/node/tests/src/Kernel/Config/NodeImportCreateTest.php +++ b/core/modules/node/tests/src/Kernel/Config/NodeImportCreateTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\node\Kernel\Config; +use Drupal\Core\Site\Settings; use Drupal\field\Entity\FieldConfig; use Drupal\node\Entity\NodeType; use Drupal\KernelTests\KernelTestBase; @@ -60,7 +61,7 @@ public function testImportCreate() { $this->copyConfig($active, $sync); // Manually add new node type. $src_dir = __DIR__ . '/../../../modules/node_test_config/sync'; - $target_dir = config_get_config_directory(CONFIG_SYNC_DIRECTORY); + $target_dir = Settings::get('config_sync_directory'); $this->assertTrue(\Drupal::service('file_system')->copy("$src_dir/$node_type_config_name.yml", "$target_dir/$node_type_config_name.yml")); // Import the content of the sync directory. diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php index 0f4af3a3a7..e173f8f35e 100644 --- a/core/modules/simpletest/src/InstallerTestBase.php +++ b/core/modules/simpletest/src/InstallerTestBase.php @@ -148,9 +148,7 @@ protected function setUp() { $request = Request::createFromGlobals(); $class_loader = require $this->container->get('app.root') . '/autoload.php'; Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader); - foreach ($GLOBALS['config_directories'] as $type => $path) { - $this->configDirectories[$type] = $path; - } + $this->configDirectories['sync'] = Settings::get('config_sync_directory'); // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 80c8eb0b7f..94ce0816da 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -138,23 +138,26 @@ protected function beforePrepareEnvironment() { /** * Create and set new configuration directories. * - * @see config_get_config_directory() + * @see \Drupal\Core\Site\Settings::getConfigDirectory() * * @throws \RuntimeException - * Thrown when CONFIG_SYNC_DIRECTORY cannot be created or made writable. + * Thrown when the configuration sync directory cannot be created or made + * writable. + * + * @return string + * The config sync directory path. */ protected function prepareConfigDirectories() { $this->configDirectories = []; - include_once DRUPAL_ROOT . '/core/includes/install.inc'; // Assign the relative path to the global variable. $path = $this->siteDirectory . '/config_' . CONFIG_SYNC_DIRECTORY; - $GLOBALS['config_directories'][CONFIG_SYNC_DIRECTORY] = $path; // Ensure the directory can be created and is writeable. if (!\Drupal::service('file_system')->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) { throw new \RuntimeException("Failed to create '" . CONFIG_SYNC_DIRECTORY . "' config directory $path"); } // Provide the already resolved path for tests. $this->configDirectories[CONFIG_SYNC_DIRECTORY] = $path; + return $path; } /** @@ -236,14 +239,14 @@ protected function setUp() { // @see \Drupal\Core\Extension\ExtensionDiscovery::scan() $settings['test_parent_site'] = $this->originalSite; + // Create and set new configuration directories. + $settings['config_sync_directory'] = $this->prepareConfigDirectories(); + // Restore and merge settings. // DrupalKernel::boot() initializes new Settings, and the containerBuild() // method sets additional settings. new Settings($settings + Settings::getAll()); - // Create and set new configuration directories. - $this->prepareConfigDirectories(); - // Set the request scope. $this->container = $this->kernel->getContainer(); $this->container->get('request_stack')->push($request); diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php index 4fce148cf1..1af310bc80 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -1103,7 +1103,6 @@ private function prepareEnvironment() { // Backup statics and globals. $this->originalContainer = \Drupal::getContainer(); $this->originalLanguage = $language_interface; - $this->originalConfigDirectories = $GLOBALS['config_directories']; // Save further contextual information. // Use the original files directory to avoid nesting it within an existing @@ -1275,9 +1274,6 @@ private function restoreEnvironment() { $GLOBALS['conf'] = $this->originalConf; new Settings($this->originalSettings); - // Restore original statics and globals. - $GLOBALS['config_directories'] = $this->originalConfigDirectories; - // Re-initialize original stream wrappers of the parent site. // This must happen after static variables have been reset and the original // container and $config_directories are restored, as simpletest_log_read() diff --git a/core/modules/system/src/Tests/Update/UpdatePathTestBase.php b/core/modules/system/src/Tests/Update/UpdatePathTestBase.php index 49d96ac4b9..673404f41c 100644 --- a/core/modules/system/src/Tests/Update/UpdatePathTestBase.php +++ b/core/modules/system/src/Tests/Update/UpdatePathTestBase.php @@ -187,9 +187,6 @@ protected function setUp() { $container = $this->initKernel($request); $this->initConfig($container); - // Add the config directories to settings.php. - drupal_install_config_directories(); - // Restore the original Simpletest batch. $this->restoreBatch(); diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 61b619dc32..1dec9d14c9 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -630,37 +630,61 @@ function system_requirements($phase) { // Check the config directory if it is defined in settings.php. If it isn't // defined, the installer will create a valid config directory later, but // during runtime we must always display an error. - if (!empty($GLOBALS['config_directories'])) { - foreach (array_keys(array_filter($GLOBALS['config_directories'])) as $type) { - $directory = config_get_config_directory($type); - // If we're installing Drupal try and create the config sync directory. - if (!is_dir($directory) && $phase == 'install') { - \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); + $config_sync_directory = Settings::get('config_sync_directory'); + if (!empty($config_sync_directory)) { + // If we're installing Drupal try and create the config sync directory. + if (!is_dir($config_sync_directory) && $phase == 'install') { + \Drupal::service('file_system')->prepareDirectory($config_sync_directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); + } + if (!is_dir($config_sync_directory)) { + if ($phase == 'install') { + $description = t('An automated attempt to create the directory %directory failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see INSTALL.txt or the online handbook.', ['%directory' => $config_sync_directory, ':handbook_url' => 'https://www.drupal.org/server-permissions']); } - if (!is_dir($directory)) { - if ($phase == 'install') { - $description = t('An automated attempt to create the directory %directory failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see INSTALL.txt or the online handbook.', ['%directory' => $directory, ':handbook_url' => 'https://www.drupal.org/server-permissions']); - } - else { - $description = t('The directory %directory does not exist.', ['%directory' => $directory]); - } - $requirements['config directory ' . $type] = [ - 'title' => t('Configuration directory: %type', ['%type' => $type]), - 'description' => $description, - 'severity' => REQUIREMENT_ERROR, - ]; + else { + $description = t('The directory %directory does not exist.', ['%directory' => $config_sync_directory]); } + $requirements['config sync directory'] = [ + 'title' => t('Configuration sync directory'), + 'description' => $description, + 'severity' => REQUIREMENT_ERROR, + ]; } } - if ($phase != 'install' && (empty($GLOBALS['config_directories']) || empty($GLOBALS['config_directories'][CONFIG_SYNC_DIRECTORY]))) { - $requirements['config directories'] = [ - 'title' => t('Configuration directories'), + if ($phase != 'install' && empty($config_sync_directory)) { + $requirements['config sync directory'] = [ + 'title' => t('Configuration sync directory'), 'value' => t('Not present'), - 'description' => t('Your %file file must define the $config_directories variable as an array containing the names of directories in which configuration files can be found. It must contain a %sync_key key.', ['%file' => $site_path . '/settings.php', '%sync_key' => CONFIG_SYNC_DIRECTORY]), + 'description' => t("Your %file file must define the %setting setting as a string containing the directory in which configuration files can be found.", ['%file' => $site_path . '/settings.php', '%setting' => "\$settings['config_sync_directory']"]), 'severity' => REQUIREMENT_ERROR, ]; } + // Handle other configuration directories. This will be removed in Drupal 9. + // See https://www.drupal.org/node/3018145. + $bc_config_directories = isset($GLOBALS['config_directories']) ? $GLOBALS['config_directories'] : []; + unset($bc_config_directories['sync']); + foreach (array_keys(array_filter($bc_config_directories)) as $type) { + @trigger_error("Automatic creation of '$type' configuration directory will be removed from drupal:9.0.0. See https://www.drupal.org/node/3018145.", E_USER_DEPRECATED); + $directory = config_get_config_directory($type); + // If we're installing Drupal try and create the config sync directory. + if (!is_dir($directory) && $phase == 'install') { + \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); + } + if (!is_dir($directory)) { + if ($phase == 'install') { + $description = t('An automated attempt to create the directory %directory failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see INSTALL.txt or the online handbook.', ['%directory' => $directory, ':handbook_url' => 'https://www.drupal.org/server-permissions']); + } + else { + $description = t('The directory %directory does not exist.', ['%directory' => $directory]); + } + $requirements['config directory ' . $type] = [ + 'title' => t('Configuration directory: %type', ['%type' => $type]), + 'description' => $description, + 'severity' => REQUIREMENT_ERROR, + ]; + } + } + $requirements['file system'] = [ 'title' => t('File system'), ]; diff --git a/core/modules/system/tests/src/Functional/System/StatusTest.php b/core/modules/system/tests/src/Functional/System/StatusTest.php index 6b25e235a3..845b5a8e92 100644 --- a/core/modules/system/tests/src/Functional/System/StatusTest.php +++ b/core/modules/system/tests/src/Functional/System/StatusTest.php @@ -24,13 +24,10 @@ class StatusTest extends BrowserTestBase { protected function setUp() { parent::setUp(); - // Unset the sync directory in settings.php to trigger $config_directories - // error. - $settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => '', - 'required' => TRUE, - ], + // Unset the sync directory in settings.php to trigger the error. + $settings['settings']['config_sync_directory'] = (object) [ + 'value' => '', + 'required' => TRUE, ]; $this->writeSettings($settings); @@ -62,7 +59,7 @@ public function testStatusPage() { $this->assertNoText(t('Out of date')); // The global $config_directories is not properly formed. - $this->assertRaw(t('Your %file file must define the $config_directories variable as an array containing the names of directories in which configuration files can be found. It must contain a %sync_key key.', ['%file' => $this->siteDirectory . '/settings.php', '%sync_key' => CONFIG_SYNC_DIRECTORY])); + $this->assertRaw(t("Your %file file must define the %setting setting", ['%file' => $this->siteDirectory . '/settings.php', '%setting' => "\$settings['config_sync_directory']"])); // Set the schema version of update_test_postupdate to a lower version, so // update_test_postupdate_update_8001() needs to be executed. diff --git a/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php index 60f3d0aa0d..d64d016e99 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php @@ -64,13 +64,11 @@ protected function prepareEnvironment() { // not be available at this point in the install process. $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_staging', - 'required' => TRUE, - ], + $this->settings['settings']['config_sync_directory'] = (object) [ + 'value' => $site_path . '/files/config_staging', + 'required' => TRUE, ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + mkdir($this->settings['settings']['config_sync_directory']->value, 0777, TRUE); } /** diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryErrorTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryErrorTest.php index 7de0652fe9..0d955b6957 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryErrorTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryErrorTest.php @@ -24,7 +24,7 @@ class InstallerConfigDirectorySetNoDirectoryErrorTest extends InstallerTestBase protected function prepareEnvironment() { parent::prepareEnvironment(); $this->configDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64(); - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + $this->settings['settings']['config_sync_directory'] = (object) [ 'value' => $this->configDirectory . '/sync', 'required' => TRUE, ]; diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php index 71e8b0594d..dcb47b5ee3 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php @@ -5,7 +5,7 @@ use Drupal\Component\Utility\Crypt; /** - * Tests the installer when a config_directory set up but does not exist. + * Tests the installer when a custom config directory set up but does not exist. * * @group Installer */ @@ -24,15 +24,10 @@ class InstallerConfigDirectorySetNoDirectoryTest extends InstallerTestBase { protected function prepareEnvironment() { parent::prepareEnvironment(); $this->syncDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64() . '/sync'; - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + $this->settings['settings']['config_sync_directory'] = (object) [ 'value' => $this->syncDirectory, 'required' => TRUE, ]; - // Other directories will be created too. - $this->settings['config_directories']['custom'] = (object) [ - 'value' => $this->publicFilesDirectory . '/config_custom', - 'required' => TRUE, - ]; } /** @@ -42,7 +37,6 @@ public function testInstaller() { $this->assertUrl('user/1'); $this->assertResponse(200); $this->assertTrue(file_exists($this->syncDirectory) && is_dir($this->syncDirectory), "The directory {$this->syncDirectory} exists."); - $this->assertTrue(file_exists($this->publicFilesDirectory . '/config_custom') && is_dir($this->publicFilesDirectory . '/config_custom'), "The directory {$this->publicFilesDirectory}/custom_config exists."); } } diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerCustomConfigDirectoryCreateTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerCustomConfigDirectoryCreateTest.php new file mode 100644 index 0000000000..9e7ab31578 --- /dev/null +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerCustomConfigDirectoryCreateTest.php @@ -0,0 +1,44 @@ +settings['config_directories']['custom'] = (object) [ + 'value' => $this->publicFilesDirectory . '/config_custom', + 'required' => TRUE, + ]; + } + + /** + * Verifies that installation succeeded. + * + * @expectedDeprecation Automatic creation of 'custom' configuration directory will be removed from drupal:9.0.0. See https://www.drupal.org/node/3018145. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertTrue(file_exists($this->publicFilesDirectory . '/config_custom') && is_dir($this->publicFilesDirectory . '/config_custom'), "The directory {$this->publicFilesDirectory}/custom_config exists."); + + // Ensure the sync directory also exists. + $sync_directory = Settings::get('config_sync_directory'); + $this->assertTrue(file_exists($sync_directory) && is_dir($sync_directory), "The directory {$sync_directory} exists."); + + } + +} diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php index 2fd69fa511..ec6b72b48f 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php @@ -23,7 +23,7 @@ protected function prepareEnvironment() { parent::prepareEnvironment(); mkdir($this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/config_read_only', 0444); $this->expectedFilePerms = fileperms($this->siteDirectory . '/config_read_only'); - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + $this->settings['settings']['config_sync_directory'] = (object) [ 'value' => $this->siteDirectory . '/config_read_only', 'required' => TRUE, ]; diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php index f902509feb..5ce2fce1da 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php @@ -44,7 +44,7 @@ protected function prepareEnvironment() { $path = $this->siteDirectory . '/profiles/' . $this->profile; if ($this->existingSyncDirectory) { $config_sync_directory = $this->siteDirectory . '/config/sync'; - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + $this->settings['settings']['config_sync_directory'] = (object) [ 'value' => $config_sync_directory, 'required' => TRUE, ]; diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php index 9ec2c767dc..596f522fb8 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php @@ -48,13 +48,11 @@ protected function prepareEnvironment() { ]; // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', - 'required' => TRUE, - ], + $this->settings['settings']['config_sync_directory'] = (object) [ + 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', + 'required' => TRUE, ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + mkdir($this->settings['settings']['config_sync_directory']->value, 0777, TRUE); } /** diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php index fdcd13c77f..791135e7a0 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php @@ -40,13 +40,11 @@ protected function prepareEnvironment() { ]; // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', - 'required' => TRUE, - ], + $this->settings['settings']['config_sync_directory'] = (object) [ + 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', + 'required' => TRUE, ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + mkdir($this->settings['settings']['config_sync_directory']->value, 0777, TRUE); } /** diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php index 2b0b35e69f..46d6f8b947 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php @@ -49,13 +49,11 @@ protected function prepareEnvironment() { // Pre-configure config directories. $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_staging', - 'required' => TRUE, - ], + $this->settings['settings']['config_sync_directory'] = (object) [ + 'value' => $site_path . '/files/config_staging', + 'required' => TRUE, ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + mkdir($this->settings['settings']['config_sync_directory']->value, 0777, TRUE); } /** diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php index 3b85dcaa3a..5af025e5ee 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php @@ -42,13 +42,11 @@ protected function prepareEnvironment() { // not be available at this point in the install process. $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_sync', - 'required' => TRUE, - ], + $this->settings['settings']['config_sync_directory'] = (object) [ + 'value' => $site_path . '/files/config_sync', + 'required' => TRUE, ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + mkdir($this->settings['settings']['config_sync_directory']->value, 0777, TRUE); } /** diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index a66bd5759e..5b93b5b7c2 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -171,9 +171,7 @@ protected function setUp() { $request = Request::createFromGlobals(); $class_loader = require $this->container->get('app.root') . '/autoload.php'; Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader); - foreach ($GLOBALS['config_directories'] as $type => $path) { - $this->configDirectories[$type] = $path; - } + $this->configDirectories['sync'] = Settings::get('config_sync_directory'); // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php index af27c7de57..74a022a83a 100644 --- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php @@ -3,11 +3,13 @@ namespace Drupal\FunctionalTests\Update; use Drupal\Component\Utility\Crypt; +use Drupal\Core\Site\Settings; use Drupal\Core\Test\TestRunnerKernel; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\SchemaCheckTestTrait; use Drupal\Core\Database\Database; use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Language\Language; use Drupal\Core\Url; use Drupal\Tests\RequirementsPageTrait; @@ -185,7 +187,8 @@ protected function setUp() { $this->installDrupal(); // Add the config directories to settings.php. - drupal_install_config_directories(); + $sync_directory = Settings::get('config_sync_directory'); + \Drupal::service('file_system')->prepareDirectory($sync_directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); // Set the container. parent::rebuildAll() would normally do this, but this // not safe to do here, because the database has not been updated yet. @@ -274,6 +277,12 @@ protected function prepareSettings() { 'required' => TRUE, ]; + // Set up sync directory. + $settings['settings']['config_sync_directory'] = (object) [ + 'value' => $this->publicFilesDirectory . '/config_sync', + 'required' => TRUE, + ]; + $this->writeSettings($settings); } diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigFileContentTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigFileContentTest.php index 4f106dab42..822ad07d30 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigFileContentTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigFileContentTest.php @@ -3,6 +3,7 @@ namespace Drupal\KernelTests\Core\Config; use Drupal\Core\Config\FileStorage; +use Drupal\Core\Site\Settings; use Drupal\KernelTests\KernelTestBase; /** @@ -205,7 +206,7 @@ public function testSerialization() { ]; // Encode and write, and reload and decode the configuration data. - $filestorage = new FileStorage(config_get_config_directory(CONFIG_SYNC_DIRECTORY)); + $filestorage = new FileStorage(Settings::get('config_sync_directory')); $filestorage->write($name, $config_data); $config_parsed = $filestorage->read($name); diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php index 29ff1fb596..9bb2cd3a5c 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php @@ -749,15 +749,18 @@ public function testInstallProfileMisMatch() { /** * Tests config_get_config_directory(). + * + * @group legacy + * @expectedDeprecation config_get_config_directory() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\Core\Site\Settings::get('config_sync_directory') instead. See https://www.drupal.org/node/3018145 */ public function testConfigGetConfigDirectory() { global $config_directories; - $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY); - $this->assertEqual($config_directories[CONFIG_SYNC_DIRECTORY], $directory); + // Ensure the global and the setting matches. + $this->assertSame(config_get_config_directory(CONFIG_SYNC_DIRECTORY), $config_directories[CONFIG_SYNC_DIRECTORY]); - $message = 'Calling config_get_config_directory() with CONFIG_ACTIVE_DIRECTORY results in an exception.'; + $message = 'Calling config_get_config_directory() with an invalid key results in an exception.'; try { - config_get_config_directory(CONFIG_ACTIVE_DIRECTORY); + config_get_config_directory('does_not_exist'); $this->fail($message); } catch (\Exception $e) { diff --git a/core/tests/Drupal/KernelTests/Core/Config/FileStorageFactoryTest.php b/core/tests/Drupal/KernelTests/Core/Config/FileStorageFactoryTest.php new file mode 100644 index 0000000000..c5fb1f965d --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Config/FileStorageFactoryTest.php @@ -0,0 +1,45 @@ +randomMachineName(); + $data = (array) $this->getRandomGenerator()->object(); + $storage = new FileStorage(Settings::get('config_sync_directory')); + $storage->write($name, $data); + + // Get the sync storage and read from it. + $sync = FileStorageFactory::getSync(); + $this->assertEquals($data, $sync->read($name)); + + // Unset the sync directory setting. + $settings = Settings::getInstance() ? Settings::getAll() : []; + unset($settings['config_sync_directory']); + new Settings($settings); + + // On an empty settings there is an exception thrown. + try { + FileStorageFactory::getSync(); + $this->fail("The exception was not thrown."); + } + catch (\Exception $exception) { + $this->assertEquals('In case the sync directory does not exist or is not defined in $settings["config_sync_directory"]', $exception->getMessage()); + } + } +} diff --git a/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php b/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php index a0982cbdb0..c22a5bce01 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php @@ -70,13 +70,10 @@ protected function setUpFilesystem() { mkdir($this->siteDirectory, 0775); mkdir($this->siteDirectory . '/files', 0775); - mkdir($this->siteDirectory . '/files/config/' . CONFIG_SYNC_DIRECTORY, 0775, TRUE); + mkdir($this->siteDirectory . '/files/config/sync', 0775, TRUE); $this->setSetting('file_public_path', $public_file_directory); - - $GLOBALS['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => $this->siteDirectory . '/files/config/sync', - ]; + $this->setSetting('config_sync_directory', $this->siteDirectory . '/files/config/sync'); } /** diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 6cfbda5ae0..b33737fae5 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -292,15 +292,12 @@ protected function setUpFilesystem() { $this->siteDirectory = vfsStream::url('root/' . $test_site_path); mkdir($this->siteDirectory . '/files', 0775); - mkdir($this->siteDirectory . '/files/config/' . CONFIG_SYNC_DIRECTORY, 0775, TRUE); + mkdir($this->siteDirectory . '/files/config/sync', 0775, TRUE); $settings = Settings::getInstance() ? Settings::getAll() : []; $settings['file_public_path'] = $this->siteDirectory . '/files'; + $settings['config_sync_directory'] = $this->siteDirectory . '/files/config/sync'; new Settings($settings); - - $GLOBALS['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => $this->siteDirectory . '/files/config/sync', - ]; } /** @@ -1051,9 +1048,9 @@ public function __get($name) { } if ($name === 'configDirectories') { - trigger_error(sprintf("KernelTestBase::\$%s no longer exists. Use config_get_config_directory() directly instead.", $name), E_USER_DEPRECATED); + trigger_error(sprintf("KernelTestBase::\$%s no longer exists. Use Settings::get('config_sync_directory') directly instead.", $name), E_USER_DEPRECATED); return [ - CONFIG_SYNC_DIRECTORY => config_get_config_directory(CONFIG_SYNC_DIRECTORY), + CONFIG_SYNC_DIRECTORY => Settings::get('config_sync_directory'), ]; } diff --git a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php index 82f98f5dcc..c43bc99a52 100644 --- a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php +++ b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php @@ -3,7 +3,9 @@ namespace Drupal\Tests\Core\Site; use Drupal\Core\Site\Settings; +use Drupal\Tests\Traits\ExpectDeprecationTrait; use Drupal\Tests\UnitTestCase; +use org\bovigo\vfs\vfsStream; /** * @coversDefaultClass \Drupal\Core\Site\Settings @@ -11,6 +13,8 @@ */ class SettingsTest extends UnitTestCase { + use ExpectDeprecationTrait; + /** * Simple settings array to test against. * @@ -117,10 +121,16 @@ public function testSerialize() { * @covers ::getApcuPrefix */ public function testGetApcuPrefix() { - $settings = new Settings(['hash_salt' => 123, 'apcu_ensure_unique_prefix' => TRUE]); + $settings = new Settings([ + 'hash_salt' => 123, + 'apcu_ensure_unique_prefix' => TRUE, + ]); $this->assertNotEquals($settings::getApcuPrefix('cache_test', '/test/a'), $settings::getApcuPrefix('cache_test', '/test/b')); - $settings = new Settings(['hash_salt' => 123, 'apcu_ensure_unique_prefix' => FALSE]); + $settings = new Settings([ + 'hash_salt' => 123, + 'apcu_ensure_unique_prefix' => FALSE, + ]); $this->assertNotEquals($settings::getApcuPrefix('cache_test', '/test/a'), $settings::getApcuPrefix('cache_test', '/test/b')); } @@ -141,4 +151,105 @@ public function testGetInstanceReflection() { $settings->getInstance(); } + /** + * @runInSeparateProcess + * @group legacy + * @covers ::__construct + * @dataProvider configDirectoriesBcLayerProvider + */ + public function testConfigDirectoriesBcLayer($settings_file_content, $directory, $expect_deprecation) { + global $config_directories; + $class_loader = NULL; + + $vfs_root = vfsStream::setup('root'); + $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); + vfsStream::newFile('settings.php') + ->at($sites_directory) + ->setContent($settings_file_content); + + if ($expect_deprecation) { + $this->expectDeprecation('$config_directories[\'sync\'] has moved to $settings[\'config_sync_directory\']. See https://www.drupal.org/node/3018145.'); + } + + Settings::initialize(vfsStream::url('root'), 'sites', $class_loader); + $this->assertSame($directory, Settings::get('config_sync_directory')); + $this->assertSame($directory, $config_directories['sync']); + } + + /** + * Data provider for self::testConfigDirectoriesBcLayer(). + */ + public function configDirectoriesBcLayerProvider() { + $no_config_directories = <<<'EOD' + [ + $no_config_directories, + 'foo', + FALSE, + ], + 'Only $config_directories' => [$only_config_directories, 'bar', TRUE], + 'Both' => [$both, 'foo', FALSE], + ]; + } + + /** + * @runInSeparateProcess + * @group legacy + */ + public function testConfigDirectoriesBcLayerEmpty() { + global $config_directories; + $class_loader = NULL; + + $vfs_root = vfsStream::setup('root'); + $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); + vfsStream::newFile('settings.php')->at($sites_directory)->setContent(<<<'EOD' +assertNull(Settings::get('config_sync_directory')); + $this->assertNull($config_directories); + } + + /** + * @runInSeparateProcess + * @group legacy + */ + public function testConfigDirectoriesBcLayerMultiple() { + global $config_directories; + $class_loader = NULL; + + $vfs_root = vfsStream::setup('root'); + $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); + vfsStream::newFile('settings.php')->at($sites_directory)->setContent(<<<'EOD' +assertSame('foo', Settings::get('config_sync_directory')); + $this->assertSame('foo', $config_directories['sync']); + $this->assertSame('custom', $config_directories['custom']); + } + } diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index ed813f1fad..d88742c677 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -229,29 +229,15 @@ /** * Location of the site configuration files. * - * The $config_directories array specifies the location of file system - * directories used for configuration data. On install, the "sync" directory is - * created. This is used for configuration imports. The "active" directory is - * not created by default since the default storage for active configuration is - * the database rather than the file system. (This can be changed. See "Active - * configuration settings" below). + * The $settings['config_sync_directory'] specifies the location of file system + * directory used for syncing configuration data. On install, the directory is + * created. This is used for configuration imports. * - * The default location for the "sync" directory is inside a randomly-named - * directory in the public files path. The setting below allows you to override - * the "sync" location. - * - * If you use files for the "active" configuration, you can tell the - * Configuration system where this directory is located by adding an entry with - * array key CONFIG_ACTIVE_DIRECTORY. - * - * Example: - * @code - * $config_directories = [ - * CONFIG_SYNC_DIRECTORY => '/directory/outside/webroot', - * ]; - * @endcode + * The default location for this directory is inside a randomly-named + * directory in the public files path. The setting below allows you to set + * its location. */ -$config_directories = []; +# $settings['config_sync_directory'] = '/directory/outside/webroot'; /** * Settings: @@ -596,25 +582,6 @@ # ini_set('pcre.backtrack_limit', 200000); # ini_set('pcre.recursion_limit', 200000); -/** - * Active configuration settings. - * - * By default, the active configuration is stored in the database in the - * {config} table. To use a different storage mechanism for the active - * configuration, do the following prior to installing: - * - Create an "active" directory and declare its path in $config_directories - * as explained under the 'Location of the site configuration files' section - * above in this file. To enhance security, you can declare a path that is - * outside your document root. - * - Override the 'bootstrap_config_storage' setting here. It must be set to a - * callable that returns an object that implements - * \Drupal\Core\Config\StorageInterface. - * - Override the service definition 'config.storage.active'. Put this - * override in a services.yml file in the same directory as settings.php - * (definitions in this file will override service definition defaults). - */ -# $settings['bootstrap_config_storage'] = ['Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage']; - /** * Configuration overrides. *