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

Backporting block supports [border, color, elements, spacing] from Gutenberg to WP 6.1 #3204

78 changes: 35 additions & 43 deletions src/wp-includes/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,24 @@
* types that support borders.
*
* @since 5.8.0
* @since 6.1.0 Improved conditional blocks optimization.
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_border_support( $block_type ) {
// Determine if any border related features are supported.
$has_border_support = block_has_support( $block_type, array( '__experimentalBorder' ) );
$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );

// Setup attributes and styles within that if needed.
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

if ( $has_border_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
if ( block_has_support( $block_type, array( '__experimentalBorder' ) ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}

if ( $has_border_color_support && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
if ( wp_has_border_feature_support( $block_type, 'color' ) && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
$block_type->attributes['borderColor'] = array(
'type' => 'string',
);
Expand All @@ -43,6 +40,7 @@ function wp_register_border_support( $block_type ) {
* attributes array. This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param WP_Block_Type $block_type Block type.
Expand All @@ -54,8 +52,9 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
return array();
}

$classes = array();
$styles = array();
$border_block_styles = array();
$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
$has_border_width_support = wp_has_border_feature_support( $block_type, 'width' );

// Border radius.
if (
Expand All @@ -65,21 +64,11 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
) {
$border_radius = $block_attributes['style']['border']['radius'];

if ( is_array( $border_radius ) ) {
// We have individual border radius corner values.
foreach ( $border_radius as $key => $radius ) {
// Convert CamelCase corner name to kebab-case.
$corner = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
$styles[] = sprintf( 'border-%s-radius: %s;', $corner, $radius );
}
} else {
// This check handles original unitless implementation.
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}

$styles[] = sprintf( 'border-radius: %s;', $border_radius );
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}

$border_block_styles['radius'] = $border_radius;
}

// Border style.
Expand All @@ -88,13 +77,12 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
isset( $block_attributes['style']['border']['style'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
) {
$border_style = $block_attributes['style']['border']['style'];
$styles[] = sprintf( 'border-style: %s;', $border_style );
$border_block_styles['style'] = $block_attributes['style']['border']['style'];
}

// Border width.
if (
wp_has_border_feature_support( $block_type, 'width' ) &&
$has_border_width_support &&
isset( $block_attributes['style']['border']['width'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
) {
Expand All @@ -105,38 +93,42 @@ function wp_apply_border_support( $block_type, $block_attributes ) {
$border_width .= 'px';
}

$styles[] = sprintf( 'border-width: %s;', $border_width );
$border_block_styles['width'] = $border_width;
}

// Border color.
if (
wp_has_border_feature_support( $block_type, 'color' ) &&
$has_border_color_support &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
) {
$has_named_border_color = array_key_exists( 'borderColor', $block_attributes );
$has_custom_border_color = isset( $block_attributes['style']['border']['color'] );

if ( $has_named_border_color || $has_custom_border_color ) {
$classes[] = 'has-border-color';
}
$preset_border_color = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
$custom_border_color = _wp_array_get( $block_attributes, array( 'style', 'border', 'color' ), null );
$border_block_styles['color'] = $preset_border_color ? $preset_border_color : $custom_border_color;
}

if ( $has_named_border_color ) {
$classes[] = sprintf( 'has-%s-border-color', $block_attributes['borderColor'] );
} elseif ( $has_custom_border_color ) {
$border_color = $block_attributes['style']['border']['color'];
$styles[] = sprintf( 'border-color: %s;', $border_color );
// Generates styles for individual border sides.
if ( $has_border_color_support || $has_border_width_support ) {
foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
$border = _wp_array_get( $block_attributes, array( '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,
);
$border_block_styles[ $side ] = $border_side_values;
}
}

// Collect classes and styles.
// Collects classes and styles.
$attributes = array();
$styles = wp_style_engine_get_styles( array( 'border' => $border_block_styles ) );

if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
if ( ! empty( $styles['classnames'] ) ) {
$attributes['class'] = $styles['classnames'];
}

if ( ! empty( $styles ) ) {
$attributes['style'] = implode( ' ', $styles );
if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}

return $attributes;
Expand Down
69 changes: 20 additions & 49 deletions src/wp-includes/block-supports/colors.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
* Registers the style and colors block attributes for block types that support it.
*
* @since 5.6.0
* @since 6.1.0 Improved $color_support assignment optimization.
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_colors_support( $block_type ) {
$color_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$color_support = _wp_array_get( $block_type->supports, array( 'color' ), false );
}
$color_support = property_exists( $block_type, 'supports' ) ? _wp_array_get( $block_type->supports, array( 'color' ), false ) : false;
$has_text_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'text' ), true ) );
$has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) );
$has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false );
Expand Down Expand Up @@ -63,6 +61,7 @@ function wp_register_colors_support( $block_type ) {
* This will be applied to the block markup in the front-end.
*
* @since 5.6.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param WP_Block_Type $block_type Block type.
Expand All @@ -83,66 +82,38 @@ function wp_apply_colors_support( $block_type, $block_attributes ) {
$has_text_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'text' ), true ) );
$has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) );
$has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false );
$classes = array();
$styles = array();
$color_block_styles = array();

