Skip to content

Commit 4c37968

Browse files
Update PHP processing of block style variations in theme.json
Includes: - absorbing block style variations from the block styles registry into theme.json - updating metadata and stylesheet generation from variations to support inner block and element styles
1 parent d02898a commit 4c37968

File tree

4 files changed

+538
-97
lines changed

4 files changed

+538
-97
lines changed

lib/class-wp-theme-json-gutenberg.php

Lines changed: 175 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
842842
foreach ( $valid_block_names as $block ) {
843843
// Build the schema for each block style variation.
844844
$style_variation_names = array();
845+
845846
if (
846847
! empty( $input['styles']['blocks'][ $block ]['variations'] ) &&
847848
is_array( $input['styles']['blocks'][ $block ]['variations'] ) &&
@@ -853,9 +854,14 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
853854
);
854855
}
855856

857+
$schema_styles_variations = array();
858+
$block_style_variation_styles = static::VALID_STYLES;
859+
$block_style_variation_styles['blocks'] = null;
860+
$block_style_variation_styles['elements'] = null;
861+
856862
$schema_styles_variations = array();
857863
if ( ! empty( $style_variation_names ) ) {
858-
$schema_styles_variations = array_fill_keys( $style_variation_names, $styles_non_top_level );
864+
$schema_styles_variations = array_fill_keys( $style_variation_names, $block_style_variation_styles );
859865
}
860866

