Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme Export: Add missing properties to theme.json #39590

Closed
wants to merge 7 commits into from

Conversation

scruffian
Copy link
Contributor

@scruffian scruffian commented Mar 18, 2022

What?

This changes our approach to getting and merging theme.json data when a user exports a theme.

Why?

The export should be a copy of the theme, including the user changes. We also should include everything that was in the original theme.json from the theme.

How?

This abstracts the merge function to a static function, so that it can be used by any two arrays. This gives us the freedom to call it from other contexts and reuse the same logic.

Testing Instructions

  • Switch to TT2
  • Export a theme from the Site Editor
  • Confirm that the $schema and settings > appearanceTools attributes are in the theme.json file.
  • Make some user edits (e.g. change the site background color, and try changing the settings for a particular block)
  • Do another export
  • Confirm that the original settings from TT2 are still present, but combined with the user settings made above.

Notes

This exports theme.json with spaces not tabs. We should convert this to tabs.

@scruffian scruffian added [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") labels Mar 18, 2022
@scruffian scruffian self-assigned this Mar 18, 2022
@pbking
Copy link
Contributor

pbking commented Mar 18, 2022

I'm a bit concerned not just that the abstraction 'appearanceTools' was missing from theme.json but that all that it represented was also added. This breaks the abstraction since now things like settings.color.link are now represented by two properties in theme.json.

If the export tool is explicitly aware of the 'appearanceTools' attribute then it (or get_data() from whence it gets the details) may need to keep out of the configuration the things that it represents.

However, it's better to have it transition over than not... this fixes MOST of the problem (where it's understood that the author's original intent was to support all 'appearance tools' both present and future).

@scruffian
Copy link
Contributor Author

Ah yeah that's a good point, maybe we should remove the added properties? I might have another idea how we can do this...

@scruffian scruffian force-pushed the update/theme-json-missing-properties branch from 74d03dc to ce5fe20 Compare March 21, 2022 14:10
@@ -14,7 +14,7 @@
*
* @access private
*/
class WP_Theme_JSON_5_9 {
class WP_Theme_JSON_5_9 extends WP_Theme_JSON {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary as the merge function inherits some functions from the original base class.

* @param array $replacements Data to add onto $base
* @return array The result of the merge
*/
public static function functional_merge( $base, $replacements ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea of this function is that it will work with any 2 arrays and do the same thing, so we can use the same logic without being in context of an object.

@scruffian
Copy link
Contributor Author

@pbking I updated the approach here... thoughts?

$merged_data = WP_Theme_JSON_Gutenberg::functional_merge( $theme_json_data, $user_data->get_raw_data() );
}
} else {
$merged_data = $user_data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be super if the complexity of merging this data together into a snapshot JSON string were something abstracted in WP_Theme_JSON_Gutenberg so that getting that could be a function call instead of repeating this logic.

@pbking
Copy link
Contributor

pbking commented Mar 22, 2022

I'm afraid the latest blows up for me when I switch to the branch.

image

Not sure why, unable to evaluate fully.

I definitely better like the way the bits are merged more abstractly rather than peeking and adding specific entries. I haven't been able to 100% follow everything here but even so definitely more comfortable with this direction.

@scruffian
Copy link
Contributor Author

I've fixed the issue above, and also created a helper function to get the merged data, so the logic lives in the class. Ready for another review...

@pbking
Copy link
Contributor

pbking commented Mar 23, 2022

Tested again and while the value appearanceTools isn't being removed (and nothing new added) I'm getting this when I change colors with the FSE (and it is working properly on trunk):

    "settings": {
        "appearanceTools": true,
        "color": {
            "palette": {
                "0": {
                    "slug": "primary",
                    "color": "#776c4e",
                    "name": "Primary"
                },
                "1": {
                    "slug": "secondary",
                    "color": "#a19982",
                    "name": "Secondary"
                },
                "2": {
                    "slug": "foreground",
                    "color": "#000000",
                    "name": "Foreground"
                },
                "3": {
                    "slug": "background",
                    "color": "#ffffff",
                    "name": "Background"
                },
                "4": {
                    "slug": "tertiary",
                    "color": "#f1ede6",
                    "name": "Tertiary"
                },
                "theme": [
                    {
                        "slug": "primary",
                        "color": "#0e00ff",
                        "name": "Primary"
                    },
                    {
                        "slug": "secondary",
                        "color": "#a19982",
                        "name": "Secondary"
                    },
                    {
                        "slug": "foreground",
                        "color": "#000000",
                        "name": "Foreground"
                    },
                    {
                        "slug": "background",
                        "color": "#ffffff",
                        "name": "Background"
                    },
                    {
                        "slug": "tertiary",
                        "color": "#f1ede6",
                        "name": "Tertiary"
                    }
                ]
            },
...

*/
public static function get_merged_theme_json() {
// Get the user data
$user_data = WP_Theme_JSON_Resolver_Gutenberg::get_user_data();
Copy link
Member

@oandregal oandregal Mar 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been trying to make the WP_Theme_JSON class agnostic from where the data comes from and from WordPress APIs (get_stylesheet, etc), while the WP_Theme_JSON_Resolver responsibilitiy is to mangle data together. I think we need to keep concerns separate.

@oandregal
Copy link
Member

The export should be a copy of the theme, including the user changes. We also should include everything that was in the original theme.json from the theme.

I understand you want appearanceTools as part of the export. That's a valid point and it's worth investigating. I disagree that "everything" in the theme.json of the theme should be part of the export: this ignores important processes such as sanitization, migration to a newer theme.json version, etc. We should keep those in place.

The core issue seems to be that appearanceTools is considered an "alias": it has no function other than "pre-configure" some other flags, and then is unset. What if we tried this?

  • do not unset appearanceTools in do_opt_in_into_settings
  • modify the existing get_data method to consider the value of appearanceTools and "undo" what it did in do_opt_in_into_settings

@scruffian
Copy link
Contributor Author

@oandregal sounds like a good idea. What about $schema?

@oandregal
Copy link
Member

What about $schema?

That's a tricky one. If we tap into the WP_Theme_JSON code, anything that's invalid at runtime, we can't export.

Options I see:

  1. Do not rely on WP_Theme_JSON and do a different thing, so we can get $schema or any other (invalid at runtime, potentially insecure) info the theme provides.
  2. Add $schema to the allowed list of settings. I'm reluctant to bend the system in this way, as the valid data is carried through the data flow (it's sent to the client and stored there).
  3. Ignore $schema from the export.

For $schema I'd go with 3. This is my thinking: this property is helpful to get type info in the editors. Though, if the dev is editing the theme.json can't they as well add that manually?

@pbking
Copy link
Contributor

pbking commented Mar 25, 2022

I understand you want appearanceTools as part of the export. That's a valid point and it's worth investigating. I disagree that "everything" in the theme.json of the theme should be part of the export: this ignores important processes such as sanitization, migration to a newer theme.json version, etc. We should keep those in place.

That concept makes me a lot more comfortable.

Add $schema to the allowed list of settings. I'm reluctant to bend the system in this way, as the valid data is carried through the data flow (it's sent to the client and stored there).

In what way does it bend the rules? Could there be a standard schema location that's exported unless overridden? Would be especially helpful if the theme.json version going in was v2 and what was exported to v3.

@oandregal
Copy link
Member

oandregal commented Mar 25, 2022

In what way does it bend the rules? Could there be a standard schema location that's exported unless overridden?

Allowing something we don't use or validate, just for the sake of making it part of the export.

Would be especially helpful if the theme.json version going in was v2 and what was exported to v3.

This is interesting. Looking at the data ("$schema": "https://json.schemastore.org/theme-v1.json"), we could generate this based on the version. Worst-case scenario is that we generate a schema not published in schemastore so it'd be ignored by the editor.

@scruffian
Copy link
Contributor Author

This is interesting. Looking at the data ("$schema": "https://json.schemastore.org/theme-v1.json"), we could generate this based on the version. Worst-case scenario is that we generate a schema not published in schemastore so it'd be ignored by the editor.

I made a PR for this: #39775

@scruffian
Copy link
Contributor Author

I also made this for appearanceTools: #39840

Closing this one...

@scruffian scruffian closed this Mar 29, 2022
@scruffian scruffian deleted the update/theme-json-missing-properties branch March 29, 2022 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Feature] Themes Questions or issues with incorporating or styling blocks in a theme.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants