WordPress.org

Make WordPress Core

Opened 8 months ago

Closed 6 months ago

#49037 closed enhancement (fixed)

Expose all theme supports in /themes endpoint

Reported by: adamboro Owned by:
Milestone: 5.4 Priority: normal
Severity: normal Version: 5.0
Component: REST API Keywords: has-patch has-unit-tests
Focuses: rest-api Cc:

Description

The /themes endpoint exposes just three of values stored in $_wp_theme_features:
https://core.trac.wordpress.org/browser/tags/5.3/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php#L108

This is different than how get_theme_support (https://developer.wordpress.org/reference/functions/get_theme_support) function works, which exposes all of them.
As it is now, In order to retrieve a theme support - which is not one of the three values - via REST API, a custom endpoint has to be created. This is pretty cumbersome - why shouldn't /themes expose all theme features?

Related: #45016, #48798

Attachments (13)

49037.patch (11.0 KB) - added by apieschel 7 months ago.
exposes automatic-feed-links feature
48937.2.diff (2.2 KB) - added by apieschel 7 months ago.
exposes custom-logo feature with unit tests
49037.2.patch (12.9 KB) - added by apieschel 7 months ago.
exposes custom-logo feature with unit tests (correct file)
49037.3.patch (20.7 KB) - added by apieschel 7 months ago.
exposed remaining features from https://developer.wordpress.org/reference/functions/add_theme_support/
49037.4.patch (21.8 KB) - added by apieschel 7 months ago.
changed format of child properties and adjusted unit test for 'title-tag'
49037.5.patch (27.2 KB) - added by apieschel 7 months ago.
added editor-styles, dark-editor-style, align-wide, and wp-block-styles
49037.diff (28.1 KB) - added by spacedmonkey 7 months ago.
49037.2.diff (25.9 KB) - added by spacedmonkey 7 months ago.
49037.3.diff (25.8 KB) - added by spacedmonkey 6 months ago.
49037.4.diff (30.7 KB) - added by TimothyBlynJacobs 6 months ago.
49037.5.diff (30.9 KB) - added by TimothyBlynJacobs 6 months ago.
49037.6.diff (30.6 KB) - added by kadamwhite 6 months ago.
Clarify schema comment and clean up tests
49037.7.diff (30.6 KB) - added by TimothyBlynJacobs 6 months ago.

Download all attachments as: .zip

Change History (38)

#1 @SergeyBiryukov
8 months ago

  • Component changed from REST API to Themes

#2 @spacedmonkey
8 months ago

  • Component changed from Themes to REST API
  • Keywords needs-patch added
  • Version changed from 5.3.1 to 5.0

This ticket was mentioned in Slack in #core-restapi by kadamwhite. View the logs.


8 months ago

#4 @TimothyBlynJacobs
8 months ago

  • Milestone changed from Awaiting Review to 5.4

Based on discussion in #core-restapi, I think we are going to start by extending this to register all WordPress Core Theme Support. 3rd party theme support might come at a later point. Provisionally milestoning for 5.4.

This ticket was mentioned in Slack in #core-restapi by timothybjacobs. View the logs.


7 months ago

#6 @TimothyBlynJacobs
7 months ago

  • Keywords good-first-bug added

Going to mark this as a good first bug. You can find a similar ticket for guidance in #48798.

@apieschel
7 months ago

exposes automatic-feed-links feature

#7 @apieschel
7 months ago

@TimothyBlynJacobs I started on this. If you have time, would you mind checking to see if it's on the right track? I moved over all the code from #48798, and added all the lines related to "automatic-feed-links" and "custom-logo".

Last edited 7 months ago by apieschel (previous) (diff)

@apieschel
7 months ago

exposes custom-logo feature with unit tests

@apieschel
7 months ago

exposes custom-logo feature with unit tests (correct file)

#8 @spacedmonkey
7 months ago

Thinking this ticket over, I wonder if we should add an api to register theme supports.

This would define the key name, description, show in rest etc. That would allow third party developers to also register their own supports. It would also mean that this definitions could be reused elsewhere. Thoughts @TimothyBlynJacobs ?

#9 @apieschel
7 months ago

Went ahead and added the remaining supports from https://developer.wordpress.org/reference/functions/add_theme_support/.

I guess I also need to add the ones from here: https://developer.wordpress.org/block-editor/developers/themes/theme-support/ ?

Is there a better place to look at a list of all possible theme supports? The documentation is a little confusing!

All new unit tests are passing except test_theme_can_manage_title_tag(). Can't figure out why

$result[0]['theme_supports']['title-tag']

keeps returning false.

Version 2, edited 7 months ago by apieschel (previous) (next) (diff)

#10 @TimothyBlynJacobs
7 months ago

#48798 was marked as a duplicate.

#11 follow-up: @TimothyBlynJacobs
7 months ago

Thinking this ticket over, I wonder if we should add an api to register theme supports.

From my perspective, such an API would make a lot of sense. I think we should open a separate ticket for it and work with the Themes component on it.

Thanks for working on these patches @apieschel! Going to take a more in-depth look later, but one thing that I saw in my initial review is that the schema format for the child properties is wrong. See the first part of my comment here: https://core.trac.wordpress.org/ticket/48798#comment:11

Also, for html5 instead of listing those as properties, they should be an enum. So

'items' => [
 	 'type'   => 'string',
 	 'enum' => array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'script', 'style' ),
],

