Problem/Motivation
- Optional configuration of module does not install during installing profile.
- So if default configuration of any module that dependences on optional configuration of module, so we could not install profile.
- System throws `Drupal\Core\Config\UnmetDependenciesException`
Steps to reproduce
- The profile dependences B module
- Module B dependences A module
- Module A has an entity field(called custom field) that puts under config/optional
- Module B has views that required custom field of A module, that puts under config/install
- Then use drush to install site.(`drush site-install profile ...`)
Why do we need to set dependence of default configuration base on optional configuration
- Optional configuration could not import translation.
- In config/optional/language/{lang_code} does not fetch/configure during installing module at all.
- I also check Process translation config files for custom modules, but it seems that system will ignore config/optional/language/{lang_code}
- As you know `lightning_media_document` was moved YAMLs file to config/optional here, so the problem occures at here.
Proposed resolution
- Check and create patch to fix.
Remaining tasks
- Test, release.
Investigate
- I checked and saw that the problem is:
- IN `core/includes/install.core.inc : install_tasks()`
system runs `install_profile_modules` before `install_install_profile`
...
'install_profile_modules' => [
'display_name' => t('Install site'),
'type' => 'batch',
],
...
'install_install_profile' => [],
....
- In `Drupal\Core\Config\ConfigInstaller : installDefaultConfig()`
When `'install_profile_modules'` runs, config/optional does not consider cause `InstallerKernel::installationAttempted()`.
At this time config/optional of A module did not install yet, so B module could not install, because dependence stuffs.
Then system throws `Drupal\Core\Config\UnmetDependenciesException`
if (!$this->isSyncing() && (!InstallerKernel::installationAttempted() || $profile_installed)) {
$optional_install_path = $extension_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
if (is_dir($optional_install_path)) {
// Install any optional config the module provides.
$storage = new FileStorage($optional_install_path, StorageInterface::DEFAULT_COLLECTION);
$this->installOptionalConfig($storage, '');
}
// Install any optional configuration entities whose dependencies can now
// be met. This searches all the installed modules config/optional
// directories.
$storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, FALSE, $this->installProfile);
$this->installOptionalConfig($storage, [$type => $name]);
}
- So I think above code should be
if (!$this->isSyncing()) {
$optional_install_path = $extension_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
...
$this->installOptionalConfig($storage, [$type => $name]);
}
- If i miss anything, please correct.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 3164982-1.patch | 945 bytes | tbcan |
Issue fork drupal-3164982
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
tbcanHope that can solve the problem
Comment #3
larowlanThe view needs to go in config/optional, not config/install
The resolver should detect that the required module is being enabled, and it will get installed.
Comment #4
tbcanHi there,
Thank you so much for reviewing.
=> Yes, i absolutely agree with you. The configuration can be imported when moves them to /config/optional
But unfortunately, YAMLs under config/optional/language/{langCode} could not be imported by ModuleHandler.
So meant that it can not import configuration translation.
As mentioned Process translation config files for custom modules, At commnet #13, we have no way to translate configuration under config/optional/language/{langCode}.
So thy why i created this patch.
Regards.
Can
Comment #7
mxr576We have bumped into this "chicken or egg problem" too and seems the short answer is currently, "required"/default dependencies cannot depend on "optional" dependencies because optional dependencies gets installed later.
Quote from our own issue tracker:
Comment #11
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Think to better show this issue it will need a test case to show the problem.
Comment #13
kingdutchWe are running into this in multiple places:
bookandnodeas dependencies to ensure the optional config's dependencies are satisfied.Attached is a patch that demonstrates this in the most simple form I could come up with:
I'll need someone smarter than me to let me know if the test is placed in the right Drupal core location or whether it should be moved elsewhere.
I'm moving this to "Needs review" for the test but to run, but I've already seen that the fix proposed in #2 is unfortunately not enough to make the test green, so this will need more work. The test-only.patch is also the interdiff :)
Comment #15
kingdutchI made a mistake in my earlier test in the naming of the config files which caused the test to be inaccurate. That's now fixed in the new test. I also had to make sure that within the test the ConfigInstaller was tricked into thinking we're in install mode to accurately show how the proposed patch fixes the issue.
The test now properly demonstrates the problem (which only exists during site installation and not for modules installed later) and shows that the proposed fix solves the issue (and all other core tests passing should show that it has no adverse effects).
I'm not sure whether the comment in the ConfigInstaller needs to be updated.
Comment #16
kingdutchTesting this patch against Open Social shows an interesting possible break for some modules:
In case Module A which is installed after module B provides a config entity in config/install that module B provides in config/optional then without this patch the installation will fail with Configuration object (object) provided by Module A already exist in active configuration.
This behavior is the same as it would be if you were to install modules after a site installation. However because optional configuration was previously only installed at the end of site-install, a rogue module that was part of the site-install process could beat the optional config to installation which makes Drupal think it was already installed.
This change might cause errors for people relying on this behavior during site-install but I don't think that should hold up this change since this is already considered incorrect from a "normal" post-site-install module installation.
Comment #17
borisson_There was a discussion about this on slack, which alex asked to summarize on this issue. I don't understand it well enough to summarize, but here's a link https://drupal.slack.com/archives/C1BMUQ9U6/p1703168240580519
I think this issue can stay in needs review, because we first have to decide on a direction, then we can look into the patch.
Comment #18
kingdutchThe request to summarize a few hours of conversation came just before the start of a Christmas holiday so Santa comes a bit later :) Below is my attempt to summarize the discussion.
There's a few different things being discussed in the thread:
Thing 1 - Drupal installation determinism
Quoted from
ConfigInstaller::installDefaultConfigaround line 153.This was introduced in Drupal quite some time ago in #2090115: Don't install a module when its default configuration has unmet dependencies and the primary reason was that the install process was not deterministic for modules that had equal weight in the dependency tree. The comment that was added in
install_install_profileprovides more details:Alex summarised this as
But he also mentions that this problem might have gone away in the past 10 years:
(introduced in version 8 which is lower than Drupal 10's minimum).
Thing 2 - Whether
config/installshould be able to depend onconfig/optionalin the first placeAlex and I disagree here. He mentioned:
I agreed initially (which is why I didn't work on this issue 6 months ago when I first encountered it), but I no longer agree with the stance. My definition of optional configuration is: configuration that provides additional functionality if some preconditions are met.
The modules that are running into errors say: "I'm making sure the preconditions are met, but I require the optional functionality provided by the module to function properly". If we don't allow required config to depend on optional config in any scenario then optional configuration is poisonous.
Additionally if a user deletes configuration from their site then they have a chance of breaking their site, that's true regardless of where the configuration is installed from.
Thing 3 - Profiles can replace configuration
Alex mentioned:
I think this is outside of the scope of this issue, because this is currently possible regardless of when config is being installed.
Thing 4 - Performance
Not installing optional config during every module that's enabled currently speeds up Drupal installation because the installer doesn't look for optional config after every module but only does this once at the end.
I believe that performance isn't great if it causes hard to solve problems. The only alternative that I see to allowing ConfigInstaller to install optional config during site installation is to go to every module that ships some
config/optionalconfig that we might want to build upon and ask them if they can move it toconfig/installfor an optional submodule instead, but that seems a waste of Drupal's optional config system.An example of currently optional config is the Book node-type which is really problematic if we say that required config can't depend on optional config, because it means Drupal ships a core feature that I can't build on (and there's no way for me to opt-out of book if both the book (for the book-system) and node module are installed).
Comment #19
kingdutchMoving this to "Needs work". I still believe that Thing 1 is the only real thing that matters and that the PHP addition of stable sorting has solved this issue for us (allowing us to install optional config during Site Installation as soon as its dependencies are met, in the same way as would happen during post-site install module installation).
The proposed patch implements that solution properly, but as pointed out by Alex in the Slack discussion the comments in the ConfigInstaller and in install_install_profile are no longer accurate after this fix, so they should be updated/removed as part of this issue.
I'm not sure if my comment from #16 is considered a breaking change, I would personally lean to "no" for two reasons:
Work to-do: