From 52e1c3eff06766ab4bd1530f576e21daef0311b3 Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Thu, 30 Mar 2017 16:55:32 +0000 Subject: [PATCH] Invalidate term query caches when setting or deleting term relationships. Prior to 4.7, term relationships - as set by `wp_set_object_terms()` or `wp_remove_object_terms()` - did not affect the term query cache. The introduction of the 'object_ids' parameter in 4.7 means that the query cache must be aware of object-term relationships. As such, the 'last_changed' incrementor is now invalidated when term relationships are modified. This bug only reared its head when delaying term counting, because term counting performs its own term query cache invalidation. Merges [40353] to the 4.7 branch. Props mboynes. Fixes #40306. git-svn-id: https://develop.svn.wordpress.org/branches/4.7@40354 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/taxonomy.php | 2 + tests/phpunit/tests/term/getTheTerms.php | 62 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 991ebce504..b602683ff2 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -2312,6 +2312,7 @@ function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) { } wp_cache_delete( $object_id, $taxonomy . '_relationships' ); + wp_cache_delete( 'last_changed', 'terms' ); /** * Fires after an object's terms have been set. @@ -2406,6 +2407,7 @@ function wp_remove_object_terms( $object_id, $terms, $taxonomy ) { $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) ); wp_cache_delete( $object_id, $taxonomy . '_relationships' ); + wp_cache_delete( 'last_changed', 'terms' ); /** * Fires immediately after an object-term relationship is deleted. diff --git a/tests/phpunit/tests/term/getTheTerms.php b/tests/phpunit/tests/term/getTheTerms.php index 6a3d4ba5c1..1bffcb6a63 100644 --- a/tests/phpunit/tests/term/getTheTerms.php +++ b/tests/phpunit/tests/term/getTheTerms.php @@ -191,4 +191,66 @@ class Tests_Term_GetTheTerms extends WP_UnitTestCase { $this->assertSame( $num_queries, $wpdb->num_queries ); } + + /** + * @ticket 40306 + */ + public function test_term_cache_should_be_invalidated_on_set_object_terms() { + register_taxonomy( 'wptests_tax', 'post' ); + + // Temporarily disable term counting, which performs its own cache invalidation. + wp_defer_term_counting( true ); + + // Create Test Category. + $term_id = self::factory()->term->create( array( + 'taxonomy' => 'wptests_tax', + ) ); + + $post_id = self::factory()->post->create(); + + // Prime cache. + get_the_terms( $post_id, 'wptests_tax' ); + + wp_set_object_terms( $post_id, $term_id, 'wptests_tax' ); + + $terms = get_the_terms( $post_id, 'wptests_tax' ); + + // Re-activate term counting so this doesn't affect other tests. + wp_defer_term_counting( false ); + + $this->assertTrue( is_array( $terms ) ); + $this->assertSame( array( $term_id ), wp_list_pluck( $terms, 'term_id' ) ); + } + + /** + * @ticket 40306 + */ + public function test_term_cache_should_be_invalidated_on_remove_object_terms() { + register_taxonomy( 'wptests_tax', 'post' ); + + // Create Test Category. + $term_ids = self::factory()->term->create_many( 2, array( + 'taxonomy' => 'wptests_tax', + ) ); + + $post_id = self::factory()->post->create(); + + wp_set_object_terms( $post_id, $term_ids, 'wptests_tax' ); + + // Prime cache. + get_the_terms( $post_id, 'wptests_tax' ); + + // Temporarily disable term counting, which performs its own cache invalidation. + wp_defer_term_counting( true ); + + wp_remove_object_terms( $post_id, $term_ids[0], 'wptests_tax' ); + + $terms = get_the_terms( $post_id, 'wptests_tax' ); + + // Re-activate term counting so this doesn't affect other tests. + wp_defer_term_counting( false ); + + $this->assertTrue( is_array( $terms ) ); + $this->assertSame( array( $term_ids[1] ), wp_list_pluck( $terms, 'term_id' ) ); + } }