WordPress.org

Make WordPress Core

Ticket #45749: 45749.9.diff

File 45749.9.diff, 8.6 KB (added by adamsilverstein, 19 months ago)
  • src/wp-includes/class-wp-network-query.php

    diff --git src/wp-includes/class-wp-network-query.php src/wp-includes/class-wp-network-query.php
    index d381e60117..13c6cd094a 100644
    class WP_Network_Query { 
    197197                 */
    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 ) );
     200                $network_ids = null;
    202201
    203                 // Ignore the $fields argument as the queried result will be the same regardless.
    204                 unset( $_args['fields'] );
     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 ) );
    205215
    206                 $key          = md5( serialize( $_args ) );
    207                 $last_changed = wp_cache_get_last_changed( 'networks' );
     216                if ( null === $network_ids ) {
    208217
    209                 $cache_key   = "get_network_ids:$key:$last_changed";
    210                 $cache_value = wp_cache_get( $cache_key, 'networks' );
     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 ) );
    211220
    212                 if ( false === $cache_value ) {
    213                         $network_ids = $this->get_network_ids();
    214                         if ( $network_ids ) {
    215                                 $this->set_found_networks();
    216                         }
     221                        // Ignore the $fields argument as the queried result will be the same regardless.
     222                        unset( $_args['fields'] );
    217223
    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'];
     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'];
     244                        }
    226245                }
    227246
    228247                if ( $this->found_networks && $this->query_vars['number'] ) {
  • src/wp-includes/class-wp-site-query.php

    diff --git src/wp-includes/class-wp-site-query.php src/wp-includes/class-wp-site-query.php
    index bc3e3519a3..507c611e24 100644
    class WP_Site_Query { 
    288288                        $this->meta_query_clauses = $this->meta_query->get_sql( 'blog', $wpdb->blogs, 'blog_id', $this );
    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 ) );
     291                $site_ids = null;
    293292
    294                 // Ignore the $fields argument as the queried result will be the same regardless.
    295                 unset( $_args['fields'] );
     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 ) );
    296306
    297                 $key          = md5( serialize( $_args ) );
    298                 $last_changed = wp_cache_get_last_changed( 'sites' );
     307                if ( null === $site_ids ) {
    299308
    300                 $cache_key   = "get_sites:$key:$last_changed";
    301                 $cache_value = wp_cache_get( $cache_key, 'sites' );
     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 ) );
    302311
    303                 if ( false === $cache_value ) {
    304                         $site_ids = $this->get_site_ids();
    305                         if ( $site_ids ) {
    306                                 $this->set_found_sites();
    307                         }
     312                        // Ignore the $fields argument as the queried result will be the same regardless.
     313                        unset( $_args['fields'] );
    308314
    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'];
     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'];
     335                        }
    317336                }
    318337
    319338                if ( $this->found_sites && $this->query_vars['number'] ) {
  • tests/phpunit/tests/multisite/networkQuery.php

    diff --git tests/phpunit/tests/multisite/networkQuery.php tests/phpunit/tests/multisite/networkQuery.php
    index 6ec7f16c42..0b48fdc8d5 100644
    if ( is_multisite() ) : 
    522522                        );
    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
    527562endif;
  • tests/phpunit/tests/multisite/siteQuery.php

    diff --git tests/phpunit/tests/multisite/siteQuery.php tests/phpunit/tests/multisite/siteQuery.php
    index bac9269ff4..c17f977932 100644
    if ( is_multisite() ) : 
    911911                        }
    912912                }
    913913
     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 );
     948                }
     949
    914950                public function data_wp_site_query_meta_query() {
    915951                        return array(
    916952                                array(