Skip to content

Commit c2bf2eb

Browse files
committed
Editor: register block style variations defined by the theme using the 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
1 parent 7bb62f4 commit c2bf2eb

File tree

4 files changed

+175
-23
lines changed

4 files changed

+175
-23
lines changed

src/wp-includes/block-supports/block-style-variations.php

Lines changed: 99 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,6 @@ function wp_render_block_style_variation_class_name( $block_content, $block ) {
213213

214214
/**
215215
* Collects block style variation data for merging with theme.json data.
216-
* As each block style variation is processed it is registered if it hasn't
217-
* been already. This registration is required for later sanitization of
218-
* theme.json data.
219216
*
220217
* @since 6.6.0
221218
* @access private
@@ -224,14 +221,13 @@ function wp_render_block_style_variation_class_name( $block_content, $block ) {
224221
*
225222
* @return array Block variations data to be merged under `styles.blocks`.
226223
*/
227-
function wp_resolve_and_register_block_style_variations( $variations ) {
224+
function wp_resolve_block_style_variations( $variations ) {
228225
$variations_data = array();
229226

230227
if ( empty( $variations ) ) {
231228
return $variations_data;
232229
}
233230

234-
$registry = WP_Block_Styles_Registry::get_instance();
235231
$have_named_variations = ! wp_is_numeric_array( $variations );
236232

237233
foreach ( $variations as $key => $variation ) {
@@ -253,23 +249,9 @@ function wp_resolve_and_register_block_style_variations( $variations ) {
253249
* Block style variations read in via standalone theme.json partials
254250
* need to have their name set to the kebab case version of their title.
255251
*/
256-
$variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
257-
$variation_label = $variation['title'] ?? $variation_name;
252+
$variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
258253

259254
foreach ( $supported_blocks as $block_type ) {
260-
$registered_styles = $registry->get_registered_styles_for_block( $block_type );
261-
262-
// Register block style variation if it hasn't already been registered.
263-
if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
264-
register_block_style(
265-
$block_type,
266-
array(
267-
'name' => $variation_name,
268-
'label' => $variation_label,
269-
)
270-
);
271-
}
272-
273255
// Add block style variation data under current block type.
274256
$path = array( $block_type, 'variations', $variation_name );
275257
_wp_array_set( $variations_data, $path, $variation_data );
@@ -327,7 +309,7 @@ function wp_merge_block_style_variations_data( $variations_data, $theme_json, $o
327309
function wp_resolve_block_style_variations_from_theme_style_variation( $theme_json ) {
328310
$theme_json_data = $theme_json->get_data();
329311
$shared_variations = $theme_json_data['styles']['blocks']['variations'] ?? array();
330-
$variations_data = wp_resolve_and_register_block_style_variations( $shared_variations );
312+
$variations_data = wp_resolve_block_style_variations( $shared_variations );
331313

332314
return wp_merge_block_style_variations_data( $variations_data, $theme_json, 'user' );
333315
}
@@ -345,7 +327,7 @@ function wp_resolve_block_style_variations_from_theme_style_variation( $theme_js
345327
*/
346328
function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json ) {
347329
$block_style_variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
348-
$variations_data = wp_resolve_and_register_block_style_variations( $block_style_variations );
330+
$variations_data = wp_resolve_block_style_variations( $block_style_variations );
349331

350332
return wp_merge_block_style_variations_data( $variations_data, $theme_json );
351333
}
@@ -364,7 +346,7 @@ function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json
364346
function wp_resolve_block_style_variations_from_primary_theme_json( $theme_json ) {
365347
$theme_json_data = $theme_json->get_data();
366348
$block_style_variations = $theme_json_data['styles']['blocks']['variations'] ?? array();
367-
$variations_data = wp_resolve_and_register_block_style_variations( $block_style_variations );
349+
$variations_data = wp_resolve_block_style_variations( $block_style_variations );
368350

369351
return wp_merge_block_style_variations_data( $variations_data, $theme_json );
370352
}
@@ -422,3 +404,97 @@ function wp_enqueue_block_style_variation_styles() {
422404
add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_styles_registry', 10, 1 );
423405

424406
add_filter( 'wp_theme_json_data_user', 'wp_resolve_block_style_variations_from_theme_style_variation', 10, 1 );
407+
408+
/**
409+
* Registers any block style variations contained within the provided
410+
* theme.json data.
411+
*
412+
* @since 6.6.0
413+
* @access private
414+
*
415+
* @param array $variations Shared block style variations.
416+
*/
417+
function wp_register_block_style_variations_from_theme_json_data( $variations ) {
418+
if ( empty( $variations ) ) {
419+
return $variations;
420+
}
421+
422+
$registry = WP_Block_Styles_Registry::get_instance();
423+
$have_named_variations = ! wp_is_numeric_array( $variations );
424+
425+
foreach ( $variations as $key => $variation ) {
426+
$supported_blocks = $variation['blockTypes'] ?? array();
427+
428+
/*
429+
* Standalone theme.json partial files for block style variations
430+
* will have their styles under a top-level property by the same name.
431+
* Variations defined within an existing theme.json or theme style
432+
* variation will themselves already be the required styles data.
433+
*/
434+
$variation_data = $variation['styles'] ?? $variation;
435+
436+
if ( empty( $variation_data ) ) {
437+
continue;
438+
}
439+
440+
/*
441+
* Block style variations read in via standalone theme.json partials
442+
* need to have their name set to the kebab case version of their title.
443+
*/
444+
$variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
445+
$variation_label = $variation['title'] ?? $variation_name;
446+
447+
foreach ( $supported_blocks as $block_type ) {
448+
$registered_styles = $registry->get_registered_styles_for_block( $block_type );
449+
450+
// Register block style variation if it hasn't already been registered.
451+
if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
452+
register_block_style(
453+
$block_type,
454+
array(
455+
'name' => $variation_name,
456+
'label' => $variation_label,
457+
)
458+
);
459+
}
460+
}
461+
}
462+
}
463+
464+
/**
465+
* Register shared block style variations defined by the theme.
466+
*
467+
* These can come in three forms:
468+
* - the theme's theme.json
469+
* - the theme's partials (standalone files in `/styles` that only define block style variations)
470+
* - the user's theme.json (for example, theme style variations the user selected)
471+
*
472+
* @since 6.6.0
473+
* @access private
474+
*/
475+
function wp_register_block_style_variations_from_theme() {
476+
// Partials from `/styles`.
477+
$variations_partials = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
478+
wp_register_block_style_variations_from_theme_json_data( $variations_partials );
479+
480+
/*
481+
* Pull the data from the specific origin instead of the merged data.
482+
* This is because, for 6.6, we only support registering block style variations
483+
* for the 'theme' and 'custom' origins but not for 'default' (core theme.json)
484+
* or 'custom' (theme.json in a block).
485+
*
486+
* When/If we add support for every origin, we should switch to using the public API
487+
* instead, e.g.: wp_get_global_styles( array( 'blocks', 'variations' ) ).
488+
*/
489+
490+
// theme.json of the theme.
491+
$theme_json_theme = WP_Theme_JSON_Resolver::get_theme_data();
492+
$variations_theme = $theme_json_theme->get_data()['styles']['blocks']['variations'] ?? array();
493+
wp_register_block_style_variations_from_theme_json_data( $variations_theme );
494+
495+
// User data linked for this theme.
496+
$theme_json_user = WP_Theme_JSON_Resolver::get_user_data();
497+
$variations_user = $theme_json_user->get_data()['styles']['blocks']['variations'] ?? array();
498+
wp_register_block_style_variations_from_theme_json_data( $variations_user );
499+
}
500+
add_action( 'init', 'wp_register_block_style_variations_from_theme' );

src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ public function update_item_permissions_check( $request ) {
231231
*
232232
* @since 5.9.0
233233
* @since 6.2.0 Added validation of styles.css property.
234+
* @since 6.6.0 Added registration of newly created style variations provided by the user.
234235
*
235236
* @param WP_REST_Request $request Request object.
236237
* @return stdClass|WP_Error Prepared item on success. WP_Error on when the custom CSS is not valid.
@@ -263,6 +264,25 @@ protected function prepare_item_for_database( $request ) {
263264
} elseif ( isset( $existing_config['styles'] ) ) {
264265
$config['styles'] = $existing_config['styles'];
265266
}
267+
268+
/*
269+
* If the incoming request is going to create a new variation
270+
* that is not yet registered, we register it here.
271+
* This is because the variations are registered on init,
272+
* but we want this endpoint to return the new variation immediately:
273+
* if we don't register it, it'll be stripped out of the response
274+
* just in this request (subsequent ones will be ok).
275+
* Take the variations defined in styles.blocks.variations from the incoming request
276+
* that are not part of the $exsting_config.
277+
*/
278+
if ( isset( $request['styles']['blocks']['variations'] ) ) {
279+
$existing_variations = isset( $existing_config['styles']['blocks']['variations'] ) ? $existing_config['styles']['blocks']['variations'] : array();
280+
$new_variations = array_diff_key( $request['styles']['blocks']['variations'], $existing_variations );
281+
if ( ! empty( $new_variations ) ) {
282+
wp_register_block_style_variations_from_theme_json_data( $new_variations );
283+
}
284+
}
285+
266286
if ( isset( $request['settings'] ) ) {
267287
$config['settings'] = $request['settings'];
268288
} elseif ( isset( $existing_config['settings'] ) ) {

tests/phpunit/tests/block-supports/block-style-variations.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ public function filter_set_theme_root() {
6565
public function test_add_registered_block_styles_to_theme_data() {
6666
switch_theme( 'block-theme' );
6767

68+
/*
69+
* Trigger block style registration that occurs on `init` action.
70+
* do_action( 'init' ) could be used here however this direct call
71+
* means only the updates being tested are performed.
72+
*/
73+
wp_register_block_style_variations_from_theme();
74+
6875
$variation_styles_data = array(
6976
'color' => array(
7077
'background' => 'darkslateblue',

tests/phpunit/tests/rest-api/rest-global-styles-controller.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,55 @@ public function test_update_item_invalid_styles_css() {
602602
$this->assertErrorResponse( 'rest_custom_css_illegal_markup', $response, 400 );
603603
}
604604

605+
/**
606+
* Tests the submission of a custom block style variation that was defined
607+
* within a theme style variation and wouldn't be registered at the time
608+
* of saving via the API.
609+
*
610+
* @covers WP_REST_Global_Styles_Controller_Gutenberg::update_item
611+
* @ticket 61312
612+
*/
613+
public function test_update_item_with_custom_block_style_variations() {
614+
wp_set_current_user( self::$admin_id );
615+
if ( is_multisite() ) {
616+
grant_super_admin( self::$admin_id );
617+
}
618+
619+
$group_variations = array(
620+
'fromThemeStyleVariation' => array(
621+
'color' => array(
622+
'background' => '#ffffff',
623+
'text' => '#000000',
624+
),
625+
),
626+
);
627+
628+
$request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id );
629+
$request->set_body_params(
630+
array(
631+
'styles' => array(
632+
'blocks' => array(
633+
'variations' => array(
634+
'fromThemeStyleVariation' => array(
635+
'blockTypes' => array( 'core/group', 'core/columns' ),
636+
'color' => array(
637+
'background' => '#000000',
638+
'text' => '#ffffff',
639+
),
640+
),
641+
),
642+
'core/group' => array(
643+
'variations' => $group_variations,
644+
),
645+
),
646+
),
647+
)
648+
);
649+
$response = rest_get_server()->dispatch( $request );
650+
$data = $response->get_data();
651+
$this->assertSame( $group_variations, $data['styles']['blocks']['core/group']['variations'] );
652+
}
653+
605654
/**
606655
* @doesNotPerformAssertions
607656
*/

0 commit comments

Comments
 (0)