Problem/Motivation
Values from custom theme settings set in *.info.yml are overridden by *.settings.yml in a theme’s config/install directory, which are in turn overridden by values set within the theme settings UI and stored in active config. Because the *.settings.yml file is in the install directory, it makes sense that those values are only relevant prior to a theme’s installation. When *.info.yml files are edited, though, the values generally have an effect once the cache is cleared. The fact that editing these values in *.info.yml sometimes doesn’t have an effect is not intuitive.
Proposed resolution
Remove custom theme settings from *.info.yml and rely solely upon *.settings.yml and active config.
User interface changes
None, assuming this works correctly.
API changes
Change notice will be needed to alert theme developers that all custom theme settings require a *.settings.yml in config/install, and these settings should not be duplicated in *.info.yml.
Original report by sun
-
Hard-coded default theme settings are specified in a theme's
.info.yml
file./core/themes/bartik/bartik.info.yml --- settings: features: favicon: true shortcut_module_link: true
-
If a theme supplies a
$theme.settings
file, then it has to manually specify the (always identical)theme_settings
config schema for it./core/themes/bartik/config/schema/bartik.settings.yml --- # Required to validate default theme settings. # + satisfy DefaultConfigTest bartik.settings: type: theme_settings label: 'Bartik settings'
-
If
$theme.settings
contains an additional configuration option of a module, then the theme's config schema has to manually specify (figure out) the config schema for that option (whereas the originating module does not specify a config schema at all)./core/themes/bartik/config/bartik.settings.yml --- # The config schema for this setting is not defined anywhere. # Additionally, because the key lives at the top-level, it is # inherently part of the 'theme_settings' schema itself. shortcut_module_link: true
-
Anything in
$theme.settings
overrides the hard-coded default theme settings from.info.yml
.bartik.info.yml:settings
←config/bartik.settings.yml
-
As soon as the theme is installed, the
$theme.settings
in the active config storage override the$theme.settings
default config file AND the hard-coded default theme settings from.info.yml
(for keys contained in$theme.settings
).bartik.info.yml:settings
←config/bartik.settings.yml
←CONFIG_ACTIVE/bartik.settings
- The
$theme.settings
active config is only saved when theme settings are saved via the admin Appearance UI. - If there is no
$theme.settings
config (yet), then a themer can simply adjust the settings in .info.yml, clear caches, and they become effective. - Nothing happens at all if the
$theme.settings
active config exists.
- The
-
Additional module options in
$theme.settings
are not properly maintained and not cleaned up when e.g. the module is uninstalled.CONFIG_ACTIVE/bartik.settings.yml --- # Will never vanish, even if obsolete. shortcut_module_link: true
-
The theme system itself has no Schema API and no update system; if a sub-theme contains config options of a base theme in
$theme.settings
, and in case the base theme config schema changes, there's no controlled way for either of both themes to update$basetheme.settings
or$subtheme.settings
(of all subthemes).Omega config schema 2014 Omega config schema 2015 layout: type: integer label: 'Layout template ID' experimental: type: boolean label: 'Enable experimental fluff-huff'
layout: type: string label: 'Layout template name' fancy_new: type: boolean label: 'Enable fancy new'
Diff Diff Consequences layout: - type: integer - label: 'Layout template ID' + type: string + label: 'Layout template name' -experimental: - type: boolean - label: 'Enable experimental fluff-huff' +fancy_new: + type: boolean + label: 'Enable fancy new'
… → (STORED) DATA TYPE/VALUE MISMATCH … … … → ORPHAN DATA (→ fancy_new?) … … → MISSING DEFAULT VALUE … …
In words: New settings, data type changes, removed settings.
Comment | File | Size | Author |
---|---|---|---|
#50 | 2235901.50.patch | 14.36 KB | alexpott |
#50 | 47-50-interdiff.txt | 367 bytes | alexpott |
#47 | 2235901.47.patch | 14.39 KB | alexpott |
#47 | 40-47-interdiff.txt | 2.28 KB | alexpott |
#40 | 2235901.40.patch | 15.75 KB | alexpott |
Comments
Comment #1
sunComment #2
sunComment #3
Jeff Burnz CreditAttribution: Jeff Burnz commentedI've been working with this "system" the past few months and here are some thoughts:
1) I'd like to see the idea of have theme setting defaults in info.yml file go away, to my mind this is what $theme.settings.yml is for. So #1, #2, #4 and #5 are not really flaws IMO, but rather one option too many (settings defaults in info files).
So, you set theme setting defaults in $theme.settings.yml and they're overridden by the active store. IMO this is fine, the defaults are there for when you first enable the theme, thereafter the user changes something/saves and those settings are saved in the active store, so it makes sense they're overridden in this fashion.
2) #3 I'm not sure that is a flaw, it's just the way it is afaict, you can get the config from the active storage and read it.
3) #6 and #7 are 100% flaws, agreed.
There is another serious flaw in the system - custom theme settings are not saved to the active store. Take a look at
theme_settings_convert_to_config()
, it's totally hard coded to convert only toggle settings (features) etc. For Adaptivetheme D8 I had to set these myself i.e.call it from submit function etc:
It's been a while since I looked at much internals in core around this, but it is/was totally flawed when I had to write this :/
On another point but somewhat related because of the "features" in particular the toggle settings - personally these are all from a bygone era and have no place in theme settings at all. The idea that you want to globally enable user pictures in posts is rather absurd. Logo, site name and slogan are a "branding" block now, as will be Main and Secondary menus etc. Logo and favicon upload are good, fine, the rest should be removed and farmed out to other parts of the system, for example user picture should be a setting in the content type alongside "Display author and date information" in the content type settings, not a theme setting.
Comment #4
sunComment #5
sunComment #6
sunComment #7
RainbowArrayIf it reduces one of the conflicts, I think it makes a lot of sense to move the default theme settings to $theme.settings.yml. Because it's in the config install folder, it's intuitive that these are only default settings, so that people don't expect they can make changes to the setting in code.
#2271529: Move breakpoint settings to theme and module *.breakpoints.yml files at root level is looking to move breakpoint definitions out of config files and into *.info.yml files, but my understanding is that doesn't necessarily run into the same issues as theme settings.
Comment #8
catchComment #9
RainbowArrayIt looks to me like #6 and #7 would likely be addressed in #2232605: Themes cannot be uninstalled. So probably the main thing to do here (or in a sub-issue) is to remove custom theme settings from *.info.yml.
For what it's worth, when I shared at a camp that settings would likely be removed from *.info.yml and changes could only be made via UI after a theme is installed, I heard a few grumbles from people that would prefer to be able to make those changes via code. But given the way configuration works, I don't see a better way that provides consistency and reliability.
Comment #10
hass CreditAttribution: hass commentedI have already filed an issue in D6/D7 days that theme settings required update hooks. I also have a lot of dynamic theme settings that require PHP code to build the config form. This worked all in D6/D7, but I have not yet tried porting to D8. I hope to not see any regressions.
Comment #11
RainbowArrayRewriting the issue title and summary to reflect that part of the original issue report is handled by #2232605: Themes cannot be uninstalled, and this issue only needs a narrower scope.
Comment #12
RainbowArrayHere's a patch that removes the custom theme settings from info.yml. The @todo indicates there is no UI for this setting, though, so that might need to be handled in another issue.
Comment #16
iMiksuAccording to testing failures, it looks like there's problems with shortcut link and some missing schema.
Comment #17
iMiksuI've added schema entry of the
shortcut_module_link
setting to seven theme which caused "Missing schema" failures.Comment #18
RainbowArrayComment #19
sunThis means that you can only change theme settings via the Appearance UI or Drush. Many themers won't be happy about that.
The abstract bottom line is that we're trying to cater for two vastly different audiences at the same time: (1) Authors of custom themes, operating to 99.9% in code, whose ideal DX is to just hit the "Reload" button, versus (2) End-users/consumers of ready-made, configurable themes, who might not have access to code at all.
For many Drupal sites, the use-case of (2) doesn't even exist, and if it was easily possible, they'd even rip out the entire Appearance UI, because their site's front-end ought to be controlled by code, not configuration.
Comment #21
iMiksuI think that use-case (1) is something that configuration management should cover. If you want to control over code you should use Configuration API for it.
I wonder do we actually need separate configuration interface for theme settings?
However, I got couple failures less in tests, but the proposed change would still need work in terms of making shortcut module detect the setting properly.
Comment #22
RainbowArrayIf you wanted control of custom settings to be solely in code, we could have an approach similar to #2271529: Move breakpoint settings to theme and module *.breakpoints.yml files at root level where some sort of plugin is used to handle the settings.
I think it's important not to underestimate the importance of UI for site builders. Themers or theme developers might prefer changes in code, but for a large number of site builders, they appreciate having a UI to change these settings.
So when UI is used to change these settings, the values of those settings go into the Active Store, which is the db. What would be helpful is if those changes were also written to code-based settings files in a theme, and if when cache was cleared, those code-based settings files were re-evaluated, and if their values were different from the active store, the code-based values would replace the db-based values.
That sounds to me like a rather large change, but something along those lines would greatly improve the experience of working with configuration, as everyone could win then, those who prefer using a UI and those who prefer code-based changes.
I have no idea how to build something like that though.
Comment #23
RainbowArrayWhat I described above may seem like a longshot, but the possibilities just got far more interesting about why it would be great to have configuration for theme settings available and configurable both in a YML file within a theme as well as in the UI.
This article describes how YML can be used within Sass and Compass: http://fabbrucci.me/2014/08/integrate-yaml-in-your-sass-through-compass/
This means that if custom theme settings were stored within YML within a theme folder, as well as within the DB, the *.settings.yml could serve as a bridge between Drupal's UI and Sass-defined styles.
That opens up pretty amazing possibilities. You could then set up theme UI to allow site builders to control certain aspects of the design like fonts and colors or a wide range of design choices. You'd still need to work out a way to trigger a recompile of Sass when such a change was made, but it seems like a pretty exciting possibility.
Making that work is an entirely different matter. However, it does make me more interested in pursuing a solution where there could be *.settings.yml file at the root of a theme directory. If a change is made in the settings.yml file, it gets picked up when cache is cleared. If a change is made in the UI, it gets saved to the active store (DB) and to the settings.yml file.
Is something like that theoretically possible?
Comment #24
SlayJay CreditAttribution: SlayJay commentedAs a theme developer that has experience working in competing CMS platforms, allow me to give some feedback:
I'm absolutely flabbergasted that D8 was allowed to hit beta with this issue still lingering. There is no good way to develop a theme for D8 right now.
When I make a change to the info.yml file, I expect it to show up immediately. Just like when I change html, or css. Theme yml files are like 20 lines of code, so I don't understand why caching them is so important in the first place. That being said, at a MINIMUM reload the yml changes when I click the clear cache button, or at least give me another button I can push somewhere to reload info.yml files.
This is beyond a critical issue.
Comment #25
Jeff Burnz CreditAttribution: Jeff Burnz commented@25 I'm not clear on what you are talking about here with regards to the Issue Summary and the proposed resolutions. For example you are not being clear about what you are changing in your info file, we already know settings won't update the active store, however Drupal provides a way to do this using the import/export system.
Comment #26
alexpottre #24
Afaik this is exactly what happens unless you've overridden the setting in the appearance UI.
Comment #27
alexpottTheme settings come from (see theme_get_setting()):
Complicating this further theme's can limit the features they support using a features key in their info.yml file. This is not inherited from any base themes. The default features are supplied by _system_default_theme_features(). Themes can also add new features by adding whatever they like to the features key in their info.yml file.
I think that the only practical way forward here is to remove the additional ability to get settings for a theme and its base themes info.yml file. Theme settings are configuration. Defaults should be supplied in config files and if people need command line access to change this they can use Drush's excellent config tools (eg. config-edit).
Less functionality is more! We have consistency - all install time defaults are supplied in config (for themes and modules) - we have less to do at runtime and theme_get_settings is simpler. All it does is merge
system.theme.global
andTHEME.settings
configurations.Comment #28
webchickThat would have the unfortunate side-effect of making theme authors write config.schema.yml files for their themes (if they want their theme settings to be translatable like the rest of Drupal), is that correct?
Not saying necessarily that's a reason to NOT have consistency in the entire configuration system (which was rather the point of the configuration system in the first place :)).... just, ouch. :(
Comment #29
alexpott@webchick #28 - so I'm not sure that writing this information into the theme's info.yml file is any easier. And with CMI you get an added bonus... configure everything through the appearance UI, export your configuration, and copy the theme's settings file to the theme's config/install folder.
Comment #30
alexpottHere's a patch that removes the ability to define settings from the theme's info.yml file. Now all the theme settings are controlled by configuration which makes it much easier to work out what is going on. Basically the theme's setting key in their info.yml was default configuration before we have default configuration. Yes we lose the inheritability from base themes but in that instance - just copy the base theme's settings.yml and rename it.
This patch also addresses the schema situation by adding a third_party_settings key in the same that we have done for many configuration entities.
theme_get_setting() documentation is also updated to remove an erroneous claim that was not true before this patch.
Comment #32
dawehnerOne thing we should/could recommend theme developers is the use of https://www.drupal.org/project/config_devel which already allows to
reimport config changes automatically. So consistency actually helps people again.
Comment #33
alexpottSo the test fails were just to prove I was wrong about this...
Included an interdiff for just the part that was necessary to fix the above fails.
The patch also adds an implementation of hook_config_schema_info_alter() to the system module so that theme that don't have any custom theme settings of their own don't have to have a config schema file.
Comment #34
Gábor Hojtsy@alexpott: that is a neat trick so long as there are no translatable settings (ones that would need to be statically figured out). Looked and theme_settings does not seem to have any translatable strings, but it would get *bad* if it get one or more.
Comment #35
alexpottSo we could
core.data_types.schema.yml
next to theme_settings informing people to not add a translatable setting hereI think I feel like we should go for the last option but also add a comment to
core.data_types.schema.yml
to make this easier to discover.Comment #36
Gábor HojtsyWe don't have such magic elsewhere and one-off magic at one place may be confusing IMHO. This may set a dangerous precedent if we don't document it strongly (and even then). Anyway, we can move to special case this in the static parser (which is probably not trivial given it works with the assumption that everything can be described by the schema and *.xyz is not describable in schema), but I don't think there is a hurry there unless for some reason we want to keep this AND introduce a translatable setting.
Comment #37
Wim Leers#27++
Only base themes and contrib themes do this; custom themes don't do this, they just hardcode the exact features they need, they don't make it configurable, because they don't need to. So the TX impact is lower than you'd think initially.
Comment #38
alexpottAdded comment to address #34 and #36. I think we could argue that theme creation is a different activity to most other activities with Drupal. Reducing the barrier to entry to theming is important for encouraging people to Drupal. Making new contributors are a boilerplate schema like:
Could be off putting and seem pointless. Obviously if we provided a code generation tool then this would go away - but I don't think we'll have that for Drupal 8 (hopefully 8.1 or 8.2). OTOH making themers add this will make them aware of how this works. I could be convinced either way.
Comment #39
Wim LeersNit: this reads to me as if we can have
*.settings
config files. But perhaps that's just me.Nit: could use a comma before "clear" for legibility.
Nit: s/'Add link'/'"Add shortcut" link'/
?
Nit: s/.././
Suppose this wasn't Seven, but a custom theme. And suppose we'd forget to define this setting. Then where would the setting come from? I don't see a default being defined anywhere?
I'd expect the default to be defined in
shortcut.schema.yml
, but I don't think it's possible to define defaults in schemas, so alas.EDIT: I guess this is the one remaining task as per the IS:
Comment #40
alexpottThanks for the review @Wim Leers.
Comment #41
Wim LeersSo this still needs a change record, but thanks to the IS update of #40, it looks like this is considered done? Is all that's still needed here just manual testing (and perhaps more code reviews)?
Comment #42
Gábor HojtsyI agree we would ideally make theme creation as easy as possible. I remain cautious and just wanted to make sure we understand the applicability of this "trick" only as long as a theme does not have translatable settings and/or the base theme system does not have translatable settings on its own. So I think this is an ok step for now because we want to make theme creation easier not because this sounds like a useful general approach.
Comment #43
Wim LeersNW for the CR, looks like #42 also has no remaining complains to delay RTBC any longer.
Comment #44
alexpottI've written the CR https://www.drupal.org/node/2382645.
I think we have an issue with the theme settings form. See the following code in ThemeSettingsForm::buildForm()
I think that code means that we need to inherit the schema from base themes.
Comment #45
Wim LeersCR looks good. I just added some formatting to it.
Can we defer #44 to a follow-up?
Comment #46
alexpottre #45 - not sure. We've removed the inheritability of the defaults from the base theme's info.yml file in this patch. Which is similar to this. I guess what we could do is remove the automatic schema from this patch - and have a new issue to discuss that and its implications.
Comment #47
alexpottPatch without automatic schema.
Comment #48
alexpottCreated #2382671: Automatically define schema for themes
Comment #49
Wim LeersBesides a tiny mistake which could be fixed on commit, I think this is RTBC then.
s/Bartik/Seven/
Comment #50
alexpottDoh!
Comment #51
Dries CreditAttribution: Dries commentedCommitted to 8.x. Thank you!