~canonical-sysadmins/wordpress/4.8.1

« back to all changes in this revision

Viewing changes to wp-includes/class-wp-site-query.php

  • Committer: Barry Price
  • Date: 2016-08-17 04:50:12 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: barry.price@canonical.com-20160817045012-qfui81zhqnqv2ba9
Merge WP4.6 from upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Site API: WP_Site_Query class
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Sites
 
7
 * @since 4.6.0
 
8
 */
 
9
 
 
10
/**
 
11
 * Core class used for querying sites.
 
12
 *
 
13
 * @since 4.6.0
 
14
 *
 
15
 * @see WP_Site_Query::__construct() for accepted arguments.
 
16
 */
 
17
class WP_Site_Query {
 
18
 
 
19
        /**
 
20
         * SQL for database query.
 
21
         *
 
22
         * @since 4.6.0
 
23
         * @access public
 
24
         * @var string
 
25
         */
 
26
        public $request;
 
27
 
 
28
        /**
 
29
         * SQL query clauses.
 
30
         *
 
31
         * @since 4.6.0
 
32
         * @access protected
 
33
         * @var array
 
34
         */
 
35
        protected $sql_clauses = array(
 
36
                'select'  => '',
 
37
                'from'    => '',
 
38
                'where'   => array(),
 
39
                'groupby' => '',
 
40
                'orderby' => '',
 
41
                'limits'  => '',
 
42
        );
 
43
 
 
44
        /**
 
45
         * Date query container.
 
46
         *
 
47
         * @since 4.6.0
 
48
         * @access public
 
49
         * @var object WP_Date_Query
 
50
         */
 
51
        public $date_query = false;
 
52
 
 
53
        /**
 
54
         * Query vars set by the user.
 
55
         *
 
56
         * @since 4.6.0
 
57
         * @access public
 
58
         * @var array
 
59
         */
 
60
        public $query_vars;
 
61
 
 
62
        /**
 
63
         * Default values for query vars.
 
64
         *
 
65
         * @since 4.6.0
 
66
         * @access public
 
67
         * @var array
 
68
         */
 
69
        public $query_var_defaults;
 
70
 
 
71
        /**
 
72
         * List of sites located by the query.
 
73
         *
 
74
         * @since 4.6.0
 
75
         * @access public
 
76
         * @var array
 
77
         */
 
78
        public $sites;
 
79
 
 
80
        /**
 
81
         * The amount of found sites for the current query.
 
82
         *
 
83
         * @since 4.6.0
 
84
         * @access public
 
85
         * @var int
 
86
         */
 
87
        public $found_sites = 0;
 
88
 
 
89
        /**
 
90
         * The number of pages.
 
91
         *
 
92
         * @since 4.6.0
 
93
         * @access public
 
94
         * @var int
 
95
         */
 
96
        public $max_num_pages = 0;
 
97
 
 
98
        /**
 
99
         * Sets up the site query, based on the query vars passed.
 
100
         *
 
101
         * @since 4.6.0
 
102
         * @access public
 
103
         *
 
104
         * @param string|array $query {
 
105
         *     Optional. Array or query string of site query parameters. Default empty.
 
106
         *
 
107
         *     @type array        $site__in          Array of site IDs to include. Default empty.
 
108
         *     @type array        $site__not_in      Array of site IDs to exclude. Default empty.
 
109
         *     @type bool         $count             Whether to return a site count (true) or array of site objects.
 
110
         *                                           Default false.
 
111
         *     @type array        $date_query        Date query clauses to limit sites by. See WP_Date_Query.
 
112
         *                                           Default null.
 
113
         *     @type string       $fields            Site fields to return. Accepts 'ids' (returns an array of site IDs)
 
114
         *                                           or empty (returns an array of complete site objects). Default empty.
 
115
         *     @type int          $ID                A site ID to only return that site. Default empty.
 
116
         *     @type int          $number            Maximum number of sites to retrieve. Default null (no limit).
 
117
         *     @type int          $offset            Number of sites to offset the query. Used to build LIMIT clause.
 
118
         *                                           Default 0.
 
119
         *     @type bool         $no_found_rows     Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
 
120
         *     @type string|array $orderby           Site status or array of statuses. Accepts 'id', 'domain', 'path',
 
121
         *                                           'network_id', 'last_updated', 'registered', 'domain_length',
 
122
         *                                           'path_length', 'site__in' and 'network__in'. Also accepts false,
 
123
         *                                           an empty array, or 'none' to disable `ORDER BY` clause.
 
124
         *                                           Default 'id'.
 
125
         *     @type string       $order             How to order retrieved sites. Accepts 'ASC', 'DESC'. Default 'ASC'.
 
126
         *     @type int          $network_id        Limit results to those affiliated with a given network ID. If 0,
 
127
         *                                           include all networks. Default 0.
 
128
         *     @type array        $network__in       Array of network IDs to include affiliated sites for. Default empty.
 
129
         *     @type array        $network__not_in   Array of network IDs to exclude affiliated sites for. Default empty.
 
130
         *     @type string       $domain            Limit results to those affiliated with a given domain.
 
131
         *                                           Default empty.
 
132
         *     @type array        $domain__in        Array of domains to include affiliated sites for. Default empty.
 
133
         *     @type array        $domain__not_in    Array of domains to exclude affiliated sites for. Default empty.
 
134
         *     @type string       $path              Limit results to those affiliated with a given path.
 
135
         *                                           Default empty.
 
136
         *     @type array        $path__in          Array of paths to include affiliated sites for. Default empty.
 
137
         *     @type array        $path__not_in      Array of paths to exclude affiliated sites for. Default empty.
 
138
         *     @type int          $public            Limit results to public sites. Accepts '1' or '0'. Default empty.
 
139
         *     @type int          $archived          Limit results to archived sites. Accepts '1' or '0'. Default empty.
 
140
         *     @type int          $mature            Limit results to mature sites. Accepts '1' or '0'. Default empty.
 
141
         *     @type int          $spam              Limit results to spam sites. Accepts '1' or '0'. Default empty.
 
142
         *     @type int          $deleted           Limit results to deleted sites. Accepts '1' or '0'. Default empty.
 
143
         *     @type string       $search            Search term(s) to retrieve matching sites for. Default empty.
 
144
         *     @type array        $search_columns    Array of column names to be searched. Accepts 'domain' and 'path'.
 
145
         *                                           Default empty array.
 
146
         *     @type bool         $update_site_cache Whether to prime the cache for found sites. Default false.
 
147
         * }
 
148
         */
 
149
        public function __construct( $query = '' ) {
 
150
                $this->query_var_defaults = array(
 
151
                        'fields'            => '',
 
152
                        'ID'                => '',
 
153
                        'site__in'          => '',
 
154
                        'site__not_in'      => '',
 
155
                        'number'            => 100,
 
156
                        'offset'            => '',
 
157
                        'no_found_rows'     => true,
 
158
                        'orderby'           => 'id',
 
159
                        'order'             => 'ASC',
 
160
                        'network_id'        => 0,
 
161
                        'network__in'       => '',
 
162
                        'network__not_in'   => '',
 
163
                        'domain'            => '',
 
164
                        'domain__in'        => '',
 
165
                        'domain__not_in'    => '',
 
166
                        'path'              => '',
 
167
                        'path__in'          => '',
 
168
                        'path__not_in'      => '',
 
169
                        'public'            => null,
 
170
                        'archived'          => null,
 
171
                        'mature'            => null,
 
172
                        'spam'              => null,
 
173
                        'deleted'           => null,
 
174
                        'search'            => '',
 
175
                        'search_columns'    => array(),
 
176
                        'count'             => false,
 
177
                        'date_query'        => null, // See WP_Date_Query
 
178
                        'update_site_cache' => true,
 
179
                );
 
180
 
 
181
                if ( ! empty( $query ) ) {
 
182
                        $this->query( $query );
 
183
                }
 
184
        }
 
185
 
 
186
        /**
 
187
         * Parses arguments passed to the site query with default query parameters.
 
188
         *
 
189
         * @since 4.6.0
 
190
         * @access public
 
191
         *
 
192
         * @see WP_Site_Query::__construct()
 
193
         *
 
194
         * @param string|array $query Array or string of WP_Site_Query arguments. See WP_Site_Query::__construct().
 
195
         */
 
196
        public function parse_query( $query = '' ) {
 
197
                if ( empty( $query ) ) {
 
198
                        $query = $this->query_vars;
 
199
                }
 
200
 
 
201
                $this->query_vars = wp_parse_args( $query, $this->query_var_defaults );
 
202
 
 
203
                /**
 
204
                 * Fires after the site query vars have been parsed.
 
205
                 *
 
206
                 * @since 4.6.0
 
207
                 *
 
208
                 * @param WP_Site_Query &$this The WP_Site_Query instance (passed by reference).
 
209
                 */
 
210
                do_action_ref_array( 'parse_site_query', array( &$this ) );
 
211
        }
 
212
 
 
213
        /**
 
214
         * Sets up the WordPress query for retrieving sites.
 
215
         *
 
216
         * @since 4.6.0
 
217
         * @access public
 
218
         *
 
219
         * @param string|array $query Array or URL query string of parameters.
 
220
         * @return array|int List of sites, or number of sites when 'count' is passed as a query var.
 
221
         */
 
222
        public function query( $query ) {
 
223
                $this->query_vars = wp_parse_args( $query );
 
224
 
 
225
                return $this->get_sites();
 
226
        }
 
227
 
 
228
        /**
 
229
         * Retrieves a list of sites matching the query vars.
 
230
         *
 
231
         * @since 4.6.0
 
232
         * @access public
 
233
         *
 
234
         * @return array|int List of sites, or number of sites when 'count' is passed as a query var.
 
235
         */
 
236
        public function get_sites() {
 
237
                $this->parse_query();
 
238
 
 
239
                /**
 
240
                 * Fires before sites are retrieved.
 
241
                 *
 
242
                 * @since 4.6.0
 
243
                 *
 
244
                 * @param WP_Site_Query &$this Current instance of WP_Site_Query, passed by reference.
 
245
                 */
 
246
                do_action_ref_array( 'pre_get_sites', array( &$this ) );
 
247
 
 
248
                // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
 
249
                $key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) );
 
