wp/wp-includes/block-supports/border.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     9 /**
     9 /**
    10  * Registers the style attribute used by the border feature if needed for block
    10  * Registers the style attribute used by the border feature if needed for block
    11  * types that support borders.
    11  * types that support borders.
    12  *
    12  *
    13  * @since 5.8.0
    13  * @since 5.8.0
       
    14  * @since 6.1.0 Improved conditional blocks optimization.
    14  * @access private
    15  * @access private
    15  *
    16  *
    16  * @param WP_Block_Type $block_type Block Type.
    17  * @param WP_Block_Type $block_type Block Type.
    17  */
    18  */
    18 function wp_register_border_support( $block_type ) {
    19 function wp_register_border_support( $block_type ) {
    19 	// Determine if any border related features are supported.
       
    20 	$has_border_support       = block_has_support( $block_type, array( '__experimentalBorder' ) );
       
    21 	$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
       
    22 
       
    23 	// Setup attributes and styles within that if needed.
    20 	// Setup attributes and styles within that if needed.
    24 	if ( ! $block_type->attributes ) {
    21 	if ( ! $block_type->attributes ) {
    25 		$block_type->attributes = array();
    22 		$block_type->attributes = array();
    26 	}
    23 	}
    27 
    24 
    28 	if ( $has_border_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
    25 	if ( block_has_support( $block_type, '__experimentalBorder' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
    29 		$block_type->attributes['style'] = array(
    26 		$block_type->attributes['style'] = array(
    30 			'type' => 'object',
    27 			'type' => 'object',
    31 		);
    28 		);
    32 	}
    29 	}
    33 
    30 
    34 	if ( $has_border_color_support && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
    31 	if ( wp_has_border_feature_support( $block_type, 'color' ) && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
    35 		$block_type->attributes['borderColor'] = array(
    32 		$block_type->attributes['borderColor'] = array(
    36 			'type' => 'string',
    33 			'type' => 'string',
    37 		);
    34 		);
    38 	}
    35 	}
    39 }
    36 }
    41 /**
    38 /**
    42  * Adds CSS classes and inline styles for border styles to the incoming
    39  * Adds CSS classes and inline styles for border styles to the incoming
    43  * attributes array. This will be applied to the block markup in the front-end.
    40  * attributes array. This will be applied to the block markup in the front-end.
    44  *
    41  *
    45  * @since 5.8.0
    42  * @since 5.8.0
       
    43  * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
    46  * @access private
    44  * @access private
    47  *
    45  *
    48  * @param WP_Block_Type $block_type       Block type.
    46  * @param WP_Block_Type $block_type       Block type.
    49  * @param array         $block_attributes Block attributes.
    47  * @param array         $block_attributes Block attributes.
    50  * @return array Border CSS classes and inline styles.
    48  * @return array Border CSS classes and inline styles.
    52 function wp_apply_border_support( $block_type, $block_attributes ) {
    50 function wp_apply_border_support( $block_type, $block_attributes ) {
    53 	if ( wp_should_skip_block_supports_serialization( $block_type, 'border' ) ) {
    51 	if ( wp_should_skip_block_supports_serialization( $block_type, 'border' ) ) {
    54 		return array();
    52 		return array();
    55 	}
    53 	}
    56 
    54 
    57 	$classes = array();
    55 	$border_block_styles      = array();
    58 	$styles  = array();
    56 	$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
       
    57 	$has_border_width_support = wp_has_border_feature_support( $block_type, 'width' );
    59 
    58 
    60 	// Border radius.
    59 	// Border radius.
    61 	if (
    60 	if (
    62 		wp_has_border_feature_support( $block_type, 'radius' ) &&
    61 		wp_has_border_feature_support( $block_type, 'radius' ) &&
    63 		isset( $block_attributes['style']['border']['radius'] ) &&
    62 		isset( $block_attributes['style']['border']['radius'] ) &&
    64 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
    63 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
    65 	) {
    64 	) {
    66 		$border_radius = $block_attributes['style']['border']['radius'];
    65 		$border_radius = $block_attributes['style']['border']['radius'];
    67 
    66 
    68 		if ( is_array( $border_radius ) ) {
    67 		if ( is_numeric( $border_radius ) ) {
    69 			// We have individual border radius corner values.
    68 			$border_radius .= 'px';
    70 			foreach ( $border_radius as $key => $radius ) {
    69 		}
    71 				// Convert CamelCase corner name to kebab-case.
       
    72 				$corner   = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
       
    73 				$styles[] = sprintf( 'border-%s-radius: %s;', $corner, $radius );
       
    74 			}
       
    75 		} else {
       
    76 			// This check handles original unitless implementation.
       
    77 			if ( is_numeric( $border_radius ) ) {
       
    78 				$border_radius .= 'px';
       
    79 			}
       
    80 
    70 
    81 			$styles[] = sprintf( 'border-radius: %s;', $border_radius );
    71 		$border_block_styles['radius'] = $border_radius;
    82 		}
       
    83 	}
    72 	}
    84 
    73 
    85 	// Border style.
    74 	// Border style.
    86 	if (
    75 	if (
    87 		wp_has_border_feature_support( $block_type, 'style' ) &&
    76 		wp_has_border_feature_support( $block_type, 'style' ) &&
    88 		isset( $block_attributes['style']['border']['style'] ) &&
    77 		isset( $block_attributes['style']['border']['style'] ) &&
    89 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
    78 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
    90 	) {
    79 	) {
    91 		$border_style = $block_attributes['style']['border']['style'];
    80 		$border_block_styles['style'] = $block_attributes['style']['border']['style'];
    92 		$styles[]     = sprintf( 'border-style: %s;', $border_style );
       
    93 	}
    81 	}
    94 
    82 
    95 	// Border width.
    83 	// Border width.
    96 	if (
    84 	if (
    97 		wp_has_border_feature_support( $block_type, 'width' ) &&
    85 		$has_border_width_support &&
    98 		isset( $block_attributes['style']['border']['width'] ) &&
    86 		isset( $block_attributes['style']['border']['width'] ) &&
    99 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
    87 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
   100 	) {
    88 	) {
   101 		$border_width = $block_attributes['style']['border']['width'];
    89 		$border_width = $block_attributes['style']['border']['width'];
   102 
    90 
   103 		// This check handles original unitless implementation.
    91 		// This check handles original unitless implementation.
   104 		if ( is_numeric( $border_width ) ) {
    92 		if ( is_numeric( $border_width ) ) {
   105 			$border_width .= 'px';
    93 			$border_width .= 'px';
   106 		}
    94 		}
   107 
    95 
   108 		$styles[] = sprintf( 'border-width: %s;', $border_width );
    96 		$border_block_styles['width'] = $border_width;
   109 	}
    97 	}
   110 
    98 
   111 	// Border color.
    99 	// Border color.
   112 	if (
   100 	if (
   113 		wp_has_border_feature_support( $block_type, 'color' ) &&
   101 		$has_border_color_support &&
   114 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
   102 		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
   115 	) {
   103 	) {
   116 		$has_named_border_color  = array_key_exists( 'borderColor', $block_attributes );
   104 		$preset_border_color          = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
   117 		$has_custom_border_color = isset( $block_attributes['style']['border']['color'] );
   105 		$custom_border_color          = isset( $block_attributes['style']['border']['color'] ) ? $block_attributes['style']['border']['color'] : null;
       
   106 		$border_block_styles['color'] = $preset_border_color ? $preset_border_color : $custom_border_color;
       
   107 	}
   118 
   108 
   119 		if ( $has_named_border_color || $has_custom_border_color ) {
   109 	// Generates styles for individual border sides.
   120 			$classes[] = 'has-border-color';
   110 	if ( $has_border_color_support || $has_border_width_support ) {
   121 		}
   111 		foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
   122 
   112 			$border                       = isset( $block_attributes['style']['border'][ $side ] ) ? $block_attributes['style']['border'][ $side ] : null;
   123 		if ( $has_named_border_color ) {
   113 			$border_side_values           = array(
   124 			$classes[] = sprintf( 'has-%s-border-color', $block_attributes['borderColor'] );
   114 				'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
   125 		} elseif ( $has_custom_border_color ) {
   115 				'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
   126 			$border_color = $block_attributes['style']['border']['color'];
   116 				'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
   127 			$styles[]     = sprintf( 'border-color: %s;', $border_color );
   117 			);
       
   118 			$border_block_styles[ $side ] = $border_side_values;
   128 		}
   119 		}
   129 	}
   120 	}
   130 
   121 
   131 	// Collect classes and styles.
   122 	// Collect classes and styles.
   132 	$attributes = array();
   123 	$attributes = array();
       
   124 	$styles     = wp_style_engine_get_styles( array( 'border' => $border_block_styles ) );
   133 
   125 
   134 	if ( ! empty( $classes ) ) {
   126 	if ( ! empty( $styles['classnames'] ) ) {
   135 		$attributes['class'] = implode( ' ', $classes );
   127 		$attributes['class'] = $styles['classnames'];
   136 	}
   128 	}
   137 
   129 
   138 	if ( ! empty( $styles ) ) {
   130 	if ( ! empty( $styles['css'] ) ) {
   139 		$attributes['style'] = implode( ' ', $styles );
   131 		$attributes['style'] = $styles['css'];
   140 	}
   132 	}
   141 
   133 
   142 	return $attributes;
   134 	return $attributes;
   143 }
   135 }
   144 
   136 
   158  * @param mixed         $default_value Fallback value for feature support, defaults to false.
   150  * @param mixed         $default_value Fallback value for feature support, defaults to false.
   159  * @return bool Whether the feature is supported.
   151  * @return bool Whether the feature is supported.
   160  */
   152  */
   161 function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
   153 function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
   162 	// Check if all border support features have been opted into via `"__experimentalBorder": true`.
   154 	// Check if all border support features have been opted into via `"__experimentalBorder": true`.
   163 	if (
   155 	if ( $block_type instanceof WP_Block_Type ) {
   164 		property_exists( $block_type, 'supports' ) &&
   156 		$block_type_supports_border = isset( $block_type->supports['__experimentalBorder'] )
   165 		( true === _wp_array_get( $block_type->supports, array( '__experimentalBorder' ), $default_value ) )
   157 			? $block_type->supports['__experimentalBorder']
   166 	) {
   158 			: $default_value;
   167 		return true;
   159 		if ( true === $block_type_supports_border ) {
       
   160 			return true;
       
   161 		}
   168 	}
   162 	}
   169 
   163 
   170 	// Check if the specific feature has been opted into individually
   164 	// Check if the specific feature has been opted into individually
   171 	// via nested flag under `__experimentalBorder`.
   165 	// via nested flag under `__experimentalBorder`.
   172 	return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
   166 	return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );