Skip to content

Commit

Permalink
Add caching to WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_c…
Browse files Browse the repository at this point in the history
…ustom_post_type() (#36584)

* Add caching to WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type

Refactor
`WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type`
to add caching to the `wp_global_styles` post type lookup, and also to
remove the duplicate code added in
`gutenberg_add_active_global_styles_link`.

Fixes #36574

* Add unit tests

* Use the correct query filter

* Use wp_cache_set instead of wp_cache_add.

* Remove the filter when finished.

* Simplify the if blocks
  • Loading branch information
xknown authored and noahtallen committed Nov 24, 2021
1 parent 660f35a commit 408481d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 37 deletions.
60 changes: 39 additions & 21 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,33 +170,49 @@ public static function get_theme_data() {
*
* It can also create and return a new draft CPT.
*
* @param bool $should_create_cpt Whether a new CPT should be created if no one was found.
* False by default.
* @param array $post_status_filter Filter CPT by post status.
* ['publish'] by default, so it only fetches published posts.
* @param WP_Theme $theme The theme object.
* If empty, it defaults to the current theme.
* @param bool $should_create_cpt Whether a new CPT should be created if no one was found.
* False by default.
* @param array $post_status_filter Filter CPT by post status.
* ['publish'] by default, so it only fetches published posts.
*
* @return array Custom Post Type for the user's origin config.
*/
private static function get_user_data_from_custom_post_type( $should_create_cpt = false, $post_status_filter = array( 'publish' ) ) {
public static function get_user_data_from_custom_post_type( $theme, $should_create_cpt = false, $post_status_filter = array( 'publish' ) ) {
if ( ! $theme instanceof WP_Theme ) {
$theme = wp_get_theme();
}
$user_cpt = array();
$post_type_filter = 'wp_global_styles';
$recent_posts = wp_get_recent_posts(
array(
'numberposts' => 1,
'orderby' => 'date',
'order' => 'desc',
'post_type' => $post_type_filter,
'post_status' => $post_status_filter,
'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
'field' => 'name',
'terms' => wp_get_theme()->get_stylesheet(),
),
$args = array(
'numberposts' => 1,
'orderby' => 'date',
'order' => 'desc',
'post_type' => $post_type_filter,
'post_status' => $post_status_filter,
'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
'field' => 'name',
'terms' => $theme->get_stylesheet(),
),
)
),
);

$cache_key = sprintf( 'wp_global_styles_%s', md5( serialize( $args ) ) );
$post_id = wp_cache_get( $cache_key );

if ( (int) $post_id > 0 ) {
return get_post( $post_id, ARRAY_A );
}

// Special case: '-1' is a results not found.
if ( -1 === $post_id && ! $should_create_cpt ) {
return $user_cpt;
}

$recent_posts = wp_get_recent_posts( $args );
if ( is_array( $recent_posts ) && ( count( $recent_posts ) === 1 ) ) {
$user_cpt = $recent_posts[0];
} elseif ( $should_create_cpt ) {
Expand All @@ -215,6 +231,8 @@ private static function get_user_data_from_custom_post_type( $should_create_cpt
);
$user_cpt = get_post( $cpt_post_id, ARRAY_A );
}
$cache_expiration = $user_cpt ? DAY_IN_SECONDS : HOUR_IN_SECONDS;
wp_cache_set( $cache_key, $user_cpt ? $user_cpt['ID'] : -1, '', $cache_expiration );

return $user_cpt;
}
Expand All @@ -230,7 +248,7 @@ public static function get_user_data() {
}

$config = array();
$user_cpt = self::get_user_data_from_custom_post_type();
$user_cpt = self::get_user_data_from_custom_post_type( wp_get_theme() );
if ( array_key_exists( 'post_content', $user_cpt ) ) {
$decoded_data = json_decode( $user_cpt['post_content'], true );

Expand Down Expand Up @@ -331,7 +349,7 @@ public static function get_user_custom_post_type_id() {
return self::$user_custom_post_type_id;
}

$user_cpt = self::get_user_data_from_custom_post_type( true );
$user_cpt = self::get_user_data_from_custom_post_type( wp_get_theme(), true );
if ( array_key_exists( 'ID', $user_cpt ) ) {
self::$user_custom_post_type_id = $user_cpt['ID'];
}
Expand Down
18 changes: 2 additions & 16 deletions lib/compat/wordpress-5.9/rest-active-global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,8 @@ function gutenberg_add_active_global_styles_link( $response, $theme ) {
// This creates a record for the current theme if not existent.
$id = WP_Theme_JSON_Resolver_Gutenberg::get_user_custom_post_type_id();
} else {
$wp_query_args = array(
'post_status' => 'publish',
'post_type' => 'wp_global_styles',
'posts_per_page' => 1,
'no_found_rows' => true,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
'field' => 'name',
'terms' => $theme->get_stylesheet(),
),
),
);
$global_styles_query = new WP_Query( $wp_query_args );
$id = ! empty( $global_styles_query->posts ) ? array_shift( $global_styles_query->posts ) : null;
$user_cpt = WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type( $theme );
$id = isset( $user_cpt['ID'] ) ? $user_cpt['ID'] : null;
}

if ( $id ) {
Expand Down
34 changes: 34 additions & 0 deletions phpunit/class-wp-theme-json-resolver-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function setUp() {
add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) );
add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) );
add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) );
$this->queries = array();
// Clear caches.
wp_clean_themes_cache();
unset( $GLOBALS['wp_themes'] );
Expand All @@ -40,6 +41,13 @@ function filter_set_locale_to_polish() {
return 'pl_PL';
}

function filter_db_query( $query ) {
if ( preg_match( '#post_type = \'wp_global_styles\'#', $query ) ) {
$this->queries[] = $query;
}
return $query;
}

function test_translations_are_applied() {
add_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) );
load_textdomain( 'block-theme', realpath( __DIR__ . '/data/languages/themes/block-theme-pl_PL.mo' ) );
Expand Down Expand Up @@ -259,4 +267,30 @@ function test_merges_child_theme_json_into_parent_theme_json() {
)
);
}

function test_get_user_data_from_custom_post_type_does_not_use_uncached_queries() {
add_filter( 'query', array( $this, 'filter_db_query' ) );
$query_count = count( $this->queries );
for ( $i = 0; $i < 3; $i++ ) {
WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type( wp_get_theme() );
WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data();
}
$query_count = count( $this->queries ) - $query_count;
$this->assertEquals( 1, $query_count, 'Only one SQL query should be peformed for multiple invocations of WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type()' );

$user_cpt = WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type( wp_get_theme() );
$this->assertEmpty( $user_cpt );

$user_cpt = WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type( wp_get_theme(), true );
$this->assertNotEmpty( $user_cpt );

$query_count = count( $this->queries );
for ( $i = 0; $i < 3; $i++ ) {
WP_Theme_JSON_Resolver_Gutenberg::get_user_data_from_custom_post_type( wp_get_theme() );
WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data();
}
$query_count = count( $this->queries ) - $query_count;
$this->assertEquals( 0, $query_count, 'Unexpected SQL queries detected for the wp_global_style post type' );
remove_filter( 'query', array( $this, 'filter_db_query' ) );
}
}

0 comments on commit 408481d

Please sign in to comment.