Make WordPress Core

Changeset 44983


Ignore:
Timestamp:
03/22/2019 05:25:38 PM (6 years ago)
Author:
adamsilverstein
Message:

Multisite: add new sites_pre_query and networks_pre_query filters to short circuit WP_Site_Query and WP_Network_Query queries.

Similar to the posts_pre_query filter for WP_Query added in #36687. These filters lets you short circuit the queries to return your own results.

Add a new filter sites_pre_query - which returns null by default. Return a non-null value to bypass WordPress's default get_sites queries.

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

Add a new filter networks_pre_query - which returns null by default. Return a non-null value to bypass WordPress's default get_networks queries.

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

Props spacedmonkey.
Fixes #45749.

Location:
trunk
Files:
4 edited

Legend:

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

    r44166 r44983  
    198198        do_action_ref_array( 'pre_get_networks', array( &$this ) );
    199199
    200         // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
    201         $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
    202 
    203         // Ignore the $fields argument as the queried result will be the same regardless.
    204         unset( $_args['fields'] );
    205 
    206         $key          = md5( serialize( $_args ) );
    207         $last_changed = wp_cache_get_last_changed( 'networks' );
    208 
    209         $cache_key   = "get_network_ids:$key:$last_changed";
    210         $cache_value = wp_cache_get( $cache_key, 'networks' );
    211 
    212         if ( false === $cache_value ) {
    213             $network_ids = $this->get_network_ids();
    214             if ( $network_ids ) {
    215                 $this->set_found_networks();
     200        $network_ids = null;
     201
     202        /**
     203         * Filter the sites array before the query takes place.
     204         *
     205         * Return a non-null value to bypass WordPress's default site queries.
     206         *
     207         *
     208         * @since 5.2.0
     209         *
     210         * @param array|null       $site_ids Return an array of site data to short-circuit WP's site query,
     211         *                                   or null to allow WP to run its normal queries.
     212         * @param WP_Network_Query $this     The WP_Network_Query instance, passed by reference.
     213         */
     214        $network_ids = apply_filters_ref_array( 'networks_pre_query', array( $network_ids, &$this ) );
     215
     216        if ( null === $network_ids ) {
     217
     218            // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
     219            $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
     220
     221            // Ignore the $fields argument as the queried result will be the same regardless.
     222            unset( $_args['fields'] );
     223
     224            $key          = md5( serialize( $_args ) );
     225            $last_changed = wp_cache_get_last_changed( 'networks' );
     226
     227            $cache_key   = "get_network_ids:$key:$last_changed";
     228            $cache_value = wp_cache_get( $cache_key, 'networks' );
     229
     230            if ( false === $cache_value ) {
     231                $network_ids = $this->get_network_ids();
     232                if ( $network_ids ) {
     233                    $this->set_found_networks();
     234                }
     235
     236                $cache_value = array(
     237                    'network_ids'    => $network_ids,
     238                    'found_networks' => $this->found_networks,
     239                );
     240                wp_cache_add( $cache_key, $cache_value, 'networks' );
     241            } else {
     242                $network_ids          = $cache_value['network_ids'];
     243                $this->found_networks = $cache_value['found_networks'];
    216244            }
    217 
    218             $cache_value = array(
    219                 'network_ids'    => $network_ids,
    220                 'found_networks' => $this->found_networks,
    221             );
    222             wp_cache_add( $cache_key, $cache_value, 'networks' );
    223         } else {
    224             $network_ids          = $cache_value['network_ids'];
    225             $this->found_networks = $cache_value['found_networks'];
    226245        }
    227246
  • trunk/src/wp-includes/class-wp-site-query.php

    r44467 r44983  
    289289        }
    290290
    291         // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
    292         $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
    293 
    294         // Ignore the $fields argument as the queried result will be the same regardless.
    295         unset( $_args['fields'] );
    296 
    297         $key          = md5( serialize( $_args ) );
    298         $last_changed = wp_cache_get_last_changed( 'sites' );
    299 
    300         $cache_key   = "get_sites:$key:$last_changed";
    301         $cache_value = wp_cache_get( $cache_key, 'sites' );
    302 
    303         if ( false === $cache_value ) {
    304             $site_ids = $this->get_site_ids();
    305             if ( $site_ids ) {
    306                 $this->set_found_sites();
     291        $site_ids = null;
     292
     293        /**
     294         * Filter the sites array before the query takes place.
     295         *
     296         * Return a non-null value to bypass WordPress's default site queries.
     297         *
     298         *
     299         * @since 5.2.0
     300         *
     301         * @param array|null    $site_ids Return an array of site data to short-circuit WP's site query,
     302         *                                or null to allow WP to run its normal queries.
     303         * @param WP_Site_Query $this The WP_Site_Query instance, passed by reference.
     304         */
     305        $site_ids = apply_filters_ref_array( 'sites_pre_query', array( $site_ids, &$this ) );
     306
     307        if ( null === $site_ids ) {
     308
     309            // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
     310            $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
     311
     312            // Ignore the $fields argument as the queried result will be the same regardless.
     313            unset( $_args['fields'] );
     314
     315            $key          = md5( serialize( $_args ) );
     316            $last_changed = wp_cache_get_last_changed( 'sites' );
     317
     318            $cache_key   = "get_sites:$key:$last_changed";
     319            $cache_value = wp_cache_get( $cache_key, 'sites' );
     320
     321            if ( false === $cache_value ) {
     322                $site_ids = $this->get_site_ids();
     323                if ( $site_ids ) {
     324                    $this->set_found_sites();
     325                }
     326
     327                $cache_value = array(
     328                    'site_ids'    => $site_ids,
     329                    'found_sites' => $this->found_sites,
     330                );
     331                wp_cache_add( $cache_key, $cache_value, 'sites' );
     332            } else {
     333                $site_ids          = $cache_value['site_ids'];
     334                $this->found_sites = $cache_value['found_sites'];
    307335            }
    308 
    309             $cache_value = array(
    310                 'site_ids'    => $site_ids,
    311                 'found_sites' => $this->found_sites,
    312             );
    313             wp_cache_add( $cache_key, $cache_value, 'sites' );
    314         } else {
    315             $site_ids          = $cache_value['site_ids'];
    316             $this->found_sites = $cache_value['found_sites'];
    317336        }
    318337
  • trunk/tests/phpunit/tests/multisite/networkQuery.php

    r42343 r44983  
    523523            $this->assertEquals( $number_of_queries + 1, $wpdb->num_queries );
    524524        }
     525
     526        /**
     527         * @ticket 45749
     528         */
     529        public function test_networks_pre_query_filter_should_bypass_database_query() {
     530            global $wpdb;
     531
     532            add_filter( 'networks_pre_query', array( __CLASS__, 'filter_networks_pre_query' ), 10, 2 );
     533
     534            $num_queries = $wpdb->num_queries;
     535
     536            $q       = new WP_Network_Query();
     537            $results = $q->query(
     538                array(
     539                    'fields' => 'ids',
     540                )
     541            );
     542
     543            remove_filter( 'networks_pre_query', array( __CLASS__, 'filter_networks_pre_query' ), 10, 2 );
     544
     545            // Make sure no queries were executed.
     546            $this->assertSame( $num_queries, $wpdb->num_queries );
     547
     548            // We manually inserted a non-existing site and overrode the results with it.
     549            $this->assertSame( array( 555 ), $q->networks );
     550
     551            // Make sure manually setting total_users doesn't get overwritten.
     552            $this->assertEquals( 1, $q->found_networks );
     553        }
     554
     555        public static function filter_networks_pre_query( $networks, $query ) {
     556            $query->found_networks = 1;
     557
     558            return array( 555 );
     559        }
    525560    }
    526561
  • trunk/tests/phpunit/tests/multisite/siteQuery.php

    r43010 r44983  
    910910                $this->assertEqualSets( $expected, $found );
    911911            }
     912        }
     913
     914
     915        /**
     916         * @ticket 45749
     917         */
     918        public function test_sites_pre_query_filter_should_bypass_database_query() {
     919            global $wpdb;
     920
     921            add_filter( 'sites_pre_query', array( __CLASS__, 'filter_sites_pre_query' ), 10, 2 );
     922
     923            $num_queries = $wpdb->num_queries;
     924
     925            $q       = new WP_Site_Query();
     926            $results = $q->query(
     927                array(
     928                    'fields' => 'ids',
     929                )
     930            );
     931
     932            remove_filter( 'sites_pre_query', array( __CLASS__, 'filter_sites_pre_query' ), 10, 2 );
     933
     934            // Make sure no queries were executed.
     935            $this->assertSame( $num_queries, $wpdb->num_queries );
     936
     937            // We manually inserted a non-existing site and overrode the results with it.
     938            $this->assertSame( array( 555 ), $q->sites );
     939
     940            // Make sure manually setting total_users doesn't get overwritten.
     941            $this->assertEquals( 1, $q->found_sites );
     942        }
     943
     944        public static function filter_sites_pre_query( $sites, $query ) {
     945            $query->found_sites = 1;
     946
     947            return array( 555 );
    912948        }
    913949
Note: See TracChangeset for help on using the changeset viewer.