Make WordPress Core

Changeset 44983


Ignore:
Timestamp:
03/22/2019 05:25:38 PM (8 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.