WordPress.org

Make WordPress Core

Ticket #39947: 39947.2.diff

File 39947.2.diff, 8.9 KB (added by jnylen0, 3 years ago)

Add more tests; test the generated SQL to catch the IN(0) fix.

  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
    index 30651d0..7e3e563 100644
    a b class WP_REST_Posts_Controller extends WP_REST_Controller { 
    220220
    221221                if ( isset( $registered['sticky'], $request['sticky'] ) ) {
    222222                        $sticky_posts = get_option( 'sticky_posts', array() );
    223                         if ( $sticky_posts && $request['sticky'] ) {
     223                        if ( ! is_array( $sticky_posts ) ) {
     224                                $sticky_posts = array();
     225                        }
     226                        if ( $request['sticky'] ) {
    224227                                /*
    225228                                 * As post__in will be used to only get sticky posts,
    226229                                 * we have to support the case where post__in was already
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    234237                                 * so we have to fake it a bit.
    235238                                 */
    236239                                if ( ! $args['post__in'] ) {
    237                                         $args['post__in'] = array( -1 );
     240                                        $args['post__in'] = array( 0 );
    238241                                }
    239242                        } elseif ( $sticky_posts ) {
    240243                                /*
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

    diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
    index 503010f..409982e 100644
    a b class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    2020        protected static $supported_formats;
    2121
    2222        protected $forbidden_cat;
    23         protected $posts_orderby;
     23        protected $posts_clauses;
    2424
    2525        public static function wpSetUpBeforeClass( $factory ) {
    2626                self::$post_id = $factory->post->create();
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    6868                parent::setUp();
    6969                register_post_type( 'youseeme', array( 'supports' => array(), 'show_in_rest' => true ) );
    7070                add_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
    71                 add_filter( 'posts_orderby', array( $this, 'save_posts_orderby' ), 10, 2 );
     71                add_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
    7272        }
    7373
    7474        public function wpSetUpBeforeRequest( $result, $server, $request ) {
    75                 $this->posts_orderby = array();
     75                $this->posts_clauses = array();
    7676                return $result;
    7777        }
    7878
    79         public function save_posts_orderby( $orderby, $query ) {
    80                 array_push( $this->posts_orderby, $orderby );
     79        public function save_posts_clauses( $orderby, $query ) {
     80                array_push( $this->posts_clauses, $orderby );
    8181                return $orderby;
    8282        }
    8383
    84         public function assertPostsOrderedBy( $pattern ) {
     84        public function assertPostsClause( $clause, $pattern ) {
    8585                global $wpdb;
    86                 $orderby = str_replace( '{posts}', $wpdb->posts, $pattern );
    87                 $this->assertEquals( array( $orderby ), $this->posts_orderby );
     86                $expected_clause = str_replace( '{posts}', $wpdb->posts, $pattern );
     87                $this->assertCount( 1, $this->posts_clauses );
     88                $this->assertEquals( $expected_clause, $this->posts_clauses[0][ $clause ] );
     89        }
     90
     91        public function assertPostsOrderedBy( $pattern ) {
     92                $this->assertPostsClause( 'orderby', $pattern );
     93        }
     94
     95        public function assertPostsWhere( $pattern ) {
     96                $this->assertPostsClause( 'where', $pattern );
    8897        }
    8998
    9099        public function test_register_routes() {
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    690699                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    691700        }
    692701
    693         public function test_get_items_sticky_query() {
     702        public function test_get_items_sticky() {
    694703                $id1 = self::$post_id;
    695704                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    696705
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    711720                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    712721        }
    713722
    714         public function test_get_items_sticky_with_post__in_query() {
     723        public function test_get_items_sticky_with_include() {
    715724                $id1 = self::$post_id;
    716725                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    717726                $id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    725734                $response = $this->server->dispatch( $request );
    726735                $this->assertCount( 0, $response->get_data() );
    727736
     737                // FIXME Since this request returns zero posts, the query is executed twice.
     738                $this->assertCount( 2, $this->posts_clauses );
     739                $this->posts_clauses = array_slice( $this->posts_clauses, 0, 1 );
     740
     741                $this->assertPostsWhere( " AND {posts}.ID IN (0) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
     742
    728743                update_option( 'sticky_posts', array( $id1, $id2 ) );
    729744
    730745                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    738753                $posts = $response->get_data();
    739754                $post = $posts[0];
    740755                $this->assertEquals( $id1, $post['id'] );
     756
     757                $this->assertPostsWhere( " AND {posts}.ID IN ($id1) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
     758        }
     759
     760        public function test_get_items_sticky_no_sticky_posts() {
     761                $id1 = self::$post_id;
     762
     763                update_option( 'sticky_posts', array() );
     764
     765                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     766                $request->set_param( 'sticky', true );
     767
     768                $response = $this->server->dispatch( $request );
     769                $this->assertCount( 0, $response->get_data() );
     770
     771                // FIXME Since this request returns zero posts, the query is executed twice.
     772                $this->assertCount( 2, $this->posts_clauses );
     773                $this->posts_clauses = array_slice( $this->posts_clauses, 0, 1 );
     774
     775                $this->assertPostsWhere( " AND {posts}.ID IN (0) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
     776        }
     777
     778        public function test_get_items_sticky_with_include_no_sticky_posts() {
     779                $id1 = self::$post_id;
     780
     781                update_option( 'sticky_posts', array() );
     782
     783                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     784                $request->set_param( 'sticky', true );
     785                $request->set_param( 'include', array( $id1 ) );
     786
     787                $response = $this->server->dispatch( $request );
     788                $this->assertCount( 0, $response->get_data() );
     789
     790                // FIXME Since this request returns zero posts, the query is executed twice.
     791                $this->assertCount( 2, $this->posts_clauses );
     792                $this->posts_clauses = array_slice( $this->posts_clauses, 0, 1 );
     793
     794                $this->assertPostsWhere( " AND {posts}.ID IN (0) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
    741795        }
    742796
    743         public function test_get_items_not_sticky_query() {
     797        public function test_get_items_not_sticky() {
    744798                $id1 = self::$post_id;
    745799                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    746800
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    755809                $posts = $response->get_data();
    756810                $post = $posts[0];
    757811                $this->assertEquals( $id1, $post['id'] );
     812
     813                $this->assertPostsWhere( " AND {posts}.ID NOT IN ($id2) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
    758814        }
    759815
    760         public function test_get_items_sticky_with_post__not_in_query() {
     816        public function test_get_items_not_sticky_with_exclude() {
    761817                $id1 = self::$post_id;
    762818                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    763819                $id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    774830                $posts = $response->get_data();
    775831                $post = $posts[0];
    776832                $this->assertEquals( $id1, $post['id'] );
     833
     834                $this->assertPostsWhere( " AND {posts}.ID NOT IN ($id3,$id2) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
     835        }
     836
     837        public function test_get_items_not_sticky_with_exclude_no_sticky_posts() {
     838                $id1 = self::$post_id;
     839                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     840                $id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     841
     842                update_option( 'sticky_posts', array() );
     843
     844                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     845                $request->set_param( 'sticky', false );
     846                $request->set_param( 'exclude', array( $id3 ) );
     847
     848                $response = $this->server->dispatch( $request );
     849                $this->assertCount( 2, $response->get_data() );
     850
     851                $posts = $response->get_data();
     852                $ids = wp_list_pluck( $posts, 'id' );
     853                sort( $ids );
     854                $this->assertEquals( array( $id1, $id2 ), $ids );
     855
     856                $this->assertPostsWhere( " AND {posts}.ID NOT IN ($id3) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
    777857        }
    778858
    779859        public function test_get_items_pagination_headers() {
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    29703050                        $this->remove_added_uploads();
    29713051                }
    29723052                remove_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
    2973                 remove_filter( 'posts_orderby', array( $this, 'save_posts_orderby' ), 10, 2 );
     3053                remove_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
    29743054                parent::tearDown();
    29753055        }
    29763056