Make WordPress Core


Ignore:
Timestamp:
04/26/2023 02:38:43 PM (18 months ago)
Author:
oandregal
Message:

Themes: improve performance of get_block_templates().

get_block_templates() is responsible for finding block templates that match a given search. The function receives a query parameter with the relevant metadata (slugs of the templates, areas of the template parts, etc) to find the user templates (database) and theme templates (file directory).

This function can be made more performant by changing how it works. Before this change, it processed all the block templates and discarded the ones that didn't match the query after it occurred. This commit makes it so it discards the templates that don't match the query before processing them. As a result, it only has to process the subset of templates that will be used, instead of all of them.

This change impacts any theme with block templates. TwentyTwentyThree reports a 15% improvement in Time To First Byte.

Props spacedmonkey, jorgefilipecosta, youknowriad, flixos90, mukesh27.
Fixes #57756.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-template-utils.php

    r55606 r55687  
    291291 *
    292292 * @since 5.9.0
     293 * @since 6.3.0 Added the `$query` parameter.
    293294 * @access private
    294295 *
    295296 * @param string $template_type 'wp_template' or 'wp_template_part'.
    296  * @return array Template.
    297  */
    298 function _get_block_templates_files( $template_type ) {
     297 * @param array  $query {
     298 *     Arguments to retrieve templates. Optional, empty by default.
     299 *
     300 *     @type array  $slug__in     List of slugs to include.
     301 *     @type array  $slug__not_in List of slugs to skip.
     302 *     @type string $area         A 'wp_template_part_area' taxonomy value to filter by (for wp_template_part template type only).
     303 *     @type string $post_type    Post type to get the templates for.
     304 * }
     305 *
     306 * @return array Template
     307 */
     308function _get_block_templates_files( $template_type, $query = array() ) {
    299309    if ( 'wp_template' !== $template_type && 'wp_template_part' !== $template_type ) {
    300310        return null;
    301311    }
    302312
    303     $themes         = array(
    304         get_stylesheet() => get_stylesheet_directory(),
    305         get_template()   => get_template_directory(),
    306     );
     313    // Prepare metadata from $query.
     314    $slugs_to_include = isset( $query['slug__in'] ) ? $query['slug__in'] : array();
     315    $slugs_to_skip    = isset( $query['slug__not_in'] ) ? $query['slug__not_in'] : array();
     316    $area             = isset( $query['area'] ) ? $query['area'] : null;
     317    $post_type        = isset( $query['post_type'] ) ? $query['post_type'] : '';
     318
     319    $stylesheet = get_stylesheet();
     320    $template   = get_template();
     321    $themes     = array(
     322        $stylesheet => get_stylesheet_directory(),
     323    );
     324    // Add the parent theme if it's not the same as the current theme.
     325    if ( $stylesheet !== $template ) {
     326        $themes[ $template ] = get_template_directory();
     327    }
    307328    $template_files = array();
    308329    foreach ( $themes as $theme_slug => $theme_dir ) {
     
    318339                -5
    319340            );
     341
     342            // Skip this item if its slug doesn't match any of the slugs to include.
     343            if ( ! empty( $slugs_to_include ) && ! in_array( $template_slug, $slugs_to_include, true ) ) {
     344                continue;
     345            }
     346
     347            // Skip this item if its slug matches any of the slugs to skip.
     348            if ( ! empty( $slugs_to_skip ) && in_array( $template_slug, $slugs_to_skip, true ) ) {
     349                continue;
     350            }
     351
    320352            $new_template_item = array(
    321353                'slug'  => $template_slug,
     
    326358
    327359            if ( 'wp_template_part' === $template_type ) {
    328                 $template_files[] = _add_block_template_part_area_info( $new_template_item );
     360                /*
     361                 * Structure of a wp_template_part item:
     362                 *
     363                 * - slug
     364                 * - path
     365                 * - theme
     366                 * - type
     367                 * - area
     368                 * - title (optional)
     369                 */
     370                $candidate = _add_block_template_part_area_info( $new_template_item );
     371                if ( ! isset( $area ) || ( isset( $area ) && $area === $candidate['area'] ) ) {
     372                    $template_files[] = $candidate;
     373                }
    329374            }
    330375
    331376            if ( 'wp_template' === $template_type ) {
    332                 $template_files[] = _add_block_template_info( $new_template_item );
     377                /*
     378                 * Structure of a wp_template item:
     379                 *
     380                 * - slug
     381                 * - path
     382                 * - theme
     383                 * - type
     384                 * - title (optional)
     385                 * - postTypes (optional)
     386                 */
     387                $candidate = _add_block_template_info( $new_template_item );
     388                if (
     389                    ! $post_type ||
     390                    ( $post_type && isset( $candidate['postTypes'] ) && in_array( $post_type, $candidate['postTypes'], true ) )
     391                ) {
     392                    $template_files[] = $candidate;
     393                }
    333394            }
    334395        }
     
    922983    }
    923984
    924     if ( isset( $query['slug__in'] ) ) {
    925         $wp_query_args['post_name__in'] = $query['slug__in'];
     985    if ( ! empty( $query['slug__in'] ) ) {
     986        $wp_query_args['post_name__in']  = $query['slug__in'];
     987        $wp_query_args['posts_per_page'] = count( array_unique( $query['slug__in'] ) );
    926988    }
    927989
     
    9581020
    9591021    if ( ! isset( $query['wp_id'] ) ) {
    960         $template_files = _get_block_templates_files( $template_type );
     1022        /*
     1023         * If the query has found some use templates, those have priority
     1024         * over the theme-provided ones, so we skip querying and building them.
     1025         */
     1026        $query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' );
     1027        $template_files        = _get_block_templates_files( $template_type, $query );
    9611028        foreach ( $template_files as $template_file ) {
    962             $template = _build_block_template_result_from_file( $template_file, $template_type );
    963 
    964             if ( $post_type && ! $template->is_custom ) {
    965                 continue;
    966             }
    967 
    968             if ( $post_type &&
    969                 isset( $template->post_types ) &&
    970                 ! in_array( $post_type, $template->post_types, true )
    971             ) {
    972                 continue;
    973             }
    974 
    975             $is_not_custom   = false === array_search(
    976                 get_stylesheet() . '//' . $template_file['slug'],
    977                 wp_list_pluck( $query_result, 'id' ),
    978                 true
    979             );
    980             $fits_slug_query =
    981                 ! isset( $query['slug__in'] ) || in_array( $template_file['slug'], $query['slug__in'], true );
    982             $fits_area_query =
    983                 ! isset( $query['area'] ) || $template_file['area'] === $query['area'];
    984             $should_include  = $is_not_custom && $fits_slug_query && $fits_area_query;
    985             if ( $should_include ) {
    986                 $query_result[] = $template;
    987             }
     1029            $query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
    9881030        }
    9891031    }
Note: See TracChangeset for help on using the changeset viewer.