Make WordPress Core


Ignore:
Timestamp:
04/27/2018 11:40:35 AM (7 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.