Make WordPress Core

Changeset 52757


Ignore:
Timestamp:
02/17/2022 04:16:59 PM (5 years ago)
Author:
audrasjb
Message:

Editor: Backport Duotone fixes for 5.9.1.

This changeset is a backport for the following Gutenberg PRs:

  • Fix duotone theme cache gutenberg#36236
  • Fix duotone render in non-fse themes gutenberg#37954
  • Duotone: Allow users to specify custom filters gutenberg#38442

Props oandregal, scruffian, Mamaduka.
See #55179.

Location:
trunk/src/wp-includes
Files:
4 edited

Legend:

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

    r52301 r52757  
    353353}
    354354
    355 
    356 /**
    357  * Registers the style and colors block attributes for block types that support it.
    358  *
    359  * @since 5.8.0
    360  * @access private
    361  *
    362  * @param WP_Block_Type $block_type Block Type.
    363  */
    364 function wp_register_duotone_support( $block_type ) {
    365         $has_duotone_support = false;
    366         if ( property_exists( $block_type, 'supports' ) ) {
    367                 $has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
    368         }
    369 
    370         if ( $has_duotone_support ) {
    371                 if ( ! $block_type->attributes ) {
    372                         $block_type->attributes = array();
    373                 }
    374 
    375                 if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
    376                         $block_type->attributes['style'] = array(
    377                                 'type' => 'object',
    378                         );
    379                 }
    380         }
    381 }
    382 
    383 /**
    384  * Renders the duotone filter SVG and returns the CSS filter property to
    385  * reference the rendered SVG.
     355/**
     356 * Returns the prefixed id for the duotone filter for use as a CSS id.
     357 *
     358 * @since 5.9.1
     359 * @access private
     360 *
     361 * @param array $preset Duotone preset value as seen in theme.json.
     362 * @return string Duotone filter CSS id.
     363 */
     364function wp_get_duotone_filter_id( $preset ) {
     365        if ( ! isset( $preset['slug'] ) ) {
     366                return '';
     367        }
     368
     369        return 'wp-duotone-' . $preset['slug'];
     370}
     371
     372/**
     373 * Returns the CSS filter property url to reference the rendered SVG.
    386374 *
    387375 * @since 5.9.0
    388376 * @access private
    389 
     377 *
    390378 * @param array $preset Duotone preset value as seen in theme.json.
    391  * @return string Duotone CSS filter property.
    392  */
    393 function wp_render_duotone_filter_preset( $preset ) {
    394         $duotone_id     = $preset['slug'];
    395         $duotone_colors = $preset['colors'];
    396         $filter_id      = 'wp-duotone-' . $duotone_id;
     379 * @return string Duotone CSS filter property url value.
     380 */
     381function wp_get_duotone_filter_property( $preset ) {
     382        $filter_id = wp_get_duotone_filter_id( $preset );
     383        return "url('#" . $filter_id . "')";
     384}
     385
     386/**
     387 * Returns the duotone filter SVG string for the preset.
     388 *
     389 * @since 5.9.1
     390 * @access private
     391 *
     392 * @param array $preset Duotone preset value as seen in theme.json.
     393 * @return string Duotone SVG filter.
     394 */
     395function wp_get_duotone_filter_svg( $preset ) {
     396        $filter_id = wp_get_duotone_filter_id( $preset );
     397
    397398        $duotone_values = array(
    398399                'r' => array(),
     
    401402                'a' => array(),
    402403        );
    403         foreach ( $duotone_colors as $color_str ) {
     404
     405        if ( ! isset( $preset['colors'] ) || ! is_array( $preset['colors'] ) ) {
     406                $preset['colors'] = array();
     407        }
     408
     409        foreach ( $preset['colors'] as $color_str ) {
    404410                $color = wp_tinycolor_string_to_rgb( $color_str );
    405411
     
    457463        }
    458464
    459         add_action(
    460                 // Safari doesn't render SVG filters defined in data URIs,
    461                 // and SVG filters won't render in the head of a document,
    462                 // so the next best place to put the SVG is in the footer.
    463                 is_admin() ? 'admin_footer' : 'wp_footer',
    464                 function () use ( $svg ) {
    465                         echo $svg;
     465        return $svg;
     466}
     467
     468/**
     469 * Registers the style and colors block attributes for block types that support it.
     470 *
     471 * @since 5.8.0
     472 * @access private
     473 *
     474 * @param WP_Block_Type $block_type Block Type.
     475 */
     476function wp_register_duotone_support( $block_type ) {
     477        $has_duotone_support = false;
     478        if ( property_exists( $block_type, 'supports' ) ) {
     479                $has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
     480        }
     481
     482        if ( $has_duotone_support ) {
     483                if ( ! $block_type->attributes ) {
     484                        $block_type->attributes = array();
    466485                }
    467         );
    468 
    469         return "url('#" . $filter_id . "')";
     486
     487                if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
     488                        $block_type->attributes['style'] = array(
     489                                'type' => 'object',
     490                        );
     491                }
     492        }
    470493}
    471494
     
    501524                'colors' => $block['attrs']['style']['color']['duotone'],
    502525        );
    503         $filter_property = wp_render_duotone_filter_preset( $filter_preset );
    504         $filter_id       = 'wp-duotone-' . $filter_preset['slug'];
     526        $filter_property = wp_get_duotone_filter_property( $filter_preset );
     527        $filter_id       = wp_get_duotone_filter_id( $filter_preset );
     528        $filter_svg      = wp_get_duotone_filter_svg( $filter_preset );
    505529
    506530        $scope     = '.' . $filter_id;
     
    521545        wp_add_inline_style( $filter_id, $filter_style );
    522546        wp_enqueue_style( $filter_id );
     547
     548        add_action(
     549                'wp_footer',
     550                static function () use ( $filter_svg, $selector ) {
     551                        echo $filter_svg;
     552
     553                        /*
     554                         * Safari renders elements incorrectly on first paint when the SVG
     555                         * filter comes after the content that it is filtering, so we force
     556                         * a repaint with a WebKit hack which solves the issue.
     557                         */
     558                        global $is_safari;
     559                        if ( $is_safari ) {
     560                                printf(
     561                                        // Simply accessing el.offsetHeight flushes layout and style
     562                                        // changes in WebKit without having to wait for setTimeout.
     563                                        '<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>',
     564                                        wp_json_encode( $selector )
     565                                );
     566                        }
     567                }
     568        );
    523569
    524570        // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
     
    539585);
    540586add_filter( 'render_block', 'wp_render_duotone_support', 10, 2 );
     587
     588/**
     589 * Render the SVG filters supplied by theme.json.
     590 *
     591 * Note that this doesn't render the per-block user-defined
     592 * filters which are handled by wp_render_duotone_support,
     593 * but it should be rendered in the same location as those to satisfy
     594 * Safari's rendering quirks.
     595 *
     596 * @since 5.9.1
     597 */
     598function wp_global_styles_render_svg_filters() {
     599        $filters = wp_get_global_styles_svg_filters();
     600        if ( ! empty( $filters ) ) {
     601                echo $filters;
     602        }
     603}
     604add_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
  • trunk/src/wp-includes/class-wp-theme-json.php

    r52744 r52757  
    133133                        'override'          => true,
    134134                        'use_default_names' => false,
    135                         'value_func'        => 'wp_render_duotone_filter_preset',
     135                        'value_func'        => 'wp_get_duotone_filter_property',
    136136                        'css_vars'          => '--wp--preset--duotone--$slug',
    137137                        'classes'           => array(),
     
    15881588
    15891589        /**
     1590         * Converts all filter (duotone) presets into SVGs.
     1591         *
     1592         * @since 5.9.1
     1593         *
     1594         * @param array $origins List of origins to process.
     1595         * @return string SVG filters.
     1596         */
     1597        public function get_svg_filters( $origins ) {
     1598                $blocks_metadata = static::get_blocks_metadata();
     1599                $setting_nodes   = static::get_setting_nodes( $this->theme_json, $blocks_metadata );
     1600
     1601                foreach ( $setting_nodes as $metadata ) {
     1602                        $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
     1603                        if ( empty( $node['color']['duotone'] ) ) {
     1604                                continue;
     1605                        }
     1606
     1607                        $duotone_presets = $node['color']['duotone'];
     1608
     1609                        $filters = '';
     1610                        foreach ( $origins as $origin ) {
     1611                                if ( ! isset( $duotone_presets[ $origin ] ) ) {
     1612                                        continue;
     1613                                }
     1614                                foreach ( $duotone_presets[ $origin ] as $duotone_preset ) {
     1615                                        $filters .= wp_get_duotone_filter_svg( $duotone_preset );
     1616                                }
     1617                        }
     1618                }
     1619
     1620                return $filters;
     1621        }
     1622
     1623        /**
    15901624         * Returns whether a presets should be overridden or not.
    15911625         *
  • trunk/src/wp-includes/deprecated.php

    r52425 r52757  
    42094209        return _excerpt_render_inner_blocks( $columns, $allowed_blocks );
    42104210}
     4211
     4212/**
     4213 * Renders the duotone filter SVG and returns the CSS filter property to
     4214 * reference the rendered SVG.
     4215 *
     4216 * @since 5.9.0
     4217 * @deprecated 5.9.1 Use `wp_get_duotone_filter_property` introduced in 5.9.1.
     4218 *
     4219 * @see wp_get_duotone_filter_property()
     4220 *
     4221 * @param array $preset Duotone preset value as seen in theme.json.
     4222 * @return string Duotone CSS filter property.
     4223 */
     4224function wp_render_duotone_filter_preset( $preset ) {
     4225        _deprecated_function( __FUNCTION__, '5.9.1', 'wp_get_duotone_filter_property()' );
     4226        return wp_get_duotone_filter_property( $preset );
     4227}
  • trunk/src/wp-includes/global-styles-and-settings.php

    r52676 r52757  
    151151        return $stylesheet;
    152152}
     153
     154/**
     155 * Returns a string containing the SVGs to be referenced as filters (duotone).
     156 *
     157 * @since 5.9.1
     158 *
     159 * @return string
     160 */
     161function wp_get_global_styles_svg_filters() {
     162        // Return cached value if it can be used and exists.
     163        // It's cached by theme to make sure that theme switching clears the cache.
     164        $can_use_cached = (
     165                ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) &&
     166                ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) &&
     167                ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) &&
     168                ! is_admin()
     169        );
     170        $transient_name = 'global_styles_svg_filters_' . get_stylesheet();
     171        if ( $can_use_cached ) {
     172                $cached = get_transient( $transient_name );
     173                if ( $cached ) {
     174                        return $cached;
     175                }
     176        }
     177
     178        $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
     179
     180        $origins = array( 'default', 'theme', 'custom' );
     181        if ( ! $supports_theme_json ) {
     182                $origins = array( 'default' );
     183        }
     184
     185        $tree = WP_Theme_JSON_Resolver::get_merged_data();
     186        $svgs = $tree->get_svg_filters( $origins );
     187
     188        if ( $can_use_cached ) {
     189                // Cache for a minute, same as wp_get_global_stylesheet.
     190                set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS );
     191        }
     192
     193        return $svgs;
     194}
Note: See TracChangeset for help on using the changeset viewer.