diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php index 7adb37ffbd9e0..eadbc759e0ced 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php @@ -57,4 +57,60 @@ public static function _clean_cached_data_upon_upgrading( $upgrader, $options ) } } + /** + * Returns the data merged from multiple origins. + * + * 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 + * (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, + * the user preference wins. + * + * @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' ) { + if ( is_array( $origin ) ) { + _deprecated_argument( __FUNCTION__, '5.9.0' ); + } + + $result = static::get_core_data(); + if ( 'default' === $origin ) { + $result->set_spacing_sizes(); + return $result; + } + + $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; + } } diff --git a/lib/compat/wordpress-6.2/default-filters.php b/lib/compat/wordpress-6.2/default-filters.php index 927ff2bd12aa3..4df9ad39dc608 100644 --- a/lib/compat/wordpress-6.2/default-filters.php +++ b/lib/compat/wordpress-6.2/default-filters.php @@ -18,7 +18,9 @@ */ add_action( 'switch_theme', 'wp_theme_has_theme_json_clean_cache' ); +add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) ); add_action( 'start_previewing_theme', 'wp_theme_has_theme_json_clean_cache' ); +add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) ); add_action( 'upgrader_process_complete', '_wp_theme_has_theme_json_clean_cache_upon_upgrading_active_theme', 10, 2 ); add_action( 'save_post_wp_global_styles', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) ); add_action( 'activated_plugin', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) ); diff --git a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php index 8974241e43a88..fd13681e5a12e 100644 --- a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php @@ -165,47 +165,4 @@ private static function remove_JSON_comments( $array ) { return $array; } - /** - * 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. - * - * Unlike the getters {@link get_core_data}, - * {@link get_theme_data}, and {@link 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. - * - * For example, if the user has set a background color - * for the paragraph block, and the theme has done it as well, - * the user preference wins. - * - * @since 5.8.0 - * @since 5.9.0 Added user data, removed the `$settings` parameter, - * added the `$origin` parameter. - * - * @param string $origin Optional. To what level should we merge data. - * Valid values are 'theme' or 'custom'. Default 'custom'. - * @return WP_Theme_JSON - */ - public static function get_merged_data( $origin = 'custom' ) { - if ( is_array( $origin ) ) { - _deprecated_argument( __FUNCTION__, '5.9' ); - } - - $result = new WP_Theme_JSON_Gutenberg(); - $result->merge( 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() ); - } - // Generate the default spacing sizes presets. - $result->set_spacing_sizes(); - - return $result; - } } diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index 153db8c560679..f872b251a7784 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -358,4 +358,134 @@ public function test_get_user_data_from_wp_global_styles_does_not_use_uncached_q $user_cpt = WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_wp_global_styles( $theme ); $this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' ); } + + /** + * Test that get_merged_data returns the data merged up to the proper origin. + * + * @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_Gutenberg::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_Gutenberg::get_merged_data( $origin ); + $settings = $theme_json->get_settings(); + $styles = $theme_json->get_styles_block_nodes(); + $this->assertSame( $core_palette, isset( $settings['color']['palette']['default'] ), $core_palette_text ); + $styles = array_filter( + $styles, + static function( $element ) { + return isset( $element['name'] ) && 'my/block-with-styles' === $element['name']; + } + ); + $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 ); + + unregister_block_type( 'my/block-with-styles' ); + } + + /** + * Data provider for test_get_merged_data_returns_origin + * + * @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', + ), + ); + } + }