All new unit tests are passing except test_theme_can_manage_title_tag(). Can't figure out why this line:

This may be because add_theme_support checks if wp_loaded has fired, and if so, prevents the theme support from being registered. In this case, it may be find to add the support manually to the $_wp_theme_features global.

@apieschel
7 months ago

changed format of child properties and adjusted unit test for 'title-tag'

@apieschel
7 months ago

added editor-styles, dark-editor-style, align-wide, and wp-block-styles

#12 in reply to: ↑ 11 @apieschel
7 months ago

Replying to TimothyBlynJacobs:

Going to take a more in-depth look later, but one thing that I saw in my initial review is that the schema format for the child properties is wrong. See the first part of my comment here: https://core.trac.wordpress.org/ticket/48798#comment:11

Thanks for this! I read that comment, but didn't get it at first for some reason. Added a patch with the schema format for child properties adjusted, and 'title-tag' support manually added to the $_wp_theme_features global in the relevant unit test. I also added supports and tests for editor-styles, dark-editor-style, align-wide, and wp-block-styles from https://developer.wordpress.org/block-editor/developers/themes/theme-support/. Let me know what else I need to change!

#13 @spacedmonkey
7 months ago

I have created a possiblity useful and related ticket for formatting color at #49270

@spacedmonkey
7 months ago

#14 @spacedmonkey
7 months ago

In 49037.2.diff, there are number of improvements.

  • Lints now pass
  • Unit tests now pass.
  • Repeated logic removed and replaced with loop
  • Make sure all array types also have items key to stop php notice.

This ticket was mentioned in Slack in #core-restapi by spacedmonkey. View the logs.


7 months ago

#16 @TimothyBlynJacobs
6 months ago

The types here aren't entirely correct. For instance, custom-logo is listed as [ 'array', 'bool'] but it looks like it should be ['object', 'bool']. Unless you are supposed to have multiple custom logos? I think this is the same for custom-header as well.

Response on Twenty Twenty.

[
  {
    "theme_supports": {
      "align-wide": true,
      "automatic-feed-links": true,
      "custom-header": false,
      "custom-logo": {
        "width": 120,
        "height": 90,
        "flex-width": true,
        "flex-height": true,
        "header-text": [
          ""
        ]
      },
      "customize-selective-refresh-widgets": true,
      "dark-editor-style": false,
      "disable-custom-colors": false,
      "disable-custom-font-sizes": false,
      "editor-color-palette": [
        {
          "name": "Accent Color",
          "slug": "accent",
          "color": "#a73050"
        },
        {
          "name": "Primary",
          "slug": "primary",
          "color": "#000000"
        },
        {
          "name": "Secondary",
          "slug": "secondary",
          "color": "#7e704b"
        },
        {
          "name": "Subtle Background",
          "slug": "subtle-background",
          "color": "#d7cfab"
        },
        {
          "name": "Background Color",
          "slug": "background",
          "color": "#fff"
        }
      ],
      "editor-font-sizes": [
        {
          "name": "Small",
          "shortName": "S",
          "size": 18,
          "slug": "small"
        },
        {
          "name": "Regular",
          "shortName": "M",
          "size": 21,
          "slug": "normal"
        },
        {
          "name": "Large",
          "shortName": "L",
          "size": 26.25,
          "slug": "large"
        },
        {
          "name": "Larger",
          "shortName": "XL",
          "size": 32,
          "slug": "larger"
        }
      ],
      "editor-styles": false,
      "formats": [
        "standard"
      ],
      "html5": [
        "search-form",
        "comment-form",
        "comment-list",
        "gallery",
        "caption",
        "script",
        "style"
      ],
      "post-thumbnails": true,
      "responsive-embeds": false,
      "title-tag": true,
      "wp-block-styles": false
    }
  }
]

