Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize experimental block supports including typography, border, and common flags #7069

28 changes: 14 additions & 14 deletions src/wp-includes/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function wp_register_border_support( $block_type ) {
$block_type->attributes = array();
}

if ( block_has_support( $block_type, '__experimentalBorder' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
if ( block_has_support( $block_type, 'border' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
Expand Down Expand Up @@ -60,7 +60,7 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
if (
wp_has_border_feature_support( $block_type, 'radius' ) &&
isset( $block_attributes['style']['border']['radius'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
! wp_should_skip_block_supports_serialization( $block_type, 'border', 'radius' )
) {
$border_radius = $block_attributes['style']['border']['radius'];

Expand All @@ -75,7 +75,7 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
if (
wp_has_border_feature_support( $block_type, 'style' ) &&
isset( $block_attributes['style']['border']['style'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' )
) {
$border_block_styles['style'] = $block_attributes['style']['border']['style'];
}
Expand All @@ -84,7 +84,7 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
if (
$has_border_width_support &&
isset( $block_attributes['style']['border']['width'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' )
) {
$border_width = $block_attributes['style']['border']['width'];

Expand All @@ -99,7 +99,7 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
// Border color.
if (
$has_border_color_support &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' )
) {
$preset_border_color = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
$custom_border_color = isset( $block_attributes['style']['border']['color'] ) ? $block_attributes['style']['border']['color'] : null;
Expand All @@ -111,9 +111,9 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
$border = isset( $block_attributes['style']['border'][ $side ] ) ? $block_attributes['style']['border'][ $side ] : null;
$border_side_values = array(
'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' ) ? $border['width'] : null,
'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' ) ? $border['color'] : null,
'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' ) ? $border['style'] : null,
);
$border_block_styles[ $side ] = $border_side_values;
}
Expand All @@ -137,7 +137,7 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
/**
* Checks whether the current block type supports the border feature requested.
*
* If the `__experimentalBorder` support flag is a boolean `true` all border
* If the `border` support flag is a boolean `true` all border
* support features are available. Otherwise, the specific feature's support
* flag nested under `experimentalBorder` must be enabled for the feature
* to be opted into.
Expand All @@ -151,19 +151,19 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
* @return bool Whether the feature is supported.
*/
function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
// Check if all border support features have been opted into via `"__experimentalBorder": true`.
// Check if all border support features have been opted into via `"border": true`.
if ( $block_type instanceof WP_Block_Type ) {
$block_type_supports_border = isset( $block_type->supports['__experimentalBorder'] )
? $block_type->supports['__experimentalBorder']
$block_type_supports_border = isset( $block_type->supports['border'] )
? $block_type->supports['border']
: $default_value;
if ( true === $block_type_supports_border ) {
return true;
}
}

// Check if the specific feature has been opted into individually
// via nested flag under `__experimentalBorder`.
return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
// via nested flag under `border`.
return block_has_support( $block_type, array( 'border', $feature ), $default_value );
}

// Register the block support.
Expand Down
26 changes: 14 additions & 12 deletions src/wp-includes/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ function wp_register_typography_support( $block_type ) {
return;
}

$has_font_family_support = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
$has_font_family_support = isset( $typography_supports['fontFamily'] ) ? $typography_supports['fontFamily'] : false;
$has_font_size_support = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
$has_font_style_support = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
$has_font_weight_support = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
$has_letter_spacing_support = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
$has_font_style_support = isset( $typography_supports['fontStyle'] ) ? $typography_supports['fontStyle'] : false;
$has_font_weight_support = isset( $typography_supports['fontWeight'] ) ? $typography_supports['fontWeight'] : false;
$has_letter_spacing_support = isset( $typography_supports['letterSpacing'] ) ? $typography_supports['letterSpacing'] : false;
$has_line_height_support = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
$has_text_align_support = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
$has_text_columns_support = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
$has_text_transform_support = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
$has_text_decoration_support = isset( $typography_supports['textDecoration'] ) ? $typography_supports['textDecoration'] : false;
$has_text_transform_support = isset( $typography_supports['textTransform'] ) ? $typography_supports['textTransform'] : false;
$has_writing_mode_support = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : false;

$has_typography_support = $has_font_family_support
Expand Down Expand Up @@ -80,6 +80,7 @@ function wp_register_typography_support( $block_type ) {
* @since 5.6.0
* @since 6.1.0 Used the style engine to generate CSS and classnames.
* @since 6.3.0 Added support for text-columns.
* @since 6.8.0 Typography block supports now use stable non-experimental keys.
* @access private
*
* @param WP_Block_Type $block_type Block type.
Expand All @@ -102,16 +103,16 @@ function wp_apply_typography_support( $block_type, $block_attributes ) {
return array();
}

$has_font_family_support = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
$has_font_family_support = isset( $typography_supports['fontFamily'] ) ? $typography_supports['fontFamily'] : false;
$has_font_size_support = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
$has_font_style_support = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
$has_font_weight_support = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
$has_letter_spacing_support = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
$has_font_style_support = isset( $typography_supports['fontStyle'] ) ? $typography_supports['fontStyle'] : false;
$has_font_weight_support = isset( $typography_supports['fontWeight'] ) ? $typography_supports['fontWeight'] : false;
$has_letter_spacing_support = isset( $typography_supports['letterSpacing'] ) ? $typography_supports['letterSpacing'] : false;
$has_line_height_support = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
$has_text_align_support = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
$has_text_columns_support = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
$has_text_transform_support = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
$has_text_decoration_support = isset( $typography_supports['textDecoration'] ) ? $typography_supports['textDecoration'] : false;
$has_text_transform_support = isset( $typography_supports['textTransform'] ) ? $typography_supports['textTransform'] : false;
$has_writing_mode_support = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : false;

// Whether to skip individual block support features.
Expand Down Expand Up @@ -268,6 +269,7 @@ function wp_apply_typography_support( $block_type, $block_attributes ) {
* * It is necessary to parse older blocks whose typography styles contain presets.
* * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`,
* but skips compiling a CSS declaration as the style engine takes over this role.
*
* @link https://github.com/wordpress/gutenberg/pull/27555
*
* @since 6.1.0
Expand Down
2 changes: 1 addition & 1 deletion src/wp-includes/block-supports/utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function wp_should_skip_block_supports_serialization( $block_type, $feature_set,
return false;
}

$path = array( $feature_set, '__experimentalSkipSerialization' );
$path = array( $feature_set, 'skipSerialization' );
$skip_serialization = _wp_array_get( $block_type->supports, $path, false );

if ( is_array( $skip_serialization ) ) {
Expand Down
156 changes: 156 additions & 0 deletions src/wp-includes/class-wp-block-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,45 @@ class WP_Block_Type {
'style',
);

/**
* Experimental to stable block supports map.
*
* @since 6.8.0
* @var array
*/
private $experimental_supports_map = array( '__experimentalBorder' => 'border' );

/**
* Map of shared experimental support properties to stable.
*
* This map relates to experimental block support flags that are
* across multiple different block supports.
*
* @since 6.8.0
* @var array
*/
private $common_experimental_support_properties = array(
'__experimentalDefaultControls' => 'defaultControls',
'__experimentalSkipSerialization' => 'skipSerialization',
);

/**
* Experimental to stable block supports properties map.
*
* @since 6.8.0
* @var array
*/
private $experimental_support_properties = array(
'typography' => array(
'__experimentalFontFamily' => 'fontFamily',
'__experimentalFontStyle' => 'fontStyle',
'__experimentalFontWeight' => 'fontWeight',
'__experimentalLetterSpacing' => 'letterSpacing',
'__experimentalTextDecoration' => 'textDecoration',
'__experimentalTextTransform' => 'textTransform',
),
);

/**
* Attributes supported by every block.
*
Expand Down Expand Up @@ -572,6 +611,11 @@ public function set_props( $args ) {
*/
$args = apply_filters( 'register_block_type_args', $args, $this->name );

// Stabilize experimental block supports.
if ( isset( $args['supports'] ) && is_array( $args['supports'] ) ) {
$args['supports'] = $this->stabilize_supports( $args['supports'] );
}

foreach ( $args as $property_name => $property_value ) {
$this->$property_name = $property_value;
}
Expand Down Expand Up @@ -634,4 +678,116 @@ public function get_uses_context() {
*/
return apply_filters( 'get_block_type_uses_context', $this->uses_context, $this );
}

/**
* Stabilize experimental block supports. This method transforms experimental
* block supports into their stable counterparts, by renaming the keys to the
* stable versions.
*
* @since 6.8.0
*
* @param array $supports The block supports array from within the block type arguments.
* @return array The stabilized block supports array.
*/
private function stabilize_supports( $supports ) {
$done = array();
$updated_supports = array();

foreach ( $supports as $support => $config ) {
/*
* If this support config has already been stabilized, skip it.
* A stable support key occurring after an experimental key, gets
* stabilized then so that the two configs can be merged effectively.
*/
if ( isset( $done[ $support ] ) ) {
continue;
}

$stable_support_key = $this->experimental_supports_map[ $support ] ?? $support;

/*
* Use the support's config as is when it's not in need of stabilization.
*
* A support does not need stabilization if:
* - The support key doesn't need stabilization AND
* - Either:
* - The config isn't an array, so can't have experimental properties OR
* - The config is an array but has no experimental properties to stabilize.
*/
if ( $support === $stable_support_key &&
( ! is_array( $config ) ||
(
! isset( $this->experimental_support_properties[ $stable_support_key ] ) &&
empty( array_intersect_key( $this->common_experimental_support_properties, $config ) )
)
)
) {
$updated_supports[ $support ] = $config;
continue;
}

$stabilize_config = function ( $unstable_config, $stable_support_key ) {
if ( ! is_array( $unstable_config ) ) {
return $unstable_config;
}

$stable_config = array();
foreach ( $unstable_config as $key => $value ) {
// Get stable key from support-specific map, common properties map, or keep original.
$stable_key = $this->experimental_support_properties[ $stable_support_key ][ $key ] ??
$this->common_experimental_support_properties[ $key ] ??
$key;

$stable_config[ $stable_key ] = $value;
}
return $stable_config;
};

// Stabilize the config value.
$stable_config = is_array( $config ) ? $stabilize_config( $config, $stable_support_key ) : $config;

/*
* If a plugin overrides the support config with the `register_block_type_args`
* filter, both experimental and stable configs may be present. In that case,
* use the order keys are defined in to determine the final value.
* - If config is an array, merge the arrays in their order of definition.
* - If config is not an array, use the value defined last.
*
* The reason for preferring the last defined key is that after filters
* are applied, the last inserted key is likely the most up-to-date value.
* We cannot determine with certainty which value was "last modified" so
* the insertion order is the best guess. The extreme edge case of multiple
* filters tweaking the same support property will become less over time as
* extenders migrate existing blocks and plugins to stable keys.
*/
if ( $support !== $stable_support_key && isset( $supports[ $stable_support_key ] ) ) {
$key_positions = array_flip( array_keys( $supports ) );
$experimental_first =
( $key_positions[ $support ] ?? PHP_INT_MAX ) <
( $key_positions[ $stable_support_key ] ?? PHP_INT_MAX );

/*
* To merge the alternative support config effectively, it also needs to be
* stabilized before merging to keep stabilized and experimental flags in sync.
*/
$supports[ $stable_support_key ] = $stabilize_config( $supports[ $stable_support_key ], $stable_support_key );
// Prevents reprocessing this support as it was merged above.
$done[ $stable_support_key ] = true;

if ( is_array( $stable_config ) && is_array( $supports[ $stable_support_key ] ) ) {
$stable_config = $experimental_first
? array_merge( $stable_config, $supports[ $stable_support_key ] )
: array_merge( $supports[ $stable_support_key ], $stable_config );
} else {
$stable_config = $experimental_first
? $supports[ $stable_support_key ]
: $stable_config;
}
}

$updated_supports[ $stable_support_key ] = $stable_config;
}

return $updated_supports;
}
}
8 changes: 4 additions & 4 deletions src/wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,10 @@ class WP_Theme_JSON {
* @var string[]
*/
const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array(
'__experimentalBorder' => 'border',
'color' => 'color',
'spacing' => 'spacing',
'typography' => 'typography',
'border' => 'border',
'color' => 'color',
'spacing' => 'spacing',
'typography' => 'typography',
);

/**
Expand Down
Loading
Loading