diff --git a/core/globals.api.php b/core/globals.api.php index 1487b1942c8a..0f60ad558532 100644 --- a/core/globals.api.php +++ b/core/globals.api.php @@ -62,7 +62,10 @@ global $config; /** * 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 69544ba76cc3..ef9090c8d3ce 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -13,6 +13,7 @@ use Drupal\Core\Config\BootstrapConfigStorageFactory; 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 @@ const CONFIG_ACTIVE_DIRECTORY = 'active'; /** * $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 @@ define('DRUPAL_ROOT', dirname(dirname(__DIR__))); * 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 6356a3f4b7a7..5327a38035c0 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 5258b5d19b9f..d788288a3a72 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 7ac7f3c6025a..2cb4b212114c 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 9e324975f9a0..ec7d82e80003 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 @@ class FileStorageFactory { * 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('The config sync directory 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 185a27be3c13..b0b72f6a995e 100644 --- a/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php @@ -5,6 +5,7 @@ namespace Drupal\Core\Installer\Form; 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 @@ class SelectProfileForm extends FormBase { * {@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 @@ class SelectProfileForm extends FormBase { } } - 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 @@ class SelectProfileForm extends FormBase { ], '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 @@ class SelectProfileForm extends FormBase { * {@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 b82bb01ae1e6..75099a2a354a 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -4,9 +4,11 @@ namespace Drupal\Core\Installer\Form; 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 @@ class SiteSettingsForm extends FormBase { '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 @@ class SiteSettingsForm extends FormBase { $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 c6fbed659f98..ad8713a7524c 100644 --- a/core/lib/Drupal/Core/Site/Settings.php +++ b/core/lib/Drupal/Core/Site/Settings.php @@ -128,6 +128,16 @@ final class Settings { // 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 46fea2f830b1..de4f9ab2cf3e 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -43,6 +43,11 @@ trait FunctionalTestSetupTrait { /** * 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 @@ trait FunctionalTestSetupTrait { */ 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 4911d98c689c..7632e1840811 100644 --- a/core/modules/config/src/Form/ConfigImportForm.php +++ b/core/modules/config/src/Form/ConfigImportForm.php @@ -7,6 +7,7 @@ use Drupal\Core\Config\StorageInterface; 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 @@ class ConfigImportForm extends FormBase { 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 @@ class ConfigImportForm extends FormBase { * {@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 @@ class ConfigImportForm extends FormBase { 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 6f6659d743ba..bc4dc7c5c32a 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 @@ class ConfigImportUploadTest extends BrowserTestBase { $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 15dc91e0f2c8..92aae4c9136f 100644 --- a/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php +++ b/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php @@ -5,6 +5,7 @@ namespace Drupal\Tests\config\Functional; 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 @@ class ConfigInstallWebTest extends BrowserTestBase { $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 8d5112ef16dc..e889905ba84e 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 @@ class FieldImportCreateTest extends FieldKernelTestBase { // 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 4df97190655e..66b41db35447 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 @@ class NodeImportCreateTest extends KernelTestBase { $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 0f4af3a3a74e..e173f8f35e42 100644 --- a/core/modules/simpletest/src/InstallerTestBase.php +++ b/core/modules/simpletest/src/InstallerTestBase.php @@ -148,9 +148,7 @@ abstract class InstallerTestBase extends WebTestBase { $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 80c8eb0b7fb8..94ce0816da05 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -138,23 +138,26 @@ abstract class KernelTestBase extends TestBase { /** * 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 @@ EOD; // @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 4fce148cf1c4..1af310bc80eb 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -1103,7 +1103,6 @@ abstract class TestBase { // 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 @@ abstract class TestBase { $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 49d96ac4b9f8..673404f41c74 100644 --- a/core/modules/system/src/Tests/Update/UpdatePathTestBase.php +++ b/core/modules/system/src/Tests/Update/UpdatePathTestBase.php @@ -187,9 +187,6 @@ abstract class UpdatePathTestBase extends WebTestBase { $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 61b619dc3281..1dec9d14c900 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 6b25e235a332..845b5a8e92e0 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 @@ class StatusTest extends BrowserTestBase { $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 60f3d0aa0d86..d64d016e99c4 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php @@ -64,13 +64,11 @@ class DistributionProfileExistingSettingsTest extends InstallerTestBase { // 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 7de0652fe93e..0d955b6957c5 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 71e8b0594d9d..dcb47b5ee340 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php @@ -5,7 +5,7 @@ namespace Drupal\FunctionalTests\Installer; 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 @@ class InstallerConfigDirectorySetNoDirectoryTest extends InstallerTestBase { $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 000000000000..9e7ab31578a2 --- /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 2fd69fa511b5..ec6b72b48fc3 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php @@ -23,7 +23,7 @@ class InstallerExistingConfigDirectoryTest extends InstallerTestBase { 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 f902509feb63..5ce2fce1da32 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php @@ -44,7 +44,7 @@ abstract class InstallerExistingConfigTestBase extends InstallerTestBase { $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 9ec2c767dc85..596f522fb842 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php @@ -48,13 +48,11 @@ class InstallerExistingSettingsMismatchProfileTest extends InstallerTestBase { ]; // 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 fdcd13c77f07..791135e7a0b1 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php @@ -40,13 +40,11 @@ class InstallerExistingSettingsNoProfileTest extends InstallerTestBase { ]; // 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 2b0b35e69f6c..46d6f8b94714 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsReadOnlyMismatchProfileTest.php @@ -49,13 +49,11 @@ class InstallerExistingSettingsReadOnlyMismatchProfileTest extends InstallerTest // 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 3b85dcaa3a6c..5af025e5ee4c 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php @@ -42,13 +42,11 @@ class InstallerExistingSettingsTest extends InstallerTestBase { // 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 a66bd5759e8b..5b93b5b7c2bd 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -171,9 +171,7 @@ abstract class InstallerTestBase extends BrowserTestBase { $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 af7b362f1071..06a0ef676bbb 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 @@ abstract class UpdatePathTestBase extends BrowserTestBase { $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 @@ abstract class UpdatePathTestBase extends BrowserTestBase { '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 4f106dab4241..822ad07d3018 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 @@ class ConfigFileContentTest extends KernelTestBase { ]; // 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 29ff1fb59683..9bb2cd3a5ccc 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php @@ -749,15 +749,18 @@ class ConfigImporterTest extends KernelTestBase { /** * 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 000000000000..0d885dac4f2f --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Config/FileStorageFactoryTest.php @@ -0,0 +1,46 @@ +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('The config sync directory 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 a0982cbdb0d4..c22a5bce0143 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileTestBase.php @@ -70,13 +70,10 @@ abstract class FileTestBase extends KernelTestBase { 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 6cfbda5ae092..b33737fae510 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -292,15 +292,12 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa $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 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa } 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 82f98f5dcc1f..c43bc99a527d 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 @@ use Drupal\Tests\UnitTestCase; */ class SettingsTest extends UnitTestCase { + use ExpectDeprecationTrait; + /** * Simple settings array to test against. * @@ -117,10 +121,16 @@ class SettingsTest extends UnitTestCase { * @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 @@ class SettingsTest extends UnitTestCase { $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 ed813f1fad80..d88742c677ae 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -229,29 +229,15 @@ $databases = []; /** * 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 @@ if ($settings['hash_salt']) { # 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. *