861867
$schema_settings_blocks[ $block ] = static::VALID_SETTINGS;
@@ -978,12 +984,34 @@ protected static function prepend_to_selector( $selector, $to_prepend ) {
978984
*/
979985
protected static function get_blocks_metadata() {
980986
// NOTE: the compat/6.1 version of this method in Gutenberg did not have these changes.
981-
$registry = WP_Block_Type_Registry::get_instance();
982-
$blocks = $registry->get_all_registered();
987+
$registry = WP_Block_Type_Registry::get_instance();
988+
$blocks = $registry->get_all_registered();
989+
$style_registry = WP_Block_Styles_Registry::get_instance();
983990

984991
// Is there metadata for all currently registered blocks?
985992
$blocks = array_diff_key( $blocks, static::$blocks_metadata );
993+
986994
if ( empty( $blocks ) ) {
995+
// New block styles may have been registered within WP_Block_Styles_Registry.
996+
// Update block metadata for any new block style variations.
997+
$registered_styles = $style_registry->get_all_registered();
998+
foreach ( static::$blocks_metadata as $block_name => $block_metadata ) {
999+
if ( ! empty( $registered_styles[ $block_name ] ) ) {
1000+
$style_selectors = $block_metadata['styleVariations'] ?? array();
1001+
1002+
foreach ( $registered_styles[ $block_name ] as $block_style ) {
1003+
if ( ! isset( $style_selectors[ $block_style['name'] ] ) ) {
1004+
$style_selectors[ $block_style['name'] ] = static::append_to_selector(
1005+
'.is-style-' . $block_style['name'] . '.is-style-' . $block_style['name'],
1006+
$block_metadata['selector']
1007+
);
1008+
}
1009+
}
1010+
1011+
static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
1012+
}
1013+
}
1014+
9871015
return static::$blocks_metadata;
9881016
}
9891017

@@ -1007,7 +1035,7 @@ protected static function get_blocks_metadata() {
10071035

10081036
if ( $duotone_support ) {
10091037
$root_selector = wp_get_block_css_selector( $block_type );
1010-
$duotone_selector = WP_Theme_JSON_Gutenberg::scope_selector( $root_selector, $duotone_support );
1038+
$duotone_selector = static::scope_selector( $root_selector, $duotone_support );
10111039
}
10121040
}
10131041

@@ -1016,12 +1044,21 @@ protected static function get_blocks_metadata() {
10161044
}
10171045

10181046
// If the block has style variations, append their selectors to the block metadata.
1047+
$style_selectors = array();
10191048
if ( ! empty( $block_type->styles ) ) {
1020-
$style_selectors = array();
10211049
foreach ( $block_type->styles as $style ) {
10221050
// The style variation classname is duplicated in the selector to ensure that it overrides core block styles.
10231051
$style_selectors[ $style['name'] ] = static::append_to_selector( '.is-style-' . $style['name'] . '.is-style-' . $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
10241052
}
1053+
}
1054+
1055+
// Block style variations can be registered through the WP_Block_Styles_Registry as well as block.json.
1056+
$registered_styles = $style_registry->get_registered_styles_for_block( $block_name );
1057+
foreach ( $registered_styles as $style ) {
1058+
$style_selectors[ $style['name'] ] = static::append_to_selector( '.is-style-' . $style['name'] . '.is-style-' . $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
1059+
}
1060+
1061+
if ( ! empty( $style_selectors ) ) {
10251062
static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
10261063
}
10271064
}
@@ -1194,7 +1231,8 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
11941231
}
11951232

11961233
if ( in_array( 'styles', $types, true ) ) {
1197-
if ( false !== $root_style_key ) {
1234+
$skip_root_layout_styles = $options['skip_root_layout_styles'] ?? false;
1235+
if ( false !== $root_style_key && ! $skip_root_layout_styles ) {
11981236
$stylesheet .= $this->get_root_layout_rules( $style_nodes[ $root_style_key ]['selector'], $style_nodes[ $root_style_key ] );
11991237
}
12001238
$stylesheet .= $this->get_block_classes( $style_nodes );
@@ -1747,6 +1785,10 @@ protected static function compute_preset_classes( $settings, $selector, $origins
17471785
* @return string Scoped selector.
17481786
*/
17491787
public static function scope_selector( $scope, $selector ) {
1788+
if ( ! $selector || ! $scope ) {
1789+
return $selector;
1790+
}
1791+
17501792
$scopes = explode( ',', $scope );
17511793
$selectors = explode( ',', $selector );
17521794

@@ -2379,38 +2421,85 @@ private static function get_block_nodes( $theme_json, $selectors = array() ) {
23792421
}
23802422

23812423
foreach ( $theme_json['styles']['blocks'] as $name => $node ) {
2382-
$selector = null;
2383-
if ( isset( $selectors[ $name ]['selector'] ) ) {
2384-
$selector = $selectors[ $name ]['selector'];
2385-
}
2424+
$selector = $selectors[ $name ]['selector'] ?? null;
2425+
$duotone_selector = $selectors[ $name ]['duotone'] ?? null;
2426+
$feature_selectors = $selectors[ $name ]['selectors'] ?? null;
2427+
$variations = $node['variations'] ?? array();
2428+
$variation_selectors = array();
2429+
$variation_nodes = array();
2430+
2431+
// TODO: Should we be supporting recursive variations and block type styles?
2432+
foreach ( $variations as $variation => $variation_node ) {
2433+
$variation_selector = $selectors[ $name ]['styleVariations'][ $variation ];
2434+
$variation_selectors[] = array(
2435+
'path' => array( 'styles', 'blocks', $name, 'variations', $variation ),
2436+
'selector' => $variation_selector,
2437+
);
23862438

2387-
$duotone_selector = null;
2388-
if ( isset( $selectors[ $name ]['duotone'] ) ) {
2389-
$duotone_selector = $selectors[ $name ]['duotone'];
2390-
}
2439+
$variation_blocks = $variation_node['blocks'] ?? array();
2440+
$variation_elements = $variation_node['elements'] ?? array();
23912441

2392-
$feature_selectors = null;
2393-
if ( isset( $selectors[ $name ]['selectors'] ) ) {
2394-
$feature_selectors = $selectors[ $name ]['selectors'];
2395-
}
2442+
foreach ( $variation_blocks as $variation_block => $variation_block_node ) {
2443+
$variation_block_selector = static::scope_selector( $variation_selector, $selectors[ $variation_block ]['selector'] ?? null );
2444+
$variation_duotone_selector = static::scope_selector( $variation_selector, $selectors[ $variation_block ]['duotone'] ?? null );
2445+
$variation_feature_selectors = $selectors[ $variation_block ]['selectors'] ?? null;
23962446

2397-
$variation_selectors = array();
2398-
if ( isset( $node['variations'] ) ) {
2399-
foreach ( $node['variations'] as $variation => $node ) {
2400-
$variation_selectors[] = array(
2401-
'path' => array( 'styles', 'blocks', $name, 'variations', $variation ),
2402-
'selector' => $selectors[ $name ]['styleVariations'][ $variation ],
2447+
if ( $variation_feature_selectors ) {
2448+
foreach ( $variation_feature_selectors as $feature => $feature_selector ) {
2449+
if ( is_string( $feature_selector ) ) {
2450+
$variation_feature_selectors[ $feature ] = static::scope_selector( $variation_selector, $feature_selector );
2451+
}
2452+
2453+
if ( is_array( $feature_selector ) ) {
2454+
foreach ( $feature_selector as $subfeature => $subfeature_selector ) {
2455+
$variation_feature_selectors[ $feature ][ $subfeature ] = static::scope_selector( $variation_selector, $subfeature_selector );
2456+
}
2457+
}
2458+
}
2459+
}
2460+
2461+
$variation_nodes[] = array(
2462+
'name' => $variation_block,
2463+
'path' => array( 'styles', 'blocks', $name, 'variations', $variation, 'blocks', $variation_block ),
2464+
'selector' => $variation_block_selector,
2465+
'selectors' => $variation_feature_selectors,
2466+
'duotone' => $variation_duotone_selector,
24032467
);
24042468
}
2469+
2470+
foreach ( $variation_elements as $variation_element => $variation_element_node ) {
2471+
// TODO: See if there is a way to clean up the generation of element selectors.
2472+
// The following code varies from standard block element selectors only to avoid
2473+
// that the $selectors[ $name ]['elements'][ $variation_element ] value would
2474+
// nest the block's root selector.
2475+
$nodes[] = array(
2476+
'path' => array( 'styles', 'blocks', $name, 'variations', $variation, 'elements', $variation_element ),
2477+
'selector' => static::scope_selector( $variation_selector, static::ELEMENTS[ $variation_element ] ),
2478+
);
2479+
2480+
// Handle any pseudo selectors for the element.
2481+
if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $variation_element ] ) ) {
2482+
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $variation_element ] as $pseudo_selector ) {
2483+
if ( isset( $variation_element_node[ $pseudo_selector ] ) ) {
2484+
$pseudo_element_selector = static::append_to_selector( static::ELEMENTS[ $variation_element ], $pseudo_selector );
2485+
$nodes[] = array(
2486+
'path' => array( 'styles', 'blocks', $name, 'variations', $variation, 'elements', $variation_element ),
2487+
'selector' => static::scope_selector( $variation_selector, $pseudo_element_selector ),
2488+
);
2489+
}
2490+
}
2491+
}
2492+
}
24052493
}
24062494

24072495
$nodes[] = array(
2408-
'name' => $name,
2409-
'path' => array( 'styles', 'blocks', $name ),
2410-
'selector' => $selector,
2411-
'selectors' => $feature_selectors,
2412-
'duotone' => $duotone_selector,
2413-
'variations' => $variation_selectors,
2496+
'name' => $name,
2497+
'path' => array( 'styles', 'blocks', $name ),
2498+
'selector' => $selector,
2499+
'selectors' => $feature_selectors,
2500+
'duotone' => $duotone_selector,
2501+
'variations' => $variation_selectors,
2502+
'variation_nodes' => $variation_nodes,
24142503
);
24152504

24162505
if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) {
@@ -2489,6 +2578,28 @@ static function ( $split_selector ) use ( $clean_style_variation_selector ) {
24892578
}
24902579
}
24912580

2581+
$style_variation_block_declarations = array();
2582+
if ( ! empty( $block_metadata['variation_nodes'] ) ) {
2583+
foreach ( $block_metadata['variation_nodes'] as $variation_node ) {
2584+
$style_variation_block_node = _wp_array_get( $this->theme_json, $variation_node['path'], array() );
2585+
$variation_block_declarations = static::get_feature_declarations_for_node( $variation_node, $style_variation_block_node );
2586+
2587+
foreach ( $variation_block_declarations as $current_selector => $new_declarations ) {
2588+
$style_variation_block_declarations[ $current_selector ] = $new_declarations;
2589+
}
2590+
2591+
// Note that `get_feature_declarations_for_node` will also unset
2592+
// feature values so they aren't duplicated in declarations via
2593+
// the call below.
2594+
$style_variation_block_declarations[ $variation_node['selector'] ] = static::compute_style_properties(
2595+
$style_variation_block_node,
2596+
$settings,
2597+
null,
2598+
$this->theme_json
2599+
);
2600+
}
2601+
}
2602+
24922603
/*
24932604
* Get a reference to element name from path.
24942605
* $block_metadata['path'] = array( 'styles','elements','link' );
@@ -2590,6 +2701,11 @@ static function ( $pseudo_selector ) use ( $selector ) {
25902701
$block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations );
25912702
}
25922703

2704+
// 7. Generate and append the block style variations for inner blocks and elements.
2705+
foreach ( $style_variation_block_declarations as $style_variation_block_selector => $indvidial_style_variation_block_declaration ) {
2706+
$block_rules .= static::to_ruleset( $style_variation_block_selector, $indvidial_style_variation_block_declaration );
2707+
}
2708+
25932709
return $block_rules;
25942710
}
25952711

@@ -3228,6 +3344,35 @@ public function get_raw_data() {
32283344
return $this->theme_json;
32293345
}
32303346

3347+
/**
3348+
* Converts block styles registered through the `WP_Block_Styles_Registry`
3349+
* with a style object, into theme.json format.
3350+
*
3351+
* @since 6.5.0
3352+
*
3353+
* @return array Styles configuration adhering to the theme.json schema.
3354+
*/
3355+
public static function get_from_block_styles_registry() {
3356+
$variations_data = array();
3357+
$registry = WP_Block_Styles_Registry::get_instance();
3358+
$styles = $registry->get_all_registered();
3359+
3360+
foreach ( $styles as $block_name => $variations ) {
3361+
foreach ( $variations as $variation_name => $variation ) {
3362+
if ( ! empty( $variation['style_data'] ) ) {
3363+
$variations_data[ $block_name ]['variations'][ $variation_name ] = $variation['style_data'];
3364+
}
3365+
}
3366+
}
3367+
3368+
return array(
3369+
'version' => static::LATEST_SCHEMA,
3370+
'styles' => array(
3371+
'blocks' => $variations_data,
3372+
),
3373+
);
3374+
}
3375+
32313376
/**
32323377
* Transforms the given editor settings according the
32333378
* add_theme_support format to the theme.json format.

0 commit comments

Comments
 (0)