Skip to content

Commit

Permalink
Theme Export: Restore appearanceTools when exporting a theme (#39840)
Browse files Browse the repository at this point in the history
* Theme Export: Restore appearanceTools when exporting a theme

* update unit test

* Rename TO_OPT_IN to APPEARANCE_TOOLS_OPT_INS

* Unset appearanceTools

we don't want to pass this to the block-editor store.

* Rename do_opt_out_of_settings to use_appearance_tools_setting

* Add unit test for desired behaviour

* Set appearanceTools if all opt-ins are true

* Add unit test for desired behaviour at the block level

* Make it work at the block level

* Make the code more compact

* Document & inline all code into get_data

* Update PHPDoc

* change inline comments into a comment block to keep the linter happy

* fix linting issues

Co-authored-by: André <583546+oandregal@users.noreply.github.com>
  • Loading branch information
scruffian and oandregal committed Apr 7, 2022
1 parent 30c1797 commit a618eaf
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 8 deletions.
133 changes: 125 additions & 8 deletions lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,18 @@ class WP_Theme_JSON_Gutenberg extends WP_Theme_JSON_5_9 {
'title',
);

const APPEARANCE_TOOLS_OPT_INS = 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' ),
);

/**
* The valid properties under the settings key.
*
Expand Down Expand Up @@ -426,18 +438,48 @@ protected static function get_metadata_boolean( $data, $path, $default = false )
}

/**
* Returns a valid theme.json for a theme.
* Essentially, it flattens the preset data.
* Returns a valid theme.json as provided by a theme.
*
* Unlike get_raw_data() this returns the presets flattened,
* as provided by a theme. This also uses appearanceTools
* instead of their opt-ins if all of them are true.
*
* @return array
*/
public function get_data() {
$flattened_theme_json = $this->theme_json;
$nodes = static::get_setting_nodes( $this->theme_json );
$output = $this->theme_json;
$nodes = static::get_setting_nodes( $output );

/**
* Flatten the theme & custom origins into a single one.
*
* For example, the following:
*
* {
* "settings": {
* "color": {
* "palette": {
* "theme": [ {} ],
* "custom": [ {} ]
* }
* }
* }
* }
*
* will be converted to:
*
* {
* "settings": {
* "color": {
* "palette": [ {} ]
* }
* }
* }
*/
foreach ( $nodes as $node ) {
foreach ( static::PRESETS_METADATA as $preset_metadata ) {
$path = array_merge( $node['path'], $preset_metadata['path'] );
$preset = _wp_array_get( $flattened_theme_json, $path, null );
$preset = _wp_array_get( $output, $path, null );
if ( null === $preset ) {
continue;
}
Expand All @@ -461,12 +503,87 @@ public function get_data() {
foreach ( $items as $slug => $value ) {
$flattened_preset[] = array_merge( array( 'slug' => $slug ), $value );
}
_wp_array_set( $flattened_theme_json, $path, $flattened_preset );
_wp_array_set( $output, $path, $flattened_preset );
}
}

wp_recursive_ksort( $flattened_theme_json );
// If all of the static::APPEARANCE_TOOLS_OPT_INS are true,
// this code unsets them and sets 'appearanceTools' instead.
foreach ( $nodes as $node ) {
$all_opt_ins_are_set = true;
foreach ( static::APPEARANCE_TOOLS_OPT_INS as $opt_in_path ) {
$full_path = array_merge( $node['path'], $opt_in_path );
// Use "unset prop" as a marker instead of "null" because
// "null" can be a valid value for some props (e.g. blockGap).
$opt_in_value = _wp_array_get( $output, $full_path, 'unset prop' );
if ( 'unset prop' === $opt_in_value ) {
$all_opt_ins_are_set = false;
break;
}
}

if ( $all_opt_ins_are_set ) {
_wp_array_set( $output, array_merge( $node['path'], array( 'appearanceTools' ) ), true );
foreach ( static::APPEARANCE_TOOLS_OPT_INS as $opt_in_path ) {
$full_path = array_merge( $node['path'], $opt_in_path );
// Use "unset prop" as a marker instead of "null" because
// "null" can be a valid value for some props (e.g. blockGap).
$opt_in_value = _wp_array_get( $output, $full_path, 'unset prop' );
if ( true !== $opt_in_value ) {
continue;
}

// The following could be improved to be path independent.
// At the moment it relies on a couple of assumptions:
//
// - all opt-ins having a path of size 2.
// - there's two sources of settings: the top-level and the block-level.
if (
( 1 === count( $node['path'] ) ) &&
( 'settings' === $node['path'][0] )
) {
// Top-level settings.
unset( $output['settings'][ $opt_in_path[0] ][ $opt_in_path[1] ] );
if ( empty( $output['settings'][ $opt_in_path[0] ] ) ) {
unset( $output['settings'][ $opt_in_path[0] ] );
}
} elseif (
( 3 === count( $node['path'] ) ) &&
( 'settings' === $node['path'][0] ) &&
( 'blocks' === $node['path'][1] )
) {
// Block-level settings.
$block_name = $node['path'][2];
unset( $output['settings']['blocks'][ $block_name ][ $opt_in_path[0] ][ $opt_in_path[1] ] );
if ( empty( $output['settings']['blocks'][ $block_name ][ $opt_in_path[0] ] ) ) {
unset( $output['settings']['blocks'][ $block_name ][ $opt_in_path[0] ] );
}
}
}
}
}

wp_recursive_ksort( $output );

return $output;
}

/**
* Enables some settings.
*
* @since 5.9.0
*
* @param array $context The context to which the settings belong.
*/
protected static function do_opt_in_into_settings( &$context ) {
foreach ( static::APPEARANCE_TOOLS_OPT_INS as $path ) {
// Use "unset prop" as a marker instead of "null" because
// "null" can be a valid value for some props (e.g. blockGap).
if ( 'unset prop' === _wp_array_get( $context, $path, 'unset prop' ) ) {
_wp_array_set( $context, $path, true );
}
}

return $flattened_theme_json;
unset( $context['appearanceTools'] );
}
}
31 changes: 31 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -2472,4 +2472,35 @@ function test_export_data_deals_with_empty_data() {
$expected_v1 = array( 'version' => 2 );
$this->assertEqualSetsWithIndex( $expected_v1, $actual_v1 );
}

function test_export_data_sets_appearance_tools() {
$theme = new WP_Theme_JSON_Gutenberg(
array(
'version' => 2,
'settings' => array(
'appearanceTools' => true,
'blocks' => array(
'core/paragraph' => array(
'appearanceTools' => true,
),
),
),
)
);

$actual = $theme->get_data();
$expected = array(
'version' => 2,
'settings' => array(
'appearanceTools' => true,
'blocks' => array(
'core/paragraph' => array(
'appearanceTools' => true,
),
),
),
);

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

0 comments on commit a618eaf

Please sign in to comment.