// Text colors.
// Check support for text colors.
if ( $has_text_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' ) ) {
$has_named_text_color = array_key_exists( 'textColor', $block_attributes );
$has_custom_text_color = isset( $block_attributes['style']['color']['text'] );

// Apply required generic class.
if ( $has_custom_text_color || $has_named_text_color ) {
$classes[] = 'has-text-color';
}
// Apply color class or inline style.
if ( $has_named_text_color ) {
$classes[] = sprintf( 'has-%s-color', _wp_to_kebab_case( $block_attributes['textColor'] ) );
} elseif ( $has_custom_text_color ) {
$styles[] = sprintf( 'color: %s;', $block_attributes['style']['color']['text'] );
}
$preset_text_color = array_key_exists( 'textColor', $block_attributes ) ? "var:preset|color|{$block_attributes['textColor']}" : null;
$custom_text_color = _wp_array_get( $block_attributes, array( 'style', 'color', 'text' ), null );
$color_block_styles['text'] = $preset_text_color ? $preset_text_color : $custom_text_color;
}

// Background colors.
if ( $has_background_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' ) ) {
$has_named_background_color = array_key_exists( 'backgroundColor', $block_attributes );
$has_custom_background_color = isset( $block_attributes['style']['color']['background'] );

// Apply required background class.
if ( $has_custom_background_color || $has_named_background_color ) {
$classes[] = 'has-background';
}
// Apply background color classes or styles.
if ( $has_named_background_color ) {
$classes[] = sprintf( 'has-%s-background-color', _wp_to_kebab_case( $block_attributes['backgroundColor'] ) );
} elseif ( $has_custom_background_color ) {
$styles[] = sprintf( 'background-color: %s;', $block_attributes['style']['color']['background'] );
}
$preset_background_color = array_key_exists( 'backgroundColor', $block_attributes ) ? "var:preset|color|{$block_attributes['backgroundColor']}" : null;
$custom_background_color = _wp_array_get( $block_attributes, array( 'style', 'color', 'background' ), null );
$color_block_styles['background'] = $preset_background_color ? $preset_background_color : $custom_background_color;
}

// Gradients.
if ( $has_gradients_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'gradients' ) ) {
$has_named_gradient = array_key_exists( 'gradient', $block_attributes );
$has_custom_gradient = isset( $block_attributes['style']['color']['gradient'] );

if ( $has_named_gradient || $has_custom_gradient ) {
$classes[] = 'has-background';
}
// Apply required background class.
if ( $has_named_gradient ) {
$classes[] = sprintf( 'has-%s-gradient-background', _wp_to_kebab_case( $block_attributes['gradient'] ) );
} elseif ( $has_custom_gradient ) {
$styles[] = sprintf( 'background: %s;', $block_attributes['style']['color']['gradient'] );
}
$preset_gradient_color = array_key_exists( 'gradient', $block_attributes ) ? "var:preset|gradient|{$block_attributes['gradient']}" : null;
$custom_gradient_color = _wp_array_get( $block_attributes, array( 'style', 'color', 'gradient' ), null );
$color_block_styles['gradient'] = $preset_gradient_color ? $preset_gradient_color : $custom_gradient_color;
}

$attributes = array();
if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
$styles = wp_style_engine_get_styles( array( 'color' => $color_block_styles ), array( 'convert_vars_to_classnames' => true ) );