#17 @spacedmonkey
6 months ago

  • Keywords has-patch has-unit-tests added; needs-patch good-first-bug removed

Good catch @TimothyBlynJacobs . I have updated the patch.

[
  {
    "theme_supports": {
      "align-wide": false,
      "automatic-feed-links": true,
      "custom-header": {
        "default-image": "",
        "random-default": false,
        "width": 1200,
        "height": 280,
        "flex-height": true,
        "flex-width": false,
        "default-text-color": "1a1a1a",
        "header-text": true,
        "uploads": true,
        "wp-head-callback": "twentysixteen_header_style",
        "admin-head-callback": "",
        "admin-preview-callback": "",
        "video": false,
        "video-active-callback": "is_front_page"
      },
      "custom-logo": {
        "width": 240,
        "height": 240,
        "flex-width": false,
        "flex-height": true,
        "header-text": ""
      },
      "customize-selective-refresh-widgets": true,
      "dark-editor-style": false,
      "disable-custom-colors": false,
      "disable-custom-font-sizes": false,
      "editor-color-palette": [
        {
          "name": "Dark Gray",
          "slug": "dark-gray",
          "color": "#1a1a1a"
        },
        {
          "name": "Medium Gray",
          "slug": "medium-gray",
          "color": "#686868"
        },
        {
          "name": "Light Gray",
          "slug": "light-gray",
          "color": "#e5e5e5"
        },
        {
          "name": "White",
          "slug": "white",
          "color": "#fff"
        },
        {
          "name": "Blue Gray",
          "slug": "blue-gray",
          "color": "#4d545c"
        },
        {
          "name": "Bright Blue",
          "slug": "bright-blue",
          "color": "#007acc"
        },
        {
          "name": "Light Blue",
          "slug": "light-blue",
          "color": "#9adffd"
        },
        {
          "name": "Dark Brown",
          "slug": "dark-brown",
          "color": "#402b30"
        },
        {
          "name": "Medium Brown",
          "slug": "medium-brown",
          "color": "#774e24"
        },
        {
          "name": "Dark Red",
          "slug": "dark-red",
          "color": "#640c1f"
        },
        {
          "name": "Bright Red",
          "slug": "bright-red",
          "color": "#ff675f"
        },
        {
          "name": "Yellow",
          "slug": "yellow",
          "color": "#ffef8e"
        }
      ],
      "editor-font-sizes": false,
      "editor-styles": true,
      "formats": [
        "standard",
        "aside",
        "image",
        "video",
        "quote",
        "link",
        "gallery",
        "status",
        "audio",
        "chat"
      ],
      "html5": [
        "search-form",
        "comment-form",
        "comment-list",
        "gallery",
        "caption",
        "script",
        "style"
      ],
      "post-thumbnails": true,
      "responsive-embeds": true,
      "title-tag": true,
      "wp-block-styles": true
    }
  }
]

This is the output of sixteen. Take not of custom-header, which is an object now.

This ticket was mentioned in Slack in #core-restapi by spacedmonkey. View the logs.


6 months ago

#19 @TimothyBlynJacobs
6 months ago

Uploaded a revised patch.

  • Adds support for custom-background, editor-gradient-presets, and disable-custom-gradients.
  • Excludes the callback properties from custom-header and custom-background. These are PHP callables, which I don't think we should expose. Passing an [ object, method ] pair for instance seems to be supported. We don't want to dump that to JSON.
  • Add additionalProperties: false to all object definitions so we don't inadvertently expose something.
  • Fixes bool type to boolean.
  • Add more schema specificity when possible.
  • Removes test descriptions. While these are present in some of the other tests in this file, we rarely follow that format in the rest of core, and the doc strings were duplicating the test function names.
  • Removed readonly properties from individual theme supports. Since the parent object is marked as readonly these are unnecessary.
  • Corrected theme_supports schema type.

I would really like a review from someone on the themes component to make sure our schema and formatting is accurate: @williampatton, @sagarprajapati.

Twenty Sixteen