250
                $last_changed = wp_cache_get( 'last_changed', 'sites' );
 
251
                if ( ! $last_changed ) {
 
252
                        $last_changed = microtime();
 
253
                        wp_cache_set( 'last_changed', $last_changed, 'sites' );
 
254
                }
 
255
 
 
256
                $cache_key = "get_sites:$key:$last_changed";
 
257
                $cache_value = wp_cache_get( $cache_key, 'sites' );
 
258
 
 
259
                if ( false === $cache_value ) {
 
260
                        $site_ids = $this->get_site_ids();
 
261
                        if ( $site_ids ) {
 
262
                                $this->set_found_sites();
 
263
                        }
 
264
 
 
265
                        $cache_value = array(
 
266
                                'site_ids' => $site_ids,
 
267
                                'found_sites' => $this->found_sites,
 
268
                        );
 
269
                        wp_cache_add( $cache_key, $cache_value, 'sites' );
 
270
                } else {
 
271
                        $site_ids = $cache_value['site_ids'];
 
272
                        $this->found_sites = $cache_value['found_sites'];
 
273
                }
 
274
 
 
275
                if ( $this->found_sites && $this->query_vars['number'] ) {
 
276
                        $this->max_num_pages = ceil( $this->found_sites / $this->query_vars['number'] );
 
277
                }
 
