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

Backport: WP_Theme_JSON_Resolver changes #3901

Closed
114 changes: 80 additions & 34 deletions src/wp-includes/class-wp-theme-json-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,16 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post
$post_type_filter = 'wp_global_styles';
$stylesheet = $theme->get_stylesheet();
$args = array(
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'desc',
'post_type' => $post_type_filter,
'post_status' => $post_status_filter,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'tax_query' => array(
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'desc',
'post_type' => $post_type_filter,
'post_status' => $post_status_filter,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
'field' => 'name',
Expand All @@ -444,7 +446,7 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post
$global_style_query = new WP_Query();
$recent_posts = $global_style_query->query( $args );
if ( count( $recent_posts ) === 1 ) {
$user_cpt = get_post( $recent_posts[0], ARRAY_A );
$user_cpt = get_object_vars( $recent_posts[0] );
} elseif ( $create_post ) {
$cpt_post_id = wp_insert_post(
array(
Expand All @@ -460,7 +462,7 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post
true
);
if ( ! is_wp_error( $cpt_post_id ) ) {
$user_cpt = get_post( $cpt_post_id, ARRAY_A );
$user_cpt = get_object_vars( get_post( $cpt_post_id ) );
}
}

Expand Down Expand Up @@ -523,17 +525,23 @@ public static function get_user_data() {
/**
* Returns the data merged from multiple origins.
*
* There are three sources of data (origins) for a site:
* default, theme, and custom. The custom's has higher priority
* than the theme's, and the theme's higher than default's.
* There are four sources of data (origins) for a site:
*
* - default => WordPress
* - blocks => each one of the blocks provides data for itself
* - theme => the active theme
* - custom => data provided by the user
*
* The custom's has higher priority than the theme's, the theme's higher than blocks',
* and block's higher than default's.
*
* Unlike the getters
* {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_core_data/ get_core_data},
* {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_theme_data/ get_theme_data},
* and {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_user_data/ get_user_data},
* this method returns data after it has been merged with the previous origins.
* This means that if the same piece of data is declared in different origins
* (user, theme, and core), the last origin overrides the previous.
* (default, blocks, theme, custom), the last origin overrides the previous.
*
* For example, if the user has set a background color
* for the paragraph block, and the theme has done it as well,
Expand All @@ -543,9 +551,10 @@ public static function get_user_data() {
* @since 5.9.0 Added user data, removed the `$settings` parameter,
* added the `$origin` parameter.
* @since 6.1.0 Added block data and generation of spacingSizes array.
Mamaduka marked this conversation as resolved.
Show resolved Hide resolved
* @since 6.2.0 Changed ' $origin' parameter values to 'default', 'blocks', 'theme' or 'custom'.
*
* @param string $origin Optional. To what level should we merge data.
* Valid values are 'theme' or 'custom'. Default 'custom'.
* @param string $origin Optional. To what level should we merge data: 'default', 'blocks', 'theme' or 'custom'.
* 'custom' is used as default value as well as fallback value if the origin is unknown.
* @return WP_Theme_JSON
*/
public static function get_merged_data( $origin = 'custom' ) {
Expand All @@ -554,14 +563,23 @@ public static function get_merged_data( $origin = 'custom' ) {
}

$result = static::get_core_data();
if ( 'default' === $origin ) {
$result->set_spacing_sizes();
return $result;
}

$result->merge( static::get_block_data() );
$result->merge( static::get_theme_data() );
if ( 'blocks' === $origin ) {
return $result;
}

if ( 'custom' === $origin ) {
$result->merge( static::get_user_data() );
$result->merge( static::get_theme_data() );
if ( 'theme' === $origin ) {
$result->set_spacing_sizes();
return $result;
}

// Generate the default spacingSizes array based on the merged spacingScale settings.
$result->merge( static::get_user_data() );
$result->set_spacing_sizes();

return $result;
Expand Down Expand Up @@ -647,33 +665,61 @@ public static function clean_cached_data() {
static::$i18n_schema = null;
}

/**
* Returns an array of all nested json files within a given directory.
Mamaduka marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 6.2.0
*
* @param string $dir The directory to recursively iterate and list files of.
* @return array The merged array.
*/
private static function recursively_iterate_json( $dir ) {
$nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ) );
$nested_json_files = iterator_to_array( new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH ) );
return $nested_json_files;
}


/**
* Returns the style variations defined by the theme.
*
* @since 6.0.0
* @since 6.2.0 Returns parent theme variations if theme is a child.
*
* @return array
*/
public static function get_style_variations() {
$variations = array();
$base_directory = get_stylesheet_directory() . '/styles';
$variation_files = array();
$variations = array();
$base_directory = get_stylesheet_directory() . '/styles';
$template_directory = get_template_directory() . '/styles';
if ( is_dir( $base_directory ) ) {
$nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_directory ) );
$nested_html_files = iterator_to_array( new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH ) );
ksort( $nested_html_files );
foreach ( $nested_html_files as $path => $file ) {
$decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) );
if ( is_array( $decoded_file ) ) {
$translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
$variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data();
if ( empty( $variation['title'] ) ) {
$variation['title'] = basename( $path, '.json' );
$variation_files = static::recursively_iterate_json( $base_directory );
}
if ( is_dir( $template_directory ) && $template_directory !== $base_directory ) {
$variation_files_parent = static::recursively_iterate_json( $template_directory );
// If the child and parent variation file basename are the same, only include the child theme's.
foreach ( $variation_files_parent as $parent_path => $parent ) {
foreach ( $variation_files as $child_path => $child ) {
if ( basename( $parent_path ) === basename( $child_path ) ) {
unset( $variation_files_parent[ $parent_path ] );
}
$variations[] = $variation;
}
}
$variation_files = array_merge( $variation_files, $variation_files_parent );
}
ksort( $variation_files );
foreach ( $variation_files as $path => $file ) {
$decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) );
if ( is_array( $decoded_file ) ) {
$translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
$variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data();
if ( empty( $variation['title'] ) ) {
$variation['title'] = basename( $path, '.json' );
}
$variations[] = $variation;
}
}
return $variations;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": 2,
"settings": {
"blocks": {
"core/post-title": {
"color": {
"palette": [
{
"slug": "dark",
"name": "Dark",
"color": "#010101"
}
]
}
}
}
}
}
18 changes: 18 additions & 0 deletions tests/phpunit/data/themedir1/block-theme/styles/variation-b.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": 2,
"settings": {
"blocks": {
"core/post-title": {
"color": {
"palette": [
{
"slug": "light",
"name": "Light",
"color": "#f1f1f1"
}
]
}
}
}
}
}
2 changes: 1 addition & 1 deletion tests/phpunit/data/themedir1/block-theme/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,4 @@
"area": "header"
}
]
}
}
27 changes: 26 additions & 1 deletion tests/phpunit/tests/rest-api/rest-global-styles-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,27 @@ public function test_get_theme_items() {
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$expected = array(
array(
'version' => 2,
'title' => 'variation-b',
'settings' => array(
'blocks' => array(
'core/post-title' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f1f1f1',
),
),
),
),
),
),
),
),
array(
'version' => 2,
'title' => 'Block theme variation',
Expand Down Expand Up @@ -511,6 +532,10 @@ public function test_get_theme_items() {
),
),
);
$this->assertSameSetsWithIndex( $data, $expected );

wp_recursive_ksort( $data );
wp_recursive_ksort( $expected );

$this->assertSameSets( $data, $expected );
Comment on lines +535 to +539
Copy link
Member Author

Choose a reason for hiding this comment

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

Is it preferred sorting arrays before assertions, or can we use something like assertEqualsCanonicalizing?

Copy link
Contributor

Choose a reason for hiding this comment

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

Here the deeply nested array of arrays are being recursively key sorted before the assertion. assertSameSets() repeats an index sort at the first dimension of the arrays. That's not necessary.

Instead of assertSameSets(), use assertSame().

I'm wondering though why this needed. Pulling down to explore.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi, @hellofromtonya

Let me know if any follow-ups are needed for PHPUnits tests on this PR.

}
}
Loading