diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 3762802a72..214d18fda8 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -1874,11 +1874,7 @@ class WP_Query { } if ( ! isset( $q['cache_results'] ) ) { - if ( wp_using_ext_object_cache() ) { - $q['cache_results'] = false; - } else { - $q['cache_results'] = true; - } + $q['cache_results'] = true; } if ( ! isset( $q['update_post_term_cache'] ) ) { @@ -3072,6 +3068,77 @@ class WP_Query { */ $this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) ); + /* + * Ensure the ID database query is able to be cached. + * + * Random queries are expected to have unpredictable results and + * cannot be cached. Note the space before `RAND` in the string + * search, that to ensure against a collision with another + * function. + */ + $id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), ' RAND(' ); + if ( $q['cache_results'] && $id_query_is_cacheable ) { + $cache_args = $q; + + unset( + $cache_args['suppress_filters'], + $cache_args['cache_results'], + $cache_args['fields'], + $cache_args['update_post_meta_cache'], + $cache_args['update_post_term_cache'], + $cache_args['lazy_load_term_meta'], + $cache_args['update_menu_item_cache'] + ); + + $new_request = str_replace( $fields, "{$wpdb->posts}.*", $this->request ); + $key = md5( serialize( $cache_args ) . $new_request ); + + $last_changed = wp_cache_get_last_changed( 'posts' ); + if ( ! empty( $this->tax_query->queried_terms ) ) { + $last_changed .= wp_cache_get_last_changed( 'terms' ); + } + + $cache_key = "wp_query:$key:$last_changed"; + + if ( null === $this->posts ) { + $cached_results = wp_cache_get( $cache_key, 'posts' ); + + if ( $cached_results ) { + if ( 'ids' === $q['fields'] ) { + /** @var int[] */ + $this->posts = array_map( 'intval', $cached_results['posts'] ); + } else { + _prime_post_caches( $cached_results['posts'], $q['update_post_term_cache'], $q['update_post_meta_cache'] ); + /** @var WP_Post[] */ + $this->posts = array_map( 'get_post', $cached_results['posts'] ); + } + + $this->post_count = count( $this->posts ); + $this->found_posts = $cached_results['found_posts']; + $this->max_num_pages = $cached_results['max_num_pages']; + + if ( 'ids' === $q['fields'] ) { + return $this->posts; + } elseif ( 'id=>parent' === $q['fields'] ) { + /** @var int[] */ + $post_parents = array(); + + foreach ( $this->posts as $key => $post ) { + $obj = new stdClass(); + $obj->ID = (int) $post->ID; + $obj->post_parent = (int) $post->post_parent; + + $this->posts[ $key ] = $obj; + + $post_parents[ $obj->ID ] = $obj->post_parent; + } + + return $post_parents; + } + } + } + } + if ( 'ids' === $q['fields'] ) { if ( null === $this->posts ) { $this->posts = $wpdb->get_col( $this->request ); @@ -3082,6 +3149,16 @@ class WP_Query { $this->post_count = count( $this->posts ); $this->set_found_posts( $q, $limits ); + if ( $q['cache_results'] && $id_query_is_cacheable ) { + $cache_value = array( + 'posts' => $this->posts, + 'found_posts' => $this->found_posts, + 'max_num_pages' => $this->max_num_pages, + ); + + wp_cache_set( $cache_key, $cache_value, 'posts' ); + } + return $this->posts; } @@ -3094,15 +3171,28 @@ class WP_Query { $this->set_found_posts( $q, $limits ); /** @var int[] */ - $r = array(); + $post_parents = array(); + $post_ids = array(); + foreach ( $this->posts as $key => $post ) { $this->posts[ $key ]->ID = (int) $post->ID; $this->posts[ $key ]->post_parent = (int) $post->post_parent; - $r[ (int) $post->ID ] = (int) $post->post_parent; + $post_parents[ (int) $post->ID ] = (int) $post->post_parent; + $post_ids[] = (int) $post->ID; } - return $r; + if ( $q['cache_results'] && $id_query_is_cacheable ) { + $cache_value = array( + 'posts' => $post_ids, + 'found_posts' => $this->found_posts, + 'max_num_pages' => $this->max_num_pages, + ); + + wp_cache_set( $cache_key, $cache_value, 'posts' ); + } + + return $post_parents; } if ( null === $this->posts ) { @@ -3144,12 +3234,12 @@ class WP_Query { */ $this->request = apply_filters( 'posts_request_ids', $this->request, $this ); - $ids = $wpdb->get_col( $this->request ); + $post_ids = $wpdb->get_col( $this->request ); - if ( $ids ) { - $this->posts = $ids; + if ( $post_ids ) { + $this->posts = $post_ids; $this->set_found_posts( $q, $limits ); - _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] ); + _prime_post_caches( $post_ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] ); } else { $this->posts = array(); } @@ -3165,6 +3255,18 @@ class WP_Query { $this->posts = array_map( 'get_post', $this->posts ); } + if ( $q['cache_results'] && $id_query_is_cacheable ) { + $post_ids = wp_list_pluck( $this->posts, 'ID' ); + + $cache_value = array( + 'posts' => $post_ids, + 'found_posts' => $this->found_posts, + 'max_num_pages' => $this->max_num_pages, + ); + + wp_cache_set( $cache_key, $cache_value, 'posts' ); + } + if ( ! empty( $this->posts ) && $q['update_menu_item_cache'] ) { update_menu_item_cache( $this->posts ); } @@ -3201,14 +3303,14 @@ class WP_Query { $comments_request = "SELECT {$wpdb->comments}.comment_ID FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits"; - $key = md5( $comments_request ); - $last_changed = wp_cache_get_last_changed( 'comment' ); + $comment_key = md5( $comments_request ); + $comment_last_changed = wp_cache_get_last_changed( 'comment' ); - $cache_key = "comment_feed:$key:$last_changed"; - $comment_ids = wp_cache_get( $cache_key, 'comment' ); + $comment_cache_key = "comment_feed:$comment_key:$comment_last_changed"; + $comment_ids = wp_cache_get( $comment_cache_key, 'comment' ); if ( false === $comment_ids ) { $comment_ids = $wpdb->get_col( $comments_request ); - wp_cache_add( $cache_key, $comment_ids, 'comment' ); + wp_cache_add( $comment_cache_key, $comment_ids, 'comment' ); } _prime_comment_caches( $comment_ids, false ); diff --git a/tests/phpunit/tests/query/cacheResults.php b/tests/phpunit/tests/query/cacheResults.php new file mode 100644 index 0000000000..226e82aeca --- /dev/null +++ b/tests/phpunit/tests/query/cacheResults.php @@ -0,0 +1,896 @@ +post->create_many( 5 ); + self::$pages = $factory->post->create_many( 5, array( 'post_type' => 'page' ) ); + + self::$t1 = $factory->term->create( + array( + 'taxonomy' => 'category', + 'slug' => 'foo', + 'name' => 'Foo', + ) + ); + + wp_set_post_terms( self::$posts[0], self::$t1, 'category' ); + add_post_meta( self::$posts[0], 'color', '#000000' ); + + // Make a user. + self::$author_id = $factory->user->create( + array( + 'role' => 'author', + ) + ); + } + + /** + * @dataProvider data_query_cache + * @ticket 22176 + */ + public function test_query_cache( $args ) { + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + $queries_before = get_num_queries(); + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + $queries_after = get_num_queries(); + + add_filter( 'split_the_query', '__return_false' ); + $split_query = new WP_Query(); + $split_posts = $split_query->query( $args ); + remove_filter( 'split_the_query', '__return_false' ); + + if ( isset( $args['fields'] ) ) { + if ( 'all' !== $args['fields'] ) { + $this->assertSameSets( $posts1, $posts2, 'Second query produces different set of posts to first.' ); + $this->assertSameSets( $posts1, $split_posts, 'Split query produces different set of posts to first.' ); + } + if ( 'id=>parent' !== $args['fields'] ) { + $this->assertSame( $queries_after, $queries_before, 'Second query produces unexpected DB queries.' ); + } + } else { + $this->assertSame( $queries_after, $queries_before, 'Second query produces unexpected DB queries.' ); + } + $this->assertSame( $query1->found_posts, $query2->found_posts, 'Second query has a different number of found posts to first.' ); + $this->assertSame( $query1->found_posts, $split_query->found_posts, 'Split query has a different number of found posts to first.' ); + $this->assertSame( $query1->max_num_pages, $query2->max_num_pages, 'Second query has a different number of total to first.' ); + $this->assertSame( $query1->max_num_pages, $split_query->max_num_pages, 'Split query has a different number of total to first.' ); + + if ( ! $query1->query_vars['no_found_rows'] ) { + wp_delete_post( self::$posts[0], true ); + wp_delete_post( self::$pages[0], true ); + $query3 = new WP_Query(); + $query3->query( $args ); + + $this->assertNotSame( $query1->found_posts, $query3->found_posts ); + $this->assertNotSame( $queries_after, get_num_queries() ); + } + } + + /** + * Data provider. + * + * @return array[] Test parameters. + */ + public function data_query_cache() { + return array( + 'cache true' => array( + 'args' => array( + 'cache_results' => true, + ), + ), + 'cache true and pagination' => array( + 'args' => array( + 'cache_results' => true, + 'posts_per_page' => 3, + 'page' => 2, + ), + ), + 'cache true and no pagination' => array( + 'args' => array( + 'cache_results' => true, + 'nopaging' => true, + ), + ), + 'cache true and post type any' => array( + 'args' => array( + 'cache_results' => true, + 'nopaging' => true, + 'post_type' => 'any', + ), + ), + 'cache true and get all' => array( + 'args' => array( + 'cache_results' => true, + 'fields' => 'all', + 'posts_per_page' => -1, + 'post_status' => 'any', + 'post_type' => 'any', + ), + ), + 'cache true and page' => array( + 'args' => array( + 'cache_results' => true, + 'post_type' => 'page', + ), + ), + 'cache true and ids' => array( + 'args' => array( + 'cache_results' => true, + 'fields' => 'ids', + ), + ), + 'cache true and id=>parent and no found rows' => array( + 'args' => array( + 'cache_results' => true, + 'fields' => 'id=>parent', + ), + ), + 'cache true and ids and no found rows' => array( + 'args' => array( + 'no_found_rows' => true, + 'cache_results' => true, + 'fields' => 'ids', + ), + ), + 'cache true and id=>parent' => array( + 'args' => array( + 'no_found_rows' => true, + 'cache_results' => true, + 'fields' => 'id=>parent', + ), + ), + 'cache and ignore_sticky_posts' => array( + 'args' => array( + 'cache_results' => true, + 'ignore_sticky_posts' => true, + ), + ), + 'cache meta query' => array( + 'args' => array( + 'cache_results' => true, + 'meta_query' => array( + array( + 'key' => 'color', + ), + ), + ), + ), + 'cache comment_count' => array( + 'args' => array( + 'cache_results' => true, + 'comment_count' => 0, + ), + ), + 'cache term query' => array( + 'args' => array( + 'cache_results' => true, + 'tax_query' => array( + array( + 'taxonomy' => 'category', + 'terms' => array( 'foo' ), + 'field' => 'slug', + ), + ), + ), + ), + ); + } + + /** + * @ticket 22176 + */ + public function test_seeded_random_queries_only_cache_post_objects() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'orderby' => 'rand(6)', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + $queries_before = get_num_queries(); + + $query2 = new WP_Query(); + $query2->query( $args ); + + $queries_after = get_num_queries(); + + $this->assertNotSame( $queries_before, $queries_after ); + } + + /** + * @ticket 22176 + */ + public function test_unseeded_random_queries_only_cache_post_objects() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'orderby' => 'rand', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + $queries_before = get_num_queries(); + + $query2 = new WP_Query(); + $query2->query( $args ); + + $queries_after = get_num_queries(); + + $this->assertNotSame( $queries_before, $queries_after ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_filter_request() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + $queries_before = get_num_queries(); + + add_filter( 'posts_request', array( $this, 'filter_posts_request' ) ); + + $query2 = new WP_Query(); + $query2->query( $args ); + + $queries_after = get_num_queries(); + + $this->assertNotSame( $queries_before, $queries_after ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_no_caching() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + $queries_before = get_num_queries(); + + $query2 = new WP_Query(); + $args['cache_results'] = false; + $query2->query( $args ); + + $queries_after = get_num_queries(); + + $this->assertNotSame( $queries_before, $queries_after ); + } + + public function filter_posts_request( $request ) { + return $request . ' -- Add comment'; + } + + /** + * @ticket 22176 + */ + public function test_query_cache_new_post() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + $p1 = self::factory()->post->create(); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_main_query_sticky_posts_change() { + add_action( 'parse_query', array( $this, 'set_cache_results' ) ); + update_option( 'posts_per_page', 5 ); + + $old_date = date_create( '-25 hours' ); + $old_post = self::factory()->post->create( array( 'post_date' => $old_date->format( 'Y-m-d H:i:s' ) ) ); + + // Post is unstuck. + $this->go_to( '/' ); + $unstuck = $GLOBALS['wp_query']->posts; + $unstuck_ids = wp_list_pluck( $unstuck, 'ID' ); + + $expected = array_reverse( self::$posts ); + $this->assertSame( $expected, $unstuck_ids ); + + // Stick the post. + stick_post( $old_post ); + + $this->go_to( '/' ); + $stuck = $GLOBALS['wp_query']->posts; + $stuck_ids = wp_list_pluck( $stuck, 'ID' ); + + $expected = array_reverse( self::$posts ); + array_unshift( $expected, $old_post ); + + $this->assertSame( $expected, $stuck_ids ); + } + + /** + * @ticket 22176 + */ + public function test_main_query_in_query_sticky_posts_change() { + add_action( 'parse_query', array( $this, 'set_cache_results' ) ); + update_option( 'posts_per_page', 5 ); + + $middle_post = self::$posts[2]; + + // Post is unstuck. + $this->go_to( '/' ); + $unstuck = $GLOBALS['wp_query']->posts; + $unstuck_ids = wp_list_pluck( $unstuck, 'ID' ); + + $expected = array_reverse( self::$posts ); + $this->assertSame( $expected, $unstuck_ids ); + + // Stick the post. + stick_post( $middle_post ); + + $this->go_to( '/' ); + $stuck = $GLOBALS['wp_query']->posts; + $stuck_ids = wp_list_pluck( $stuck, 'ID' ); + + $expected = array_diff( array_reverse( self::$posts ), array( $middle_post ) ); + array_unshift( $expected, $middle_post ); + + $this->assertSame( $expected, $stuck_ids ); + } + + /** + * @ticket 22176 + */ + public function test_query_sticky_posts_change() { + add_action( 'parse_query', array( $this, 'set_cache_results' ) ); + + $old_date = date_create( '-25 hours' ); + $old_post = self::factory()->post->create( array( 'post_date' => $old_date->format( 'Y-m-d H:i:s' ) ) ); + + // Post is unstuck. + $unstuck = new WP_Query( array( 'posts_per_page' => 5 ) ); + $unstuck_ids = wp_list_pluck( $unstuck->posts, 'ID' ); + + $expected = array_reverse( self::$posts ); + + $this->assertSame( $expected, $unstuck_ids ); + + // Stick the post. + stick_post( $old_post ); + + $stuck = new WP_Query( array( 'posts_per_page' => 5 ) ); + $stuck_ids = wp_list_pluck( $stuck->posts, 'ID' ); + + $expected = array_reverse( self::$posts ); + array_unshift( $expected, $old_post ); + + $this->assertSame( $expected, $stuck_ids ); + + // Ignore sticky posts. + $ignore_stuck = new WP_Query( + array( + 'posts_per_page' => 5, + 'ignore_sticky_posts' => true, + ) + ); + $ignore_stuck_ids = wp_list_pluck( $ignore_stuck->posts, 'ID' ); + + $expected = array_reverse( self::$posts ); + + $this->assertSame( $expected, $ignore_stuck_ids ); + + // Just to make sure everything has changed. + $this->assertNotSame( $unstuck, $stuck ); + } + + /** + * @ticket 22176 + */ + public function test_query_in_query_sticky_posts_change() { + add_action( 'parse_query', array( $this, 'set_cache_results' ) ); + + $middle_post = self::$posts[2]; + + // Post is unstuck. + $unstuck = new WP_Query( array( 'posts_per_page' => 5 ) ); + $unstuck_ids = wp_list_pluck( $unstuck->posts, 'ID' ); + + $expected = array_reverse( self::$posts ); + + $this->assertSame( $expected, $unstuck_ids ); + + // Stick the post. + stick_post( $middle_post ); + + $stuck = new WP_Query( array( 'posts_per_page' => 5 ) ); + $stuck_ids = wp_list_pluck( $stuck->posts, 'ID' ); + + $expected = array_diff( array_reverse( self::$posts ), array( $middle_post ) ); + array_unshift( $expected, $middle_post ); + + $this->assertSame( $expected, $stuck_ids ); + + // Ignore sticky posts. + $ignore_stuck = new WP_Query( + array( + 'posts_per_page' => 5, + 'ignore_sticky_posts' => true, + ) + ); + $ignore_stuck_ids = wp_list_pluck( $ignore_stuck->posts, 'ID' ); + + $expected = array_reverse( self::$posts ); + + $this->assertSame( $expected, $ignore_stuck_ids ); + + // Just to make sure everything has changed. + $this->assertNotSame( $unstuck, $stuck ); + } + + public function set_cache_results( $q ) { + $q->set( 'cache_results', true ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_different_args() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'suppress_filters' => true, + 'cache_results' => true, + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'lazy_load_term_meta' => false, + ); + $queries_before = get_num_queries(); + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + $queries_after = get_num_queries(); + + $this->assertSame( $queries_before, $queries_after ); + $this->assertSame( $posts1, $posts2 ); + $this->assertSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_different_fields() { + $args = array( + 'cache_results' => true, + 'fields' => 'all', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + + $args = array( + 'cache_results' => true, + 'fields' => 'id=>parent', + ); + $queries_before = get_num_queries(); + $query2 = new WP_Query(); + $query2->query( $args ); + $queries_after = get_num_queries(); + + $this->assertSame( $queries_before, $queries_after ); + $this->assertCount( 5, $query1->posts ); + $this->assertCount( 5, $query2->posts ); + $this->assertSame( $query1->found_posts, $query2->found_posts ); + + /* + * Make sure the returned post objects differ due to the field argument. + * + * This uses assertNotEquals rather than assertNotSame as the former is + * agnostic to the instance ID of objects, whereas the latter will take + * it in to account. The test needs to discard the instance ID when + * confirming inequality. + */ + $this->assertNotEquals( $query1->posts, $query2->posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_logged_in() { + $user_id = self::$author_id; + + self::factory()->post->create( + array( + 'post_status' => 'private', + 'post_author' => $user_id, + ) + ); + + $args = array( + 'cache_results' => true, + 'author' => $user_id, + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_set_current_user( $user_id ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + $this->assertEmpty( $posts1 ); + $this->assertNotSame( $posts1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_logged_in_password() { + $user_id = self::$author_id; + self::factory()->post->create( + array( + 'post_title' => 'foo', + 'post_password' => 'password', + 'post_author' => $user_id, + ) + ); + + $args = array( + 'cache_results' => true, + 's' => 'foo', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_set_current_user( $user_id ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + $this->assertEmpty( $posts1 ); + $this->assertNotSame( $posts1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_new_comment() { + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'comment_count' => 1, + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + self::factory()->comment->create( array( 'comment_post_ID' => self::$posts[0] ) ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( self::$posts[0], $posts2 ); + $this->assertNotEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_main_comments_feed_includes_attachment_comments() { + $attachment_id = self::factory()->post->create( array( 'post_type' => 'attachment' ) ); + $comment_id = self::factory()->comment->create( + array( + 'comment_post_ID' => $attachment_id, + 'comment_approved' => '1', + ) + ); + + $args = array( + 'cache_results' => true, + 'withcomments' => 1, + 'feed' => 'feed', + ); + $query1 = new WP_Query(); + $query1->query( $args ); + + $query2 = new WP_Query(); + $query2->query( $args ); + + $this->assertTrue( $query1->have_comments() ); + $this->assertTrue( $query2->have_comments() ); + + $feed_comment = $query1->next_comment(); + $this->assertEquals( $comment_id, $feed_comment->comment_ID ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_delete_comment() { + $comment_id = self::factory()->comment->create( array( 'comment_post_ID' => self::$posts[0] ) ); + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'comment_count' => 1, + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_delete_comment( $comment_id, true ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_update_post() { + $p1 = self::$posts[0]; + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_update_post( + array( + 'ID' => $p1, + 'post_status' => 'draft', + ) + ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts1 ); + $this->assertNotContains( $p1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_new_meta() { + $p1 = self::$posts[1]; // Post 0 already has a color meta value. + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'color', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + add_post_meta( $p1, 'color', 'black' ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_update_meta() { + // Posts[0] already has a color meta value set to #000000. + $p1 = self::$posts[0]; + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'color', + 'value' => '#000000', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + update_post_meta( $p1, 'color', 'blue' ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts1 ); + $this->assertEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + + /** + * @ticket 22176 + */ + public function test_query_cache_delete_attachment() { + $p1 = self::factory()->post->create( + array( + 'post_type' => 'attachment', + 'post_status' => 'inherit', + ) + ); + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'post_type' => 'attachment', + 'post_status' => 'inherit', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_delete_attachment( $p1 ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts1 ); + $this->assertEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_delete_meta() { + // Post 0 already has a color meta value. + $p1 = self::$posts[1]; + add_post_meta( $p1, 'color', 'black' ); + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'color', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + delete_post_meta( $p1, 'color' ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts1 ); + $this->assertNotEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_new_term() { + // Post 0 already has the category foo. + $p1 = self::$posts[1]; + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'tax_query' => array( + array( + 'taxonomy' => 'category', + 'terms' => array( 'foo' ), + 'field' => 'slug', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_set_post_terms( $p1, array( self::$t1 ), 'category' ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } + + /** + * @ticket 22176 + */ + public function test_query_cache_delete_term() { + // Post 0 already has the category foo. + $p1 = self::$posts[1]; + register_taxonomy( 'wptests_tax1', 'post' ); + + $t1 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax1' ) ); + + wp_set_object_terms( $p1, array( $t1 ), 'wptests_tax1' ); + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'tax_query' => array( + array( + 'taxonomy' => 'wptests_tax1', + 'terms' => array( $t1 ), + 'field' => 'term_id', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + + wp_delete_term( $t1, 'wptests_tax1' ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertNotSame( $posts1, $posts2 ); + $this->assertContains( $p1, $posts1 ); + $this->assertEmpty( $posts2 ); + $this->assertNotSame( $query1->found_posts, $query2->found_posts ); + } +} diff --git a/tests/phpunit/tests/query/commentFeed.php b/tests/phpunit/tests/query/commentFeed.php index 2deda2df40..35c4eb0b60 100644 --- a/tests/phpunit/tests/query/commentFeed.php +++ b/tests/phpunit/tests/query/commentFeed.php @@ -39,6 +39,7 @@ class Tests_Query_CommentFeed extends WP_UnitTestCase { 'update_post_term_cache' => false, 'ignore_sticky_posts' => false, 'no_found_rows' => true, + 'cache_results' => false, ); $q1->query( $args ); $num_queries = $wpdb->num_queries; @@ -98,6 +99,7 @@ class Tests_Query_CommentFeed extends WP_UnitTestCase { 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'ignore_sticky_posts' => false, + 'cache_results' => false, ); $q1->query( $args );