Skip to content

Commit

Permalink
theme.json: add appearanceTools flag to opt-in into appearance UI c…
Browse files Browse the repository at this point in the history
…ontrols (#36646)
  • Loading branch information
oandregal committed Nov 23, 2021
1 parent 28995aa commit 1e78e92
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 7 deletions.
10 changes: 10 additions & 0 deletions docs/how-to-guides/themes/theme-json.md
Expand Up @@ -218,6 +218,7 @@ The settings section has the following structure:
{
"version": 1,
"settings": {
"appearanceTools": false,
"border": {
"color": false,
"radius": false,
Expand Down Expand Up @@ -282,6 +283,15 @@ Each block can configure any of these settings separately, providing a more fine

Note, however, that not all settings are relevant for all blocks. The settings section provides an opt-in/opt-out mechanism for themes, but it's the block's responsibility to add support for the features that are relevant to it. For example, if a block doesn't implement the `dropCap` feature, a theme can't enable it for such a block through `theme.json`.

### Opt-in into UI controls

There's one special setting property, `appearanceTools`, which is a boolean and its default value is false. Themes can use this setting to enable the following ones:

- border: color, radius, style, width
- color: link
- spacing: blockGap, margin, padding
- typography: lineHeight

#### Backward compatibility with add_theme_support

To retain backward compatibility, the existing `add_theme_support` declarations that configure the block editor are retrofit in the proper categories for the top-level section. For example, if a theme uses `add_theme_support('disable-custom-colors')`, it'll be the same as setting `settings.color.custom` to `false`. If the `theme.json` contains any settings, these will take precedence over the values declared via `add_theme_support`. This is the complete list of equivalences:
Expand Down
67 changes: 60 additions & 7 deletions lib/class-wp-theme-json-gutenberg.php
Expand Up @@ -81,13 +81,14 @@ class WP_Theme_JSON_Gutenberg {
);

const VALID_SETTINGS = array(
'border' => array(
'appearanceTools' => null,
'border' => array(
'color' => null,
'radius' => null,
'style' => null,
'width' => null,
),
'color' => array(
'color' => array(
'background' => null,
'custom' => null,
'customDuotone' => null,
Expand All @@ -100,18 +101,18 @@ class WP_Theme_JSON_Gutenberg {
'palette' => null,
'text' => null,
),
'custom' => null,
'layout' => array(
'custom' => null,
'layout' => array(
'contentSize' => null,
'wideSize' => null,
),
'spacing' => array(
'spacing' => array(
'blockGap' => null,
'margin' => null,
'padding' => null,
'units' => null,
),
'typography' => array(
'typography' => array(
'customFontSize' => null,
'dropCap' => null,
'fontFamilies' => null,
Expand Down Expand Up @@ -292,7 +293,8 @@ public function __construct( $theme_json = array(), $origin = 'theme' ) {

$valid_block_names = array_keys( self::get_blocks_metadata() );
$valid_element_names = array_keys( self::ELEMENTS );
$this->theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );
$theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );
$this->theme_json = self::maybe_opt_in_into_settings( $theme_json );

// Internally, presets are keyed by origin.
$nodes = self::get_setting_nodes( $this->theme_json );
Expand All @@ -309,6 +311,57 @@ public function __construct( $theme_json = array(), $origin = 'theme' ) {
}
}

/**
* Enables some opt-in settings if theme declared support.
*
* @param array $theme_json A theme.json structure to modify.
* @return array The modified theme.json structure.
*/
private static function maybe_opt_in_into_settings( $theme_json ) {
$new_theme_json = $theme_json;

if ( isset( $new_theme_json['settings']['appearanceTools'] ) ) {
self::do_opt_in_into_settings( $new_theme_json['settings'] );
}

if ( isset( $new_theme_json['settings']['blocks'] ) && is_array( $new_theme_json['settings']['blocks'] ) ) {
foreach ( $new_theme_json['settings']['blocks'] as &$block ) {
if ( isset( $block['appearanceTools'] ) ) {
self::do_opt_in_into_settings( $block );
}
}
}

return $new_theme_json;
}

/**
* Enables some settings.
*
* @param array $context The context to which the settings belong.
*/
private static function do_opt_in_into_settings( &$context ) {
$to_opt_in = array(
array( 'border', 'color' ),
array( 'border', 'radius' ),
array( 'border', 'style' ),
array( 'border', 'width' ),
array( 'color', 'link' ),
array( 'spacing', 'blockGap' ),
array( 'spacing', 'margin' ),
array( 'spacing', 'padding' ),
array( 'typography', 'lineHeight' ),
);

foreach ( $to_opt_in as $path ) {
if ( null === _wp_array_get( $context, $path, null ) ) {
_wp_array_set( $context, $path, true );
}
}

unset( $context['appearanceTools'] );
}

/**
* Sanitizes the input according to the schemas.
*
Expand Down
1 change: 1 addition & 0 deletions lib/theme.json
@@ -1,6 +1,7 @@
{
"version": 2,
"settings": {
"appearanceTools": false,
"color": {
"background": true,
"palette": [
Expand Down
73 changes: 73 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Expand Up @@ -188,6 +188,79 @@ function test_get_settings_presets_are_keyed_by_origin() {
$this->assertEqualSetsWithIndex( $expected_no_origin, $actual_no_origin );
}

function test_get_settings_using_opt_in_key() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'settings' => array(
'appearanceTools' => true,
'blocks' => array(
'core/paragraph' => array(
'typography' => array(
'lineHeight' => false,
),
),
'core/group' => array(
'appearanceTools' => true,
'typography' => array(
'lineHeight' => false, // This should override appearanceTools.
),
),
),
),
)
);

$actual = $theme_json->get_settings();
$expected = array(
'border' => array(
'width' => true,
'style' => true,
'radius' => true,
'color' => true,
),
'color' => array(
'link' => true,
),
'spacing' => array(
'blockGap' => true,
'margin' => true,
'padding' => true,
),
'typography' => array(
'lineHeight' => true,
),
'blocks' => array(
'core/paragraph' => array(
'typography' => array(
'lineHeight' => false,
),
),
'core/group' => array(
'border' => array(
'width' => true,
'style' => true,
'radius' => true,
'color' => true,
),
'color' => array(
'link' => true,
),
'spacing' => array(
'blockGap' => true,
'margin' => true,
'padding' => true,
),
'typography' => array(
'lineHeight' => false,
),
),
),
);

$this->assertEqualSetsWithIndex( $expected, $actual );
}

function test_get_stylesheet_support_for_shorthand_and_longhand_values() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
Expand Down
5 changes: 5 additions & 0 deletions schemas/json/theme.json
Expand Up @@ -9,6 +9,11 @@
},
"settingsProperties": {
"properties": {
"appearanceTools": {
"description": "Setting that enables ui tools. \nGutenberg plugin required.",
"type": "boolean",
"default": false
},
"border": {
"description": "Settings related to borders.\nGutenberg plugin required.",
"type": "object",
Expand Down

0 comments on commit 1e78e92

Please sign in to comment.