278
 
 
279
                // If querying for a count only, there's nothing more to do.
 
280
                if ( $this->query_vars['count'] ) {
 
281
                        // $site_ids is actually a count in this case.
 
282
                        return intval( $site_ids );
 
283
                }
 
284
 
 
285
                $site_ids = array_map( 'intval', $site_ids );
 
286
 
 
287
                if ( 'ids' == $this->query_vars['fields'] ) {
 
288
                        $this->sites = $site_ids;
 
289
 
 
290
                        return $this->sites;
 
291
                }
 
292
 
 
293
                // Prime site network caches.
 
294
                if ( $this->query_vars['update_site_cache'] ) {
 
295
                        _prime_site_caches( $site_ids );
 
296
                }
 
297
 
 
298
                // Fetch full site objects from the primed cache.
 
299
                $_sites = array();
 
300
                foreach ( $site_ids as $site_id ) {
 
301
                        if ( $_site = get_site( $site_id ) ) {
 
302
                                $_sites[] = $_site;
 
303
                        }
 
304
                }
 
305
 
 
306
                /**
 
307
                 * Filters the site query results.
 
308
                 *
 
309
                 * @since 4.6.0
 
310
                 *
 
311
                 * @param array         $results An array of sites.
 
312
                 * @param WP_Site_Query &$this   Current instance of WP_Site_Query, passed by reference.
 
313
                 */
 
