Skip to content

Commit

Permalink
Merge branch 'trunk' into update/site-title-link-toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
aristath committed Jun 14, 2021
2 parents 1c64ce0 + 279fe5c commit 1fda801
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 303 deletions.
114 changes: 62 additions & 52 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class WP_Theme_JSON_Gutenberg {
*/
const ROOT_BLOCK_SELECTOR = 'body';

const VALID_ORIGINS = array(
'core',
'theme',
'user',
);

const VALID_TOP_LEVEL_KEYS = array(
'customTemplates',
'templateParts',
Expand Down Expand Up @@ -277,9 +283,14 @@ class WP_Theme_JSON_Gutenberg {
/**
* Constructor.
*
* @param array $theme_json A structure that follows the theme.json schema.
* @param array $theme_json A structure that follows the theme.json schema.
* @param string $origin What source of data this object represents. One of core, theme, or user. Default: theme.
*/
public function __construct( $theme_json = array() ) {
public function __construct( $theme_json = array(), $origin = 'theme' ) {
if ( ! in_array( $origin, self::VALID_ORIGINS, true ) ) {
$origin = 'theme';
}

// The old format is not meant to be ported to core.
// We can remove it at that point.
if ( ! isset( $theme_json['version'] ) || 0 === $theme_json['version'] ) {
Expand All @@ -289,6 +300,18 @@ public function __construct( $theme_json = array() ) {
$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 );

// Internally, presets are keyed by origin.
$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $node ) {
foreach ( self::PRESETS_METADATA as $preset ) {
$path = array_merge( $node['path'], $preset['path'] );
$preset = _wp_array_get( $this->theme_json, $path, array() );
if ( ! empty( $preset ) ) {
gutenberg_experimental_set( $this->theme_json, $path, array( $origin => $preset ) );
}
}
}
}

/**
Expand Down Expand Up @@ -657,9 +680,8 @@ private static function append_to_selector( $selector, $to_append ) {
* @return array Array of presets where each key is a slug and each value is the preset value.
*/
private static function get_merged_preset_by_slug( $preset_per_origin, $value_key ) {
$origins = array( 'core', 'theme', 'user' );
$result = array();
foreach ( $origins as $origin ) {
$result = array();
foreach ( self::VALID_ORIGINS as $origin ) {
if ( ! isset( $preset_per_origin[ $origin ] ) ) {
continue;
}
Expand Down Expand Up @@ -1133,59 +1155,34 @@ public function get_stylesheet( $type = 'all' ) {
* Merge new incoming data.
*
* @param WP_Theme_JSON $incoming Data to merge.
* @param string $origin origin of the incoming data (e.g: core, theme, or user).
*/
public function merge( $incoming, $origin ) {

public function merge( $incoming ) {
$incoming_data = $incoming->get_raw_data();
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );

// The array_replace_recursive algorithm merges at the leaf level.
// For leaf values that are arrays it will use the numeric indexes for replacement.
// In those cases, what we want is to use the incoming value, if it exists.
//
// These are the cases that have array values at the leaf levels.
$properties = array();
$properties[] = array( 'custom' );
$properties[] = array( 'spacing', 'units' );
$properties[] = array( 'color', 'duotone' );

$to_append = array();
$to_append[] = array( 'color', 'palette' );
$to_append[] = array( 'color', 'gradients' );
$to_append[] = array( 'typography', 'fontSizes' );
$to_append[] = array( 'typography', 'fontFamilies' );
// In those cases, we want to replace the existing with the incoming value, if it exists.
$to_replace = array();
$to_replace[] = array( 'custom' );
$to_replace[] = array( 'spacing', 'units' );
$to_replace[] = array( 'color', 'duotone' );
foreach ( self::VALID_ORIGINS as $origin ) {
$to_replace[] = array( 'color', 'palette', $origin );
$to_replace[] = array( 'color', 'gradients', $origin );
$to_replace[] = array( 'typography', 'fontSizes', $origin );
$to_replace[] = array( 'typography', 'fontFamilies', $origin );
}

$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $metadata ) {
foreach ( $properties as $property_path ) {
foreach ( $to_replace as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
$node = _wp_array_get( $incoming_data, $path, array() );
if ( ! empty( $node ) ) {
gutenberg_experimental_set( $this->theme_json, $path, $node );
}
}

foreach ( $to_append as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
$node = _wp_array_get( $incoming_data, $path, null );
if ( null !== $node ) {
$existing_node = _wp_array_get( $this->theme_json, $path, null );
$new_node = array_filter(
$existing_node,
function ( $key ) {
return in_array( $key, array( 'core', 'theme', 'user ' ), true );
},
ARRAY_FILTER_USE_KEY
);
if ( isset( $node[ $origin ] ) ) {
$new_node[ $origin ] = $node[ $origin ];
} else {
$new_node[ $origin ] = $node;
}
gutenberg_experimental_set( $this->theme_json, $path, $new_node );
}
}
}

}
Expand Down Expand Up @@ -1282,14 +1279,26 @@ private static function is_safe_css_declaration( $property_name, $property_value

/**
* Removes insecure data from theme.json.
*
* @param array $theme_json Structure to sanitize.
*
* @return array Sanitized structure.
*/
public function remove_insecure_properties() {
public static function remove_insecure_properties( $theme_json ) {
$sanitized = array();

if ( ! isset( $theme_json['version'] ) || 0 === $theme_json['version'] ) {
$theme_json = WP_Theme_JSON_Schema_V0::parse( $theme_json );
}

$valid_block_names = array_keys( self::get_blocks_metadata() );
$valid_element_names = array_keys( self::ELEMENTS );
$theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );

$blocks_metadata = self::get_blocks_metadata();
$style_nodes = self::get_style_nodes( $this->theme_json, $blocks_metadata );
$style_nodes = self::get_style_nodes( $theme_json, $blocks_metadata );
foreach ( $style_nodes as $metadata ) {
$input = _wp_array_get( $this->theme_json, $metadata['path'], array() );
$input = _wp_array_get( $theme_json, $metadata['path'], array() );
if ( empty( $input ) ) {
continue;
}
Expand All @@ -1300,9 +1309,9 @@ public function remove_insecure_properties() {
}
}

$setting_nodes = self::get_setting_nodes( $this->theme_json );
$setting_nodes = self::get_setting_nodes( $theme_json );
foreach ( $setting_nodes as $metadata ) {
$input = _wp_array_get( $this->theme_json, $metadata['path'], array() );
$input = _wp_array_get( $theme_json, $metadata['path'], array() );
if ( empty( $input ) ) {
continue;
}
Expand All @@ -1314,17 +1323,18 @@ public function remove_insecure_properties() {
}

if ( empty( $sanitized['styles'] ) ) {
unset( $this->theme_json['styles'] );
unset( $theme_json['styles'] );
} else {
$this->theme_json['styles'] = $sanitized['styles'];
$theme_json['styles'] = $sanitized['styles'];
}

if ( empty( $sanitized['settings'] ) ) {
unset( $this->theme_json['settings'] );
unset( $theme_json['settings'] );
} else {
$this->theme_json['settings'] = $sanitized['settings'];
$theme_json['settings'] = $sanitized['settings'];
}

return $theme_json;
}

/**
Expand Down
14 changes: 7 additions & 7 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public static function get_core_data() {

$config = self::read_json_file( __DIR__ . '/experimental-default-theme.json' );
$config = self::translate( $config );
self::$core = new WP_Theme_JSON_Gutenberg( $config );
self::$core = new WP_Theme_JSON_Gutenberg( $config, 'core' );

return self::$core;
}
Expand Down Expand Up @@ -290,7 +290,7 @@ public static function get_theme_data( $theme_support_data = array() ) {
* to override the ones declared via add_theme_support.
*/
$with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );
$with_theme_supports->merge( self::$theme, 'theme' );
$with_theme_supports->merge( self::$theme );

return $with_theme_supports;
}
Expand Down Expand Up @@ -368,7 +368,7 @@ public static function get_user_data() {
$json_decoding_error = json_last_error();
if ( JSON_ERROR_NONE !== $json_decoding_error ) {
trigger_error( 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() );
return new WP_Theme_JSON_Gutenberg( $config );
return new WP_Theme_JSON_Gutenberg( $config, 'user' );
}

// Very important to verify if the flag isGlobalStylesUserThemeJSON is true.
Expand All @@ -382,7 +382,7 @@ public static function get_user_data() {
$config = $decoded_data;
}
}
self::$user = new WP_Theme_JSON_Gutenberg( $config );
self::$user = new WP_Theme_JSON_Gutenberg( $config, 'user' );

return self::$user;
}
Expand Down Expand Up @@ -415,11 +415,11 @@ public static function get_merged_data( $settings = array(), $origin = 'user' )
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $settings );

$result = new WP_Theme_JSON_Gutenberg();
$result->merge( self::get_core_data(), 'core' );
$result->merge( self::get_theme_data( $theme_support_data ), 'theme' );
$result->merge( self::get_core_data() );
$result->merge( self::get_theme_data( $theme_support_data ) );

if ( 'user' === $origin ) {
$result->merge( self::get_user_data(), 'user' );
$result->merge( self::get_user_data() );
}

return $result;
Expand Down
2 changes: 1 addition & 1 deletion lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ function gutenberg_register_packages_scripts( $scripts ) {
// When in production, use the plugin's version as the default asset version;
// else (for development or test) default to use the current time.
$default_version = defined( 'GUTENBERG_VERSION' ) && ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? GUTENBERG_VERSION : time();
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.js' : '.min.js';
$suffix = '.min.js';

foreach ( glob( gutenberg_dir_path() . "build/*/index$suffix" ) as $path ) {
// Prefix `wp-` to package directory to get script handle.
Expand Down
6 changes: 3 additions & 3 deletions lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ function gutenberg_global_styles_filter_post( $content ) {
$decoded_data['isGlobalStylesUserThemeJSON']
) {
unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
$theme_json = new WP_Theme_JSON_Gutenberg( $decoded_data );
$theme_json->remove_insecure_properties();
$data_to_encode = $theme_json->get_raw_data();

$data_to_encode = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $decoded_data );

$data_to_encode['isGlobalStylesUserThemeJSON'] = true;
return wp_json_encode( $data_to_encode );
}
Expand Down
9 changes: 4 additions & 5 deletions packages/data/src/components/use-select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,11 @@ export default function useSelect( _mapSelect, deps ) {
errorMessage += `\nThe error may be correlated with this previous error:\n`;
errorMessage += `${ latestMapOutputError.current.stack }\n\n`;
errorMessage += 'Original stack trace:';

throw new Error( errorMessage );
} else {
// eslint-disable-next-line no-console
console.error( errorMessage );
}

// eslint-disable-next-line no-console
console.error( errorMessage );
mapOutput = latestMapOutput.current;
}
}

Expand Down
30 changes: 17 additions & 13 deletions phpunit/class-wp-theme-json-resolver-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,17 @@ function test_translations_are_applied() {
array(
'color' => array(
'palette' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
),
array(
'slug' => 'dark',
'name' => 'Ciemny',
'color' => '#000',
'theme' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
),
array(
'slug' => 'dark',
'name' => 'Ciemny',
'color' => '#000',
),
),
),
'custom' => false,
Expand All @@ -172,10 +174,12 @@ function test_translations_are_applied() {
'core/paragraph' => array(
'color' => array(
'palette' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
'theme' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
),
),
),
),
Expand Down
Loading

0 comments on commit 1fda801

Please sign in to comment.