Problem/Motivation

When active configuration was stored in files very early access to $config_directories was necessary. That's no longer the case. Let's move it to $settings so it is more injectable into services, have less globals, and at the same time clean up:

  • config_get_config_directory()
  • CONFIG_SYNC_DIRECTORY

Additionally whilst we clear this up we could take the opportunity to reduce the ability to set multiple directories to a single sync directory. The support for multiple directories stems from a early CMI development in which the active config was also read from files. Later it was decided to have the active config storage by default in the database for several good reasons (performance, security, etc). So Drupal core only uses one config directory for the synchronisation.

Proposed resolution

We've decided to support only the config sync directory - see #13.

Only support sync directory

  • Use $settings['config_sync_directory'] instead of $config_directories[CONFIG_SYNC_DIRECTORY] in settings.php.
  • Deprecate CONFIG_SYNC_DIRECTORY
  • Deprecate config_get_config_directory() and recommend Settings::get('config_sync_directory') instead.
  • Deprecate drupal_install_config_directories()

Support multiple

  • Move global $config_directories to $settings['config_directories']
  • Add Settings::getConfigDirectory() and deprecate config_get_config_directory()
  • Move CONFIG_SYNC_DIRECTORY to StorageInterface::SYNC_DIRECTORY

Remaining tasks

User interface changes

None

API changes

  • Use $settings['config_sync_directory'] instead of $config_directories[CONFIG_SYNC_DIRECTORY] in settings.php.
  • Deprecate CONFIG_SYNC_DIRECTORY
  • Deprecate config_get_config_directory() and recommend Settings::get('config_sync_directory') instead.
  • Deprecate drupal_install_config_directories()

Data model changes

None

Release notes snippet

The configuration sync directory is now defined in $settings['config_sync_directory'] in settings.php.
The use of $config_directories is deprecated in Drupal 8.8 and will be removed from Drupal 9. See https://www.drupal.org/node/3018145 for more information.

CommentFileSizeAuthor
#59 2980712-2-59.patch65.58 KBalexpott
#59 53-59-interdiff.txt1.71 KBalexpott
#53 2980712-53.patch64.55 KBbircher
#53 interdiff-2980712-48-53.txt1.5 KBbircher
#48 interdiff-2980712-45-48.txt2.66 KByogeshmpawar
#48 2980712-48.patch64.56 KByogeshmpawar
#45 interdiff-2980712-42-45.txt923 bytesyogeshmpawar
#45 2980712-45.patch64.59 KByogeshmpawar
#42 interdiff-2980712-40-42.txt5.88 KBbircher
#42 2980712-42.patch64.62 KBbircher
#40 interdiff-2980712-39-40.txt1.83 KBbircher
#40 2980712-40.patch64.66 KBbircher
#39 interdiff-2980712-36-39.txt6.89 KBbircher
#39 2980712-39-minus-9.patch65.05 KBbircher
#39 2980712-39-minus-8.patch65.68 KBbircher
#39 2980712-39.patch66.07 KBbircher
#36 interdiff-2980712-35-36.txt1.64 KBbircher
#36 2980712-36.patch64.6 KBbircher
#35 interdiff-2980712-31-35-reroll.txt2.21 KBbircher
#35 2980712-35-reroll.patch62.52 KBbircher
#35 interdiff-2980712-31-35.txt3.22 KBbircher
#35 2980712-35.patch62.96 KBbircher
#31 2980712-31.patch62.62 KBbircher
#31 interdiff-2980712-29-31.txt5.67 KBbircher
#31 interdiff-2980712-28-29.txt9.47 KBbircher
#29 2980712-29.patch60.53 KBmpotter
#28 2980712-28.patch62.88 KBalexpott
#28 23-28-interdiff.txt9.98 KBalexpott
#23 2980712-23.patch62.87 KBalexpott
#23 21-23-interdiff.txt838 bytesalexpott
#21 2980712-20.patch62.83 KBalexpott
#21 19-20-interdiff.txt7.8 KBalexpott
#19 2980712-18.patch66.5 KBalexpott
#19 14-18-interdiff.txt13.6 KBalexpott
#14 2980712-14.patch55.31 KBalexpott
#11 2980712-11.patch57.29 KBalexpott
#11 5-11-interdiff.txt1.68 KBalexpott
#5 2980712-5.patch54.68 KBalexpott
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bircher created an issue. See original summary.