[
  {
    "theme_supports": {
      "align-wide": false,
      "automatic-feed-links": true,
      "custom-header": {
        "default-image": "",
        "random-default": false,
        "width": 1200,
        "height": 280,
        "flex-height": true,
        "flex-width": false,
        "default-text-color": "1a1a1a",
        "header-text": true,
        "uploads": true,
        "video": false
      },
      "custom-background": {
        "default-image": "",
        "default-preset": "default",
        "default-position-x": "left",
        "default-position-y": "top",
        "default-size": "auto",
        "default-repeat": "repeat",
        "default-attachment": "scroll",
        "default-color": "1a1a1a"
      },
      "custom-logo": {
        "width": 240,
        "height": 240,
        "flex-width": false,
        "flex-height": true,
        "header-text": []
      },
      "customize-selective-refresh-widgets": true,
      "dark-editor-style": false,
      "disable-custom-colors": false,
      "disable-custom-font-sizes": false,
      "disable-custom-gradients": false,
      "editor-color-palette": [
        {
          "name": "Dark Gray",
          "slug": "dark-gray",
          "color": "#1a1a1a"
        },
        {
          "name": "Medium Gray",
          "slug": "medium-gray",
          "color": "#686868"
        },
        {
          "name": "Light Gray",
          "slug": "light-gray",
          "color": "#e5e5e5"
        },
        {
          "name": "White",
          "slug": "white",
          "color": "#fff"
        },
        {
          "name": "Blue Gray",
          "slug": "blue-gray",
          "color": "#4d545c"
        },
        {
          "name": "Bright Blue",
          "slug": "bright-blue",
          "color": "#007acc"
        },
        {
          "name": "Light Blue",
          "slug": "light-blue",
          "color": "#9adffd"
        },
        {
          "name": "Dark Brown",
          "slug": "dark-brown",
          "color": "#402b30"
        },
        {
          "name": "Medium Brown",
          "slug": "medium-brown",
          "color": "#774e24"
        },
        {
          "name": "Dark Red",
          "slug": "dark-red",
          "color": "#640c1f"
        },
        {
          "name": "Bright Red",
          "slug": "bright-red",
          "color": "#ff675f"
        },
        {
          "name": "Yellow",
          "slug": "yellow",
          "color": "#ffef8e"
        }
      ],
      "editor-font-sizes": false,
      "editor-gradient-presets": false,
      "editor-styles": true,
      "html5": [
        "search-form",
        "comment-form",
        "comment-list",
        "gallery",
        "caption",
        "script",
        "style"
      ],
      "post-thumbnails": true,
      "responsive-embeds": true,
      "title-tag": true,
      "wp-block-styles": true,
      "formats": [
        "standard",
        "aside",
        "image",
        "video",
        "quote",
        "link",
        "gallery",
        "status",
        "audio",
        "chat"
      ]
    }
  }
]

Schema:

