Make WordPress Core

Changeset 55086


Ignore:
Timestamp:
01/18/2023 11:38:16 AM (5 months ago)
Author:
hellofromTonya
Message:

Themes: Introduce wp_theme_has_theme_json() for public consumption.

Adds wp_theme_has_theme_json() for public consumption, to replace the private internal Core-only WP_Theme_JSON_Resolver::theme_has_support() method. This new global function checks if a theme or its parent has a theme.json file.

For performance, results are cached as an integer 1 or 0 in the 'theme_json' group with 'wp_theme_has_theme_json' key. This is a non-persistent cache. Why? To make the derived data from theme.json is always fresh from the potential modifications done via hooks that can use dynamic data (modify the stylesheet depending on some option, settings depending on user permissions, etc.).

Also adds a new public function wp_clean_theme_json_cache() to clear the cache on 'switch_theme' and start_previewing_theme'.

References:

Follow-up to [54493], [53282], [52744], [52049], [50959].

Props oandregal, afragen, alexstine, aristath, azaozz, costdev, flixos90, hellofromTonya, mamaduka, mcsf, ocean90, spacedmonkey.
Fixes #56975.

Location:
trunk
Files:
5 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/edit-form-blocks.php

    r54663 r55086  
    204204        'ajaxUrl'     => admin_url( 'admin-ajax.php' ),
    205205    ),
    206     'supportsLayout'       => WP_Theme_JSON_Resolver::theme_has_support(),
     206    'supportsLayout'       => wp_theme_has_theme_json(),
    207207    'supportsTemplateMode' => current_theme_supports( 'block-templates' ),
    208208
  • trunk/src/wp-admin/site-editor.php

    r54817 r55086  
    7575    'defaultTemplateTypes'      => $indexed_template_types,
    7676    'defaultTemplatePartAreas'  => get_allowed_block_template_part_areas(),
    77     'supportsLayout'            => WP_Theme_JSON_Resolver::theme_has_support(),
     77    'supportsLayout'            => wp_theme_has_theme_json(),
    7878    'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ),
    7979    '__unstableHomeTemplate'    => $home_template,
  • trunk/src/wp-includes/block-editor.php

    r54776 r55086  
    418418    }
    419419
    420     if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
     420    if ( wp_theme_has_theme_json() ) {
    421421        $block_classes = array(
    422422            'css'            => 'styles',
  • trunk/src/wp-includes/block-patterns.php

    r54263 r55086  
    140140    }
    141141
    142     if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
     142    if ( ! wp_theme_has_theme_json() ) {
    143143        return;
    144144    }
  • trunk/src/wp-includes/block-supports/layout.php

    r54633 r55086  
    465465
    466466    if (
    467         WP_Theme_JSON_Resolver::theme_has_support() ||
     467        wp_theme_has_theme_json() ||
    468468        1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
    469469        ( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] )
     
    528528
    529529    if (
    530         WP_Theme_JSON_Resolver::theme_has_support() ||
     530        wp_theme_has_theme_json() ||
    531531        0 === preg_match( $image_with_align, $block_content, $matches )
    532532    ) {
  • trunk/src/wp-includes/block-template-utils.php

    r54998 r55086  
    348348 */
    349349function _add_block_template_info( $template_item ) {
    350     if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
     350    if ( ! wp_theme_has_theme_json() ) {
    351351        return $template_item;
    352352    }
     
    371371 */
    372372function _add_block_template_part_area_info( $template_info ) {
    373     if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
     373    if ( wp_theme_has_theme_json() ) {
    374374        $theme_data = WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) )->get_template_parts();
    375375    }
  • trunk/src/wp-includes/class-wp-theme-json-resolver.php

    r55067 r55086  
    5959
    6060    /**
    61      * Whether or not the theme supports theme.json.
    62      *
    63      * @since 5.8.0
    64      * @var bool
    65      */
    66     protected static $theme_has_support = null;
    67 
    68     /**
    6961     * Container for data coming from the user.
    7062     *
     
    296288         */
    297289        $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
    298         if ( ! static::theme_has_support() ) {
     290        if ( ! wp_theme_has_theme_json() ) {
    299291            if ( ! isset( $theme_support_data['settings']['color'] ) ) {
    300292                $theme_support_data['settings']['color'] = array();
     
    422414         * Bail early if the theme does not support a theme.json.
    423415         *
    424          * Since WP_Theme_JSON_Resolver::theme_has_support() only supports the active
     416         * Since wp_theme_has_theme_json() only supports the active
    425417         * theme, the extra condition for whether $theme is the active theme is
    426418         * present here.
    427419         */
    428         if ( $theme->get_stylesheet() === get_stylesheet() && ! static::theme_has_support() ) {
     420        if ( $theme->get_stylesheet() === get_stylesheet() && ! wp_theme_has_theme_json() ) {
    429421            return array();
    430422        }
     
    603595     * @since 5.8.0
    604596     * @since 5.9.0 Added a check in the parent theme.
     597     * @deprecated 6.2.0 Use wp_theme_has_theme_json() instead.
    605598     *
    606599     * @return bool
    607600     */
    608601    public static function theme_has_support() {
    609         if ( ! isset( static::$theme_has_support ) ) {
    610             static::$theme_has_support = (
    611                 static::get_file_path_from_theme( 'theme.json' ) !== '' ||
    612                 static::get_file_path_from_theme( 'theme.json', true ) !== ''
    613             );
    614         }
    615 
    616         return static::$theme_has_support;
     602        _deprecated_function( __METHOD__, '6.2.0', 'wp_theme_has_theme_json()' );
     603
     604        return wp_theme_has_theme_json();
    617605    }
    618606
     
    657645        static::$user                     = null;
    658646        static::$user_custom_post_type_id = null;
    659         static::$theme_has_support        = null;
    660647        static::$i18n_schema              = null;
    661648    }
  • trunk/src/wp-includes/default-filters.php

    r54999 r55086  
    347347add_action( 'init', 'check_theme_switched', 99 );
    348348add_action( 'init', array( 'WP_Block_Supports', 'init' ), 22 );
    349 add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
    350 add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
     349add_action( 'switch_theme', 'wp_clean_theme_json_cache' );
     350add_action( 'start_previewing_theme', 'wp_clean_theme_json_cache' );
    351351add_action( 'after_switch_theme', '_wp_menus_changed' );
    352352add_action( 'after_switch_theme', '_wp_sidebars_changed' );
  • trunk/src/wp-includes/global-styles-and-settings.php

    r54703 r55086  
    103103    $tree = WP_Theme_JSON_Resolver::get_merged_data();
    104104
    105     $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
     105    $supports_theme_json = wp_theme_has_theme_json();
    106106    if ( empty( $types ) && ! $supports_theme_json ) {
    107107        $types = array( 'variables', 'presets', 'base-layout-styles' );
     
    185185    }
    186186
    187     $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
     187    $supports_theme_json = wp_theme_has_theme_json();
    188188
    189189    $origins = array( 'default', 'theme', 'custom' );
     
    256256    }
    257257}
     258
     259/**
     260 * Checks whether a theme or its parent has a theme.json file.
     261 *
     262 * @since 6.2.0
     263 *
     264 * @return bool Returns true if theme or its parent has a theme.json file, false otherwise.
     265 */
     266function wp_theme_has_theme_json() {
     267    /*
     268     * By using the 'theme_json' group, this data is marked to be non-persistent across requests.
     269     * @see `wp_cache_add_non_persistent_groups()`.
     270     *
     271     * The rationale for this is to make sure derived data from theme.json
     272     * is always fresh from the potential modifications done via hooks
     273     * that can use dynamic data (modify the stylesheet depending on some option,
     274     * settings depending on user permissions, etc.).
     275     * For some of the existing hooks to modify theme.json behavior:
     276     * @see https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/
     277     *
     278     * A different alternative considered was to invalidate the cache upon certain
     279     * events such as options add/update/delete, user meta, etc.
     280     * It was judged not enough, hence this approach.
     281     * @see https://github.com/WordPress/gutenberg/pull/45372
     282     */
     283    $cache_group       = 'theme_json';
     284    $cache_key         = 'wp_theme_has_theme_json';
     285    $theme_has_support = wp_cache_get( $cache_key, $cache_group );
     286
     287    /*
     288     * $theme_has_support is stored as an int in the cache.
     289     *
     290     * The reason not to store it as a boolean is to avoid working
     291     * with the $found parameter which apparently had some issues in some implementations
     292     * @see https://developer.wordpress.org/reference/functions/wp_cache_get/
     293     *
     294     * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme
     295     * developer's workflow.
     296     *
     297     * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core.
     298     */
     299    if ( ! WP_DEBUG && is_int( $theme_has_support ) ) {
     300        return (bool) $theme_has_support;
     301    }
     302
     303    // Does the theme have its own theme.json?
     304    $theme_has_support = is_readable( get_stylesheet_directory() . '/theme.json' );
     305
     306    // Look up the parent if the child does not have a theme.json.
     307    if ( ! $theme_has_support ) {
     308        $theme_has_support = is_readable( get_template_directory() . '/theme.json' );
     309    }
     310
     311    $theme_has_support = $theme_has_support ? 1 : 0;
     312
     313    wp_cache_set( $cache_key, $theme_has_support, $cache_group );
     314
     315    return (bool) $theme_has_support;
     316}
     317
     318/**
     319 * Cleans the caches under the theme_json group.
     320 *
     321 * @since 6.2.0
     322 */
     323function wp_clean_theme_json_cache() {
     324    wp_cache_delete( 'wp_theme_has_theme_json', 'theme_json' );
     325    WP_Theme_JSON_Resolver::clean_cached_data();
     326}
  • trunk/src/wp-includes/load.php

    r54944 r55086  
    754754        );
    755755
    756         wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
     756        wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
    757757    }
    758758
  • trunk/src/wp-includes/ms-blogs.php

    r54945 r55086  
    576576            }
    577577
    578             wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
     578            wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
    579579        }
    580580    }
     
    667667            }
    668668
    669             wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
     669            wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
    670670        }
    671671    }
  • trunk/src/wp-includes/script-loader.php

    r55084 r55086  
    16211621
    16221622    // Only load the default layout and margin styles for themes without theme.json file.
    1623     if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
     1623    if ( ! wp_theme_has_theme_json() ) {
    16241624        $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
    16251625    }
     
    36683668 */
    36693669function wp_enqueue_classic_theme_styles() {
    3670     if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
     3670    if ( ! wp_theme_has_theme_json() ) {
    36713671        $suffix = wp_scripts_get_suffix();
    36723672        wp_register_style( 'classic-theme-styles', '/' . WPINC . "/css/classic-themes$suffix.css", array(), true );
     
    36863686 */
    36873687function wp_add_editor_classic_theme_styles( $editor_settings ) {
    3688     if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
     3688    if ( wp_theme_has_theme_json() ) {
    36893689        return $editor_settings;
    36903690    }
  • trunk/src/wp-includes/theme-templates.php

    r54817 r55086  
    210210 */
    211211function wp_enable_block_templates() {
    212     if ( wp_is_block_theme() || WP_Theme_JSON_Resolver::theme_has_support() ) {
     212    if ( wp_is_block_theme() || wp_theme_has_theme_json() ) {
    213213        add_theme_support( 'block-templates' );
    214214    }
  • trunk/tests/phpunit/includes/abstract-testcase.php

    r55019 r55086  
    402402        );
    403403
    404         wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
     404        wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
    405405    }
    406406
  • trunk/tests/phpunit/tests/theme/themeDir.php

    r54497 r55086  
    164164        $expected    = array(
    165165            'WordPress Default',
     166            'Default Child Theme with no theme.json',
    166167            'Sandbox',
    167168            'Stylesheet Only',
     
    178179            'Block Theme',
    179180            'Block Theme Child Theme',
     181            'Block Theme Child with no theme.json',
    180182            'Block Theme Child Theme With Fluid Typography',
    181183            'Block Theme [0.4.0]',
  • trunk/tests/phpunit/tests/theme/wpThemeJsonResolver.php

    r55067 r55086  
    111111
    112112        // Reset data between tests.
    113         WP_Theme_JSON_Resolver::clean_cached_data();
     113        wp_clean_theme_json_cache();
    114114        parent::tear_down();
    115115    }
     
    377377     */
    378378    public function test_get_core_data( $should_fire_filter, $core_is_cached, $blocks_are_cached ) {
    379         WP_Theme_JSON_Resolver::clean_cached_data();
     379        wp_clean_theme_json_cache();
    380380
    381381        // If should cache core, then fire the method to cache it before running the tests.
     
    430430            ),
    431431        );
    432     }
    433 
    434     /**
    435      * @ticket 52991
    436      */
    437     public function test_switching_themes_recalculates_data() {
    438         // The "default" theme doesn't have theme.json support.
    439         switch_theme( 'default' );
    440         $default = WP_Theme_JSON_Resolver::theme_has_support();
    441 
    442         // Switch to a theme that does have support.
    443         switch_theme( 'block-theme' );
    444         $has_theme_json_support = WP_Theme_JSON_Resolver::theme_has_support();
    445 
    446         $this->assertFalse( $default );
    447         $this->assertTrue( $has_theme_json_support );
    448432    }
    449433
     
    483467        remove_theme_support( 'appearance-tools' );
    484468
    485         $this->assertFalse( WP_Theme_JSON_Resolver::theme_has_support() );
     469        $this->assertFalse( wp_theme_has_theme_json() );
    486470        $this->assertTrue( $settings['typography']['lineHeight'] );
    487471        $this->assertSame( $color_palette, $settings['color']['palette']['theme'] );
     
    644628        for ( $i = 0; $i < 3; $i++ ) {
    645629            WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    646             WP_Theme_JSON_Resolver::clean_cached_data();
     630            wp_clean_theme_json_cache();
    647631        }
    648632        $this->assertSame( 0, $global_styles_query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
     
    657641        for ( $i = 0; $i < 3; $i++ ) {
    658642            $new_user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    659             WP_Theme_JSON_Resolver::clean_cached_data();
     643            wp_clean_theme_json_cache();
    660644            $this->assertSameSets( $user_cpt, $new_user_cpt, "User CPTs do not match on run {$i}." );
    661645        }
     
    674658        for ( $i = 0; $i < 3; $i++ ) {
    675659            WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    676             WP_Theme_JSON_Resolver::clean_cached_data();
     660            wp_clean_theme_json_cache();
    677661        }
    678662        $query_count = get_num_queries() - $query_count;
  • trunk/tests/phpunit/tests/webfonts/wpThemeJsonWebfontsHandler.php

    r53319 r55086  
    130130        switch_theme( $theme_name );
    131131        do_action( 'after_setup_theme' );
    132         WP_Theme_JSON_Resolver::clean_cached_data();
     132        wp_clean_theme_json_cache();
    133133        do_action( 'wp_loaded' );
    134134        do_action( 'wp_enqueue_scripts' );
Note: See TracChangeset for help on using the changeset viewer.