moshe weitzman’s picture

This is a good cleanup IMO.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

lpeabody’s picture

Just going to throw this out there for those who use the platform, but in my experience Acquia Cloud Site Factory no longer provides a mechanism to detect what the installed site profile is at the settings.php file at run time. If this change was added I'm pretty sure this would hose a lot of ACSF subscriptions.

EDIT: I am in no way implying that Drupal should be built around ACSF ;)

alexpott’s picture

andypost’s picture

Issue tags: +Kill includes
alexpott’s picture

So #5 moves the $config_directories global to $settings['config_directories']. If we are going to do this I think it is also worth discussing whether or not we make it $settings['config_sync_directory'} and stop supporting multiple directories in core. I think this could make sense but it would be great to have more opinions. One advantage of the current situation is that you can write code that deals with config and it can scan all the config_directories and provide generic functionality. If we make it a single value and not an array then we lose that functionality.

alexpott’s picture

Issue summary: View changes

Updated the IS to reflect the 2 solutions and the choice we should be making on this issue.

alexpott’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 5: 2980712-5.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review
FileSize
1.68 KB
57.29 KB

Status: Needs review » Needs work

The last submitted patch, 11: 2980712-11.patch, failed testing. View results

alexpott’s picture

Discussed the multiple config directories vs the single configuration sync directory with @bircher in Slack. Here's our discussion:


bircher [11:07 AM]

@alexpott I think we should not have it be an array. core uses one sync storage, and should use a setting for that, I am not against other workflows with other storages, but then core should also support that, in my opinion it is a disservice to users and developers to think that there can be more than one when you can't.

alexpott [11:09 AM]

@bircher yeah but… the array does mean as a contrib maintainer you can write generic modules that can deal with whatever storages are defined their. Removing the array means we no longer support that.

bircher [11:17 AM]

hmm, yea I think there are some modules that do that now, I don't really know what for though
@alexpott the only thing I can think of is multisite/site-factories where you want to maintain several sites with one code base and easily switch which site is active in your environment

and for that you can just put some logic around how you set the settings

alexpott [11:22 AM]

@bircher I’m on the fence. I’m not sure I care too much :slightly_smiling_face: but I think if we move to a single value we need to make the decision knowing what contrib / custom flows we would affect.

bircher [11:29 AM]

@alexpott that is true. but if we want to give a standardised way to deal with multiple config directories then we should also have a service for them.. otherwise we might as well not have it.. the way we have it now feels like it is not really done on purpose and more just happened by accident

alexpott’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
55.31 KB

Here's a patch that only supports the sync directory and moves it to $settings['config_sync_directory']

moshe weitzman’s picture

I support the switch to one directory. Its much clearer for the common use case.

andypost’s picture

Status: Needs review » Needs work

The last submitted patch, 14: 2980712-14.patch, failed testing. View results

alexpott’s picture

@andypost yep but I don't think a general refactor of Settings and how we do that means we should not try to centralise our current globals on it. Once everything is in Settings is becomes easier to consider how to fix all the global application settings in one go.

alexpott’s picture

Status: Needs work » Needs review
FileSize
13.6 KB
66.5 KB

Here's some more work. We can deprecate some other methods that don't make much sense.

andypost’s picture

@alexpott yep, totally agree - iterative approach makes the whole picture clear

alexpott’s picture

I've reverted some changes to deprecated functions because if a function is deprecated then there is no point taking the risk to update the code. Also updated default.settings.php. This shows us that some people were at one point very very keen to keep active configuration in the filesystem. With this change that probably comes trickier but CONFIG_ACTIVE_DIRECTORY has been deprecated for a very long time.

The last submitted patch, 19: 2980712-18.patch, failed testing. View results

alexpott’s picture

The last submitted patch, 21: 2980712-20.patch, failed testing. View results

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

We can do a slightly better deprecation in Settings so it has less unrelated impact.

mpotter’s picture

Here is a reroll against latest 8.7.x. My Mac interdiff utility gives an error when trying to create it but I can't pin down why. But there were some changed in tests so #28 failed to apply. Also, calls to `file_prepare_directory()` were removed in core and replaced with `\Drupal::service('file_system')->prepareDirectory()` so I made that change to the new tests also.

