Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Currently default_content_modules_installed()
only runs the default content import only if a module is enabled outside of a configuration sync.
This means that an approach like Configuration Installer, which allows you to install a fresh site based on existing config, doesn't work. Or installing a module via a configuration deployment and drush config-import or the Config UI.
Proposed resolution
Add an additional condition to allow the default content import if the config sync occurs during the drupal installation. We can use drupal_installation_attempted()
to achieve this.
Remaining tasks
Reviews needed.
User interface changes
None
API changes
None
Comment | File | Size | Author |
---|---|---|---|
#2 | default_content-compatibility-with-config_installer-2833562-2.patch | 519 bytes | das-peter |
| |||
#4 | 2833562-4.patch | 2.39 KB | tstoeckler |
| |||
#18 | 2833562-18.patch | 2.37 KB | alexpott |
| |||
#20 | 18-20-interdiff.txt | 4.78 KB | alexpott |
#20 | 2833562-20.patch | 4.53 KB | alexpott |
|
Comments
Comment #2
das-peter CreditAttribution: das-peter at Cando commentedDon't mind me just updating the embarrassingly wrong condition in the last patch.
Lets see how many times I can get the condition wrong... :P
Comment #3
aimevpI've tried the dev version with this patch and the config_install profile but it doesn't seem to work. When the install is done no default content was added. When I uninstall my default content module and reinstall it then the content is present.
Comment #4
tstoecklerSo ignoring the sync state is problematic even during installation as the default content that is being imported might depend on configuration (entities) to exist, which is not the case at the time
hook_modules_installed()
is called during configuration syncing.I hit this with using files as default content with File Entity installed, as the file entities cannot be imported when the respective file entity bundles have not yet been imported.
What we can do instead is subscribe to the config import process and check if any modules were installed and explicitly call those then at that time. This worked for me locally.
Comment #5
andypostInteresting idea, but how to get difference in config sync called from module and with config installer?
I guess a lot of contrib using sync and running import on each sync needs some kill switch
BTW why there's no priority for subscriber?
Comment #6
tstoecklerNote that this will only import default content from modules that were explicitly installed as part of the configuration synchronization. Those are precisely those that
default_content_modules_installed()
will ignore. If a module triggers a configuration synchronization this will only trigger if additional modules are installed as part of that synchronization as well, in which case you want it to trigger because - again -default_content_modules_installed()
will skip those additional modules.Maybe I'm missing something but I don't quite understand what problems you are anticipating maybe you can explain in a bit more detail.
No priority because there really is no need for one. I think we generally only add priorities when we explicitly want to run before or after another subscriber.
Comment #7
andypostMy main concerns is that I does not understand all details of config sync and it's strange that modules can be enabled in that process but hooks are not called. That looks very strange to me.
That looks more like core bug and missing
hook_modules_installed
,hook_modules_uninstalled
andhook_module_preuninstall
may have side effects@tstoeckler please point me where to check that behavior looks nothing in ConfigInstaller
Comment #8
tstoecklerSo the hook are called, but in
default_content_modules_uninstalled()
we explicitly bail out if we are in the configuration synchronization process. So there is so core bug, as far as I can tell. Modules can be installed as part of configuration synchronization if thecore.extension.yml
changed. It is important (as you correctly point out yourself) that corecore.extension.yml
not just the values are saved into configuration but that the respective modules are properly installed or uninstalled including all hooks, etc.So the first question is: Why do we not import content during configuration synchronization?
If you look at
ConfigInstaller
starting at line 296:(I have removed some parts to emphasize the important parts.) This means that the configuration entities that a module ships in its
config/install
are not installed when the module is installed as part of a configuration synchronization. Instead, those configuration entities are expected to be part of the configuration set, so that they will be installed later during the synchronization. This means, however, that at the time ofhook_install()
andhook_modules_installed()
you can not depend on configuration entities existing - at least not if\Drupal::isConfigSyncing()
returnsTRUE
. And because content that we create with default content might depend on certain config entities to exist (primarily as bundle entities), we thus cannot import content of modules that are enabled during config synchronization.The followup question then is: When can we import content of modules that are enabled during config synchronization?
Having said the above, the answer is simple: As soon as all configuration entities are guaranteed to exist, in other words as soon as the configuration synchronization is complete. Luckily the configuration system provides an event for this (see
ConfigImporter::finish()
) which the patch utilizes.Hope that makes it clear.
Regarding tests, yeah I guess you're right, that it would be nice to test this as it's somewhat hard to wrap your head around and could easily be broken again in the future.
Comment #9
moshe weitzman CreditAttribution: moshe weitzman commentedLast comment makes me think of #2361423: Add a step to config import to allow contrib to create content based on config dependencies
Comment #10
andypostNW for #9
It looks that core has special event
\Drupal\Core\Config\ConfigEvents::IMPORT_MISSING_CONTENT
I think we should keep both
hook_modules_installed()
and sync event but that should not break related workComment #11
tstoecklerSo
ConfigEvent::IMPORT_MISSING_CONTENT
is for content that config depends on via:This issue is about content that depends on configuration. I.e. if you have a
news.module
that ships anode.type.news
node type and some default news content with$node->bundle() === 'news'
then you need the news bundle to exist before importing the content.I think we should add support for
ConfigEvent::IMPORT_MISSING_CONTENT
as well, but that's a little bit harder to solve, as we cannot import specific content (i.e. content with specific UUIDs) at the moment. Also we will then have to consider config that depends on content that in turn depends on config. I.e. with the example above, you have a view that shows a specific news item in its header. So the view requires the news item to exist, but the news item requires the news node type to exist.Marking back to needs review for now, looking forward to your thoughts.
Comment #12
andypostI tested the patch and it works with config installer but
this fails on second config sync because content, already imported
To solve that #2698425: Do not reimport existing entities should be commited first
Support for
ConfigEvent::IMPORT_MISSING_CONTENT
is separate issueComment #13
andypostI filed #2849128: Add handling of ConfigEvent::IMPORT_MISSING_CONTENT
Going to test it properly on custom project and add tests
Comment #14
larowlanAgree that #2698425: Do not reimport existing entities should come first, but happy with the patch above.
Comment #15
tstoecklerRe #12 / #14: Actually no, because the module actually is only installed once, so this will only be called once, unless the module is subsequently uninstalled and reinstalled. But this does not make the current situation any worse, IMO.
Don't mind waiting for #2698425: Do not reimport existing entities either, though, just wanted to clarify.
Comment #16
andypostimporter after #2614644: Split DefaultContentManager into Exporter and Importer
Comment #17
alexpottThis is not just about the Configuration Installer - it's about an install of a module via config import - even via the UI. And as such is not a feature but a bug. This module is supposed to guarantee the default content is create on module install - atm it doesn't. Nice fix @tstoeckler
#2698425: Do not reimport existing entities and #2849128: Add handling of ConfigEvent::IMPORT_MISSING_CONTENT also look sensible. I'm not sure about waiting on #2698425: Do not reimport existing entities as this does not exacerbate the existing problem.
Comment #18
alexpottHere's a reroll.
Comment #20
alexpottAdded a test and fixed the patch.
Comment #21
alexpottComment #22
tstoecklerWow, that test looks sweet, thanks!
Comment #23
larowlanLooks good, a couple of minor nits that need not hold this up or be fixed on commit.
unused?
Could use the 'admin role' argument instead?
Comment #24
larowlanComment #25
alexpottSmall refactor of the tests and fixing #23.
Comment #26
larowlanThanks, looks good to go, will check in with @andypost with regards to commit order.
Comment #28
andypost@alexpott Thanx for tests clean-up! Nice refactoring
After #2867579: Core 8.3 compatibility next alpha can be released