if ( ! empty( $styles['classnames'] ) ) {
$attributes['class'] = $styles['classnames'];
}
if ( ! empty( $styles ) ) {
$attributes['style'] = implode( ' ', $styles );

if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}

return $attributes;
Expand Down
44 changes: 16 additions & 28 deletions src/wp-includes/block-supports/elements.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function wp_render_elements_support( $block_content, $block ) {
* we want the descendant style to take priority, and this is done by loading it after, in DOM order.
*
* @since 6.0.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param string|null $pre_render The pre-rendered content. Default null.
Expand All @@ -97,40 +98,27 @@ function wp_render_elements_support( $block_content, $block ) {
* @return null
*/
function wp_render_elements_support_styles( $pre_render, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
if ( $skip_link_color_serialization ) {
return null;
}

$link_color = null;
if ( ! empty( $block['attrs'] ) ) {
$link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
}
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$element_block_styles = isset( $block['attrs']['style']['elements'] ) ? $block['attrs']['style']['elements'] : null;

/*
* For now we only care about link color.
* This code in the future when we have a public API
* should take advantage of WP_Theme_JSON::compute_style_properties
* and work for any element and style.
*/
if ( null === $link_color ) {
return null;
}

$class_name = wp_get_elements_class_name( $block );
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );

if ( strpos( $link_color, 'var:preset|color|' ) !== false ) {
// Get the name from the string and add proper styles.
$index_to_splice = strrpos( $link_color, '|' ) + 1;
$link_color_name = substr( $link_color, $index_to_splice );
$link_color = "var(--wp--preset--color--$link_color_name)";
if ( $skip_link_color_serialization ) {
return null;
}
$link_color_declaration = esc_html( safecss_filter_attr( "color: $link_color" ) );

$style = ".$class_name a{" . $link_color_declaration . ';}';

wp_enqueue_block_support_styles( $style );
$class_name = wp_get_elements_class_name( $block );
$link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null;

wp_style_engine_get_styles(
$link_block_styles,
array(
'selector' => ".$class_name a",
'context' => 'block-supports',
)
);
Comment on lines +115 to +121
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have to do something with the return value? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried a paragraph block with a link and the link color set to orange, and it really isn't reflected on the frontend:

image

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, looks like this needs #3273 in order for the relevant styling to be added!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have to do something with the return value? 🤔

Not here since the style engine will register styles in a store using the context as key. Gutenberg fetches stored styles at render time and prints them out.


return null;
}
Expand Down
37 changes: 15 additions & 22 deletions src/wp-includes/block-supports/spacing.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function wp_register_spacing_support( $block_type ) {
* This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param WP_Block_Type $block_type Block Type.
Expand All @@ -48,35 +49,27 @@ function wp_apply_spacing_support( $block_type, $block_attributes ) {
return array();
}

$attributes = array();
$has_padding_support = block_has_support( $block_type, array( 'spacing', 'padding' ), false );
$has_margin_support = block_has_support( $block_type, array( 'spacing', 'margin' ), false );
$skip_padding = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
$skip_margin = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
$styles = array();
$block_styles = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;

if ( $has_padding_support && ! $skip_padding ) {
$padding_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'padding' ), null );
if ( is_array( $padding_value ) ) {
foreach ( $padding_value as $key => $value ) {
$styles[] = sprintf( 'padding-%s: %s;', $key, $value );
}
} elseif ( null !== $padding_value ) {
$styles[] = sprintf( 'padding: %s;', $padding_value );
}
if ( ! $block_styles ) {
return $attributes;
}

if ( $has_margin_support && ! $skip_margin ) {
$margin_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'margin' ), null );
if ( is_array( $margin_value ) ) {
foreach ( $margin_value as $key => $value ) {
$styles[] = sprintf( 'margin-%s: %s;', $key, $value );
}
} elseif ( null !== $margin_value ) {
$styles[] = sprintf( 'margin: %s;', $margin_value );
}
$skip_padding = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
$skip_margin = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
$spacing_block_styles = array();
$spacing_block_styles['padding'] = $has_padding_support && ! $skip_padding ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null;
$spacing_block_styles['margin'] = $has_margin_support && ! $skip_margin ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null;
$styles = wp_style_engine_get_styles( array( 'spacing' => $spacing_block_styles ) );

if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}

return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
return $attributes;
}

// Register the block support.
Expand Down
Loading