Status: Needs review » Needs work

The last submitted patch, 29: 2980712-29.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

bircher’s picture

Status: Needs work » Needs review
FileSize
9.47 KB
5.67 KB
62.62 KB

So I tried re-rolling the patch from #28 and I ended up with a different diff to 8.7.x.
Attached is the interdiff from my re-roll of #28 to #29.

The additional file_system service usage makes sense so I incorporated them also in this patch.

bircher’s picture

While re-rolling I noticed the following:

+++ b/core/modules/config/src/Form/ConfigImportForm.php
@@ -52,7 +64,8 @@ public function getFormId() {
    public function buildForm(array $form, FormStateInterface $form_state) {
+    // @todo what about the unset case?

What does this mean?

alexpott’s picture

  1. +++ b/core/lib/Drupal/Core/Installer/Form/SelectProfileForm.php
    @@ -134,10 +135,11 @@ public function buildForm(array $form, FormStateInterface $form_state, $install_
    +      // @todo inject and handle case where config_sync_directory is not set.
    +      $sync = new FileStorage(Settings::get('config_sync_directory'));
    

    Not sure about this @todo anymore either. Not sure why we'd both injecting anything here. So early in the installer. I guess the current HEAD behaviour here is that we would throw an exception if the directory was not configured. I guess we should continue to do that.

  2. +++ b/core/modules/config/src/Form/ConfigImportForm.php
    @@ -52,7 +64,8 @@ public function getFormId() {
    -    $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
    +    // @todo what about the unset case?
    +    $directory = $this->settings->get('config_sync_directory');
    

    I guess the thing is before we would have thrown an exception if config_get_config_directory() was unable to determine a directory. Now we don't. Which makes things a bit more fragile because we're not throwing an early error.

Status: Needs review » Needs work

The last submitted patch, 31: 2980712-31.patch, failed testing. View results

bircher’s picture

Attached a fixed reroll patch.

I removed the two todos because I checked and it is not necessary to do anything further.

I went through the list of code occurrences of get('config_sync_directory' to see where we use the new settings. And they are replacing where we currently directly access the global variable (so no exception) or they have the same outcome also without the exception.
The only thing where we don't throw the exception is in FileStorageFactory::getSync so I added a patch that does that.

bircher’s picture

adding a test for the exception.

mpotter’s picture

  1. +++ b/core/globals.api.php
    @@ -62,7 +62,11 @@
      * @see drupal_install_config_directories()
    

    Do we still need to reference drupal_install_config_directories() since it's being deprecated and the issue reference should cover it?

  2. +++ b/core/includes/bootstrap.inc
    @@ -137,6 +138,10 @@
    + * @see https://www.drupal.org/node/2501187
    

    Is this the correct reference? Others here are for https://www.drupal.org/node/3018145

  3. +++ b/core/includes/bootstrap.inc
    @@ -137,6 +138,10 @@
      * @see config_get_config_directory()
    

    Do we still need to reference config_get_config_directory() here?

  4. +++ b/core/includes/install.core.inc
    @@ -380,7 +380,7 @@ function install_begin_request($class_loader, &$install_state) {
    +    $sync_directory = Settings::get('config_sync_directory', FALSE);
    

    We reference 'config_sync_directory' a LOT now. Should this be a new constant? (We can't reuse CONFIG_SYNC_DIRECTORY though).

  5. +++ b/core/lib/Drupal/Core/Config/FileStorageFactory.php
    @@ -23,9 +25,18 @@ public static function getActive() {
    +   *   In case the sync directory does not exist or is not set up.
    

    What do we mean by "or is not set up"? Could change to "In case the sync directory does not exist or is not defined in $settings['config_sync_directory']"

  6. +++ b/core/lib/Drupal/Core/Config/FileStorageFactory.php
    @@ -23,9 +25,18 @@ public static function getActive() {
    +      throw new \Exception("The sync configuration directory does not exist or is not set up.");
    

    See above comment for improved exception message.

  7. +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
    @@ -225,12 +227,36 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +    // If settings.php does not contain a config sync directory name we need to
    +    // configure one.
    +    if (empty(Settings::get('config_sync_directory'))) {
    ...
    +    }
    

    Previously we encapsulated this code into the drupal_install_config_directories() function. With that function deprecated, I still wonder about splitting this code into a helper function for readability. Perhaps a protected drupal_install_config_directory().

  8. +++ b/core/lib/Drupal/Core/Site/Settings.php
    @@ -181,4 +191,11 @@ public static function getApcuPrefix($identifier, $root, $site_path = '') {
    +  /**
    +   * Destroys the settings singleton instance.
    +   */
    +  public static function destroy() {
    +    self::$instance = NULL;
    +  }
    +
    

    Is this related to the config_sync_directory change or some other bug fix?

  9. +++ b/core/modules/system/system.install
    @@ -423,17 +423,19 @@ function system_requirements($phase) {
    +  // Find the site path. Kernel service is not always available at this point,
    +  // but is preferred, when available.
    +  if (\Drupal::hasService('kernel')) {
    +    $site_path = \Drupal::service('site.path');
    +  }
    +  else {
    +    $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
    +  }
    +
    

    This doesn't seem related to this issue. The check for $phase of "runtime" around this was removed and not sure how that's related to the config_sync_directory.

  10. +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerCustomConfigDirectoryCreateTest.php
    @@ -0,0 +1,44 @@
    + * Tests the installer when a custom config_directory set up but does not exist.
    

    This is the same comment as for InstallerConfigDirectorySetNoDirectoryTest.php, so one of the comments is probably incorrect.

  11. +++ b/core/tests/Drupal/KernelTests/Core/Config/FileStorageFactoryTest.php
    @@ -0,0 +1,45 @@
    +      $this->assertEquals("The sync configuration directory does not exist or is not set up.", $exception->getMessage());
    

    If changing the exception message above, change it here too.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

bircher’s picture

I had to re-roll the patch, so the interdiff is not really all that correct I think as I might have changed something inadvertently.

#37
1) yes, changed
2) true, changed
3) no, changed
4) I think it is fine, usually settings keys are referenced by their string values. Also we can add a constant in a followup if we really want to.
5) changed the string as suggested.
6) see 5
7) sure, added a method
8) I think this is related to the tests needing the settings now in places they didn't before, attached is a patch without that change.
9) I think this is related to the code later down the function needing the settings singleton set up, but attached is also a patch without that change.
10) They are almost the same test, and test almost the same thing, one is the new one and one is legacy functionality one. I removed the underscore since that makes one think about the variable.
11) see 5

