diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php index b85e8e335037af..86ca0f683a1a3e 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php @@ -258,6 +258,56 @@ public static function get_user_data() { return static::$user; } + /** + * Gets the styles for blocks from the block.json file. + * + * @return WP_Theme_JSON + */ + public static function get_block_data() { + $registry = WP_Block_Type_Registry::get_instance(); + $blocks = $registry->get_all_registered(); + $config = array( 'version' => 1 ); + foreach ( $blocks as $block_name => $block_type ) { + if ( is_array( $block_type->style ) ) { + foreach ( $block_type->style as $style_override_maybe ) { + if ( is_array( $style_override_maybe ) ) { + $config['styles']['blocks'][ $block_name ] = static::remove_JSON_comments( $style_override_maybe ); + } + } + } + + if ( + isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) && + null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null ) + ) { + // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value. + // The real blockGap value to be used will be determined when the styles are rendered for output. + $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null; + } + } + + // Core here means it's the lower level part of the styles chain. + // It can be a core or a third-party block. + return new WP_Theme_JSON_Gutenberg( $config, 'core' ); + } + + /** + * When given an array, this will remove any keys with the name `//`. + * + * @param array $array The array to filter. + * @return array The filtered array. + */ + private static function remove_JSON_comments( $array ) { + unset( $array['//'] ); + foreach ( $array as $k => $v ) { + if ( is_array( $v ) ) { + $array[ $k ] = static::remove_JSON_comments( $v ); + } + } + + return $array; + } + /** * There are three sources of data (origins) for a site: * default, theme, and custom. The custom's has higher priority diff --git a/lib/compat/wordpress-6.0/client-assets.php b/lib/compat/wordpress-6.0/client-assets.php index 0c5697817a94a8..a0487c5c7f7ffc 100644 --- a/lib/compat/wordpress-6.0/client-assets.php +++ b/lib/compat/wordpress-6.0/client-assets.php @@ -61,11 +61,27 @@ function gutenberg_resolve_assets() { foreach ( $block_registry->get_all_registered() as $block_type ) { if ( ! empty( $block_type->style ) ) { - $style_handles[] = $block_type->style; + if ( is_array( $block_type->style ) ) { + foreach ( $block_type->style as $single_style ) { + if ( is_string( $single_style ) ) { + $style_handles[] = $single_style; + } + } + } else { + $style_handles[] = $block_type->style; + } } if ( ! empty( $block_type->editor_style ) ) { - $style_handles[] = $block_type->editor_style; + if ( is_array( $block_type->editor_style ) ) { + foreach ( $block_type->editor_style as $single_style ) { + if ( is_string( $single_style ) ) { + $style_handles[] = $single_style; + } + } + } else { + $style_handles[] = $block_type->editor_style; + } } if ( ! empty( $block_type->script ) ) { diff --git a/lib/compat/wordpress-6.1/blocks.php b/lib/compat/wordpress-6.1/blocks.php index ed41c5aa8cd098..8949362860f21c 100644 --- a/lib/compat/wordpress-6.1/blocks.php +++ b/lib/compat/wordpress-6.1/blocks.php @@ -178,3 +178,68 @@ function gutenberg_block_type_metadata_multiple_view_scripts( $metadata ) { return $metadata; } add_filter( 'block_type_metadata', 'gutenberg_block_type_metadata_multiple_view_scripts' ); + +/** + * Allow multiple block styles. + * + * @since 5.9.0 + * + * @param array $metadata Metadata for registering a block type. + * + * @return array + */ +function gutenberg_multiple_block_styles_compat_6_1( $metadata ) { + foreach ( array( 'style', 'editorStyle' ) as $key ) { + if ( ! empty( $metadata[ $key ] ) && is_array( $metadata[ $key ] ) ) { + foreach ( $metadata[ $key ] as $handle ) { + // Do not enqueue style arrays such as { "color": { "text": "#fff" } }. + if ( is_array( $handle ) ) { + continue; + } + + $args = array( 'handle' => $handle ); + if ( 0 === strpos( $handle, 'file:' ) && isset( $metadata['file'] ) ) { + $style_path = remove_block_asset_path_prefix( $handle ); + $theme_path_norm = wp_normalize_path( get_theme_file_path() ); + $style_path_norm = wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $style_path ) ); + $is_theme_block = isset( $metadata['file'] ) && 0 === strpos( $metadata['file'], $theme_path_norm ); + + $style_uri = plugins_url( $style_path, $metadata['file'] ); + + if ( $is_theme_block ) { + $style_uri = get_theme_file_uri( str_replace( $theme_path_norm, '', $style_path_norm ) ); + } + + $args = array( + 'handle' => sanitize_key( "{$metadata['name']}-{$style_path}" ), + 'src' => $style_uri, + ); + } + + wp_enqueue_block_style( $metadata['name'], $args ); + } + } + } + return $metadata; +} + +/* + * Priority 11 is used to ensure this runs *after* _wp_multiple_block_styles. + * + * The order of execution matters in WordPress 6.0 where style arrays such as below are unsupported: + * + * { + * "style": [ "wp-block-button", { + * "border": { + * "radius": "9999px" + * } + * } ] + * } + * + * _wp_multiple_block_styles flattens the above definition to just {"style": "wp-block-button"} which + * is supported in WordPress 6.0. + * + * In WordPress 6.1, _wp_multiple_block_styles is deprecated and doesn't do anything so the full style + * definition is preserved in block metadata for further processing in the theme resolver. + */ +add_filter( 'block_type_metadata', 'gutenberg_multiple_block_styles_compat_6_1', 11 ); diff --git a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php index a4d4e4dfc7066d..7d5fcb637ec989 100644 --- a/lib/experimental/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/experimental/class-wp-theme-json-resolver-gutenberg.php @@ -99,52 +99,6 @@ public static function get_theme_data( $deprecated = array(), $settings = array( return $with_theme_supports; } - /** - * Gets the styles for blocks from the block.json file. - * - * @return WP_Theme_JSON - */ - public static function get_block_data() { - $registry = WP_Block_Type_Registry::get_instance(); - $blocks = $registry->get_all_registered(); - $config = array( 'version' => 1 ); - foreach ( $blocks as $block_name => $block_type ) { - if ( isset( $block_type->supports['__experimentalStyle'] ) ) { - $config['styles']['blocks'][ $block_name ] = static::remove_JSON_comments( $block_type->supports['__experimentalStyle'] ); - } - - if ( - isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) && - null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null ) - ) { - // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value. - // The real blockGap value to be used will be determined when the styles are rendered for output. - $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null; - } - } - - // Core here means it's the lower level part of the styles chain. - // It can be a core or a third-party block. - return new WP_Theme_JSON_Gutenberg( $config, 'core' ); - } - - /** - * When given an array, this will remove any keys with the name `//`. - * - * @param array $array The array to filter. - * @return array The filtered array. - */ - private static function remove_JSON_comments( $array ) { - unset( $array['//'] ); - foreach ( $array as $k => $v ) { - if ( is_array( $v ) ) { - $array[ $k ] = static::remove_JSON_comments( $v ); - } - } - - return $array; - } - /** * Returns the data merged from multiple origins. * diff --git a/packages/block-library/src/button/block.json b/packages/block-library/src/button/block.json index f86030c7460a57..97bf9a11dbf88c 100644 --- a/packages/block-library/src/button/block.json +++ b/packages/block-library/src/button/block.json @@ -96,5 +96,30 @@ { "name": "outline", "label": "Outline" } ], "editorStyle": "wp-block-button-editor", - "style": "wp-block-button" + "style": [ + "wp-block-button", + { + "border": { + "//": "100% causes an oval, but any explicit but really high value retains the pill shape.", + "radius": "9999px" + }, + "color": { + "text": "#fff", + "background": "#32373c" + }, + "typography": { + "fontSize": "1.125em", + "textDecoration": "none" + }, + "spacing": { + "padding": { + "//": "The extra 2px are added to size solids the same as the outline versions.", + "top": "calc(0.667em + 2px)", + "right": "calc(1.333em + 2px)", + "bottom": "calc(0.667em + 2px) !important", + "left": "calc(1.333em + 2px)" + } + } + } + ] } diff --git a/schemas/json/block.json b/schemas/json/block.json index fd7bd5a06f708e..0dbc5d2f539536 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -464,7 +464,10 @@ { "type": "array", "items": { - "type": "string" + "oneOf": [ + { "type": "string" }, + { "type": "object" } + ] } } ] @@ -478,7 +481,10 @@ { "type": "array", "items": { - "type": "string" + "oneOf": [ + { "type": "string" }, + { "type": "object" } + ] } } ]