Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve get_block_templates performance #4097

Closed
wants to merge 16 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Convert the user_templates param into slugs__not_in query param
oandregal committed Apr 18, 2023
commit dc1e44ce9fcc24091a647940e7a26a18412e1c6b
35 changes: 20 additions & 15 deletions src/wp-includes/block-template-utils.php
Original file line number Diff line number Diff line change
@@ -290,30 +290,31 @@ function _get_block_template_file( $template_type, $slug ) {
* Retrieves the template files from the theme.
*
* @since 5.9.0
* @since 6.3.0 Added the `$query` and `$user_templates` parameters.
* @since 6.3.0 Added the `$query` parameter.
* @access private
*
* @param string $template_type 'wp_template' or 'wp_template_part'.
* @param array $query {
* Arguments to retrieve templates. Optional, empty by default.
*
* @type array $slug__in List of slugs to include.
* @type string $area A 'wp_template_part_area' taxonomy value to filter by (for wp_template_part template type only).
* @type string $post_type Post type to get the templates for.
* @type array $slug__in List of slugs to include.
* @type array $slug__not_in List of slugs to skip.
* @type string $area A 'wp_template_part_area' taxonomy value to filter by (for wp_template_part template type only).
* @type string $post_type Post type to get the templates for.
oandregal marked this conversation as resolved.
Show resolved Hide resolved
* }
* @param array $user_templates Array of user templates that match the search. Optional, empty by default.
*
* @return array Template
*/
function _get_block_templates_files( $template_type, $query = array(), $user_templates = array() ) {
function _get_block_templates_files( $template_type, $query = array() ) {
if ( 'wp_template' !== $template_type && 'wp_template_part' !== $template_type ) {
return null;
}

// Prepare metadata from $query.
$slugs = isset( $query['slug__in'] ) ? $query['slug__in'] : array();
$area = isset( $query['area'] ) ? $query['area'] : null;
$post_type = isset( $query['post_type'] ) ? $query['post_type'] : '';
$slugs_to_include = isset( $query['slug__in'] ) ? $query['slug__in'] : array();
$slugs_to_skip = isset( $query['slug__not_in'] ) ? $query['slug__not_in'] : array();
$area = isset( $query['area'] ) ? $query['area'] : null;
$post_type = isset( $query['post_type'] ) ? $query['post_type'] : '';

$stylesheet = get_stylesheet();
$template = get_template();
@@ -338,13 +339,13 @@ function _get_block_templates_files( $template_type, $query = array(), $user_tem
-5
);

// Skip this item if its slug doesn't match any of the list provided by the consumer.
if ( ! empty( $slugs ) && ( false === array_search( $template_slug, $slugs, true ) ) ) {
// Skip this item if its slug doesn't match any of the slugs to include.
if ( ! empty( $slugs_to_include ) && ( false === array_search( $template_slug, $slugs_to_include, true ) ) ) {
oandregal marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

// Skip this item if there's already an user-provided item with the same slug.
if ( false !== array_search( $stylesheet . '//' . $template_slug, $user_templates, true ) ) {
// Skip this item if its slug matches any of the slugs to skip.
if ( ! empty( $slugs_to_skip ) && ( false !== array_search( $template_slug, $slugs_to_skip, true ) ) ) {
oandregal marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

@@ -1017,8 +1018,12 @@ function get_block_templates( $query = array(), $template_type = 'wp_template' )
}
oandregal marked this conversation as resolved.
Show resolved Hide resolved

if ( ! isset( $query['wp_id'] ) ) {
$user_templates = wp_list_pluck( $query_result, 'id' );
$template_files = _get_block_templates_files( $template_type, $query, $user_templates );
/*
* If the query has found some use templates, those have priority
* over the theme-provided ones, so we skip querying and building them.
*/
$query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' );
$template_files = _get_block_templates_files( $template_type, $query );
foreach ( $template_files as $template_file ) {
$query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
Copy link
Member Author

@oandregal oandregal Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the key change of this PR: instead of building the template object for all items and filter them after, we filter before this step, so we have to build less items. We can do this because all the data used to filter the items is already available in the step before.

Copy link
Member Author

@oandregal oandregal Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The impact of this change can be seen in the XDebug profiler by looking at the number of times the _build_block_template_result_from_file function is called:

Before (22 times) After (5 times)
image image

}