Make WordPress Core

Changeset 58222


Ignore:
Timestamp:
05/28/2024 06:04:37 AM (2 years ago)
Author:
noisysocks
Message:

Block Themes: Allow setting site-wide background images in theme.json

Syncs the necessary changes from Gutenberg to allow setting site-wide
background images using the top-level styles.background key in theme.json.

Props ramonopoly.
Fixes #61123.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-supports/background.php

    r57365 r58222  
    4242 * @since 6.4.0
    4343 * @since 6.5.0 Added support for `backgroundPosition` and `backgroundRepeat` output.
     44 * @since 6.6.0 Removed requirement for `backgroundImage.source`. A file/url is the default.
     45 *
    4446 * @access private
    4547 *
     
    5557        if (
    5658                ! $has_background_image_support ||
    57                 wp_should_skip_block_supports_serialization( $block_type, 'background', 'backgroundImage' )
     59                wp_should_skip_block_supports_serialization( $block_type, 'background', 'backgroundImage' ) ||
     60                ! isset( $block_attributes['style']['background'] )
    5861        ) {
    5962                return $block_content;
    6063        }
    6164
    62         $background_image_source = isset( $block_attributes['style']['background']['backgroundImage']['source'] )
    63                 ? $block_attributes['style']['background']['backgroundImage']['source']
    64                 : null;
    65         $background_image_url    = isset( $block_attributes['style']['background']['backgroundImage']['url'] )
    66                 ? $block_attributes['style']['background']['backgroundImage']['url']
    67                 : null;
     65        $background_styles                    = array();
     66        $background_styles['backgroundImage'] = isset( $block_attributes['style']['background']['backgroundImage'] ) ? $block_attributes['style']['background']['backgroundImage'] : array();
    6867
    69         if ( ! $background_image_source && ! $background_image_url ) {
    70                 return $block_content;
    71         }
    72 
    73         $background_size     = isset( $block_attributes['style']['background']['backgroundSize'] )
    74                 ? $block_attributes['style']['background']['backgroundSize']
    75                 : 'cover';
    76         $background_position = isset( $block_attributes['style']['background']['backgroundPosition'] )
    77                 ? $block_attributes['style']['background']['backgroundPosition']
    78                 : null;
    79         $background_repeat   = isset( $block_attributes['style']['background']['backgroundRepeat'] )
    80                 ? $block_attributes['style']['background']['backgroundRepeat']
    81                 : null;
    82 
    83         $background_block_styles = array();
    84 
    85         if (
    86                 'file' === $background_image_source &&
    87                 $background_image_url
    88         ) {
    89                 // Set file based background URL.
    90                 $background_block_styles['backgroundImage']['url'] = $background_image_url;
    91                 // Only output the background size and repeat when an image url is set.
    92                 $background_block_styles['backgroundSize']     = $background_size;
    93                 $background_block_styles['backgroundRepeat']   = $background_repeat;
    94                 $background_block_styles['backgroundPosition'] = $background_position;
     68        if ( ! empty( $background_styles['backgroundImage'] ) ) {
     69                $background_styles['backgroundSize']     = isset( $block_attributes['style']['background']['backgroundSize'] ) ? $block_attributes['style']['background']['backgroundSize'] : 'cover';
     70                $background_styles['backgroundPosition'] = isset( $block_attributes['style']['background']['backgroundPosition'] ) ? $block_attributes['style']['background']['backgroundPosition'] : null;
     71                $background_styles['backgroundRepeat']   = isset( $block_attributes['style']['background']['backgroundRepeat'] ) ? $block_attributes['style']['background']['backgroundRepeat'] : null;
    9572
    9673                // If the background size is set to `contain` and no position is set, set the position to `center`.
    97                 if ( 'contain' === $background_size && ! isset( $background_position ) ) {
    98                         $background_block_styles['backgroundPosition'] = 'center';
     74                if ( 'contain' === $background_styles['backgroundSize'] && ! $background_styles['backgroundPosition'] ) {
     75                        $background_styles['backgroundPosition'] = 'center';
    9976                }
    10077        }
    10178
    102         $styles = wp_style_engine_get_styles( array( 'background' => $background_block_styles ) );
     79        $styles = wp_style_engine_get_styles( array( 'background' => $background_styles ) );
    10380
    10481        if ( ! empty( $styles['css'] ) ) {
  • trunk/src/wp-includes/class-wp-theme-json.php

    r58171 r58222  
    214214         * @since 6.4.0 Added `writing-mode` property.
    215215         * @since 6.5.0 Added `aspect-ratio` property.
     216         * @since 6.6.0 Added `background-[image|position|repeat|size]` properties.
    216217         *
    217218         * @var array
     
    221222                'background'                        => array( 'color', 'gradient' ),
    222223                'background-color'                  => array( 'color', 'background' ),
     224                'background-image'                  => array( 'background', 'backgroundImage' ),
     225                'background-position'               => array( 'background', 'backgroundPosition' ),
     226                'background-repeat'                 => array( 'background', 'backgroundRepeat' ),
     227                'background-size'                   => array( 'background', 'backgroundSize' ),
    223228                'border-radius'                     => array( 'border', 'radius' ),
    224229                'border-top-left-radius'            => array( 'border', 'radius', 'topLeft' ),
     
    284289         * Indirect properties are not output directly by `compute_style_properties`,
    285290         * but are used elsewhere in the processing of global styles. The indirect
    286          * property is used to validate whether or not a style value is allowed.
     291         * property is used to validate whether a style value is allowed.
    287292         *
    288293         * @since 6.2.0
     294         * @since 6.6.0 Added background-image properties.
    289295         *
    290296         * @var array
     
    303309                        array( 'layout', 'contentSize' ),
    304310                        array( 'layout', 'wideSize' ),
     311                ),
     312                'background-image' => array(
     313                        array( 'background', 'backgroundImage', 'url' ),
    305314                ),
    306315        );
     
    483492         * @since 6.3.0 Added support for `typography.textColumns`.
    484493         * @since 6.5.0 Added support for `dimensions.aspectRatio`.
     494         * @since 6.6.0 Added `background` sub properties to top-level only.
    485495         *
    486496         * @var array
    487497         */
    488498        const VALID_STYLES = array(
     499                'background' => array(
     500                        'backgroundImage'    => 'top',
     501                        'backgroundPosition' => 'top',
     502                        'backgroundRepeat'   => 'top',
     503                        'backgroundSize'     => 'top',
     504                ),
    489505                'border'     => array(
    490506                        'color'  => null,
     
    20522068         * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters.
    20532069         * @since 6.5.0 Output a `min-height: unset` rule when `aspect-ratio` is set.
    2054          * @since 6.6.0 Passing current theme JSON settings to wp_get_typography_font_size_value().
     2070         * @since 6.6.0 Pass current theme JSON settings to wp_get_typography_font_size_value(), and process background properties.
    20552071         *
    20562072         * @param array   $styles Styles to process.
     
    21042120                                        continue;
    21052121                                }
     2122                        }
     2123
     2124                        // Processes background styles.
     2125                        if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) {
     2126                                $background_styles = wp_style_engine_get_styles( array( 'background' => $styles['background'] ) );
     2127                                $value             = isset( $background_styles['declarations'][ $css_property ] ) ? $background_styles['declarations'][ $css_property ] : $value;
    21062128                        }
    21072129
     
    24852507         *
    24862508         * @since 6.1.0
     2509         * @since 6.6.0 Setting a min-height of HTML when root styles have a background gradient or image.
    24872510         *
    24882511         * @param array $block_metadata Metadata about the block to get styles for.
     
    24962519                $settings             = isset( $this->theme_json['settings'] ) ? $this->theme_json['settings'] : array();
    24972520                $feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $node );
     2521                $is_root_selector     = static::ROOT_BLOCK_SELECTOR === $selector;
    24982522
    24992523                // If there are style variations, generate the declarations for them, including any feature selectors the block may have.
     
    25782602
    25792603                /*
    2580                  * 1. Separate the declarations that use the general selector
     2604                 * 1. Bespoke declaration modifiers:
     2605                 * - 'filter': Separate the declarations that use the general selector
    25812606                 * from the ones using the duotone selector.
     2607                 * - 'background|background-image': set the html min-height to 100%
     2608                 * to ensure the background covers the entire viewport.
    25822609                 */
    2583                 $declarations_duotone = array();
     2610                $declarations_duotone       = array();
     2611                $should_set_root_min_height = false;
     2612
    25842613                foreach ( $declarations as $index => $declaration ) {
    25852614                        if ( 'filter' === $declaration['name'] ) {
     2615                                /*
     2616                                 * 'unset' filters happen when a filter is unset
     2617                                 * in the site-editor UI. Because the 'unset' value
     2618                                 * in the user origin overrides the value in the
     2619                                 * theme origin, we can skip rendering anything
     2620                                 * here as no filter needs to be applied anymore.
     2621                                 * So only add declarations to with values other
     2622                                 * than 'unset'.
     2623                                 */
     2624                                if ( 'unset' !== $declaration['value'] ) {
     2625                                        $declarations_duotone[] = $declaration;
     2626                                }
    25862627                                unset( $declarations[ $index ] );
    2587                                 $declarations_duotone[] = $declaration;
    2588                         }
     2628                        }
     2629
     2630                        if ( $is_root_selector && ( 'background-image' === $declaration['name'] || 'background' === $declaration['name'] ) ) {
     2631                                $should_set_root_min_height = true;
     2632                        }
     2633                }
     2634
     2635                /*
     2636                 * If root styles has a background-image or a background (gradient) set,
     2637                 * set the min-height to '100%'. Minus `--wp-admin--admin-bar--height` for logged-in view.
     2638                 * Setting the CSS rule on the HTML tag ensures background gradients and images behave similarly,
     2639                 * and matches the behavior of the site editor.
     2640                 */
     2641                if ( $should_set_root_min_height ) {
     2642                        $block_rules .= static::to_ruleset(
     2643                                'html',
     2644                                array(
     2645                                        array(
     2646                                                'name'  => 'min-height',
     2647                                                'value' => 'calc(100% - var(--wp-admin--admin-bar--height, 0px))',
     2648                                        ),
     2649                                )
     2650                        );
    25892651                }
    25902652
     
    26042666                // 4. Generate Layout block gap styles.
    26052667                if (
    2606                         static::ROOT_BLOCK_SELECTOR !== $selector &&
     2668                        ! $is_root_selector &&
    26072669                        ! empty( $block_metadata['name'] )
    26082670                ) {
  • trunk/tests/phpunit/tests/block-supports/wpRenderBackgroundSupport.php

    r58181 r58222  
    6969         * @ticket 59357
    7070         * @ticket 60175
     71         * @ticket 61123
    7172         *
    7273         * @covers ::wp_render_background_support
     
    133134                                'background_style'    => array(
    134135                                        'backgroundImage' => array(
    135                                                 'url'    => 'https://example.com/image.jpg',
    136                                                 'source' => 'file',
     136                                                'url' => 'https://example.com/image.jpg',
    137137                                        ),
    138138                                ),
     
    148148                                'background_style'    => array(
    149149                                        'backgroundImage'  => array(
    150                                                 'url'    => 'https://example.com/image.jpg',
    151                                                 'source' => 'file',
     150                                                'url' => 'https://example.com/image.jpg',
    152151                                        ),
    153152                                        'backgroundRepeat' => 'no-repeat',
     
    165164                                'background_style'    => array(
    166165                                        'backgroundImage' => array(
    167                                                 'url'    => 'https://example.com/image.jpg',
    168                                                 'source' => 'file',
     166                                                'url' => 'https://example.com/image.jpg',
    169167                                        ),
    170168                                ),
     
    180178                                'background_style'    => array(
    181179                                        'backgroundImage' => array(
    182                                                 'url'    => 'https://example.com/image.jpg',
    183                                                 'source' => 'file',
     180                                                'url' => 'https://example.com/image.jpg',
    184181                                        ),
    185182                                ),
     
    195192                                'background_style'    => array(
    196193                                        'backgroundImage' => array(
    197                                                 'url'    => 'https://example.com/image.jpg',
    198                                                 'source' => 'file',
     194                                                'url' => 'https://example.com/image.jpg',
    199195                                        ),
    200196                                ),
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r58173 r58222  
    49864986
    49874987        /**
     4988         * Tests that theme background image styles are correctly generated.
     4989         *
     4990         * @ticket 61123
     4991         */
     4992        public function test_get_top_level_background_image_styles() {
     4993                $theme_json = new WP_Theme_JSON(
     4994                        array(
     4995                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
     4996                                'styles'  => array(
     4997                                        'background' => array(
     4998                                                'backgroundImage'    => array(
     4999                                                        'url' => 'http://example.org/image.png',
     5000                                                ),
     5001                                                'backgroundSize'     => 'contain',
     5002                                                'backgroundRepeat'   => 'no-repeat',
     5003                                                'backgroundPosition' => 'center center',
     5004                                        ),
     5005                                        'blocks'     => array(
     5006                                                'core/paragraph' => array(
     5007                                                        'background' => array(
     5008                                                                'backgroundImage'    => array(
     5009                                                                        'url' => 'http://example.org/image.png',
     5010                                                                ),
     5011                                                                'backgroundSize'     => 'cover',
     5012                                                                'backgroundRepeat'   => 'no-repeat',
     5013                                                                'backgroundPosition' => 'center center',
     5014                                                        ),
     5015                                                ),
     5016                                        ),
     5017                                        'elements'   => array(
     5018                                                'button' => array(
     5019                                                        'background' => array(
     5020                                                                'backgroundImage'    => array(
     5021                                                                        'url' => 'http://example.org/image.png',
     5022                                                                ),
     5023                                                                'backgroundSize'     => 'cover',
     5024                                                                'backgroundRepeat'   => 'no-repeat',
     5025                                                                'backgroundPosition' => 'center center',
     5026                                                        ),
     5027                                                ),
     5028                                        ),
     5029                                ),
     5030                        )
     5031                );
     5032
     5033                $expected_styles = "body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}";
     5034                $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background styles type does not match expectations' );
     5035
     5036                $theme_json = new WP_Theme_JSON(
     5037                        array(
     5038                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
     5039                                'styles'  => array(
     5040                                        'background' => array(
     5041                                                'backgroundImage'    => "url('http://example.org/image.png')",
     5042                                                'backgroundSize'     => 'contain',
     5043                                                'backgroundRepeat'   => 'no-repeat',
     5044                                                'backgroundPosition' => 'center center',
     5045                                        ),
     5046                                ),
     5047                        )
     5048                );
     5049
     5050                $expected_styles = "body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}";
     5051                $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background image as string type does not match expectations' );
     5052        }
     5053
     5054        /**
    49885055         * @ticket 57536
    49895056         */
Note: See TracChangeset for help on using the changeset viewer.