diff --git a/lib/class-wp-rest-global-styles-controller-gutenberg.php b/lib/class-wp-rest-global-styles-controller-gutenberg.php index 9bbca1ffcab404..fa8bce4f5484c3 100644 --- a/lib/class-wp-rest-global-styles-controller-gutenberg.php +++ b/lib/class-wp-rest-global-styles-controller-gutenberg.php @@ -358,6 +358,7 @@ protected function prepare_item_for_database( $request ) { * @since 5.9.0 * @since 6.2.0 Handling of style.css was added to WP_Theme_JSON. * @since 6.6.0 Added custom relative theme file URIs to `_links`. + * @since 6.6.0 Added registration of custom block style variations to prevent them being stripped in response. * * @param WP_Post $post Global Styles post object. * @param WP_REST_Request $request Request object. @@ -369,6 +370,29 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V $config = array(); $theme_json = null; if ( $is_global_styles_user_theme_json ) { + if ( isset( $raw_config['styles']['blocks'] ) && is_array( $raw_config['styles']['blocks'] ) ) { + // Ensure custom block style variations are registered so their data isn't stripped during sanitization in WP_Theme_JSON. + $registry = WP_Block_Styles_Registry::get_instance(); + foreach ( $raw_config['styles']['blocks'] as $block_name => $block_data ) { + if ( isset( $block_data['variations'] ) && is_array( $block_data['variations'] ) ) { + $registered_styles = $registry->get_registered_styles_for_block( $block_name ); + + foreach ( $block_data['variations'] as $variation_name => $variation_data ) { + // Register block style variation only if it hasn't already been registered. + if ( ! array_key_exists( $variation_name, $registered_styles ) ) { + register_block_style( + $block_name, + array( + 'name' => $variation_name, + 'label' => $variation_name, + ) + ); + } + } + } + } + } + $theme_json = new WP_Theme_JSON_Gutenberg( $raw_config, 'custom' ); $config = $theme_json->get_raw_data(); } diff --git a/lib/experimental/kses.php b/lib/experimental/kses.php index bed5c58697e626..18fa6c7608b58a 100644 --- a/lib/experimental/kses.php +++ b/lib/experimental/kses.php @@ -31,6 +31,29 @@ function gutenberg_filter_global_styles_post( $data ) { ) { unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); + // Ensure block style variations are automatically registered so they will not + // be omitted during theme.json sanitization. + if ( isset( $decoded_data['styles']['blocks'] ) && is_array( $decoded_data['styles']['blocks'] ) ) { + $registry = WP_Block_Styles_Registry::get_instance(); + foreach ( $decoded_data['styles']['blocks'] as $block_name => $block_data ) { + if ( isset( $block_data['variations'] ) && is_array( $block_data['variations'] ) ) { + $registered_styles = $registry->get_registered_styles_for_block( $block_name ); + + foreach ( $block_data['variations'] as $variation_name => $variation_data ) { + // Register block style variation only if it hasn't already been registered. + if ( ! array_key_exists( $variation_name, $registered_styles ) ) { + register_block_style( + $block_name, + array( + 'name' => $variation_name, + 'label' => $variation_name, + ) + ); + } + } + } + } + } $data_to_encode = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $decoded_data ); $data_to_encode['isGlobalStylesUserThemeJSON'] = true; diff --git a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php index f5b216a084a4c9..ff5b291b2f315b 100644 --- a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php +++ b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php @@ -513,6 +513,39 @@ public function test_update_item_invalid_styles_css() { $this->assertErrorResponse( 'rest_custom_css_illegal_markup', $response, 400 ); } + /** + * @covers WP_REST_Global_Styles_Controller_Gutenberg::update_item + */ + public function test_update_item_with_custom_block_style_variations() { + wp_set_current_user( self::$admin_id ); + if ( is_multisite() ) { + grant_super_admin( self::$admin_id ); + } + $variations = array( + 'dark' => array( + 'color' => array( + 'background' => '#000000', + 'text' => '#ffffff', + ), + ), + ); + $request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id ); + $request->set_body_params( + array( + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'variations' => $variations, + ), + ), + ), + ) + ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertSame( $variations, $data['styles']['blocks']['core/group']['variations'] ); + } + /** * @doesNotPerformAssertions */