WordPress.org

Make WordPress Core

Ticket #36687: 36687.diff

File 36687.diff, 5.8 KB (added by boonebgorges, 3 years ago)
  • src/wp-includes/query.php

    diff --git src/wp-includes/query.php src/wp-includes/query.php
    index 02bfba7..660cae4 100644
    class WP_Query { 
    35483548                        $this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this ) );
    35493549                }
    35503550
     3551                /**
     3552                 * Filter the posts array before the query takes place.
     3553                 *
     3554                 * Return a non-null value to bypass WordPress's default post queries.
     3555                 *
     3556                 * @since 4.6.0
     3557                 *
     3558                 * @param array|null $posts Return an array of post data to short-circuit WP's query,
     3559                 *                          or null to allow WP to run its normal queries.
     3560                 * @param WP_Query   $this  The WP_Query instance, passed by reference.
     3561                 */
     3562                $this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) );
     3563
    35513564                if ( 'ids' == $q['fields'] ) {
    3552                         $this->posts = $wpdb->get_col( $this->request );
     3565                        if ( null === $this->posts ) {
     3566                                $this->posts = $wpdb->get_col( $this->request );
     3567                        }
     3568
    35533569                        $this->posts = array_map( 'intval', $this->posts );
    35543570                        $this->post_count = count( $this->posts );
    35553571                        $this->set_found_posts( $q, $limits );
    class WP_Query { 
    35583574                }
    35593575
    35603576                if ( 'id=>parent' == $q['fields'] ) {
    3561                         $this->posts = $wpdb->get_results( $this->request );
     3577                        if ( null === $this->posts ) {
     3578                                $this->posts = $wpdb->get_results( $this->request );
     3579                        }
     3580
    35623581                        $this->post_count = count( $this->posts );
    35633582                        $this->set_found_posts( $q, $limits );
    35643583
    class WP_Query { 
    35733592                        return $r;
    35743593                }
    35753594
    3576                 $split_the_query = ( $old_request == $this->request && "$wpdb->posts.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
    3577 
    3578                 /**
    3579                  * Filter whether to split the query.
    3580                  *
    3581                  * Splitting the query will cause it to fetch just the IDs of the found posts
    3582                  * (and then individually fetch each post by ID), rather than fetching every
    3583                  * complete row at once. One massive result vs. many small results.
    3584                  *
    3585                  * @since 3.4.0
    3586                  *
    3587                  * @param bool     $split_the_query Whether or not to split the query.
    3588                  * @param WP_Query $this            The WP_Query instance.
    3589                  */
    3590                 $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this );
    3591 
    3592                 if ( $split_the_query ) {
    3593                         // First get the IDs and then fill in the objects
    3594 
    3595                         $this->request = "SELECT $found_rows $distinct $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
     3595                if ( null === $this->posts ) {
     3596                        $split_the_query = ( $old_request == $this->request && "$wpdb->posts.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
    35963597
    35973598                        /**
    3598                          * Filter the Post IDs SQL request before sending.
     3599                         * Filter whether to split the query.
     3600                         *
     3601                         * Splitting the query will cause it to fetch just the IDs of the found posts
     3602                         * (and then individually fetch each post by ID), rather than fetching every
     3603                         * complete row at once. One massive result vs. many small results.
    35993604                         *
    36003605                         * @since 3.4.0
    36013606                         *
    3602                          * @param string   $request The post ID request.
    3603                          * @param WP_Query $this    The WP_Query instance.
     3607                         * @param bool     $split_the_query Whether or not to split the query.
     3608                         * @param WP_Query $this            The WP_Query instance.
    36043609                         */
    3605                         $this->request = apply_filters( 'posts_request_ids', $this->request, $this );
     3610                        $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this );
     3611
     3612                        if ( $split_the_query ) {
     3613                                // First get the IDs and then fill in the objects
     3614
     3615                                $this->request = "SELECT $found_rows $distinct $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
     3616
     3617                                /**
     3618                                 * Filter the Post IDs SQL request before sending.
     3619                                 *
     3620                                 * @since 3.4.0
     3621                                 *
     3622                                 * @param string   $request The post ID request.
     3623                                 * @param WP_Query $this    The WP_Query instance.
     3624                                 */
     3625                                $this->request = apply_filters( 'posts_request_ids', $this->request, $this );
    36063626
    3607                         $ids = $wpdb->get_col( $this->request );
     3627                                $ids = $wpdb->get_col( $this->request );
    36083628
    3609                         if ( $ids ) {
    3610                                 $this->posts = $ids;
    3611                                 $this->set_found_posts( $q, $limits );
    3612                                 _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
     3629                                if ( $ids ) {
     3630                                        $this->posts = $ids;
     3631                                        _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
     3632                                } else {
     3633                                        $this->posts = array();
     3634                                }
    36133635                        } else {
    3614                                 $this->posts = array();
     3636                                $this->posts = $wpdb->get_results( $this->request );
    36153637                        }
    3616                 } else {
    3617                         $this->posts = $wpdb->get_results( $this->request );
    3618                         $this->set_found_posts( $q, $limits );
    36193638                }
    36203639
    3621                 // Convert to WP_Post objects
    3622                 if ( $this->posts )
     3640                // Convert to WP_Post objects.
     3641                if ( $this->posts ) {
     3642                        $this->set_found_posts( $q, $limits );
    36233643                        $this->posts = array_map( 'get_post', $this->posts );
     3644                }
    36243645
    36253646                if ( ! $q['suppress_filters'] ) {
    36263647                        /**
  • tests/phpunit/tests/post/query.php

    diff --git tests/phpunit/tests/post/query.php tests/phpunit/tests/post/query.php
    index acc8e4e..551dc1e 100644
    class Tests_Post_Query extends WP_UnitTestCase { 
    388388                $actual_posts = $q->get_posts();
    389389                $this->assertEqualSets( $requested, $actual_posts );
    390390        }
     391
     392        /**
     393         * @ticket 36687
     394         */
     395        public function test_posts_pre_query_filter_should_bypass_database_query() {
     396                global $wpdb;
     397
     398                add_filter( 'posts_pre_query', array( __CLASS__, 'filter_posts_pre_query' ) );
     399
     400                $num_queries = $wpdb->num_queries;
     401                $q = new WP_Query( array(
     402                        'fields' => 'ids',
     403                        'no_found_rows' => true,
     404                ) );
     405
     406                remove_filter( 'posts_pre_query', array( __CLASS__, 'filter_posts_pre_query' ) );
     407
     408                $this->assertSame( $num_queries, $wpdb->num_queries );
     409                $this->assertSame( array( 12345 ), $q->posts );
     410        }
     411
     412        public static function filter_posts_pre_query( $posts ) {
     413                return array( 12345 );
     414        }
    391415}