From 2b2e12c3c3b5265ae4ed517759614ab7b9e0554e Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:11:23 +1000 Subject: [PATCH] Section Styles: Register block style variations on `init` (#62461) Co-authored-by: aaronrobertshaw Co-authored-by: oandregal Co-authored-by: annezazu --- backport-changelog/6.6/6756.md | 3 + lib/block-supports/block-style-variations.php | 126 ++++++++++++++---- .../block-style-variations-test.php | 5 + 3 files changed, 111 insertions(+), 23 deletions(-) create mode 100644 backport-changelog/6.6/6756.md diff --git a/backport-changelog/6.6/6756.md b/backport-changelog/6.6/6756.md new file mode 100644 index 00000000000000..e60e128bf45cb4 --- /dev/null +++ b/backport-changelog/6.6/6756.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/6756 + +* https://github.com/WordPress/gutenberg/pull/62461 diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index e09bd4ce90bf0e..bdda388bdcf61a 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -209,9 +209,6 @@ function gutenberg_render_block_style_variation_class_name( $block_content, $blo /** * Collects block style variation data for merging with theme.json data. - * As each block style variation is processed it is registered if it hasn't - * been already. This registration is required for later sanitization of - * theme.json data. * * @since 6.6.0 * @@ -219,14 +216,13 @@ function gutenberg_render_block_style_variation_class_name( $block_content, $blo * * @return array Block variations data to be merged under `styles.blocks`. */ -function gutenberg_resolve_and_register_block_style_variations( $variations ) { +function gutenberg_resolve_block_style_variations( $variations ) { $variations_data = array(); if ( empty( $variations ) ) { return $variations_data; } - $registry = WP_Block_Styles_Registry::get_instance(); $have_named_variations = ! wp_is_numeric_array( $variations ); foreach ( $variations as $key => $variation ) { @@ -248,23 +244,9 @@ function gutenberg_resolve_and_register_block_style_variations( $variations ) { * Block style variations read in via standalone theme.json partials * need to have their name set to the kebab case version of their title. */ - $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] ); - $variation_label = $variation['title'] ?? $variation_name; + $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] ); foreach ( $supported_blocks as $block_type ) { - $registered_styles = $registry->get_registered_styles_for_block( $block_type ); - - // Register block style variation if it hasn't already been registered. - if ( ! array_key_exists( $variation_name, $registered_styles ) ) { - gutenberg_register_block_style( - $block_type, - array( - 'name' => $variation_name, - 'label' => $variation_label, - ) - ); - } - // Add block style variation data under current block type. $path = array( $block_type, 'variations', $variation_name ); _wp_array_set( $variations_data, $path, $variation_data ); @@ -320,7 +302,7 @@ function gutenberg_merge_block_style_variations_data( $variations_data, $theme_j function gutenberg_resolve_block_style_variations_from_theme_style_variation( $theme_json ) { $theme_json_data = $theme_json->get_data(); $shared_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); - $variations_data = gutenberg_resolve_and_register_block_style_variations( $shared_variations ); + $variations_data = gutenberg_resolve_block_style_variations( $shared_variations ); return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json, 'user' ); } @@ -337,7 +319,7 @@ function gutenberg_resolve_block_style_variations_from_theme_style_variation( $t */ function gutenberg_resolve_block_style_variations_from_theme_json_partials( $theme_json ) { $block_style_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( 'block' ); - $variations_data = gutenberg_resolve_and_register_block_style_variations( $block_style_variations ); + $variations_data = gutenberg_resolve_block_style_variations( $block_style_variations ); return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json ); } @@ -355,7 +337,7 @@ function gutenberg_resolve_block_style_variations_from_theme_json_partials( $the function gutenberg_resolve_block_style_variations_from_primary_theme_json( $theme_json ) { $theme_json_data = $theme_json->get_data(); $block_style_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); - $variations_data = gutenberg_resolve_and_register_block_style_variations( $block_style_variations ); + $variations_data = gutenberg_resolve_block_style_variations( $block_style_variations ); return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json ); } @@ -411,3 +393,101 @@ function gutenberg_enqueue_block_style_variation_styles() { add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_styles_registry', 10, 1 ); add_filter( 'wp_theme_json_data_user', 'gutenberg_resolve_block_style_variations_from_theme_style_variation', 10, 1 ); + + +/** + * Registers any block style variations contained within the provided + * theme.json data. + * + * @access private + * + * @param array $variations Shared block style variations. + */ +function gutenberg_register_block_style_variations_from_theme_json_data( $variations ) { + if ( empty( $variations ) ) { + return; + } + + $registry = WP_Block_Styles_Registry::get_instance(); + $have_named_variations = ! wp_is_numeric_array( $variations ); + + foreach ( $variations as $key => $variation ) { + $supported_blocks = $variation['blockTypes'] ?? array(); + + /* + * Standalone theme.json partial files for block style variations + * will have their styles under a top-level property by the same name. + * Variations defined within an existing theme.json or theme style + * variation will themselves already be the required styles data. + */ + $variation_data = $variation['styles'] ?? $variation; + + if ( empty( $variation_data ) ) { + continue; + } + + /* + * Block style variations read in via standalone theme.json partials + * need to have their name set to the kebab case version of their title. + */ + $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] ); + $variation_label = $variation['title'] ?? $variation_name; + + foreach ( $supported_blocks as $block_type ) { + $registered_styles = $registry->get_registered_styles_for_block( $block_type ); + + // Register block style variation if it hasn't already been registered. + if ( ! array_key_exists( $variation_name, $registered_styles ) ) { + register_block_style( + $block_type, + array( + 'name' => $variation_name, + 'label' => $variation_label, + ) + ); + } + } + } +} + +/** + * Register shared block style variations defined by the theme. + * + * These can come in three forms: + * - the theme's theme.json + * - the theme's partials (standalone files in `/styles` that only define block style variations) + * - the user's theme.json (for example, theme style variations the user selected) + * + * @access private + */ +function gutenberg_register_block_style_variations_from_theme() { + // Partials from `/styles`. + $variations_partials = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( 'block' ); + gutenberg_register_block_style_variations_from_theme_json_data( $variations_partials ); + + /* + * Pull the data from the specific origin instead of the merged data. + * This is because, for 6.6, we only support registering block style variations + * for the 'theme' and 'custom' origins but not for 'default' (core theme.json) + * or 'custom' (theme.json in a block). + * + * When/If we add support for every origin, we should switch to using the public API + * instead, e.g.: wp_get_global_styles( array( 'blocks', 'variations' ) ). + */ + + // theme.json of the theme. + $theme_json_theme = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data(); + $variations_theme = $theme_json_theme->get_data()['styles']['blocks']['variations'] ?? array(); + gutenberg_register_block_style_variations_from_theme_json_data( $variations_theme ); + + // User data linked for this theme. + $theme_json_user = WP_Theme_JSON_Resolver_Gutenberg::get_user_data(); + $variations_user = $theme_json_user->get_data()['styles']['blocks']['variations'] ?? array(); + gutenberg_register_block_style_variations_from_theme_json_data( $variations_user ); +} + +// Remove core init action registering variations. +if ( function_exists( 'wp_register_block_style_variations_from_theme' ) ) { + remove_action( 'init', 'wp_register_block_style_variations_from_theme' ); +} +add_action( 'init', 'gutenberg_register_block_style_variations_from_theme' ); diff --git a/phpunit/block-supports/block-style-variations-test.php b/phpunit/block-supports/block-style-variations-test.php index b84267446330cc..870a76a4fb4a49 100644 --- a/phpunit/block-supports/block-style-variations-test.php +++ b/phpunit/block-supports/block-style-variations-test.php @@ -63,6 +63,11 @@ public function filter_set_theme_root() { public function test_add_registered_block_styles_to_theme_data() { switch_theme( 'block-theme' ); + // Trigger block style registration that occurs on `init` action. + // do_action( 'init' ) could be used here however this direct call + // means only the updates being tested are performed. + gutenberg_register_block_style_variations_from_theme(); + $variation_styles_data = array( 'color' => array( 'background' => 'darkslateblue',