Problem/Motivation
Once a theme's configuration has been saved, it is impossible to revert the theme back to use the global configuration.
Steps to Reproduce
- Install a clean Drupal 8.3.x site
- Go to the global theme configuration page /admin/appearance/settings define some settings and save the form.
- Go to a theme (Bartik) specific configuration page /admin/appearance/settings/bartik see the same settings as defined above.
- Change some settings in Bartik's configuration and save the form.
- Make some more changes to the global theme config and notice they are not visible in the website, nor in the theme specific config.
Discoveries so far
theme_get_setting() will always use the theme specific configuration (if defined) to override the global configuration:
$cache[$theme]->setData(\Drupal::config('system.theme.global')->get());
// Get the values for the theme-specific settings from the .info.yml files
// of the theme and all its base themes.
$themes = \Drupal::service('theme_handler')->listInfo();
if (isset($themes[$theme])) {
$theme_object = $themes[$theme];
// Retrieve configured theme-specific settings, if any.
try {
if ($theme_settings = \Drupal::config($theme . '.settings')->get()) {
$cache[$theme]->merge($theme_settings);
}
}
catch (StorageException $e) {
}
The only way to get it back to default is to remove the bartik.settings configuration (or one single key from it). I think there should be a way to 'reset' a theme setting and to fall back to the globally defined setting.
This appears to be related to #2402467: Prevent theme settings configuration overrides from bleeding into stored configuration, where overridden theme configuration values bleed into forms. I have suggested there to stop using theme_get_setting() for configuration forms and use an editable configuration instead (which always loads without overrides). This however also means that every core theme should provide a configuration file out of the box. Which means there will be no undefined theme settings and theme specific configuration will always override the global config (global config becomes useless).
Proposed resolution
1. Apart from TRUE/FALSE on the theme specific configuration form, allow a third value to indicate the value should follow the global configuration.
Or
2. Reverse the theme_get_setting() logic and make sure that a global configuration always overrides a theme specific implementation. But also here a 3rd value is required: Force enabled, force disabled, not enforcing.
Remaining tasks
- Decide on the resolution.
- Rework the theme_get_setting() logic accordingly.
User interface changes
Before:
After:

- 'Inherit Global' is referring to the global settings
- Styling of radio's is achieved after committing #2236789: Styling of inline radios broken: inappropriate trailing colons (breaks EditorImageDialog).
API changes
TBD
Data model changes
The theme settings are still boolean values, however tests had to be adjusted to use integer values during submission (boolean values are not in the options allowed list and were ignored).
| Comment | File | Size | Author |
|---|
Comments
Comment #2
neograph734Comment #3
neograph734Comment #4
neograph734Comment #5
neograph734Comment #6
neograph734Comment #7
joelpittetFor the issue summary, the second option seems like too much of a BC break to consider the global option overriding the specific theme settings, so maybe concentrate on fallbacks based on empty values in theme specific settings?
That's not a full answer but hopefully narrows the scope a bit...
Comment #8
neograph734Hi joelpittet,
Thanks for getting back to me. I agree that option 2 is a big change and might break more than we'd like.
That is unfortunately part of the problem. Most of the theme features are checkboxes which are either TRUE or FALSE, but never empty. (False is not the same as empty as the user should be able to disable a feature for a specific theme.)
So IMO the only solution would be to have 3 radio buttons per feature: enabled, disabled and global, with the respective values TRUE, FALSE and NULL. I'll see if I can create a patch for that, unless you have any other ideas?
Comment #9
neograph734It could look something like this:
Obviously, for the global theme settings form the last value should be cut off.
Comment #10
joelpittetGood point yeah having a global or default option would be good. I wonder how base theme settings will compound this problem?
Comment #11
neograph734I guess this could be a rough idea for the patch. I have tried to keep the types for the form configuration the same (booleans) so casting them to integers during the form building process. Setting a value to 'global' will explicitly clear it from the theme specific configuration and theme_get_setting() will inherit its value from the global theme. (After saving the form, all global values inherit the default config via theme_get_setting and display either 'enabled' or 'disabled'. This will be fixed in #2402467: Prevent theme settings configuration overrides from bleeding into stored configuration.)
And while writing this comment I realize that I am explicitly clearing feature-configuration items, so it probably does not yet work nicely for default logo and image.
Nothing in the scheme definition is changed, so defining TRUE of FALSE will enable or disable the feature. Omitting it will make it assume global. In the worst case a user will have to edit the configuration and revert it to global. It would allow themers to ship their theme with sensible defaults, so I foresee not many problems.
Comment #14
neograph734Finally some time to have another look at this. Lets see what tests need fixing as of 8.5.
Comment #16
neograph734Comment #17
neograph734This should make the tests pass.
Comment #18
neograph734Comment #20
neograph734Great, now there are some minor UI issues left to iron out.
Comment #21
neograph734I believe this covers it all. Tagging for usability review to hear feedback on the radios.
Not sure if this requires a change record. The functional test had to be adjusted from TRUE/FALSE to 1/0 so they comply with the options allowed values list. I cannot imagine there will be anybody posting values directly to the form. (Boolean values written directly to configuration will remain functioning.)
Styling of radio's is achieved after implementing #2236789: Styling of inline radios broken: inappropriate trailing colons (breaks EditorImageDialog).
This patch should also resolve #2402467: Prevent theme settings configuration overrides from bleeding into stored configuration.
Comment #22
neograph734Comment #23
neograph734Comment #24
neograph734I am upping this to a major bug. It is not completely broken, but certainly undesired behavior and clearly not functioning as it should.
Comment #25
Bojhan commentedThis is an odd bug.
However this is not from my point of view the desired solution, in my mind:
Comment #26
neograph734@Bojhan, I am not really getting what you mean. By just using checkboxes you can only have 2 sates (enabled/disabled). This is a problem because if you override someting at the theme-specific level, there is no way to revert that setting to global.
To replicate:
I set my logo to show for all themes (global config).
Then in one theme, I disable the logo.
Then in the same theme I enable it again.
(so far so good)
Now I disable it globally, and the theme specific implementation will persist.
Adding some indication that the value is overridden is a possibility, but it will not allow a user to 'reset' a theme to follow the global defined settings.
There is a need for more than 2 states.
Comment #27
Bojhan commentedCan we not assume, when a user selects the global default - that this is the the desired state? And to only allow for "overriding", whereas inheriting is implied when the user selects the same option?
Comment #28
neograph734Yes, that makes sense.
Not per sé. There might be themes where you want to explicitly disable a certain function (ugly logo implementation so you do it in a block or something). If you were to change some feature and save the form, you could end up setting others to global without wanting to.
Checkboxes can be used in 2 ways;
Enabled and empty
or
Explictly enabled and Explicitly disabled
In the first case it would not matter much because if the checkbox is empty we can skip its value during submission and inherit global as we please. However on the theme configuration page they are used to explicitly enable and explicitly disable a feature.
I have thought of adding an inline link behind the checkbox to 'revert to global', but even then, the next time the form is submitted the empty checkboxes would happily define new overrides.
Using 2 checkboxes (one to 'enable' the override and one for the feature) would seem bad UX as well. That is why I ultimately ended up with the radios.
Comment #30
markhalliwellComment #31
kostyashupenkooops, wrong task :)
Comment #32
kostyashupenkoComment #33
kostyashupenkoComment #34
kostyashupenkonow should be ok, rerolled.
there was conflict here /core/includes/theme.inc -L 487. Pay attention on it at patch please.
Comment #39
Ruchi Joshi commented@Neograph734- Need to re-roll patch for drupal 8.9 and 9.1. Tested this problem on Drupal 9.1 and screenshot is attached in support of same.
Comment #40
neograph734As long as there is no alternative to the UI, I do personally do not know how to proceed here.
IMO the theme specific pages need an option to revert to the default setting, but as Bojhan explained in #25 these need to be checkboxes. But then you simply miss a state (explicit enabled for this theme, explicit disabled for this theme, inherit default)
Comment #41
Ruchi Joshi commentedBased on comment #25 and #28, changes would be required for Drupal 8 and Drupal 9. Hence, moving it to "Needs Work"
Comment #42
shaktikPatch re-rolled for D9.1.x please check.
Comment #44
shaktikfixing test case, please check.
Comment #45
neograph734@shaktik please try to understand the issue before writing code. We currently do not need a patch, but somebody has to decide on the design instead. As Bojhan explained in #25 we cannot use radio's because of the UI standards. As long as that is an issue, all your effort will be wasted because it will not be used.
Comment #46
neograph734Comment #51
neograph734Not sure if the product manager is the right person here, but we're stuck. #25 more or less states that checkboxes are needed for a 3-state situation. It would be nice if somebody could make a choice here so that we can progress with #2402467: Prevent theme settings configuration overrides from bleeding into stored configuration as well.
Comment #53
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #55
acbramley commentedI don't think either option is going to fly to be honest. Turning all settings from booleans into a 0, 1, or -1 is a task in itself not to mention the UX implications. And we can't reverse theme_get_setting logic without massive BC concerns.
What about something that allows the user to reset each setting to the global config, which would effectively clear (delete) that specific key from that theme's settings which in turn (from what I can see) would allow the fallback to global.
Comment #56
acbramley commentedForgot the tags.
Another thing we could do I suppose is hide the Global tab once there's an enabled theme?