{
  "$schema": "http:\/\/json-schema.org\/draft-04\/schema#",
  "title": "theme",
  "type": "object",
  "properties": {
    "theme_supports": {
      "description": "Features supported by this theme.",
      "type": "object",
      "readonly": true,
      "properties": {
        "align-wide": {
          "description": "Whether theme opts in to wide alignment CSS class.",
          "type": "boolean"
        },
        "automatic-feed-links": {
          "description": "Whether posts and comments RSS feed links are added to head.",
          "type": "boolean"
        },
        "custom-header": {
          "description": "Custom header if defined by the theme.",
          "type": [
            "boolean",
            "object"
          ],
          "properties": {
            "default-image": {
              "type": "string",
              "format": "uri"
            },
            "random-default": {
              "type": "boolean"
            },
            "width": {
              "type": "integer"
            },
            "height": {
              "type": "integer"
            },
            "flex-height": {
              "type": "boolean"
            },
            "flex-width": {
              "type": "boolean"
            },
            "default-text-color": {
              "type": "string"
            },
            "header-text": {
              "type": "boolean"
            },
            "uploads": {
              "type": "boolean"
            },
            "video": {
              "type": "boolean"
            }
          },
          "additionalProperties": false
        },
        "custom-background": {
          "description": "Custom background if defined by the theme.",
          "type": [
            "boolean",
            "object"
          ],
          "properties": {
            "default-image": {
              "type": "string",
              "format": "uri"
            },
            "default-preset": {
              "type": "string",
              "enum": [
                "default",
                "fill",
                "fit",
                "repeat",
                "custom"
              ]
            },
            "default-position-x": {
              "type": "string",
              "enum": [
                "left",
                "center",
                "right"
              ]
            },
            "default-position-y": {
              "type": "string",
              "enum": [
                "left",
                "center",
                "right"
              ]
            },
            "default-size": {
              "type": "string",
              "enum": [
                "auto",
                "contain",
                "cover"
              ]
            },
            "default-repeat": {
              "type": "string",
              "enum": [
                "repeat-x",
                "repeat-y",
                "repeat",
                "no-repeat"
              ]
            },
            "default-attachment": {
              "type": "string",
              "enum": [
                "scroll",
                "fixed"
              ]
            },
            "default-color": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        "custom-logo": {
          "description": "Custom logo if defined by the theme.",
          "type": [
            "boolean",
            "object"
          ],
          "properties": {
            "width": {
              "type": "integer"
            },
            "height": {
              "type": "integer"
            },
            "flex-width": {
              "type": "boolean"
            },
            "flex-height": {
              "type": "boolean"
            },
            "header-text": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "additionalProperties": false
        },
        "customize-selective-refresh-widgets": {
          "description": "Whether the theme enables Selective Refresh for Widgets being managed with the Customizer.",
          "type": "boolean"
        },
        "dark-editor-style": {
          "description": "Whether theme opts in to the dark editor style UI.",
          "type": "boolean"
        },
        "disable-custom-colors": {
          "description": "Whether the theme disables custom colors.",
          "type": "boolean"
        },
        "disable-custom-font-sizes": {
          "description": "Whether the theme disables custom font sizes.",
          "type": "boolean"
        },
        "disable-custom-gradients": {
          "description": "Whether the theme disables custom graidients.",
          "type": "boolean"
        },
        "editor-color-palette": {
          "description": "Custom color palette if defined by the theme.",
          "type": [
            "boolean",
            "array"
          ],
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "color": {
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "editor-font-sizes": {
          "description": "Custom font sizes if defined by the theme.",
          "type": [
            "boolean",
            "array"
          ],
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "size": {
                "type": "number"
              },
              "slug": {
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "editor-gradient-presets": {
          "description": "Custom gradient presets if defined by the theme.",
          "type": [
            "boolean",
            "array"
          ],
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "gradient": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "editor-styles": {
          "description": "Whether theme opts in to the editor styles CSS wrapper.",
          "type": "boolean"
        },
        "formats": {
          "description": "Post formats supported.",
          "type": "array",
          "items": {
            "type": "string",
            "enum": {
              "standard": "standard",
              "aside": "aside",
              "chat": "chat",
              "gallery": "gallery",
              "link": "link",
              "image": "image",
              "quote": "quote",
              "status": "status",
              "video": "video",
              "audio": "audio"
            }
          }
        },
        "html5": {
          "description": "Allows use of html5 markup for search forms, comment forms, comment lists, gallery, and caption.",
          "type": [
            "boolean",
            "array"
          ],
          "items": {
            "type": "string",
            "enum": [
              "search-form",
              "comment-form",
              "comment-list",
              "gallery",
              "caption",
              "script",
              "style"
            ]
          }
        },
        "post-thumbnails": {
          "description": "Whether the theme supports post thumbnails.",
          "type": [
            "boolean",
            "array"
          ],
          "items": {
            "type": "string"
          }
        },
        "responsive-embeds": {
          "description": "Whether the theme supports responsive embedded content.",
          "type": "boolean"
        },
        "title-tag": {
          "description": "Whether the theme can manage the document title tag.",
          "type": "boolean"
        },
        "wp-block-styles": {
          "description": "Whether theme opts in to default WordPress block styles for viewing.",
          "type": "boolean"
        }
      }
    }
  }
}

@kadamwhite
6 months ago

Clarify schema comment and clean up tests

#20 @TimothyBlynJacobs
6 months ago

When running the entire test suite, @kadamwhite noticed that the test_theme_supports_custom_header test failed. This is because earlier tests that call add_theme_support( 'custom-header' ) have a side effect of defining the HEADER_IMAGE constant to an empty string which overrides our custom image. The only way we can really fix this is by adjusting our test to just use an empty string. Constants 😢

This ticket was mentioned in PR #153 on WordPress/wordpress-develop by TimothyBJacobs.


6 months ago

#22 @kadamwhite
6 months ago

In 47258:

REST API: List all core theme feature support details in /themes endpoint response.

Fully list which first-party core theme features are supported in the /themes endpoint response. This brings the REST API themes controller's response more in line with the output of get_theme_support().

Props adamboro, apieschel, koke, spacedmonkey, TimothyBlynJacobs.
See #49037.

#23 @kadamwhite
6 months ago

Landed 49037.7.diff to implement first-party theme supports for 5.4. Thank you to everybody involved in preparing the patch. I think it's probably best to spin up another ticket for "Future Release" to discuss enhancing the controller to handle third-party theme supports, so that we can close out this piece of the work; any objections?

This ticket was mentioned in Slack in #core-restapi by kadamwhite. View the logs.


6 months ago

#25 @kadamwhite
6 months ago

  • Resolution set to fixed
  • Status changed from new to closed

We opened #49406 to cover discussing a new register_theme_support method which would let us extend this logic to cover third-party plugin theme features.

I am closing this original ticket as resolved by [47258]

Note: See TracTickets for help on using tickets.