mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-06-30 23:30:05 +00:00
Block editor: Update WP_Theme_JSON_Resolver and improve its performance.
This commit includes the latest updates WP_Theme_JSON_Resolver class made in the block editor. Some of these updates improve the performance of the class. Props Mamaduka, hellofromTonya, flixos90, jorgefilipecosta, oandregal, spacedmonkey, audrasjb, costdev, scruffian. Closes #57545. git-svn-id: https://develop.svn.wordpress.org/trunk@55231 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -427,14 +427,16 @@ class WP_Theme_JSON_Resolver {
|
||||
$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',
|
||||
@@ -446,7 +448,7 @@ class WP_Theme_JSON_Resolver {
|
||||
$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(
|
||||
@@ -462,7 +464,7 @@ class WP_Theme_JSON_Resolver {
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,9 +527,15 @@ class WP_Theme_JSON_Resolver {
|
||||
/**
|
||||
* 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},
|
||||
@@ -535,7 +543,7 @@ class WP_Theme_JSON_Resolver {
|
||||
* 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,
|
||||
@@ -545,9 +553,10 @@ class WP_Theme_JSON_Resolver {
|
||||
* @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.
|
||||
* @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' ) {
|
||||
@@ -556,14 +565,23 @@ class WP_Theme_JSON_Resolver {
|
||||
}
|
||||
|
||||
$result = static::get_core_data();
|
||||
$result->merge( static::get_block_data() );
|
||||
$result->merge( static::get_theme_data() );
|
||||
|
||||
if ( 'custom' === $origin ) {
|
||||
$result->merge( static::get_user_data() );
|
||||
if ( 'default' === $origin ) {
|
||||
$result->set_spacing_sizes();
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Generate the default spacingSizes array based on the merged spacingScale settings.
|
||||
$result->merge( static::get_block_data() );
|
||||
if ( 'blocks' === $origin ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result->merge( static::get_theme_data() );
|
||||
if ( 'theme' === $origin ) {
|
||||
$result->set_spacing_sizes();
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result->merge( static::get_user_data() );
|
||||
$result->set_spacing_sizes();
|
||||
|
||||
return $result;
|
||||
@@ -649,33 +667,61 @@ class WP_Theme_JSON_Resolver {
|
||||
static::$i18n_schema = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all nested JSON files within a given directory.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"settings": {
|
||||
"blocks": {
|
||||
"core/post-title": {
|
||||
"color": {
|
||||
"palette": [
|
||||
{
|
||||
"slug": "dark",
|
||||
"name": "Dark",
|
||||
"color": "#010101"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"settings": {
|
||||
"blocks": {
|
||||
"core/post-title": {
|
||||
"color": {
|
||||
"palette": [
|
||||
{
|
||||
"slug": "light",
|
||||
"name": "Light",
|
||||
"color": "#f1f1f1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,4 +124,4 @@
|
||||
"area": "header"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +484,27 @@ class WP_REST_Global_Styles_Controller_Test extends WP_Test_REST_Controller_Test
|
||||
$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',
|
||||
@@ -511,7 +532,11 @@ class WP_REST_Global_Styles_Controller_Test extends WP_Test_REST_Controller_Test
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->assertSameSetsWithIndex( $data, $expected );
|
||||
|
||||
wp_recursive_ksort( $data );
|
||||
wp_recursive_ksort( $expected );
|
||||
|
||||
$this->assertSameSets( $data, $expected );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,7 @@ class Tests_Theme_wpThemeJsonResolver extends WP_UnitTestCase {
|
||||
);
|
||||
$this->assertSame(
|
||||
'Wariant motywu blokowego',
|
||||
$style_variations[0]['title']
|
||||
$style_variations[1]['title']
|
||||
);
|
||||
}
|
||||
|
||||
@@ -775,4 +775,209 @@ class Tests_Theme_wpThemeJsonResolver extends WP_UnitTestCase {
|
||||
$this->assertSame( $empty_theme_json, $theme_data->get_raw_data(), 'Theme data should be empty without theme support.' );
|
||||
$this->assertNull( $property->getValue(), 'Theme i18n schema should not have been loaded without theme support.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that get_merged_data returns the data merged up to the proper origin.
|
||||
*
|
||||
* @ticket 57545
|
||||
*
|
||||
* @covers WP_Theme_JSON_Resolver::get_merged_data
|
||||
*
|
||||
* @dataProvider data_get_merged_data_returns_origin
|
||||
*
|
||||
* @param string $origin What origin to get data from.
|
||||
* @param bool $core_palette Whether the core palette is present.
|
||||
* @param string $core_palette_text Message.
|
||||
* @param string $block_styles Whether the block styles are present.
|
||||
* @param string $block_styles_text Message.
|
||||
* @param bool $theme_palette Whether the theme palette is present.
|
||||
* @param string $theme_palette_text Message.
|
||||
* @param bool $user_palette Whether the user palette is present.
|
||||
* @param string $user_palette_text Message.
|
||||
*/
|
||||
public function test_get_merged_data_returns_origin( $origin, $core_palette, $core_palette_text, $block_styles, $block_styles_text, $theme_palette, $theme_palette_text, $user_palette, $user_palette_text ) {
|
||||
// Make sure there is data from the blocks origin.
|
||||
register_block_type(
|
||||
'my/block-with-styles',
|
||||
array(
|
||||
'api_version' => 2,
|
||||
'attributes' => array(
|
||||
'borderColor' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'style' => array(
|
||||
'type' => 'object',
|
||||
),
|
||||
),
|
||||
'supports' => array(
|
||||
'__experimentalStyle' => array(
|
||||
'typography' => array(
|
||||
'fontSize' => '42rem',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Make sure there is data from the theme origin.
|
||||
switch_theme( 'block-theme' );
|
||||
|
||||
// Make sure there is data from the user origin.
|
||||
wp_set_current_user( self::$administrator_id );
|
||||
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( wp_get_theme(), true );
|
||||
$config = json_decode( $user_cpt['post_content'], true );
|
||||
$config['settings']['color']['palette']['custom'] = array(
|
||||
array(
|
||||
'color' => 'hotpink',
|
||||
'name' => 'My color',
|
||||
'slug' => 'my-color',
|
||||
),
|
||||
);
|
||||
$user_cpt['post_content'] = wp_json_encode( $config );
|
||||
wp_update_post( $user_cpt, true, false );
|
||||
|
||||
$theme_json = WP_Theme_JSON_Resolver::get_merged_data( $origin );
|
||||
$settings = $theme_json->get_settings();
|
||||
$styles = $theme_json->get_styles_block_nodes();
|
||||
$styles = array_filter(
|
||||
$styles,
|
||||
static function( $element ) {
|
||||
return isset( $element['name'] ) && 'my/block-with-styles' === $element['name'];
|
||||
}
|
||||
);
|
||||
unregister_block_type( 'my/block-with-styles' );
|
||||
|
||||
$this->assertSame( $core_palette, isset( $settings['color']['palette']['default'] ), $core_palette_text );
|
||||
$this->assertSame( $block_styles, count( $styles ) === 1, $block_styles_text );
|
||||
$this->assertSame( $theme_palette, isset( $settings['color']['palette']['theme'] ), $theme_palette_text );
|
||||
$this->assertSame( $user_palette, isset( $settings['color']['palette']['custom'] ), $user_palette_text );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_get_merged_data_returns_origin() {
|
||||
return array(
|
||||
'origin_default' => array(
|
||||
'origin' => 'default',
|
||||
'core_palette' => true,
|
||||
'core_palette_text' => 'Core palette must be present',
|
||||
'block_styles' => false,
|
||||
'block_styles_text' => 'Block styles should not be present',
|
||||
'theme_palette' => false,
|
||||
'theme_palette_text' => 'Theme palette should not be present',
|
||||
'user_palette' => false,
|
||||
'user_palette_text' => 'User palette should not be present',
|
||||
),
|
||||
'origin_blocks' => array(
|
||||
'origin' => 'blocks',
|
||||
'core_palette' => true,
|
||||
'core_palette_text' => 'Core palette must be present',
|
||||
'block_styles' => true,
|
||||
'block_styles_text' => 'Block styles must be present',
|
||||
'theme_palette' => false,
|
||||
'theme_palette_text' => 'Theme palette should not be present',
|
||||
'user_palette' => false,
|
||||
'user_palette_text' => 'User palette should not be present',
|
||||
),
|
||||
'origin_theme' => array(
|
||||
'origin' => 'theme',
|
||||
'core_palette' => true,
|
||||
'core_palette_text' => 'Core palette must be present',
|
||||
'block_styles' => true,
|
||||
'block_styles_text' => 'Block styles must be present',
|
||||
'theme_palette' => true,
|
||||
'theme_palette_text' => 'Theme palette must be present',
|
||||
'user_palette' => false,
|
||||
'user_palette_text' => 'User palette should not be present',
|
||||
),
|
||||
'origin_custom' => array(
|
||||
'origin' => 'custom',
|
||||
'core_palette' => true,
|
||||
'core_palette_text' => 'Core palette must be present',
|
||||
'block_styles' => true,
|
||||
'block_styles_text' => 'Block styles must be present',
|
||||
'theme_palette' => true,
|
||||
'theme_palette_text' => 'Theme palette must be present',
|
||||
'user_palette' => true,
|
||||
'user_palette_text' => 'User palette must be present',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that get_style_variations returns all variations, including parent theme variations if the theme is a child,
|
||||
* and that the child variation overwrites the parent variation of the same name.
|
||||
*
|
||||
* @ticket 57545
|
||||
*
|
||||
* @covers WP_Theme_JSON_Resolver::get_style_variations
|
||||
**/
|
||||
public function test_get_style_variations_returns_all_variations() {
|
||||
// Switch to a child theme.
|
||||
switch_theme( 'block-theme-child' );
|
||||
wp_set_current_user( self::$administrator_id );
|
||||
|
||||
$actual_settings = WP_Theme_JSON_Resolver::get_style_variations();
|
||||
$expected_settings = array(
|
||||
array(
|
||||
'version' => 2,
|
||||
'title' => 'variation-b',
|
||||
'settings' => array(
|
||||
'blocks' => array(
|
||||
'core/post-title' => array(
|
||||
'color' => array(
|
||||
'palette' => array(
|
||||
'theme' => array(
|
||||
array(
|
||||
'slug' => 'dark',
|
||||
'name' => 'Dark',
|
||||
'color' => '#010101',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'version' => 2,
|
||||
'title' => 'Block theme variation',
|
||||
'settings' => array(
|
||||
'color' => array(
|
||||
'palette' => array(
|
||||
'theme' => array(
|
||||
array(
|
||||
'slug' => 'foreground',
|
||||
'name' => 'Foreground',
|
||||
'color' => '#3F67C6',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'styles' => array(
|
||||
'blocks' => array(
|
||||
'core/post-title' => array(
|
||||
'typography' => array(
|
||||
'fontWeight' => '700',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
wp_recursive_ksort( $actual_settings );
|
||||
wp_recursive_ksort( $expected_settings );
|
||||
|
||||
$this->assertSame(
|
||||
$expected_settings,
|
||||
$actual_settings
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user