Make WordPress Core

Changeset 44373


Ignore:
Timestamp:
12/29/2018 04:05:50 PM (6 years ago)
Author:
adamsilverstein
Message:

Users: Add a users_pre_query filter to short circuit WP_User_Query results.

Add a new filter users_pre_query - filters the users array before the query takes place. Return a non-null value to bypass WordPress's default user queries. Similar to the posts_pre_query filter for WP_Query added in #36687. This filter lets you short circuit the WP_User_Query MySQL query to return your own results.

Developers should note that filtering functions that require pagination information are encouraged to set the total_users property of the WP_User_Query object, passed to the filter by reference. If WP_User_Query does not perform a database query, it will not have enough information to generate these values itself.

Props tlovett1, birgire, boonebgorges, spacedmonkey.
Fixes #44169.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-user-query.php

    r44348 r44373  
    593593        $qv =& $this->query_vars;
    594594
    595         $this->request = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit";
    596 
    597         if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {
    598             $this->results = $wpdb->get_results( $this->request );
    599         } else {
    600             $this->results = $wpdb->get_col( $this->request );
    601         }
    602 
    603         if ( isset( $qv['count_total'] ) && $qv['count_total'] ) {
    604             /**
    605              * Filters SELECT FOUND_ROWS() query for the current WP_User_Query instance.
    606              *
    607              * @since 3.2.0
    608              * @since 5.1.0 Added the `$this` parameter.
    609              *
    610              * @global wpdb $wpdb WordPress database abstraction object.
    611              *
    612              * @param string $sql         The SELECT FOUND_ROWS() query for the current WP_User_Query.
    613              * @param WP_User_Query $this The current WP_User_Query instance.
    614              */
    615             $found_users_query = apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()', $this );
    616 
    617             $this->total_users = (int) $wpdb->get_var( $found_users_query );
     595        /**
     596         * Filters the users array before the query takes place.
     597         *
     598         * Return a non-null value to bypass WordPress's default user queries.
     599         * Filtering functions that require pagination information are encouraged to set
     600         * the `total_users` property of the WP_User_Query object, passed to the filter
     601         * by reference. If WP_User_Query does not perform a database query, it will not
     602         * have enough information to generate these values itself.
     603         *
     604         * @since 5.0.3
     605         *
     606         * @param array|null $results Return an array of user data to short-circuit WP's user query or null to allow WP to run its normal queries.
     607         * @param WP_User_Query $this The WP_User_Query instance (passed by reference).
     608         */
     609        $this->results = apply_filters_ref_array( 'users_pre_query', array( null, &$this ) );
     610
     611        if ( null === $this->results ) {
     612            $this->request = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit";
     613
     614            if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {
     615                $this->results = $wpdb->get_results( $this->request );
     616            } else {
     617                $this->results = $wpdb->get_col( $this->request );
     618            }
     619
     620            if ( isset( $qv['count_total'] ) && $qv['count_total'] ) {
     621                /**
     622                 * Filters SELECT FOUND_ROWS() query for the current WP_User_Query instance.
     623                 *
     624                 * @since 3.2.0
     625                 * @since 5.0.3 Added the `$this` parameter.
     626                 *
     627                 * @global wpdb $wpdb WordPress database abstraction object.
     628                 *
     629                 * @param string $sql         The SELECT FOUND_ROWS() query for the current WP_User_Query.
     630                 * @param WP_User_Query $this The current WP_User_Query instance.
     631                 */
     632                $found_users_query = apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()', $this );
     633
     634                $this->total_users = (int) $wpdb->get_var( $found_users_query );
     635            }
    618636        }
    619637
  • trunk/tests/phpunit/tests/user/query.php

    r43571 r44373  
    16911691        $this->assertEquals( array(), $ids );
    16921692    }
     1693
     1694    /**
     1695     * @ticket 44169
     1696     */
     1697    public function test_users_pre_query_filter_should_bypass_database_query() {
     1698        global $wpdb;
     1699
     1700        add_filter( 'users_pre_query', array( __CLASS__, 'filter_users_pre_query' ), 10, 2 );
     1701
     1702        $num_queries = $wpdb->num_queries;
     1703        $q           = new WP_User_Query(
     1704            array(
     1705                'fields' => 'ID',
     1706            )
     1707        );
     1708
     1709        remove_filter( 'users_pre_query', array( __CLASS__, 'filter_users_pre_query' ), 10, 2 );
     1710
     1711        // Make sure no queries were executed.
     1712        $this->assertSame( $num_queries, $wpdb->num_queries );
     1713
     1714        // We manually inserted a non-existing user and overrode the results with it.
     1715        $this->assertSame( array( 555 ), $q->results );
     1716
     1717        // Make sure manually setting total_users doesn't get overwritten.
     1718        $this->assertEquals( 1, $q->total_users );
     1719    }
     1720
     1721    public static function filter_users_pre_query( $posts, $query ) {
     1722        $query->total_users = 1;
     1723
     1724        return array( 555 );
     1725    }
    16931726}
Note: See TracChangeset for help on using the changeset viewer.