314
                $_sites = apply_filters_ref_array( 'the_sites', array( $_sites, &$this ) );
 
315
 
 
316
                // Convert to WP_Site instances.
 
317
                $this->sites = array_map( 'get_site', $_sites );
 
318
 
 
319
                return $this->sites;
 
320
        }
 
321
 
 
322
        /**
 
323
         * Used internally to get a list of site IDs matching the query vars.
 
324
         *
 
325
         * @since 4.6.0
 
326
         * @access protected
 
327
         *
 
328
         * @global wpdb $wpdb WordPress database abstraction object.
 
329
         *
 
330
         * @return int|array A single count of site IDs if a count query. An array of site IDs if a full query.
 
331
         */
 
332
        protected function get_site_ids() {
 
333
                global $wpdb;
 
334
 
 
335
                $order = $this->parse_order( $this->query_vars['order'] );
 
336
 
 
337
                // Disable ORDER BY with 'none', an empty array, or boolean false.
 
338
                if ( in_array( $this->query_vars['orderby'], array( 'none', array(), false ), true ) ) {
 
339
                        $orderby = '';
 
340
                } elseif ( ! empty( $this->query_vars['orderby'] ) ) {
 
341
                        $ordersby = is_array( $this->query_vars['orderby'] ) ?
 
342
                                $this->query_vars['orderby'] :
 
343
                                preg_split( '/[,\s]/', $this->query_vars['orderby'] );
 
344
 
 
345
                        $orderby_array = array();
 
346
                        foreach ( $ordersby as $_key => $_value ) {
 
347
                                if ( ! $_value ) {
 
348
                                        continue;
 
349
                                }
 
350
 
 
351
                                if ( is_int( $_key ) ) {
 
352
                                        $_orderby = $_value;
 
353
                                        $_order = $order;
 
354
                                } else {
 
355
                                        $_orderby = $_key;
 
356
                                        $_order = $_value;
 
357
                                }
 
358
 
 
359
                                $parsed = $this->parse_orderby( $_orderby );
 
360
 
 
361
                                if ( ! $parsed ) {
 
362
                                        continue;
 
363
                                }
 
364
 
 
365
                                if ( 'site__in' === $_orderby || 'network__in' === $_orderby ) {
 
366
                                        $orderby_array[] = $parsed;
 
367
                                        continue;
 
368
                                }
 
369
 
 
370
                                $orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
 
371
                        }
 
372
 
 
373
                        $orderby = implode( ', ', $orderby_array );
 
374
                } else {
 
375
                        $orderby = "blog_id $order";
 
376
                }
 
377
 
 
378
                $number = absint( $this->query_vars['number'] );
 
379
                $offset = absint( $this->query_vars['offset'] );
 
380
 
 
381
                if ( ! empty( $number ) ) {
 
382
                        if ( $offset ) {
 
383
                                $limits = 'LIMIT ' . $offset . ',' . $number;
 
384
                        } else {
 
385
                                $limits = 'LIMIT ' . $number;
 
386
                        }
 
387
                }
 
388
 
 
389
                if ( $this->query_vars['count'] ) {
 
390
                        $fields = 'COUNT(*)';
 
391
                } else {
 
392
                        $fields = 'blog_id';
 
393
                }
 
394
 
 
395
                // Parse site IDs for an IN clause.
 
396
                $site_id = absint( $this->query_vars['ID'] );
 
397
                if ( ! empty( $site_id ) ) {
 
398
                        $this->sql_clauses['where']['ID'] = $wpdb->prepare( 'blog_id = %d', $site_id );
 
399
                }
 
400
 
 
401
                // Parse site IDs for an IN clause.
 
402
                if ( ! empty( $this->query_vars['site__in'] ) ) {
 
403
                        $this->sql_clauses['where']['site__in'] = "blog_id IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['site__in'] ) ) . ' )';
 
404
                }
 
405
 
 
406
                // Parse site IDs for a NOT IN clause.
 
407
                if ( ! empty( $this->query_vars['site__not_in'] ) ) {
 
408
                        $this->sql_clauses['where']['site__not_in'] = "blog_id NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['site__not_in'] ) ) . ' )';
 
409
                }
 
410
 
 
411
                $network_id = absint( $this->query_vars['network_id'] );
 
412
 
 
413
                if ( ! empty( $network_id ) ) {
 
414
                        $this->sql_clauses['where']['network_id'] = $wpdb->prepare( 'site_id = %d', $network_id );
 
415
                }
 
416
 
 
417
                // Parse site network IDs for an IN clause.
 
418
                if ( ! empty( $this->query_vars['network__in'] ) ) {
 
419
                        $this->sql_clauses['where']['network__in'] = 'site_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['network__in'] ) ) . ' )';
 
420
                }
 
