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

Backport background image block support from Gutenberg #5209

112 changes: 112 additions & 0 deletions src/wp-includes/block-supports/background.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Background block support flag.
*
* @package WordPress
* @since 6.4.0
*/

/**
* Registers the style block attribute for block types that support it.
*
* @since 6.4.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_background_support( $block_type ) {
// Setup attributes and styles within that if needed.
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

// Check for existing style attribute definition e.g. from block.json.
if ( array_key_exists( 'style', $block_type->attributes ) ) {
return;
}

$has_background_support = block_has_support( $block_type, array( 'background' ), false );

if ( $has_background_support ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}

/**
* Renders the background styles to the block wrapper.
* This block support uses the `render_block` hook to ensure that
* it is also applied to non-server-rendered blocks.
*
* @since 6.4.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_background_support( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$block_attributes = $block['attrs'];
$has_background_image_support = block_has_support( $block_type, array( 'background', 'backgroundImage' ), false );

if (
! $has_background_image_support ||
wp_should_skip_block_supports_serialization( $block_type, 'background', 'backgroundImage' )
) {
return $block_content;
}

$background_image_source = _wp_array_get( $block_attributes, array( 'style', 'background', 'backgroundImage', 'source' ), null );
$background_image_url = _wp_array_get( $block_attributes, array( 'style', 'background', 'backgroundImage', 'url' ), null );
$background_size = _wp_array_get( $block_attributes, array( 'style', 'background', 'backgroundSize' ), 'cover' );

$background_block_styles = array();

if (
'file' === $background_image_source &&
$background_image_url
) {
// Set file based background URL.
$background_block_styles['backgroundImage']['url'] = $background_image_url;
// Only output the background size when an image url is set.
$background_block_styles['backgroundSize'] = $background_size;
}

$styles = wp_style_engine_get_styles( array( 'background' => $background_block_styles ) );

if ( ! empty( $styles['css'] ) ) {
// Inject background styles to the first element, presuming it's the wrapper, if it exists.
$tags = new WP_HTML_Tag_Processor( $block_content );

if ( $tags->next_tag() ) {
$existing_style = $tags->get_attribute( 'style' );
$updated_style = '';

if ( ! empty( $existing_style ) ) {
$updated_style = $existing_style;
if ( ! str_ends_with( $existing_style, ';' ) ) {
$updated_style .= ';';
}
}

$updated_style .= $styles['css'];
$tags->set_attribute( 'style', $updated_style );
}

return $tags->get_updated_html();
}

return $block_content;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'background',
array(
'register_attribute' => 'wp_register_background_support',
)
);

add_filter( 'render_block', 'wp_render_background_support', 10, 2 );
9 changes: 7 additions & 2 deletions src/wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,13 +342,16 @@ class WP_Theme_JSON {
* @since 6.2.0 Added `dimensions.minHeight`, 'shadow.presets', 'shadow.defaultPresets',
* `position.fixed` and `position.sticky`.
* @since 6.3.0 Added support for `typography.textColumns`, removed `layout.definitions`.
* @since 6.4.0 Added `layout.allowEditing` and `typography.writingMode`.
*
* @since 6.4.0 Added support for `layout.allowEditing`, `background.backgroundImage`,
* and `typography.writingMode`.
* @var array
*/
const VALID_SETTINGS = array(
'appearanceTools' => null,
'useRootPaddingAwareAlignments' => null,
'background' => array(
'backgroundImage' => null,
),
'border' => array(
'color' => null,
'radius' => null,
Expand Down Expand Up @@ -563,9 +566,11 @@ public static function get_element_class_name( $element ) {
*
* @since 6.0.0
* @since 6.2.0 Added `dimensions.minHeight` and `position.sticky`.
* @since 6.4.0 Added `background.backgroundImage`.
* @var array
*/
const APPEARANCE_TOOLS_OPT_INS = array(
array( 'background', 'backgroundImage' ),
array( 'border', 'color' ),
array( 'border', 'radius' ),
array( 'border', 'style' ),
Expand Down
52 changes: 52 additions & 0 deletions src/wp-includes/style-engine/class-wp-style-engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @access private
* @since 6.1.0
* @since 6.3.0 Added support for text-columns.
* @since 6.4.0 Added support for background.backgroundImage.
*/
#[AllowDynamicProperties]
final class WP_Style_Engine {
Expand Down Expand Up @@ -51,6 +52,21 @@ final class WP_Style_Engine {
* @var array
*/
const BLOCK_STYLE_DEFINITIONS_METADATA = array(
'background' => array(
'backgroundImage' => array(
'property_keys' => array(
'default' => 'background-image',
),
'value_func' => array( self::class, 'get_url_or_value_css_declaration' ),
'path' => array( 'background', 'backgroundImage' ),
),
'backgroundSize' => array(
'property_keys' => array(
'default' => 'background-size',
),
'path' => array( 'background', 'backgroundSize' ),
),
),
'color' => array(
'text' => array(
'property_keys' => array(
Expand Down Expand Up @@ -589,6 +605,42 @@ protected static function get_individual_property_css_declarations( $style_value
return $css_declarations;
}

/**
* Style value parser that constructs a CSS definition array comprising a single CSS property and value.
* If the provided value is an array containing a `url` property, the function will return a CSS definition array
* with a single property and value, with `url` escaped and injected into a CSS `url()` function,
* e.g., array( 'background-image' => "url( '...' )" ).
*
* @since 6.4.0
*
* @param array $style_value A single raw style value from $block_styles array.
* @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA.
* @return string[] An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ).
*/
protected static function get_url_or_value_css_declaration( $style_value, $style_definition ) {
if ( empty( $style_value ) ) {
return array();
}

$css_declarations = array();

if ( isset( $style_definition['property_keys']['default'] ) ) {
$value = null;

if ( ! empty( $style_value['url'] ) ) {
$value = "url('" . $style_value['url'] . "')";
} elseif ( is_string( $style_value ) ) {
$value = $style_value;
}

if ( null !== $value ) {
$css_declarations[ $style_definition['property_keys']['default'] ] = $value;
}
}

return $css_declarations;
}

/**
* Returns compiled CSS from CSS declarations.
*
Expand Down
1 change: 1 addition & 0 deletions src/wp-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@
require ABSPATH . WPINC . '/class-wp-block-supports.php';
require ABSPATH . WPINC . '/block-supports/utils.php';
require ABSPATH . WPINC . '/block-supports/align.php';
require ABSPATH . WPINC . '/block-supports/background.php';
require ABSPATH . WPINC . '/block-supports/border.php';
require ABSPATH . WPINC . '/block-supports/colors.php';
require ABSPATH . WPINC . '/block-supports/custom-classname.php';
Expand Down
Loading