From 410889469f29a39c308619c7437d8a7520575860 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Wed, 18 Jan 2023 11:18:36 +0000 Subject: [PATCH] Posts, Post Types: Use persistent caching in `get_adjacent_post` function. The function `get_adjacent_post` cached the results of database query in the cache group `counts`. This is a none persistent group and meant cache would not persist on the next request. Change cache to save to the `posts` cache group. Cache invalidation is done by using get last changed value of the `posts` and `terms` group as a salt for the cache key. Props spacedmonkey, peterwilsoncc, johnbillion, boonebgorges, mukesh27, dd32. Fixes #41131. git-svn-id: https://develop.svn.wordpress.org/trunk@55085 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/link-template.php | 14 +++- tests/phpunit/tests/link/getAdjacentPost.php | 78 ++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index 6ff622f257493..d4cf7b55cdeaa 100644 --- a/src/wp-includes/link-template.php +++ b/src/wp-includes/link-template.php @@ -1976,9 +1976,15 @@ function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previo */ $sort = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1", $post, $order ); - $query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort"; - $query_key = 'adjacent_post_' . md5( $query ); - $result = wp_cache_get( $query_key, 'counts' ); + $query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort"; + $key = md5( $query ); + $last_changed = wp_cache_get_last_changed( 'posts' ); + if ( $in_same_term || ! empty( $excluded_terms ) ) { + $last_changed .= wp_cache_get_last_changed( 'terms' ); + } + $cache_key = "adjacent_post:$key:$last_changed"; + + $result = wp_cache_get( $cache_key, 'posts' ); if ( false !== $result ) { if ( $result ) { $result = get_post( $result ); @@ -1991,7 +1997,7 @@ function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previo $result = ''; } - wp_cache_set( $query_key, $result, 'counts' ); + wp_cache_set( $cache_key, $result, 'posts' ); if ( $result ) { $result = get_post( $result ); diff --git a/tests/phpunit/tests/link/getAdjacentPost.php b/tests/phpunit/tests/link/getAdjacentPost.php index 505d52a1dccde..d365aa49dd7d9 100644 --- a/tests/phpunit/tests/link/getAdjacentPost.php +++ b/tests/phpunit/tests/link/getAdjacentPost.php @@ -350,4 +350,82 @@ public function filter_excluded_terms( $excluded_terms ) { $excluded_terms[] = $this->exclude_term; return $excluded_terms; } + + /** + * @ticket 41131 + */ + public function test_get_adjacent_post_cache() { + // Need some sample posts to test adjacency. + $post_one = self::factory()->post->create_and_get( + array( + 'post_title' => 'First', + 'post_date' => '2012-01-01 12:00:00', + ) + ); + + $post_two = self::factory()->post->create_and_get( + array( + 'post_title' => 'Second', + 'post_date' => '2012-02-01 12:00:00', + ) + ); + + $post_three = self::factory()->post->create_and_get( + array( + 'post_title' => 'Third', + 'post_date' => '2012-03-01 12:00:00', + ) + ); + + $post_four = self::factory()->post->create_and_get( + array( + 'post_title' => 'Fourth', + 'post_date' => '2012-04-01 12:00:00', + ) + ); + + // Assign some terms. + wp_set_object_terms( $post_one->ID, 'WordPress', 'category', false ); + wp_set_object_terms( $post_three->ID, 'WordPress', 'category', false ); + + wp_set_object_terms( $post_two->ID, 'plugins', 'post_tag', false ); + wp_set_object_terms( $post_four->ID, 'plugins', 'post_tag', false ); + + // Test normal post adjacency. + $this->go_to( get_permalink( $post_two->ID ) ); + + // Test getting the right result. + $first_run = get_adjacent_post( false, '', true ); + $this->assertEquals( $post_one, $first_run, 'Did not get first post when on second post' ); + $this->assertNotEquals( $post_two, $first_run, 'Got second post when on second post' ); + + // Query count to test caching. + $num_queries = get_num_queries(); + $second_run = get_adjacent_post( false, '', true ); + $this->assertNotEquals( $post_two, $second_run, 'Got second post when on second post on second run' ); + $this->assertEquals( $post_one, $second_run, 'Did not get first post when on second post on second run' ); + $this->assertSame( $num_queries, get_num_queries() ); + + // Test creating new post busts cache. + $post_five = self::factory()->post->create_and_get( + array( + 'post_title' => 'Five', + 'post_date' => '2012-04-01 12:00:00', + ) + ); + $num_queries = get_num_queries(); + + $this->assertEquals( $post_one, get_adjacent_post( false, '', true ), 'Did not get first post after new post is added' ); + $this->assertSame( get_num_queries() - $num_queries, 1, 'Number of queries run was not one after new post is added' ); + + $this->assertEquals( $post_four, get_adjacent_post( true, '', false ), 'Did not get forth post after new post is added' ); + $num_queries = get_num_queries(); + $this->assertEquals( $post_four, get_adjacent_post( true, '', false ), 'Did not get forth post after new post is added' ); + $this->assertSame( $num_queries, get_num_queries() ); + wp_set_object_terms( $post_four->ID, 'themes', 'post_tag', false ); + + $num_queries = get_num_queries(); + $this->assertEquals( $post_four, get_adjacent_post( true, '', false ), 'Result of function call is wrong after after adding new term' ); + $this->assertSame( get_num_queries() - $num_queries, 2, 'Number of queries run was not two after adding new term' ); + } }