Make WordPress Core

Changeset 54800 for branches/6.1


Ignore:
Timestamp:
11/10/2022 10:40:59 PM (4 years ago)
Author:
flixos90
Message:

Editor: Avoid running certain logic around theme.json parsing unnecessarily for classic themes.

Here's what it does:

  • Do not load and parse theme-i18n.json schema if the theme does not have a theme.json file.
  • Fix the variable caching layer around the theme's theme.json parsing so that a parent's theme theme.json is cached as well.
  • Do not run a WP_Query for global styles for a user when the theme does not have a theme.json.

In a basic WordPress setup, this changeset improves wp_head execution time for classic themes by 10%, and overall response time for both block themes and classic themes by 4%. This may seem like a small win, but 4% reduced overall response time is actually quite a bit for one change, and it is worth mentioning that this is just one of several other little performance tweaks which are being worked on to improve performance of theme.json parsing further.

Props flixos90, manuilov, oandregal, peterwilsoncc, spacedmonkey.
Merges [54799] to the 6.1 branch.
Fixes #56945.

Location:
branches/6.1
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/6.1

  • branches/6.1/src/wp-includes/class-wp-theme-json-resolver.php

    r54779 r54800  
    247247
    248248                if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
    249                         $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
    250                         $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
     249                        $theme_json_file = static::get_file_path_from_theme( 'theme.json' );
     250                        if ( '' !== $theme_json_file ) {
     251                                $theme_json_data = static::read_json_file( $theme_json_file );
     252                                $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
     253                        } else {
     254                                $theme_json_data = array();
     255                        }
    251256
    252257                        /**
     
    260265                        $theme_json_data = $theme_json->get_data();
    261266                        static::$theme   = new WP_Theme_JSON( $theme_json_data );
    262                 }
    263 
    264                 if ( wp_get_theme()->parent() ) {
    265                         // Get parent theme.json.
    266                         $parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) );
    267                         $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
    268                         $parent_theme           = new WP_Theme_JSON( $parent_theme_json_data );
    269 
    270                         /*
    271                          * Merge the child theme.json into the parent theme.json.
    272                          * The child theme takes precedence over the parent.
    273                          */
    274                         $parent_theme->merge( static::$theme );
    275                         static::$theme = $parent_theme;
     267
     268                        if ( wp_get_theme()->parent() ) {
     269                                // Get parent theme.json.
     270                                $parent_theme_json_file = static::get_file_path_from_theme( 'theme.json', true );
     271                                if ( '' !== $parent_theme_json_file ) {
     272                                        $parent_theme_json_data = static::read_json_file( $parent_theme_json_file );
     273                                        $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
     274                                        $parent_theme           = new WP_Theme_JSON( $parent_theme_json_data );
     275
     276                                        /*
     277                                         * Merge the child theme.json into the parent theme.json.
     278                                         * The child theme takes precedence over the parent.
     279                                         */
     280                                        $parent_theme->merge( static::$theme );
     281                                        static::$theme = $parent_theme;
     282                                }
     283                        }
    276284                }
    277285
     
    404412                        $theme = wp_get_theme();
    405413                }
     414
     415                /*
     416                 * Bail early if the theme does not support a theme.json.
     417                 *
     418                 * Since WP_Theme_JSON_Resolver::theme_has_support() only supports the active
     419                 * theme, the extra condition for whether $theme is the active theme is
     420                 * present here.
     421                 */
     422                if ( $theme->get_stylesheet() === get_stylesheet() && ! static::theme_has_support() ) {
     423                        return array();
     424                }
     425
    406426                $user_cpt         = array();
    407427                $post_type_filter = 'wp_global_styles';
     
    583603                if ( ! isset( static::$theme_has_support ) ) {
    584604                        static::$theme_has_support = (
    585                                 is_readable( static::get_file_path_from_theme( 'theme.json' ) ) ||
    586                                 is_readable( static::get_file_path_from_theme( 'theme.json', true ) )
     605                                static::get_file_path_from_theme( 'theme.json' ) !== '' ||
     606                                static::get_file_path_from_theme( 'theme.json', true ) !== ''
    587607                        );
    588608                }
  • branches/6.1/src/wp-includes/class-wp-theme-json.php

    r54778 r54800  
    29402940                $spacing_scale = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'spacingScale' ), array() );
    29412941
    2942                 if ( ! is_numeric( $spacing_scale['steps'] )
     2942                if ( ! isset( $spacing_scale['steps'] )
     2943                        || ! is_numeric( $spacing_scale['steps'] )
    29432944                        || ! isset( $spacing_scale['mediumStep'] )
    29442945                        || ! isset( $spacing_scale['unit'] )
  • branches/6.1/tests/phpunit/tests/theme/wpThemeJsonResolver.php

    r54707 r54800  
    3535
    3636        /**
    37          * Queries.
    38          *
    39          * @var array
    40          */
    41         private $queries = array();
    42 
    43         /**
    4437         * WP_Theme_JSON_Resolver::$blocks_cache property.
    4538         *
     
    10699                add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) );
    107100                add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) );
    108                 $this->queries = array();
     101
    109102                // Clear caches.
    110103                wp_clean_themes_cache();
     
    128121        public function filter_set_locale_to_polish() {
    129122                return 'pl_PL';
    130         }
    131 
    132         function filter_db_query( $query ) {
    133                 if ( preg_match( '#post_type = \'wp_global_styles\'#', $query ) ) {
    134                         $this->queries[] = $query;
    135                 }
    136                 return $query;
    137123        }
    138124
     
    635621         */
    636622        function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries() {
     623                // Switch to a theme that does have support.
     624                switch_theme( 'block-theme' );
    637625                wp_set_current_user( self::$administrator_id );
    638626                $theme = wp_get_theme();
    639627                WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    640                 add_filter( 'query', array( $this, 'filter_db_query' ) );
    641                 $query_count = count( $this->queries );
     628                $global_styles_query_count = 0;
     629                add_filter(
     630                        'query',
     631                        function( $query ) use ( &$global_styles_query_count ) {
     632                                if ( preg_match( '#post_type = \'wp_global_styles\'#', $query ) ) {
     633                                        $global_styles_query_count++;
     634                                }
     635                                return $query;
     636                        }
     637                );
    642638                for ( $i = 0; $i < 3; $i++ ) {
    643639                        WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    644640                        WP_Theme_JSON_Resolver::clean_cached_data();
    645641                }
    646                 $query_count = count( $this->queries ) - $query_count;
    647                 $this->assertSame( 0, $query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
     642                $this->assertSame( 0, $global_styles_query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
    648643
    649644                $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
     
    653648                $this->assertNotEmpty( $user_cpt, 'User CPT is expected not to be empty.' );
    654649
    655                 $query_count = count( $this->queries );
     650                $global_styles_query_count = 0;
    656651                for ( $i = 0; $i < 3; $i ++ ) {
    657652                        $new_user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
     
    659654                        $this->assertSameSets( $user_cpt, $new_user_cpt, "User CPTs do not match on run {$i}." );
    660655                }
    661                 $query_count = count( $this->queries ) - $query_count;
    662                 $this->assertSame( 1, $query_count, 'Unexpected SQL queries detected for the wp_global_style post type after creation.' );
     656                $this->assertSame( 1, $global_styles_query_count, 'Unexpected SQL queries detected for the wp_global_style post type after creation.' );
    663657        }
    664658
     
    667661         */
    668662        function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries_for_logged_out_users() {
     663                // Switch to a theme that does have support.
     664                switch_theme( 'block-theme' );
    669665                $theme = wp_get_theme();
    670666                WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    671                 add_filter( 'query', array( $this, 'filter_db_query' ) );
    672                 $query_count = count( $this->queries );
     667                $query_count = get_num_queries();
    673668                for ( $i = 0; $i < 3; $i++ ) {
    674669                        WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
    675670                        WP_Theme_JSON_Resolver::clean_cached_data();
    676671                }
    677                 $query_count = count( $this->queries ) - $query_count;
     672                $query_count = get_num_queries() - $query_count;
    678673                $this->assertSame( 0, $query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
    679674
     
    683678
    684679        /**
     680         * @ticket 56945
     681         * @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
     682         */
     683        function test_get_user_data_from_wp_global_styles_does_not_run_for_theme_without_support() {
     684                // The 'default' theme does not support theme.json.
     685                switch_theme( 'default' );
     686                wp_set_current_user( self::$administrator_id );
     687                $theme = wp_get_theme();
     688
     689                $start_queries = get_num_queries();
     690
     691                // When theme.json is not supported, the method should not run a query and always return an empty result.
     692                $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
     693                $this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
     694                $this->assertSame( 0, get_num_queries() - $start_queries, 'Unexpected SQL query detected for theme without theme.json support.' );
     695
     696                $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
     697                $this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
     698                $this->assertSame( 0, get_num_queries() - $start_queries, 'Unexpected SQL query detected for theme without theme.json support.' );
     699        }
     700
     701        /**
    685702         * @ticket 55392
    686703         * @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
    687704         */
    688705        function test_get_user_data_from_wp_global_styles_does_exist() {
     706                // Switch to a theme that does have support.
     707                switch_theme( 'block-theme' );
    689708                $theme = wp_get_theme();
    690709                $post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
     
    702721         */
    703722        function test_get_user_data_from_wp_global_styles_create_post() {
     723                // Switch to a theme that does have support.
     724                switch_theme( 'block-theme' );
    704725                $theme = wp_get_theme( 'testing' );
    705726                $post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
     
    719740         */
    720741        function test_get_user_data_from_wp_global_styles_filter_state() {
     742                // Switch to a theme that does have support.
     743                switch_theme( 'block-theme' );
    721744                $theme = wp_get_theme( 'foo' );
    722745                $post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true, array( 'publish' ) );
     
    750773                $this->assertTrue( $line_height, 'lineHeight setting after add_theme_support() should be true.' );
    751774        }
     775
     776        /**
     777         * @ticket 56945
     778         * @covers WP_Theme_JSON_Resolver::get_theme_data
     779         */
     780        function test_get_theme_data_does_not_parse_theme_json_if_not_present() {
     781                // The 'default' theme does not support theme.json.
     782                switch_theme( 'default' );
     783
     784                $theme_json_resolver = new WP_Theme_JSON_Resolver();
     785
     786                // Force-unset $i18n_schema property to "unload" translation schema.
     787                $property = new ReflectionProperty( $theme_json_resolver, 'i18n_schema' );
     788                $property->setAccessible( true );
     789                $property->setValue( null );
     790
     791                // A completely empty theme.json data set still has the 'version' key when parsed.
     792                $empty_theme_json = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
     793
     794                // Call using 'with_supports' set to false, so that the method only considers theme.json.
     795                $theme_data = $theme_json_resolver->get_theme_data( array(), array( 'with_supports' => false ) );
     796                $this->assertInstanceOf( 'WP_Theme_JSON', $theme_data, 'Theme data should be an instance of WP_Theme_JSON.' );
     797                $this->assertSame( $empty_theme_json, $theme_data->get_raw_data(), 'Theme data should be empty without theme support.' );
     798                $this->assertNull( $property->getValue(), 'Theme i18n schema should not have been loaded without theme support.' );
     799        }
    752800}
Note: See TracChangeset for help on using the changeset viewer.