bircher’s picture

#37
8 & 9, so patches without that pass so this was unrelated improvements so attached is a patch without it.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/globals.api.php
    @@ -62,7 +62,10 @@
    + * @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use
    + *   \Drupal\Core\Site\Settings::get('config_sync_directory') instead.
    

    We need to update all the deprecations to 8.8.0 - and lets use the new format.
    @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use...

    There's more than just this one... also the @trigger_error()'s use the same format.

bircher’s picture

Status: Needs work » Needs review
FileSize
64.62 KB
5.88 KB

Of course! thanks for catching that, yes we are in 8.8 now.

Status: Needs review » Needs work

The last submitted patch, 42: 2980712-42.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
FileSize
64.59 KB
923 bytes

Updated patch with an interdiff.

borisson_’s picture

Most of this looks really good already, I found some nitpicks but haven't read everything yet.

  1. +++ b/core/includes/install.inc
    @@ -479,10 +477,13 @@ function _drupal_rewrite_settings_dump_one(\stdClass $variable, $prefix = '', $s
    + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
    + *   There is no replacement.
    

    I did not know this, but we have a precedent of doing this.

  2. +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
    @@ -241,4 +257,26 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +  private function createRandomConfigDirectory() {
    

    This should probably be protected instead of private?

  3. +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
    @@ -241,4 +257,26 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +      // 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.
    

    80 cols.

  4. +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
    @@ -749,15 +749,19 @@ public function testInstallProfileMisMatch() {
    +    // @todo this is a legacy test.
    

    I think this todo can be removed?

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
FileSize
64.56 KB
2.66 KB

Comments addressed in #46 & added an interdiff as well.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

As far as I understand it, this seems like a good way to deprecate the old way of doing things.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 48: 2980712-48.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs work » Reviewed & tested by the community

Back to rtbc, looks like that was a random fail.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Config/FileStorageFactory.php
@@ -23,9 +25,19 @@ public static function getActive() {
+      throw new \Exception('In case the sync directory does not exist or is not defined in $settings["config_sync_directory"]');

This exception message reads wrong to me - shouldn't it just say 'The config sync directory is not defined in $settings['config_sync_directory']'?

bircher’s picture

Status: Needs work » Needs review
FileSize
1.5 KB
64.55 KB

#52 Oh of course!

bircher’s picture

Issue summary: View changes

I added the Release notes snippet too so that it won't get held up by that in the end.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

The exception was changed to @catch's suggestion, back to rtbc.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 53: 2980712-53.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs work » Reviewed & tested by the community

Retesting because the error message indicated that the failure probably had nothing to do with this patch.

PDOStatement::execute(): MySQL server has gone away

borisson_’s picture

Status: Reviewed & tested by the community » Needs work

I came back to check if the test was green after I put it on rtbc earlier this morning, I noticed that this is introducing 3 new CS errors, we should fix those as well, back to NW for that small change.

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
1.71 KB
65.58 KB

Fixed up the coding standards

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 59: 2980712-2-59.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Reviewed & tested by the community

  • catch committed 1a2babd on 8.8.x
    Issue #2980712 by bircher, alexpott, yogeshmpawar, mpotter, borisson_:...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 1a2babd and pushed to 8.8.x. Thanks!

xjm’s picture

Status: Fixed » Needs work
Issue tags: +Needs release note

This has been reported to be a disruptive change; can we get a release note? (Edit: And/or update the CR to clarify that there isn't actually a break and merely a deprecation, depending on what's actually the case here.)

bircher’s picture

Issue summary: View changes
Status: Needs work » Needs review

I added a sentence about the depreciation. Is that what you would expect? We could add a link to the chance notice.

bircher’s picture

Issue summary: View changes
xjm’s picture

Thanks @bircher. So based on that note, the old API will continue to work and there's no impact on existing sites? (Is the same also true of the related functions and constants?) If so (if there's no actual disruptions in D8) let's instead update the CR to clarify that for all of them. (Deprecation is mentioned for some but not all of the affected APIs.)

Berdir’s picture

I think this is worth mentioning. The important change here isn't the API changes, those are mostly internal and probably almost nobody uses them except some config-related modules.

The change that affects every site is that site owners need to update their settings.php file and change the generated PHP code (or the one they adjusted themself) to something else. And that seems worth mentioning. It doesn't break D8 in any way, but users need to do this before updating to D9.

bircher’s picture

Issue summary: View changes

Yes everything continues to work for Drupal 8. This is a Drupal 9 thing which sites have a chance to adopt from 8.8.0 onwards. As Berdir correctly pointed out the deprecated functions are most likely not widely used but the change in settings.php affects everyone.

But since this is literally just a global php variable it is not complex to continue using it in custom code.

webchick’s picture

The change that affects every site is that site owners need to update their settings.php file and change the generated PHP code (or the one they adjusted themself) to something else.

Just a reminder that we're trying really hard to make Drupal 9 easy to upgrade to. We should try and minimize these kinds of "all site owners need to..." changes outside of major/critical issues, IMO. (Not arguing for rolling this back, per se, just a general plea to consider "downstream" impact of DX improvements in general, especially this late in D8's lifetime.)

moshe weitzman’s picture

if not in a major version, when are we supposed to make a change like this? IMO we should be making more cleanups in Drupal 9, not less.

alexpott’s picture

Issue summary: View changes
bircher’s picture

I understand that we want to limit the amount of deprecations for Drupal 9 to be easier to upgrade to. But at the same time this issue has caused confusion and false hope that CMI (1) was going to be more than it was because the current array came to be an array in early days of CMI and it just wasn't a priority to clean it up before 8.0.0. So people (me included) saw an array and automatically assumed that there should be more than one key when core only ever supported one.

On the bright side the work for updating it is in almost all cases a simple string replace away. And a site is not broken if it is not done, just the config import won't work and there is an insructive error message.

bircher’s picture

Status: Needs review » Fixed
Issue tags: -Needs release note +8.8.0 highlights

I think the reason this was re-opened is addressed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.