From 2c6bf77a9e7532c6ac3a03502b44d108cae86179 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Fri, 21 Apr 2023 09:22:04 +0000 Subject: [PATCH] Taxonomy: Always lazily load term meta. In [34529] introduced lazy loading of term meta. However, this was only in the context of `WP_Query`. Other parts of the codebase, like `WP_Term_Query` did not lazily load term meta. In this change, calls to `update_termmeta_cache` are now replaced with `wp_lazyload_term_meta`, that instead of priming term meta caches, just adds them to the queue to be primed it ever called. This results in far less database queries, as there a number of places where term meta is being primed unnecessarily and never used. Adding everything to the term meta queue, also means that if term meta is used, that is all loaded in a single database / cache call. Props spacedmonkey, mukesh27, peterwilsoncc. Fixes #57645. git-svn-id: https://develop.svn.wordpress.org/trunk@55671 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-term-query.php | 2 +- src/wp-includes/post.php | 5 +-- src/wp-includes/taxonomy.php | 23 +++++++++-- tests/phpunit/includes/abstract-testcase.php | 13 ++++-- tests/phpunit/tests/post/nav-menu.php | 9 +++-- .../phpunit/tests/query/lazyLoadTermMeta.php | 1 + tests/phpunit/tests/term/getTerms.php | 4 +- tests/phpunit/tests/term/meta.php | 5 +-- tests/phpunit/tests/term/query.php | 40 +++++++++++++++++++ tests/phpunit/tests/term/wpGetObjectTerms.php | 8 ++-- 10 files changed, 86 insertions(+), 24 deletions(-) diff --git a/src/wp-includes/class-wp-term-query.php b/src/wp-includes/class-wp-term-query.php index 0a74f57b9f..d1cc69d96c 100644 --- a/src/wp-includes/class-wp-term-query.php +++ b/src/wp-includes/class-wp-term-query.php @@ -865,7 +865,7 @@ class WP_Term_Query { // Prime termmeta cache. if ( $args['update_term_meta_cache'] ) { $term_ids = wp_list_pluck( $term_objects, 'term_id' ); - update_termmeta_cache( $term_ids ); + wp_lazyload_term_meta( $term_ids ); } if ( 'all_with_object_id' === $_fields && ! empty( $args['object_ids'] ) ) { diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 7dc67105e1..3c1af397a3 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -7692,10 +7692,7 @@ function wp_queue_posts_for_term_meta_lazyload( $posts ) { } } - if ( $term_ids ) { - $lazyloader = wp_metadata_lazyloader(); - $lazyloader->queue_objects( 'term', $term_ids ); - } + wp_lazyload_term_meta( $term_ids ); } /** diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index e32afbd2c4..925bcb41ee 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -1426,6 +1426,22 @@ function update_termmeta_cache( $term_ids ) { return update_meta_cache( 'term', $term_ids ); } + +/** + * Queue term meta for lazy-loading. + * + * @since 6.3.0 + * + * @param array $term_ids List of term IDs. + */ +function wp_lazyload_term_meta( array $term_ids ) { + if ( empty( $term_ids ) ) { + return; + } + $lazyloader = wp_metadata_lazyloader(); + $lazyloader->queue_objects( 'term', $term_ids ); +} + /** * Gets all meta data, including meta IDs, for the given term ID. * @@ -4003,6 +4019,7 @@ function _pad_term_counts( &$terms, $taxonomy ) { * * @since 4.6.0 * @since 6.1.0 This function is no longer marked as "private". + * @since 6.3.0 Use wp_lazyload_term_meta() for lazy-loading of term meta. * * @global wpdb $wpdb WordPress database abstraction object. * @@ -4017,10 +4034,10 @@ function _prime_term_caches( $term_ids, $update_meta_cache = true ) { $fresh_terms = $wpdb->get_results( sprintf( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id IN (%s)", implode( ',', array_map( 'intval', $non_cached_ids ) ) ) ); update_term_cache( $fresh_terms ); + } - if ( $update_meta_cache ) { - update_termmeta_cache( $non_cached_ids ); - } + if ( $update_meta_cache ) { + wp_lazyload_term_meta( $term_ids ); } } diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php index 6db307f256..dd8caa33e2 100644 --- a/tests/phpunit/includes/abstract-testcase.php +++ b/tests/phpunit/includes/abstract-testcase.php @@ -195,9 +195,7 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase { $this->_restore_hooks(); wp_set_current_user( 0 ); - $lazyloader = wp_metadata_lazyloader(); - $lazyloader->reset_queue( 'term' ); - $lazyloader->reset_queue( 'comment' ); + $this->reset_lazyload_queue(); } /** @@ -276,6 +274,15 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase { } + /** + * Reset the lazy load meta queue. + */ + protected function reset_lazyload_queue() { + $lazyloader = wp_metadata_lazyloader(); + $lazyloader->reset_queue( 'term' ); + $lazyloader->reset_queue( 'comment' ); + } + /** * Unregisters existing post types and register defaults. * diff --git a/tests/phpunit/tests/post/nav-menu.php b/tests/phpunit/tests/post/nav-menu.php index 918b76e8e1..5a0efcbde1 100644 --- a/tests/phpunit/tests/post/nav-menu.php +++ b/tests/phpunit/tests/post/nav-menu.php @@ -304,6 +304,7 @@ class Tests_Post_Nav_Menu extends WP_UnitTestCase { add_filter( 'update_term_metadata_cache', array( $action, 'filter' ), 10, 2 ); update_menu_item_cache( $query_result ); + get_term_meta( $term_id ); $args = $action->get_args(); $last = end( $args ); @@ -383,12 +384,14 @@ class Tests_Post_Nav_Menu extends WP_UnitTestCase { $start_num_queries = get_num_queries(); wp_get_nav_menu_items( $this->menu_id ); + get_term_meta( $term_ids[0] ); $queries_made = get_num_queries() - $start_num_queries; $this->assertSame( 6, $queries_made, 'Only does 6 database queries when running wp_get_nav_menu_items.' ); - $args = $action_terms->get_args(); - $last = end( $args ); - $this->assertSameSets( $term_ids, $last[1], '_prime_term_caches() was not executed.' ); + $args = $action_terms->get_args(); + $first = reset( $args ); + $term_ids[] = $this->menu_id; + $this->assertSameSets( $term_ids, $first[1], '_prime_term_caches() was not executed.' ); $args = $action_posts->get_args(); $this->assertSameSets( $menu_nav_ids, $args[0][1], '_prime_post_caches() was not executed.' ); diff --git a/tests/phpunit/tests/query/lazyLoadTermMeta.php b/tests/phpunit/tests/query/lazyLoadTermMeta.php index 85ef586dc6..fc34f84bb3 100644 --- a/tests/phpunit/tests/query/lazyLoadTermMeta.php +++ b/tests/phpunit/tests/query/lazyLoadTermMeta.php @@ -45,6 +45,7 @@ class Test_Lazy_Load_Term_Meta extends WP_UnitTestCase { * @covers ::wp_queue_posts_for_term_meta_lazyload */ public function test_wp_queue_posts_for_term_meta_lazyload() { + $this->reset_lazyload_queue(); $filter = new MockAction(); add_filter( 'update_term_metadata_cache', array( $filter, 'filter' ), 10, 2 ); new WP_Query( diff --git a/tests/phpunit/tests/term/getTerms.php b/tests/phpunit/tests/term/getTerms.php index 5c0d67f72e..168bcc81c0 100644 --- a/tests/phpunit/tests/term/getTerms.php +++ b/tests/phpunit/tests/term/getTerms.php @@ -2756,7 +2756,7 @@ class Tests_Term_getTerms extends WP_UnitTestCase { /** * @ticket 10142 */ - public function test_termmeta_cache_should_be_primed_by_default() { + public function test_termmeta_cache_should_be_lazy_loaded_by_default() { global $wpdb; register_taxonomy( 'wptests_tax', 'post' ); @@ -2779,7 +2779,7 @@ class Tests_Term_getTerms extends WP_UnitTestCase { $this->assertSame( 'bar', get_term_meta( $t, 'foo', true ) ); } - $this->assertSame( $num_queries, $wpdb->num_queries ); + $this->assertSame( $num_queries + 1, $wpdb->num_queries ); } /** diff --git a/tests/phpunit/tests/term/meta.php b/tests/phpunit/tests/term/meta.php index 976889fd8b..53b883f913 100644 --- a/tests/phpunit/tests/term/meta.php +++ b/tests/phpunit/tests/term/meta.php @@ -116,9 +116,6 @@ class Tests_Term_Meta extends WP_UnitTestCase { public function test_term_meta_should_be_lazy_loaded_for_all_terms_in_wp_query_loop() { global $wpdb; - // Clear any previous term IDs from the queue. - wp_metadata_lazyloader()->reset_queue( 'term' ); - $p = self::factory()->post->create( array( 'post_status' => 'publish' ) ); register_taxonomy( 'wptests_tax', 'post' ); @@ -199,7 +196,7 @@ class Tests_Term_Meta extends WP_UnitTestCase { foreach ( $terms as $t ) { add_term_meta( $t, 'foo', 'bar' ); } - + $this->reset_lazyload_queue(); $q = new WP_Query( array( 'cache_results' => true, diff --git a/tests/phpunit/tests/term/query.php b/tests/phpunit/tests/term/query.php index b15b4787fc..4100ab192e 100644 --- a/tests/phpunit/tests/term/query.php +++ b/tests/phpunit/tests/term/query.php @@ -46,6 +46,46 @@ class Tests_Term_Query extends WP_UnitTestCase { $this->assertSameSets( array( $term_2 ), $q->terms ); } + /** + * @ticket 57645 + */ + public function test_lazy_load_term_meta() { + $filter = new MockAction(); + add_filter( 'update_term_metadata_cache', array( $filter, 'filter' ), 10, 2 ); + register_taxonomy( 'wptests_tax_1', 'post' ); + register_taxonomy( 'wptests_tax_2', 'post' ); + + $term_1 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax_1' ) ); + $term_2 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax_2' ) ); + + $q = new WP_Term_Query( + array( + 'taxonomy' => 'wptests_tax_1', + 'fields' => 'ids', + 'hide_empty' => false, + ) + ); + + $this->assertSameSets( array( $term_1 ), $q->terms ); + + $q = new WP_Term_Query( + array( + 'taxonomy' => 'wptests_tax_2', + 'fields' => 'ids', + 'hide_empty' => false, + ) + ); + + $this->assertSameSets( array( $term_2 ), $q->terms ); + + get_term_meta( $term_1 ); + + $args = $filter->get_args(); + $first = reset( $args ); + $term_ids = end( $first ); + $this->assertSameSets( $term_ids, array( $term_1, $term_2 ) ); + } + public function test_taxonomy_should_accept_taxonomy_array() { register_taxonomy( 'wptests_tax_1', 'post' ); register_taxonomy( 'wptests_tax_2', 'post' ); diff --git a/tests/phpunit/tests/term/wpGetObjectTerms.php b/tests/phpunit/tests/term/wpGetObjectTerms.php index f246fccf71..d23102af4c 100644 --- a/tests/phpunit/tests/term/wpGetObjectTerms.php +++ b/tests/phpunit/tests/term/wpGetObjectTerms.php @@ -615,7 +615,7 @@ class Tests_Term_WpGetObjectTerms extends WP_UnitTestCase { /** * @ticket 10142 */ - public function test_termmeta_cache_should_be_primed_by_default() { + public function test_termmeta_cache_should_be_lazy_loaded_by_default() { global $wpdb; register_taxonomy( 'wptests_tax', 'post' ); @@ -635,7 +635,7 @@ class Tests_Term_WpGetObjectTerms extends WP_UnitTestCase { $this->assertSame( 'bar', get_term_meta( $t, 'foo', true ) ); } - $this->assertSame( $num_queries, $wpdb->num_queries ); + $this->assertSame( $num_queries + 1, $wpdb->num_queries ); } /** @@ -700,7 +700,7 @@ class Tests_Term_WpGetObjectTerms extends WP_UnitTestCase { $this->assertSame( 'bar', get_term_meta( $t, 'foo', true ) ); } - $this->assertSame( $num_queries, $wpdb->num_queries ); + $this->assertSame( $num_queries + 1, $wpdb->num_queries ); } /** @@ -733,7 +733,7 @@ class Tests_Term_WpGetObjectTerms extends WP_UnitTestCase { $this->assertSame( 'bar', get_term_meta( $t, 'foo', true ) ); } - $this->assertSame( $num_queries, $wpdb->num_queries ); + $this->assertSame( $num_queries + 1, $wpdb->num_queries ); } /**