Problem/Motivation
The Locale module has an implementation of hook_modules_installed() that calls
locale_system_set_config_langcodes();
This function attempts to go through all of the active config and set a 'langcode' value on it. If you have strict config schema checking turned on, as it is when you are running a SimpleTest test, this currently fails if you try to install in a foreign language, because not every config schema has a 'langcode' value defined on it.
They should -- top-level config is supposed to either inherit from config_object or config_entity, but it doesn't all.
Without patching, currently when you try to set up a simpletest test that installs in Spanish, it fails with:
Drupal\Core\Config\Schema\SchemaIncompleteException: Schema errors for menu_ui.settings with the following errors: menu_ui.settings:langcode missing schema in Drupal\Core\Config\Testing\ConfigSchemaChecker->onConfigSave() (line 98 of /opt/www/fmarket/core/lib/Drupal/Core/Config/Testing/ConfigSchemaChecker.php).
The stack trace is, down to WebTestBase->setUp():
Drupal\Core\Config\Testing\ConfigSchemaChecker->onConfigSave(Object, 'config.save', Object)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('config.save', Object)
Drupal\Core\Config\Config->save()
locale_system_set_config_langcodes()
locale_modules_installed(Array)
call_user_func_array('locale_modules_installed', Array)
Drupal\Core\Extension\ModuleHandler->invokeAll('modules_installed', Array)
Drupal\Core\Extension\ModuleInstaller->install(Array, )
_install_module_batch('menu_ui', 'Menu UI', Array)
call_user_func_array('_install_module_batch', Array)
_batch_process()
batch_process(Object, Object)
install_run_task(Array, Array)
install_run_tasks(Array)
install_drupal(Object, Array)
Drupal\simpletest\WebTestBase->doInstall(Array)
Drupal\simpletest\WebTestBase->setUp()
Note that the existing multilingual install tests don't use the standard install profile (which installs menu_ui, containing this menu_ui.settings config item), so they're not hitting this problem.
Proposed resolution
Audit config for which objects do not inherit from the config_object type and fix them. Write a test so it stays fixed.
Remaining tasks
Make a patch with a test.
User interface changes
None.
API changes
None.
Data model changes
Not really. Some config schema will change from mapping to config_object, but this will not introduce any backwards incompatibility changes.
Beta phase evaluation
Issue category | Bug because some config schema are not following our standards according to https://www.drupal.org/node/2460751 |
---|---|
Issue priority | Major because incorrect config schemas are data model problems, and it is preventing installation within SimpleTest. |
Prioritized changes | It's a bug fix. |
Disruption | Not really. Some config schema will inherit a 'lancode' config key that they didn't already have, and no one should be using this key for anything else anyway as it's reserved. Only affects one core config top-level schema, plus a few in tests. Doesn't affect existing config/install or config/optional YML config files because 'langcode' is optional. |
Comment | File | Size | Author |
---|---|---|---|
#29 | 2541800-with-test-29.patch | 3.46 KB | jhodgdon |
#22 | 2541800-failing-test-22.patch | 1.21 KB | jhodgdon |
Comments
Comment #1
jhodgdonHere's the failing test.
Comment #2
jhodgdonComment #4
jhodgdonLet's try this patch. The test failed on the bot the same as for me, so that's good. Here's a patch with the test... may break everything... let's see.
Comment #6
Gábor HojtsyThe way the config system works if a config file does not have a langcode key, it has an assumed langcode of English. Lack of a langcode key does not indicate that there is no key in the file that may have human readable text (and therefore need a langcode associated, so we know what language it is in). So only *changing* langcode if one already exists does not fly because if one does not exist, it is implicitly English. In the Spanish case, we need to set it to Spanish, so the translation will be stored within the default config and not as a Spanish translation override.
The top level langcode key is reserved in configuration and people should use the config_object base type in their config schema to get one automatically. See https://www.drupal.org/node/2460751
Retitled accordingly. Updated issue summary accordingly.
Comment #7
Gábor HojtsyLanguage :D
Comment #8
Gábor HojtsyNot sure if other objects are affected, but this would be the change at least for menu UI settings:
Comment #9
jhodgdonInteresting. So that would be a better fix. It would be interesting to make a test profile that has every module enabled and see if this installation test would pass using that, after fixing Menu UI's config. That would smoke out any other config in config/install that doesn't inherit from config_object.
We should also document that at the top level you should always inherit from config_object. It's certainly something I wasn't aware of.
Comment #10
jhodgdonI'll take this on...
Comment #11
jhodgdonOK. As a first step towards making sure Core has all good config that inherits from config_base, I make a slightly different test -- only difference it that it uses a new testing profile that enables all the modules. Here's a patch for that.
Next I'll see about fixing it by
- patching the core config as suggested in #8 until the test passes
- also making sure the docs are updated (may be a .api.php topic needs an update, or maybe just d.o docs).
Setting to needs review so we can confirm the "test-only" patch fails with the same error reported above (it did locally).
Comment #13
jhodgdonWell that's interesting. Apparently menu_ui was the only problematic schema, and fixing its two config things to inherit from config_object made the test in #11 pass.
Just to make sure, I added all the config/install config items from the standard profile to the testing_everything profile, and ran the test again. Still passed. Here's a patch with the test, added schema for the "everything" profile, and the two lines of actual pass in menu_ui.schema.yml.
Also I checked and there are no specifics about mapping vs. config_object in the Config API topic on api.drupal.org, so I'll update the docs page under https://www.drupal.org/developing/api/8/configuration instead.
Comment #14
Gábor HojtsyOne definite problem with the fix:
This should not be a config object, its not a top level config object, its a third party setting within a node type config entity.
Not sure about the testing everything profile. Config already has a test to enable all the modules and it checks config schema there too I believe (ConfigImportAllTest using the SchemaCheckTestTrait), it does not come with a foreign language, so this issue was not spotted by that test.
Comment #15
jhodgdonHm... I wonder if in that existing test we could also assert that the top-level config objects either start with config_object or config_entity somehow?
Comment #16
jhodgdonTalked to berdir and Gabor in IRC. Let's try this patch:
- Test patch: Adds to SchemaCheckTrait a few lines that verify that top-level schema has a langcode element on it... Hopefully this is OK, I am assuming this method only gets called for top-level schema? If not it will definitely fail. Let's see. As a note, we'd ideally want to make sure it's either config_entity or config_object but that is not really possible. config_object just adds langcode, so that is a minimal test.
- The patch with test just fixes the one menu_ui schema element as noted in #14.
No interdiff, it would be almost the whole patch, and this patch is small. So let's see if this test finds the bad spot, doesn't break anything else, and if the patch fixes it.
Comment #19
jhodgdonwhoops.
= vs. => in
I must not be awake yet. ;)
Comment #22
jhodgdonWell. So apparently when you do
it only generates schema for data that exists. And langcode (as with any part of config) is optional. So, this failed miserably.
Trying another tactic...
Comment #25
jhodgdonOK, now we're getting somewhere. The failing test did catch the errors that it was intended to catch. But it also located a few config schema entries in test modules whose top level was 'mapping' instead of 'config_object', which is why the with-test-22 patch also failed some tests.
So here is a new patch that fixes these as well.
Comment #26
jhodgdonUpdating summary.
Comment #27
Gábor HojtsyI looked at the changed schema types. Schema types with multiple dots in them are always suspect, because they would usually be a config entity or internal type. Indeed, this was an internal type:
This is not a top level type:
core/modules/views/config/schema/views.data_types.schema.yml: type: views.access.[%parent.type]
Comment #28
Gábor HojtsyComment #29
jhodgdonDoh! Right. The others in the patch all came up in the test results. Shouldn't have done that one.
Same patch without that one bit.
Comment #30
Gábor HojtsyLooks good now, yay!
Comment #32
Gábor HojtsyHow did this not fail when this new(?) migration landed?
Schema key block.settings.statistics_popular_block:langcode failed with: missing schema Other MigrateStatisticsPopularBlockSettingsTest.php
Looks like a new missing thing found...
Comment #33
jhodgdonBecause this test wasn't in place yet. This patch hasn't been committed.
I'm not sure how to fix this. Here's the schema, which is in statistics.schema.yml:
And block_settings is defined in core/config/schema.yml:
So it looks to me as though block_settings is not meant to be a top-level type. But for some reason, the statistics module is putting this block's settings as a top-level schema object, and using block_settings as a top-level type. Not sure what to do here, maybe just add a 'langcode' element to this manually?
If you look at what the settings are for this block, they are really not translatable (they are all just numbers).
Thoughts?
Comment #34
BerdirIsn't the part about "the statistics module is putting this block's settings as a top-level schema object" the problem here? That makes no sense, it shouldn't do that.
Comment #35
jhodgdonYeah, I agree, but I'm not sure how to fix it?
Comment #36
jhodgdonDo we know which commit this came from and can we go back and reopen that issue? And give a bop on the head to whoever did that, reviewed it, and/or committed it? :)
Comment #37
Gábor HojtsyIt only happens in *migrate* *tests* currently, that may mean its the migrations fault just as much.
Comment #38
Gábor Hojtsy@jhodgdon: Looks like http://cgit.drupalcode.org/drupal/commit/?id=f541fae97c910e53e7fef93c2ac... migrates to the wrong place, it attempts to use this internal type as a top level config name. Either that should be rolled back or fixed.
Comment #39
jhodgdonThe other issue has been rolled back. Hitting retest.
Comment #41
alexpottThis might break a few contrib module tests - BUT - in a good way as this will mean that their schema is wrong. NIce work everyone. This issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 2d56224 and pushed to 8.0.x. Thanks!
Comment #43
benjy CreditAttribution: benjy at PreviousNext commentedThis broke my tests for entity_print, fixed by changing the top level type from mapping to config_object in #2559883: Top level type should be config_object
Comment #44
Gábor Hojtsy@benjy: looks like the tests succeeded then :)
Comment #45
Gábor Hojtsy