421
 
 
422
                // Parse site network IDs for a NOT IN clause.
 
423
                if ( ! empty( $this->query_vars['network__not_in'] ) ) {
 
424
                        $this->sql_clauses['where']['network__not_in'] = 'site_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['network__not_in'] ) ) . ' )';
 
425
                }
 
426
 
 
427
                if ( ! empty( $this->query_vars['domain'] ) ) {
 
428
                        $this->sql_clauses['where']['domain'] = $wpdb->prepare( 'domain = %s', $this->query_vars['domain'] );
 
429
                }
 
430
 
 
431
                // Parse site domain for an IN clause.
 
432
                if ( is_array( $this->query_vars['domain__in'] ) ) {
 
433
                        $this->sql_clauses['where']['domain__in'] = "domain IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__in'] ) ) . "' )";
 
434
                }
 
435
 
 
436
                // Parse site domain for a NOT IN clause.
 
437
                if ( is_array( $this->query_vars['domain__not_in'] ) ) {
 
438
                        $this->sql_clauses['where']['domain__not_in'] = "domain NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__not_in'] ) ) . "' )";
 
439
                }
 
440
 
 
441
                if ( ! empty( $this->query_vars['path'] ) ) {
 
442
                        $this->sql_clauses['where']['path'] = $wpdb->prepare( 'path = %s', $this->query_vars['path'] );
 
443
                }
 
444
 
 
445
                // Parse site path for an IN clause.
 
446
                if ( is_array( $this->query_vars['path__in'] ) ) {
 
447
                        $this->sql_clauses['where']['path__in'] = "path IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__in'] ) ) . "' )";
 
448
                }
 
449
 
 
450
                // Parse site path for a NOT IN clause.
 
451
                if ( is_array( $this->query_vars['path__not_in'] ) ) {
 
452
                        $this->sql_clauses['where']['path__not_in'] = "path NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__not_in'] ) ) . "' )";
 
453
                }
 
454
 
 
455
                if ( is_numeric( $this->query_vars['archived'] ) ) {
 
456
                        $archived = absint( $this->query_vars['archived'] );
 
457
                        $this->sql_clauses['where']['archived'] = $wpdb->prepare( "archived = %d ", $archived );
 
458
                }
 
459
 
 
460
                if ( is_numeric( $this->query_vars['mature'] ) ) {
 
461
                        $mature = absint( $this->query_vars['mature'] );
 
462
                        $this->sql_clauses['where']['mature'] = $wpdb->prepare( "mature = %d ", $mature );
 
463
                }
 
464
 
 
465
                if ( is_numeric( $this->query_vars['spam'] ) ) {
 
466
                        $spam = absint( $this->query_vars['spam'] );
 
467
                        $this->sql_clauses['where']['spam'] = $wpdb->prepare( "spam = %d ", $spam );
 
468
                }
 
469
 
 
470
                if ( is_numeric( $this->query_vars['deleted'] ) ) {
 
471
                        $deleted = absint( $this->query_vars['deleted'] );
 
472
                        $this->sql_clauses['where']['deleted'] = $wpdb->prepare( "deleted = %d ", $deleted );
 
473
                }
 
474
 
 
475
                if ( is_numeric( $this->query_vars['public'] ) ) {
 
476
                        $public = absint( $this->query_vars['public'] );
 
477
                        $this->sql_clauses['where']['public'] = $wpdb->prepare( "public = %d ", $public );
 
478
                }
 
479
 
 
480
                // Falsey search strings are ignored.
 
