Make WordPress Core


Ignore:
Timestamp:
04/27/2018 11:40:35 AM (8 years ago)
Author:
flixos90
Message:

Multisite: Add meta query functionality to WP_Site_Query.

After the introduction of site metadata in [42836], it should be possible to query sites by that data.

Fixes #40229.

File:
1 edited

Legend:

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

    r42876 r43010  
    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         *
    … …  
    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 {
    … …  
    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         */
    … …  
    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
    … …  
    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();
     271
     272                // Parse meta query.
     273                $this->meta_query = new WP_Meta_Query();
     274                $this->meta_query->parse_query_vars( $this->query_vars );
    236275
    237276                /**
    … …  
    243282                 */
    244283                do_action_ref_array( 'pre_get_sites', array( &$this ) );
     284
     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                }
    245290
    246291                // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
    … …  
    371416                        $orderby = implode( ', ', $orderby_array );
    372417                } else {
    373                         $orderby = "blog_id $order";
     418                        $orderby = "{$wpdb->blogs}.blog_id $order";
    374419                }
    375420
    … …  
    388433                        $fields = 'COUNT(*)';
    389434                } else {
    390                         $fields = 'blog_id';
     435                        $fields = "{$wpdb->blogs}.blog_id";
    391436                }
    392437
    … …  
    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
    … …  
    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
    … …  
    676732                                break;
    677733                        case 'id':
    678                                 $parsed = 'blog_id';
    679                                 break;
     734                                $parsed = "{$wpdb->blogs}.blog_id";
     735                                break;
     736                }
     737
     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                                }
    680768                }
    681769
Note: See TracChangeset for help on using the changeset viewer.