Skip to content

Commit

Permalink
Editor: register block style variations defined by the theme using th…
Browse files Browse the repository at this point in the history
…e init action.

Props oandregal, aaronrobertshaw, annezazu.

Follow-up to [58264].
See #61312.



git-svn-id: https://develop.svn.wordpress.org/trunk@58394 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
oandregal committed Jun 12, 2024
1 parent 7bb62f4 commit c2bf2eb
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 23 deletions.
122 changes: 99 additions & 23 deletions src/wp-includes/block-supports/block-style-variations.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ function wp_render_block_style_variation_class_name( $block_content, $block ) {

/**
* 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
* @access private
Expand All @@ -224,14 +221,13 @@ function wp_render_block_style_variation_class_name( $block_content, $block ) {
*
* @return array Block variations data to be merged under `styles.blocks`.
*/
function wp_resolve_and_register_block_style_variations( $variations ) {
function wp_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 ) {
Expand All @@ -253,23 +249,9 @@ function wp_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 ) ) {
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 );
Expand Down Expand Up @@ -327,7 +309,7 @@ function wp_merge_block_style_variations_data( $variations_data, $theme_json, $o
function wp_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 = wp_resolve_and_register_block_style_variations( $shared_variations );
$variations_data = wp_resolve_block_style_variations( $shared_variations );

return wp_merge_block_style_variations_data( $variations_data, $theme_json, 'user' );
}
Expand All @@ -345,7 +327,7 @@ function wp_resolve_block_style_variations_from_theme_style_variation( $theme_js
*/
function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json ) {
$block_style_variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
$variations_data = wp_resolve_and_register_block_style_variations( $block_style_variations );
$variations_data = wp_resolve_block_style_variations( $block_style_variations );

return wp_merge_block_style_variations_data( $variations_data, $theme_json );
}
Expand All @@ -364,7 +346,7 @@ function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json
function wp_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 = wp_resolve_and_register_block_style_variations( $block_style_variations );
$variations_data = wp_resolve_block_style_variations( $block_style_variations );

return wp_merge_block_style_variations_data( $variations_data, $theme_json );
}
Expand Down Expand Up @@ -422,3 +404,97 @@ function wp_enqueue_block_style_variation_styles() {
add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_styles_registry', 10, 1 );

add_filter( 'wp_theme_json_data_user', 'wp_resolve_block_style_variations_from_theme_style_variation', 10, 1 );

/**
* Registers any block style variations contained within the provided
* theme.json data.
*
* @since 6.6.0
* @access private
*
* @param array $variations Shared block style variations.
*/
function wp_register_block_style_variations_from_theme_json_data( $variations ) {
if ( empty( $variations ) ) {
return $variations;
}

$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)
*
* @since 6.6.0
* @access private
*/
function wp_register_block_style_variations_from_theme() {
// Partials from `/styles`.
$variations_partials = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
wp_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::get_theme_data();
$variations_theme = $theme_json_theme->get_data()['styles']['blocks']['variations'] ?? array();
wp_register_block_style_variations_from_theme_json_data( $variations_theme );

// User data linked for this theme.
$theme_json_user = WP_Theme_JSON_Resolver::get_user_data();
$variations_user = $theme_json_user->get_data()['styles']['blocks']['variations'] ?? array();
wp_register_block_style_variations_from_theme_json_data( $variations_user );
}
add_action( 'init', 'wp_register_block_style_variations_from_theme' );
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ public function update_item_permissions_check( $request ) {
*
* @since 5.9.0
* @since 6.2.0 Added validation of styles.css property.
* @since 6.6.0 Added registration of newly created style variations provided by the user.
*
* @param WP_REST_Request $request Request object.
* @return stdClass|WP_Error Prepared item on success. WP_Error on when the custom CSS is not valid.
Expand Down Expand Up @@ -263,6 +264,25 @@ protected function prepare_item_for_database( $request ) {
} elseif ( isset( $existing_config['styles'] ) ) {
$config['styles'] = $existing_config['styles'];
}

/*
* If the incoming request is going to create a new variation
* that is not yet registered, we register it here.
* This is because the variations are registered on init,
* but we want this endpoint to return the new variation immediately:
* if we don't register it, it'll be stripped out of the response
* just in this request (subsequent ones will be ok).
* Take the variations defined in styles.blocks.variations from the incoming request
* that are not part of the $exsting_config.
*/
if ( isset( $request['styles']['blocks']['variations'] ) ) {
$existing_variations = isset( $existing_config['styles']['blocks']['variations'] ) ? $existing_config['styles']['blocks']['variations'] : array();
$new_variations = array_diff_key( $request['styles']['blocks']['variations'], $existing_variations );
if ( ! empty( $new_variations ) ) {
wp_register_block_style_variations_from_theme_json_data( $new_variations );
}
}

if ( isset( $request['settings'] ) ) {
$config['settings'] = $request['settings'];
} elseif ( isset( $existing_config['settings'] ) ) {
Expand Down
7 changes: 7 additions & 0 deletions tests/phpunit/tests/block-supports/block-style-variations.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ 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.
*/
wp_register_block_style_variations_from_theme();

$variation_styles_data = array(
'color' => array(
'background' => 'darkslateblue',
Expand Down
49 changes: 49 additions & 0 deletions tests/phpunit/tests/rest-api/rest-global-styles-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,55 @@ public function test_update_item_invalid_styles_css() {
$this->assertErrorResponse( 'rest_custom_css_illegal_markup', $response, 400 );
}

/**
* Tests the submission of a custom block style variation that was defined
* within a theme style variation and wouldn't be registered at the time
* of saving via the API.
*
* @covers WP_REST_Global_Styles_Controller_Gutenberg::update_item
* @ticket 61312
*/
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 );
}

$group_variations = array(
'fromThemeStyleVariation' => array(
'color' => array(
'background' => '#ffffff',
'text' => '#000000',
),
),
);

$request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id );
$request->set_body_params(
array(
'styles' => array(
'blocks' => array(
'variations' => array(
'fromThemeStyleVariation' => array(
'blockTypes' => array( 'core/group', 'core/columns' ),
'color' => array(
'background' => '#000000',
'text' => '#ffffff',
),
),
),
'core/group' => array(
'variations' => $group_variations,
),
),
),
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( $group_variations, $data['styles']['blocks']['core/group']['variations'] );
}

/**
* @doesNotPerformAssertions
*/
Expand Down

0 comments on commit c2bf2eb

Please sign in to comment.