481
                if ( strlen( $this->query_vars['search'] ) ) {
 
482
                        $search_columns = array();
 
483
 
 
484
                        if ( $this->query_vars['search_columns'] ) {
 
485
                                $search_columns = array_intersect( $this->query_vars['search_columns'], array( 'domain', 'path' ) );
 
486
                        }
 
487
 
 
488
                        if ( ! $search_columns ) {
 
489
                                $search_columns = array( 'domain', 'path' );
 
490
                        }
 
491
 
 
492
                        /**
 
493
                         * Filters the columns to search in a WP_Site_Query search.
 
494
                         *
 
495
                         * The default columns include 'domain' and 'path.
 
496
                         *
 
497
                         * @since 4.6.0
 
498
                         *
 
499
                         * @param array         $search_columns Array of column names to be searched.
 
500
                         * @param string        $search         Text being searched.
 
501
                         * @param WP_Site_Query $this           The current WP_Site_Query instance.
 
502
                         */
 
503
                        $search_columns = apply_filters( 'site_search_columns', $search_columns, $this->query_vars['search'], $this );
 
504
 
 
505
                        $this->sql_clauses['where']['search'] = $this->get_search_sql( $this->query_vars['search'], $search_columns );
 
506
                }
 
507
 
 
508
                $date_query = $this->query_vars['date_query'];
 
509
                if ( ! empty( $date_query ) && is_array( $date_query ) ) {
 
510
                        $this->date_query = new WP_Date_Query( $date_query, 'registered' );
 
511
                        $this->sql_clauses['where']['date_query'] = preg_replace( '/^\s*AND\s*/', '', $this->date_query->get_sql() );
 
512
                }
 
513
 
 
514
                $where = implode( ' AND ', $this->sql_clauses['where'] );
 
515
 
 
516
                $pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
 
517
 
 
518
                /**
 
519
                 * Filters the site query clauses.
 
520
                 *
 
521
                 * @since 4.6.0
 
522
                 *
 
523
                 * @param array $pieces A compacted array of site query clauses.
 
524
                 * @param WP_Site_Query &$this Current instance of WP_Site_Query, passed by reference.
 
525
                 */
 
526
                $clauses = apply_filters_ref_array( 'sites_clauses', array( compact( $pieces ), &$this ) );
 
527
 
 
528
                $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : '';
 
529
                $join = isset( $clauses['join'] ) ? $clauses['join'] : '';
 
530
                $where = isset( $clauses['where'] ) ? $clauses['where'] : '';
 
531
                $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';
 
532
                $limits = isset( $clauses['limits'] ) ? $clauses['limits'] : '';
 
533
                $groupby = isset( $clauses['groupby'] ) ? $clauses['groupby'] : '';
 
534
 
 
535
                if ( $where ) {
 
536
                        $where = 'WHERE ' . $where;
 
537
                }
 
538
 
 
539
                if ( $groupby ) {
 
540
                        $groupby = 'GROUP BY ' . $groupby;
 
541
                }
 
542
 
 
543
                if ( $orderby ) {
 
544
                        $orderby = "ORDER BY $orderby";
 
545
                }
 
546
 
 
547
                $found_rows = '';
 
548
                if ( ! $this->query_vars['no_found_rows'] ) {
 
549
                        $found_rows = 'SQL_CALC_FOUND_ROWS';
 
550
                }
 
551
 
 
552
                $this->sql_clauses['select']  = "SELECT $found_rows $fields";
 
553
                $this->sql_clauses['from']    = "FROM $wpdb->blogs $join";
 
554
                $this->sql_clauses['groupby'] = $groupby;
 
555
                $this->sql_clauses['orderby'] = $orderby;
 
556
                $this->sql_clauses['limits']  = $limits;
 
557
 
 
558
                $this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
 
559
 
 
560
                if ( $this->query_vars['count'] ) {
 
561
                        return intval( $wpdb->get_var( $this->request ) );
 
562
                }
 
563
 
 
564
                $site_ids = $wpdb->get_col( $this->request );
 
565
 
 
566
                return array_map( 'intval', $site_ids );
 
567
        }
 
568
 
 
569
        /**
 
570
         * Populates found_sites and max_num_pages properties for the current query
 
571
         * if the limit clause was used.
 
572
         *
 
573
         * @since 4.6.0
 
574
         * @access private
 
575
         *
 
576
         * @global wpdb $wpdb WordPress database abstraction object.
 
577
         */
 
