WordPress.org

Make WordPress Core

Ticket #40229: 40229.diff

File 40229.diff, 15.3 KB (added by flixos90, 2 years ago)
  • src/wp-includes/class-wp-site-query.php

     
    4040        );
    4141
    4242        /**
     43         * Metadata query container.
     44         *
     45         * @since 5.0.0
     46         * @var WP_Meta_Query
     47         */
     48        public $meta_query = false;
     49
     50        /**
     51         * Metadata query clauses.
     52         *
     53         * @since 5.0.0
     54         * @var array
     55         */
     56        protected $meta_query_clauses;
     57
     58        /**
    4359         * Date query container.
    4460         *
    4561         * @since 4.6.0
     
    92108         *
    93109         * @since 4.6.0
    94110         * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters.
    95          * @since 5.0.0 Introduced the 'update_site_meta_cache' parameter.
     111         * @since 5.0.0 Introduced the 'update_site_meta_cache', 'meta_query', 'meta_key',
     112         *              'meta_value', 'meta_type' and 'meta_compare' parameters.
    96113         *
    97114         * @param string|array $query {
    98115         *     Optional. Array or query string of site query parameters. Default empty.
     
    139156         *                                                Default empty array.
    140157         *     @type bool         $update_site_cache      Whether to prime the cache for found sites. Default true.
    141158         *     @type bool         $update_site_meta_cache Whether to prime the metadata cache for found sites. Default true.
     159         *     @type array        $meta_query             Meta query clauses to limit retrieved sites by. See `WP_Meta_Query`.
     160         *                                                Default empty.
     161         *     @type string       $meta_key               Limit sites to those matching a specific metadata key.
     162         *                                                Can be used in conjunction with `$meta_value`. Default empty.
     163         *     @type string       $meta_value             Limit sites to those matching a specific metadata value.
     164         *                                                Usually used in conjunction with `$meta_key`. Default empty.
     165         *     @type string       $meta_type              Data type that the `$meta_value` column will be CAST to for
     166         *                                                comparisons. Default empty.
     167         *     @type string       $meta_compare           Comparison operator to test the `$meta_value`. Default empty.
    142168         * }
    143169         */
    144170        public function __construct( $query = '' ) {
     
    175201                        'date_query'             => null, // See WP_Date_Query
    176202                        'update_site_cache'      => true,
    177203                        'update_site_meta_cache' => true,
     204                        'meta_query'             => '',
     205                        'meta_key'               => '',
     206                        'meta_value'             => '',
     207                        'meta_type'              => '',
     208                        'meta_compare'           => '',
    178209                );
    179210
    180211                if ( ! empty( $query ) ) {
     
    228259         *
    229260         * @since 4.6.0
    230261         *
     262         * @global wpdb $wpdb WordPress database abstraction object.
     263         *
    231264         * @return array|int List of WP_Site objects, a list of site ids when 'fields' is set to 'ids',
    232265         *                   or the number of sites when 'count' is passed as a query var.
    233266         */
    234267        public function get_sites() {
     268                global $wpdb;
     269
    235270                $this->parse_query();
    236271
     272                // Parse meta query.
     273                $this->meta_query = new WP_Meta_Query();
     274                $this->meta_query->parse_query_vars( $this->query_vars );
     275
    237276                /**
    238277                 * Fires before sites are retrieved.
    239278                 *
     
    243282                 */
    244283                do_action_ref_array( 'pre_get_sites', array( &$this ) );
    245284
     285                // Reparse query vars, in case they were modified in a 'pre_get_sites' callback.
     286                $this->meta_query->parse_query_vars( $this->query_vars );
     287                if ( ! empty( $this->meta_query->queries ) ) {
     288                        $this->meta_query_clauses = $this->meta_query->get_sql( 'blog', $wpdb->blogs, 'blog_id', $this );
     289                }
     290
    246291                // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
    247292                $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
    248293
     
    370415
    371416                        $orderby = implode( ', ', $orderby_array );
    372417                } else {
    373                         $orderby = "blog_id $order";
     418                        $orderby = "{$wpdb->blogs}.blog_id $order";
    374419                }
    375420
    376421                $number = absint( $this->query_vars['number'] );
     
    387432                if ( $this->query_vars['count'] ) {
    388433                        $fields = 'COUNT(*)';
    389434                } else {
    390                         $fields = 'blog_id';
     435                        $fields = "{$wpdb->blogs}.blog_id";
    391436                }
    392437
    393438                // Parse site IDs for an IN clause.
    394439                $site_id = absint( $this->query_vars['ID'] );
    395440                if ( ! empty( $site_id ) ) {
    396                         $this->sql_clauses['where']['ID'] = $wpdb->prepare( 'blog_id = %d', $site_id );
     441                        $this->sql_clauses['where']['ID'] = $wpdb->prepare( "{$wpdb->blogs}.blog_id = %d", $site_id );
    397442                }
    398443
    399444                // Parse site IDs for an IN clause.
    400445                if ( ! empty( $this->query_vars['site__in'] ) ) {
    401                         $this->sql_clauses['where']['site__in'] = 'blog_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['site__in'] ) ) . ' )';
     446                        $this->sql_clauses['where']['site__in'] = "{$wpdb->blogs}.blog_id IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['site__in'] ) ) . ' )';
    402447                }
    403448
    404449                // Parse site IDs for a NOT IN clause.
    405450                if ( ! empty( $this->query_vars['site__not_in'] ) ) {
    406                         $this->sql_clauses['where']['site__not_in'] = 'blog_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['site__not_in'] ) ) . ' )';
     451                        $this->sql_clauses['where']['site__not_in'] = "{$wpdb->blogs}.blog_id NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['site__not_in'] ) ) . ' )';
    407452                }
    408453
    409454                $network_id = absint( $this->query_vars['network_id'] );
     
    526571
    527572                $join = '';
    528573
     574                if ( ! empty( $this->meta_query_clauses ) ) {
     575                        $join .= $this->meta_query_clauses['join'];
     576
     577                        // Strip leading 'AND'.
     578                        $this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $this->meta_query_clauses['where'] );
     579
     580                        if ( ! $this->query_vars['count'] ) {
     581                                $groupby = "{$wpdb->blogs}.blog_id";
     582                        }
     583                }
     584
    529585                $where = implode( ' AND ', $this->sql_clauses['where'] );
    530586
    531587                $pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
     
    675731                                $parsed = 'CHAR_LENGTH(path)';
    676732                                break;
    677733                        case 'id':
    678                                 $parsed = 'blog_id';
     734                                $parsed = "{$wpdb->blogs}.blog_id";
    679735                                break;
    680736                }
    681737
     738                if ( ! empty( $parsed ) || empty( $this->meta_query_clauses ) ) {
     739                        return $parsed;
     740                }
     741
     742                $meta_clauses = $this->meta_query->get_clauses();
     743                if ( empty( $meta_clauses ) ) {
     744                        return $parsed;
     745                }
     746
     747                $primary_meta_query = reset( $meta_clauses );
     748                if ( ! empty( $primary_meta_query['key'] ) && $primary_meta_query['key'] === $orderby ) {
     749                        $orderby = 'meta_value';
     750                }
     751
     752                switch ( $orderby ) {
     753                        case 'meta_value':
     754                                if ( ! empty( $primary_meta_query['type'] ) ) {
     755                                        $parsed = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
     756                                } else {
     757                                        $parsed = "{$primary_meta_query['alias']}.meta_value";
     758                                }
     759                                break;
     760                        case 'meta_value_num':
     761                                $parsed = "{$primary_meta_query['alias']}.meta_value+0";
     762                                break;
     763                        default:
     764                                if ( isset( $meta_clauses[ $orderby ] ) ) {
     765                                        $meta_clause = $meta_clauses[ $orderby ];
     766                                        $parsed      = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
     767                                }
     768                }
     769
    682770                return $parsed;
    683771        }
    684772
  • src/wp-settings.php

     
    9898require( ABSPATH . WPINC . '/formatting.php' );
    9999require( ABSPATH . WPINC . '/meta.php' );
    100100require( ABSPATH . WPINC . '/functions.php' );
     101require( ABSPATH . WPINC . '/class-wp-meta-query.php' );
    101102require( ABSPATH . WPINC . '/class-wp-matchesmapregex.php' );
    102103require( ABSPATH . WPINC . '/class-wp.php' );
    103104require( ABSPATH . WPINC . '/class-wp-error.php' );
     
    159160require( ABSPATH . WPINC . '/class-wp-user-query.php' );
    160161require( ABSPATH . WPINC . '/class-wp-session-tokens.php' );
    161162require( ABSPATH . WPINC . '/class-wp-user-meta-session-tokens.php' );
    162 require( ABSPATH . WPINC . '/class-wp-meta-query.php' );
    163163require( ABSPATH . WPINC . '/class-wp-metadata-lazyloader.php' );
    164164require( ABSPATH . WPINC . '/general-template.php' );
    165165require( ABSPATH . WPINC . '/link-template.php' );
  • tests/phpunit/tests/multisite/siteMeta.php

     
    256256                get_site_meta( self::$site_id, 'foo', true );
    257257                $this->assertSame( $num_queries + 1, $wpdb->num_queries);
    258258        }
     259
     260        /**
     261         * @ticket 40229
     262         */
     263        public function test_add_site_meta_should_bust_get_sites_cache() {
     264                if ( ! is_site_meta_supported() ) {
     265                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     266                }
     267
     268                add_site_meta( self::$site_id, 'foo', 'bar' );
     269
     270                // Prime cache.
     271                $found = get_sites( array(
     272                        'fields' => 'ids',
     273                        'meta_query' => array(
     274                                array(
     275                                        'key' => 'foo',
     276                                        'value' => 'bar',
     277                                ),
     278                        ),
     279                ) );
     280
     281                $this->assertEqualSets( array( self::$site_id ), $found );
     282
     283                add_site_meta( self::$site_id2, 'foo', 'bar' );
     284
     285                $found = get_sites( array(
     286                        'fields' => 'ids',
     287                        'meta_query' => array(
     288                                array(
     289                                        'key' => 'foo',
     290                                        'value' => 'bar',
     291                                ),
     292                        ),
     293                ) );
     294
     295                $this->assertEqualSets( array( self::$site_id, self::$site_id2 ), $found );
     296        }
     297
     298        /**
     299         * @ticket 40229
     300         */
     301        public function test_update_site_meta_should_bust_get_sites_cache() {
     302                if ( ! is_site_meta_supported() ) {
     303                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     304                }
     305
     306                add_site_meta( self::$site_id, 'foo', 'bar' );
     307                add_site_meta( self::$site_id2, 'foo', 'baz' );
     308
     309                // Prime cache.
     310                $found = get_sites( array(
     311                        'fields' => 'ids',
     312                        'meta_query' => array(
     313                                array(
     314                                        'key' => 'foo',
     315                                        'value' => 'bar',
     316                                ),
     317                        ),
     318                ) );
     319
     320                $this->assertEqualSets( array( self::$site_id ), $found );
     321
     322                update_site_meta( self::$site_id2, 'foo', 'bar' );
     323
     324                $found = get_sites( array(
     325                        'fields' => 'ids',
     326                        'meta_query' => array(
     327                                array(
     328                                        'key' => 'foo',
     329                                        'value' => 'bar',
     330                                ),
     331                        ),
     332                ) );
     333
     334                $this->assertEqualSets( array( self::$site_id, self::$site_id2 ), $found );
     335        }
     336
     337        /**
     338         * @ticket 40229
     339         */
     340        public function test_delete_site_meta_should_bust_get_sites_cache() {
     341                if ( ! is_site_meta_supported() ) {
     342                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     343                }
     344
     345                add_site_meta( self::$site_id, 'foo', 'bar' );
     346                add_site_meta( self::$site_id2, 'foo', 'bar' );
     347
     348                // Prime cache.
     349                $found = get_sites( array(
     350                        'fields' => 'ids',
     351                        'meta_query' => array(
     352                                array(
     353                                        'key' => 'foo',
     354                                        'value' => 'bar',
     355                                ),
     356                        ),
     357                ) );
     358
     359                $this->assertEqualSets( array( self::$site_id, self::$site_id2 ), $found );
     360
     361                delete_site_meta( self::$site_id2, 'foo', 'bar' );
     362
     363                $found = get_sites( array(
     364                        'fields' => 'ids',
     365                        'meta_query' => array(
     366                                array(
     367                                        'key' => 'foo',
     368                                        'value' => 'bar',
     369                                ),
     370                        ),
     371                ) );
     372
     373                $this->assertEqualSets( array( self::$site_id ), $found );
     374        }
    259375}
    260376
    261377endif;
  • tests/phpunit/tests/multisite/siteQuery.php

     
    878878                        );
    879879                        $this->assertEquals( $number_of_queries + 1, $wpdb->num_queries );
    880880                }
     881
     882                /**
     883                 * @ticket 40229
     884                 * @dataProvider data_wp_site_query_meta_query
     885                 */
     886                public function test_wp_site_query_meta_query( $query, $expected, $strict ) {
     887                        if ( ! is_site_meta_supported() ) {
     888                                $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     889                        }
     890
     891                        add_site_meta( self::$site_ids['wordpress.org/'], 'foo', 'foo' );
     892                        add_site_meta( self::$site_ids['wordpress.org/foo/'], 'foo', 'bar' );
     893                        add_site_meta( self::$site_ids['wordpress.org/foo/bar/'], 'foo', 'baz' );
     894                        add_site_meta( self::$site_ids['make.wordpress.org/'], 'bar', 'baz' );
     895                        add_site_meta( self::$site_ids['wordpress.org/'], 'numberfoo', 1 );
     896                        add_site_meta( self::$site_ids['wordpress.org/foo/'], 'numberfoo', 2 );
     897
     898                        $query['fields'] = 'ids';
     899
     900                        $q     = new WP_Site_Query();
     901                        $found = $q->query( $query );
     902
     903                        foreach ( $expected as $index => $domain_path ) {
     904                                $expected[ $index ] = self::$site_ids[ $domain_path ];
     905                        }
     906
     907                        if ( $strict ) {
     908                                $this->assertEquals( $expected, $found );
     909                        } else {
     910                                $this->assertEqualSets( $expected, $found );
     911                        }
     912                }
     913
     914                public function data_wp_site_query_meta_query() {
     915                        return array(
     916                                array(
     917                                        array(
     918                                                'meta_key' => 'foo',
     919                                        ),
     920                                        array(
     921                                                'wordpress.org/',
     922                                                'wordpress.org/foo/',
     923                                                'wordpress.org/foo/bar/',
     924                                        ),
     925                                        false,
     926                                ),
     927                                array(
     928                                        array(
     929                                                'meta_key'   => 'foo',
     930                                                'meta_value' => 'bar',
     931                                        ),
     932                                        array(
     933                                                'wordpress.org/foo/',
     934                                        ),
     935                                        false,
     936                                ),
     937                                array(
     938                                        array(
     939                                                'meta_key'     => 'foo',
     940                                                'meta_value'   => array( 'bar', 'baz' ),
     941                                                'meta_compare' => 'IN',
     942                                        ),
     943                                        array(
     944                                                'wordpress.org/foo/',
     945                                                'wordpress.org/foo/bar/',
     946                                        ),
     947                                        false,
     948                                ),
     949                                array(
     950                                        array(
     951                                                'meta_query' => array(
     952                                                        array(
     953                                                                'key'   => 'foo',
     954                                                                'value' => 'bar',
     955                                                        ),
     956                                                        array(
     957                                                                'key'   => 'numberfoo',
     958                                                                'value' => 2,
     959                                                                'type'  => 'NUMERIC',
     960                                                        ),
     961                                                ),
     962                                        ),
     963                                        array(
     964                                                'wordpress.org/foo/',
     965                                        ),
     966                                        false,
     967                                ),
     968                                array(
     969                                        array(
     970                                                'meta_key' => 'foo',
     971                                                'orderby'  => 'meta_value',
     972                                                'order'    => 'ASC',
     973                                        ),
     974                                        array(
     975                                                'wordpress.org/foo/',
     976                                                'wordpress.org/foo/bar/',
     977                                                'wordpress.org/',
     978                                        ),
     979                                        true,
     980                                ),
     981                                array(
     982                                        array(
     983                                                'meta_key' => 'foo',
     984                                                'orderby'  => 'foo',
     985                                                'order'    => 'ASC',
     986                                        ),
     987                                        array(
     988                                                'wordpress.org/foo/',
     989                                                'wordpress.org/foo/bar/',
     990                                                'wordpress.org/',
     991                                        ),
     992                                        true,
     993                                ),
     994                                array(
     995                                        array(
     996                                                'meta_key' => 'numberfoo',
     997                                                'orderby'  => 'meta_value_num',
     998                                                'order'    => 'DESC',
     999                                        ),
     1000                                        array(
     1001                                                'wordpress.org/foo/',
     1002                                                'wordpress.org/',
     1003                                        ),
     1004                                        true,
     1005                                ),
     1006                                array(
     1007                                        array(
     1008                                                'meta_query' => array(
     1009                                                        array(
     1010                                                                'key'     => 'foo',
     1011                                                                'value'   => array( 'foo', 'bar' ),
     1012                                                                'compare' => 'IN',
     1013                                                        ),
     1014                                                        array(
     1015                                                                'key' => 'numberfoo',
     1016                                                        ),
     1017                                                ),
     1018                                                'orderby'    => array( 'meta_value' => 'ASC' ),
     1019                                        ),
     1020                                        array(
     1021                                                'wordpress.org/foo/',
     1022                                                'wordpress.org/',
     1023                                        ),
     1024                                        true,
     1025                                ),
     1026                                array(
     1027                                        array(
     1028                                                'meta_query' => array(
     1029                                                        array(
     1030                                                                'key'     => 'foo',
     1031                                                                'value'   => array( 'foo', 'bar' ),
     1032                                                                'compare' => 'IN',
     1033                                                        ),
     1034                                                        array(
     1035                                                                'key' => 'numberfoo',
     1036                                                        ),
     1037                                                ),
     1038                                                'orderby'    => array( 'foo' => 'ASC' ),
     1039                                        ),
     1040                                        array(
     1041                                                'wordpress.org/foo/',
     1042                                                'wordpress.org/',
     1043                                        ),
     1044                                        true,
     1045                                ),
     1046                                array(
     1047                                        array(
     1048                                                'meta_query' => array(
     1049                                                        array(
     1050                                                                'key'     => 'foo',
     1051                                                                'value'   => array( 'foo', 'bar' ),
     1052                                                                'compare' => 'IN',
     1053                                                        ),
     1054                                                        'my_subquery' => array(
     1055                                                                'key' => 'numberfoo',
     1056                                                        ),
     1057                                                ),
     1058                                                'orderby'    => array( 'my_subquery' => 'DESC' ),
     1059                                        ),
     1060                                        array(
     1061                                                'wordpress.org/foo/',
     1062                                                'wordpress.org/',
     1063                                        ),
     1064                                        true,
     1065                                ),
     1066                        );
     1067                }
    8811068        }
    8821069
    8831070endif;