578
        private function set_found_sites() {
 
579
                global $wpdb;
 
580
 
 
581
                if ( $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) {
 
582
                        /**
 
583
                         * Filters the query used to retrieve found site count.
 
584
                         *
 
585
                         * @since 4.6.0
 
586
                         *
 
587
                         * @param string        $found_sites_query SQL query. Default 'SELECT FOUND_ROWS()'.
 
588
                         * @param WP_Site_Query $site_query        The `WP_Site_Query` instance.
 
589
                         */
 
590
                        $found_sites_query = apply_filters( 'found_sites_query', 'SELECT FOUND_ROWS()', $this );
 
591
 
 
592
                        $this->found_sites = (int) $wpdb->get_var( $found_sites_query );
 
593
                }
 
594
        }
 
595
 
 
596
        /**
 
597
         * Used internally to generate an SQL string for searching across multiple columns.
 
598
         *
 
599
         * @since 4.6.0
 
600
         * @access protected
 
601
         *
 
602
         * @global wpdb  $wpdb WordPress database abstraction object.
 
603
         *
 
604
         * @param string $string  Search string.
 
605
         * @param array  $columns Columns to search.
 
606
         * @return string Search SQL.
 
607
         */
 
608
        protected function get_search_sql( $string, $columns ) {
 
609
                global $wpdb;
 
610
 
 
611
                if ( false !== strpos( $string, '*' ) ) {
 
612
                        $like = '%' . implode( '%', array_map( array( $wpdb, 'esc_like' ), explode( '*', $string ) ) ) . '%';
 
613
                } else {
 
614
                        $like = '%' . $wpdb->esc_like( $string ) . '%';
 
615
                }
 
616
 
 
617
                $searches = array();
 
618
                foreach ( $columns as $column ) {
 
619
                        $searches[] = $wpdb->prepare( "$column LIKE %s", $like );
 
620
                }
 
621
 
 
622
                return '(' . implode( ' OR ', $searches ) . ')';
 
623
        }
 
624
 
 
625
        /**
 
626
         * Parses and sanitizes 'orderby' keys passed to the site query.
 
627
         *
 
628
         * @since 4.6.0
 
629
         * @access protected
 
630
         *
 
631
         * @global wpdb $wpdb WordPress database abstraction object.
 
632
         *
 
633
         * @param string $orderby Alias for the field to order by.
 
634
         * @return string|false Value to used in the ORDER clause. False otherwise.
 
635
         */
 
636
        protected function parse_orderby( $orderby ) {
 
637
                global $wpdb;
 
638
 
 
639
                $parsed = false;
 
640
 
 
641
                switch ( $orderby ) {
 
642
                        case 'site__in':
 
643
                                $site__in = implode( ',', array_map( 'absint', $this->query_vars['site__in'] ) );
 
644
                                $parsed = "FIELD( {$wpdb->blogs}.blog_id, $site__in )";
 
645
                                break;
 
646
                        case 'network__in':
 
647
                                $network__in = implode( ',', array_map( 'absint', $this->query_vars['network__in'] ) );
 
648
                                $parsed = "FIELD( {$wpdb->blogs}.site_id, $network__in )";
 
649
                                break;
 
650
                        case 'domain':
 
651
                        case 'last_updated':
 
652
                        case 'path':
 
653
                        case 'registered':
 
654
                                $parsed = $orderby;
 
655
                                break;
 
656
                        case 'network_id':
 
657
                                $parsed = 'site_id';
 
658
                                break;
 
659
                        case 'domain_length':
 
660
                                $parsed = 'CHAR_LENGTH(domain)';
 
661
                                break;
 
662
                        case 'path_length':
 
663
                                $parsed = 'CHAR_LENGTH(path)';
 
664
                                break;
 
665
                        case 'id':
 
666
                                $parsed = 'blog_id';
 
667
                                break;
 
668
                }
 
669
 
 
670
                return $parsed;
 
671
        }
 
672
 
 
673
        /**
 
674
         * Parses an 'order' query variable and cast it to 'ASC' or 'DESC' as necessary.
 
675
         *
 
676
         * @since 4.6.0
 
677
         * @access protected
 
678
         *
 
679
         * @param string $order The 'order' query variable.
 
680
         * @return string The sanitized 'order' query variable.
 
681
         */
 
682
        protected function parse_order( $order ) {
 
683
                if ( ! is_string( $order ) || empty( $order ) ) {
 
684
                        return 'ASC';
 
685
                }
 
686
 
 
687
                if ( 'ASC' === strtoupper( $order ) ) {
 
688
                        return 'ASC';
 
689
                } else {
 
690
                        return 'DESC';
 
691
                }
 
692
        }
 
693
}