Completed
Push — master ( a7cd2a...eabd6c )
by Stephen
38:42
created

WP_Comment_Query::get_comment_ids()   F

Complexity

Conditions 88
Paths 0

Size

Total Lines 420
Code Lines 229

Duplication

Lines 41
Ratio 9.76 %
Metric Value
dl 41
loc 420
rs 2
cc 88
eloc 229
nc 0
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Comment API: WP_Comment_Query class
4
 *
5
 * @package WordPress
6
 * @subpackage Comments
7
 * @since 4.4.0
8
 */
9
10
/**
11
 * Core class used for querying comments.
12
 *
13
 * @since 3.1.0
14
 *
15
 * @see WP_Comment_Query::__construct() for accepted arguments.
16
 */
17
class WP_Comment_Query {
18
19
	/**
20
	 * SQL for database query.
21
	 *
22
	 * @since 4.0.1
23
	 * @access public
24
	 * @var string
25
	 */
26
	public $request;
27
28
	/**
29
	 * Metadata query container
30
	 *
31
	 * @since 3.5.0
32
	 * @access public
33
	 * @var object WP_Meta_Query
34
	 */
35
	public $meta_query = false;
36
37
	/**
38
	 * Metadata query clauses.
39
	 *
40
	 * @since 4.4.0
41
	 * @access protected
42
	 * @var array
43
	 */
44
	protected $meta_query_clauses;
45
46
	/**
47
	 * SQL query clauses.
48
	 *
49
	 * @since 4.4.0
50
	 * @access protected
51
	 * @var array
52
	 */
53
	protected $sql_clauses = array(
54
		'select'  => '',
55
		'from'    => '',
56
		'where'   => array(),
57
		'groupby' => '',
58
		'orderby' => '',
59
		'limits'  => '',
60
	);
61
62
	/**
63
	 * SQL WHERE clause.
64
	 *
65
	 * Stored after the 'comments_clauses' filter is run on the compiled WHERE sub-clauses.
66
	 *
67
	 * @since 4.4.2
68
	 * @access protected
69
	 * @var string
70
	 */
71
	protected $filtered_where_clause;
72
73
	/**
74
	 * Date query container
75
	 *
76
	 * @since 3.7.0
77
	 * @access public
78
	 * @var object WP_Date_Query
79
	 */
80
	public $date_query = false;
81
82
	/**
83
	 * Query vars set by the user.
84
	 *
85
	 * @since 3.1.0
86
	 * @access public
87
	 * @var array
88
	 */
89
	public $query_vars;
90
91
	/**
92
	 * Default values for query vars.
93
	 *
94
	 * @since 4.2.0
95
	 * @access public
96
	 * @var array
97
	 */
98
	public $query_var_defaults;
99
100
	/**
101
	 * List of comments located by the query.
102
	 *
103
	 * @since 4.0.0
104
	 * @access public
105
	 * @var array
106
	 */
107
	public $comments;
108
109
	/**
110
	 * The amount of found comments for the current query.
111
	 *
112
	 * @since 4.4.0
113
	 * @access public
114
	 * @var int
115
	 */
116
	public $found_comments = 0;
117
118
	/**
119
	 * The number of pages.
120
	 *
121
	 * @since 4.4.0
122
	 * @access public
123
	 * @var int
124
	 */
125
	public $max_num_pages = 0;
126
127
	/**
128
	 * Make private/protected methods readable for backwards compatibility.
129
	 *
130
	 * @since 4.0.0
131
	 * @access public
132
	 *
133
	 * @param callable $name      Method to call.
134
	 * @param array    $arguments Arguments to pass when calling.
135
	 * @return mixed|false Return value of the callback, false otherwise.
136
	 */
137
	public function __call( $name, $arguments ) {
138
		if ( 'get_search_sql' === $name ) {
139
			return call_user_func_array( array( $this, $name ), $arguments );
140
		}
141
		return false;
142
	}
143
144
	/**
145
	 * Constructor.
146
	 *
147
	 * Sets up the comment query, based on the query vars passed.
148
	 *
149
	 * @since 4.2.0
150
	 * @since 4.4.0 `$parent__in` and `$parent__not_in` were added.
151
	 * @since 4.4.0 Order by `comment__in` was added. `$update_comment_meta_cache`, `$no_found_rows`,
152
	 *              `$hierarchical`, and `$update_comment_post_cache` were added.
153
	 * @since 4.5.0 Introduced the `$author_url` argument.
154
	 * @access public
155
	 *
156
	 * @param string|array $query {
157
	 *     Optional. Array or query string of comment query parameters. Default empty.
158
	 *
159
	 *     @type string       $author_email              Comment author email address. Default empty.
160
	 *     @type string       $author_url                Comment author URL. Default empty.
161
	 *     @type array        $author__in                Array of author IDs to include comments for. Default empty.
162
	 *     @type array        $author__not_in            Array of author IDs to exclude comments for. Default empty.
163
	 *     @type array        $comment__in               Array of comment IDs to include. Default empty.
164
	 *     @type array        $comment__not_in           Array of comment IDs to exclude. Default empty.
165
	 *     @type bool         $count                     Whether to return a comment count (true) or array of
166
	 *                                                   comment objects (false). Default false.
167
	 *     @type array        $date_query                Date query clauses to limit comments by. See WP_Date_Query.
168
	 *                                                   Default null.
169
	 *     @type string       $fields                    Comment fields to return. Accepts 'ids' for comment IDs
170
	 *                                                   only or empty for all fields. Default empty.
171
	 *     @type int          $ID                        Currently unused.
172
	 *     @type array        $include_unapproved        Array of IDs or email addresses of users whose unapproved
173
	 *                                                   comments will be returned by the query regardless of
174
	 *                                                   `$status`. Default empty.
175
	 *     @type int          $karma                     Karma score to retrieve matching comments for.
176
	 *                                                   Default empty.
177
	 *     @type string       $meta_key                  Include comments with a matching comment meta key.
178
	 *                                                   Default empty.
179
	 *     @type string       $meta_value                Include comments with a matching comment meta value.
180
	 *                                                   Requires `$meta_key` to be set. Default empty.
181
	 *     @type array        $meta_query                Meta query clauses to limit retrieved comments by.
182
	 *                                                   See WP_Meta_Query. Default empty.
183
	 *     @type int          $number                    Maximum number of comments to retrieve.
184
	 *                                                   Default null (no limit).
185
	 *     @type int          $offset                    Number of comments to offset the query. Used to build
186
	 *                                                   LIMIT clause. Default 0.
187
	 *     @type bool         $no_found_rows             Whether to disable the `SQL_CALC_FOUND_ROWS` query.
188
	 *                                                   Default: true.
189
	 *     @type string|array $orderby                   Comment status or array of statuses. To use 'meta_value'
190
	 *                                                   or 'meta_value_num', `$meta_key` must also be defined.
191
	 *                                                   To sort by a specific `$meta_query` clause, use that
192
	 *                                                   clause's array key. Accepts 'comment_agent',
193
	 *                                                   'comment_approved', 'comment_author',
194
	 *                                                   'comment_author_email', 'comment_author_IP',
195
	 *                                                   'comment_author_url', 'comment_content', 'comment_date',
196
	 *                                                   'comment_date_gmt', 'comment_ID', 'comment_karma',
197
	 *                                                   'comment_parent', 'comment_post_ID', 'comment_type',
198
	 *                                                   'user_id', 'comment__in', 'meta_value', 'meta_value_num',
199
	 *                                                   the value of $meta_key, and the array keys of
200
	 *                                                   `$meta_query`. Also accepts false, an empty array, or
201
	 *                                                   'none' to disable `ORDER BY` clause.
202
	 *                                                   Default: 'comment_date_gmt'.
203
	 *     @type string       $order                     How to order retrieved comments. Accepts 'ASC', 'DESC'.
204
	 *                                                   Default: 'DESC'.
205
	 *     @type int          $parent                    Parent ID of comment to retrieve children of.
206
	 *                                                   Default empty.
207
	 *     @type array        $parent__in                Array of parent IDs of comments to retrieve children for.
208
	 *                                                   Default empty.
209
	 *     @type array        $parent__not_in            Array of parent IDs of comments *not* to retrieve
210
	 *                                                   children for. Default empty.
211
	 *     @type array        $post_author__in           Array of author IDs to retrieve comments for.
212
	 *                                                   Default empty.
213
	 *     @type array        $post_author__not_in       Array of author IDs *not* to retrieve comments for.
214
	 *                                                   Default empty.
215
	 *     @type int          $post_ID                   Currently unused.
216
	 *     @type int          $post_id                   Limit results to those affiliated with a given post ID.
217
	 *                                                   Default 0.
218
	 *     @type array        $post__in                  Array of post IDs to include affiliated comments for.
219
	 *                                                   Default empty.
220
	 *     @type array        $post__not_in              Array of post IDs to exclude affiliated comments for.
221
	 *                                                   Default empty.
222
	 *     @type int          $post_author               Post author ID to limit results by. Default empty.
223
	 *     @type string|array $post_status               Post status or array of post statuses to retrieve
224
	 *                                                   affiliated comments for. Pass 'any' to match any value.
225
	 *                                                   Default empty.
226
	 *     @type string       $post_type                 Post type or array of post types to retrieve affiliated
227
	 *                                                   comments for. Pass 'any' to match any value. Default empty.
228
	 *     @type string       $post_name                 Post name to retrieve affiliated comments for.
229
	 *                                                   Default empty.
230
	 *     @type int          $post_parent               Post parent ID to retrieve affiliated comments for.
231
	 *                                                   Default empty.
232
	 *     @type string       $search                    Search term(s) to retrieve matching comments for.
233
	 *                                                   Default empty.
234
	 *     @type string       $status                    Comment status to limit results by. Accepts 'hold'
235
	 *                                                   (`comment_status=0`), 'approve' (`comment_status=1`),
236
	 *                                                   'all', or a custom comment status. Default 'all'.
237
	 *     @type string|array $type                      Include comments of a given type, or array of types.
238
	 *                                                   Accepts 'comment', 'pings' (includes 'pingback' and
239
	 *                                                   'trackback'), or anycustom type string. Default empty.
240
	 *     @type array        $type__in                  Include comments from a given array of comment types.
241
	 *                                                   Default empty.
242
	 *     @type array        $type__not_in              Exclude comments from a given array of comment types.
243
	 *                                                   Default empty.
244
	 *     @type int          $user_id                   Include comments for a specific user ID. Default empty.
245
	 *     @type bool|string  $hierarchical              Whether to include comment descendants in the results.
246
	 *                                                   'threaded' returns a tree, with each comment's children
247
	 *                                                   stored in a `children` property on the `WP_Comment`
248
	 *                                                   object. 'flat' returns a flat array of found comments plus
249
	 *                                                   their children. Pass `false` to leave out descendants.
250
	 *                                                   The parameter is ignored (forced to `false`) when
251
	 *                                                   `$fields` is 'ids' or 'counts'. Accepts 'threaded',
252
	 *                                                   'flat', or false. Default: false.
253
	 *     @type bool         $update_comment_meta_cache Whether to prime the metadata cache for found comments.
254
	 *                                                   Default true.
255
	 *     @type bool         $update_comment_post_cache Whether to prime the cache for comment posts.
256
	 *                                                   Default false.
257
	 * }
258
	 */
259
	public function __construct( $query = '' ) {
260
		$this->query_var_defaults = array(
261
			'author_email' => '',
262
			'author_url' => '',
263
			'author__in' => '',
264
			'author__not_in' => '',
265
			'include_unapproved' => '',
266
			'fields' => '',
267
			'ID' => '',
268
			'comment__in' => '',
269
			'comment__not_in' => '',
270
			'karma' => '',
271
			'number' => '',
272
			'offset' => '',
273
			'no_found_rows' => true,
274
			'orderby' => '',
275
			'order' => 'DESC',
276
			'parent' => '',
277
			'parent__in' => '',
278
			'parent__not_in' => '',
279
			'post_author__in' => '',
280
			'post_author__not_in' => '',
281
			'post_ID' => '',
282
			'post_id' => 0,
283
			'post__in' => '',
284
			'post__not_in' => '',
285
			'post_author' => '',
286
			'post_name' => '',
287
			'post_parent' => '',
288
			'post_status' => '',
289
			'post_type' => '',
290
			'status' => 'all',
291
			'type' => '',
292
			'type__in' => '',
293
			'type__not_in' => '',
294
			'user_id' => '',
295
			'search' => '',
296
			'count' => false,
297
			'meta_key' => '',
298
			'meta_value' => '',
299
			'meta_query' => '',
300
			'date_query' => null, // See WP_Date_Query
301
			'hierarchical' => false,
302
			'update_comment_meta_cache' => true,
303
			'update_comment_post_cache' => false,
304
		);
305
306
		if ( ! empty( $query ) ) {
307
			$this->query( $query );
308
		}
309
	}
310
311
	/**
312
	 * Parse arguments passed to the comment query with default query parameters.
313
	 *
314
	 * @since  4.2.0 Extracted from WP_Comment_Query::query().
315
	 *
316
	 * @access public
317
	 *
318
	 * @param string|array $query WP_Comment_Query arguments. See WP_Comment_Query::__construct()
319
	 */
320
	public function parse_query( $query = '' ) {
321
		if ( empty( $query ) ) {
322
			$query = $this->query_vars;
323
		}
324
325
		$this->query_vars = wp_parse_args( $query, $this->query_var_defaults );
326
		do_action_ref_array( 'parse_comment_query', array( &$this ) );
327
	}
328
329
	/**
330
	 * Sets up the WordPress query for retrieving comments.
331
	 *
332
	 * @since 3.1.0
333
	 * @since 4.1.0 Introduced 'comment__in', 'comment__not_in', 'post_author__in',
334
	 *              'post_author__not_in', 'author__in', 'author__not_in', 'post__in',
335
	 *              'post__not_in', 'include_unapproved', 'type__in', and 'type__not_in'
336
	 *              arguments to $query_vars.
337
	 * @since 4.2.0 Moved parsing to WP_Comment_Query::parse_query().
338
	 * @access public
339
	 *
340
	 * @param string|array $query Array or URL query string of parameters.
341
	 * @return array|int List of comments, or number of comments when 'count' is passed as a query var.
342
	 */
343
	public function query( $query ) {
344
		$this->query_vars = wp_parse_args( $query );
345
		return $this->get_comments();
346
	}
347
348
	/**
349
	 * Get a list of comments matching the query vars.
350
	 *
351
	 * @since 4.2.0
352
	 * @access public
353
	 *
354
	 * @global wpdb $wpdb WordPress database abstraction object.
355
	 *
356
	 * @return int|array The list of comments.
357
	 */
358
	public function get_comments() {
359
		global $wpdb;
360
361
		$this->parse_query();
362
363
		// Parse meta query
364
		$this->meta_query = new WP_Meta_Query();
365
		$this->meta_query->parse_query_vars( $this->query_vars );
366
367
		/**
368
		 * Fires before comments are retrieved.
369
		 *
370
		 * @since 3.1.0
371
		 *
372
		 * @param WP_Comment_Query &$this Current instance of WP_Comment_Query, passed by reference.
373
		 */
374
		do_action_ref_array( 'pre_get_comments', array( &$this ) );
375
376
		// Reparse query vars, in case they were modified in a 'pre_get_comments' callback.
377
		$this->meta_query->parse_query_vars( $this->query_vars );
378
		if ( ! empty( $this->meta_query->queries ) ) {
379
			$this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->meta_query->get_s...s, 'comment_ID', $this) can also be of type false. However, the property $meta_query_clauses is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
380
		}
381
382
		// $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
383
		$key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) );
384
		$last_changed = wp_cache_get( 'last_changed', 'comment' );
385
		if ( ! $last_changed ) {
386
			$last_changed = microtime();
387
			wp_cache_set( 'last_changed', $last_changed, 'comment' );
388
		}
389
		$cache_key = "get_comment_ids:$key:$last_changed";
390
391
		$comment_ids = wp_cache_get( $cache_key, 'comment' );
392
		if ( false === $comment_ids ) {
393
			$comment_ids = $this->get_comment_ids();
394
			wp_cache_add( $cache_key, $comment_ids, 'comment' );
395
		}
396
397
		// If querying for a count only, there's nothing more to do.
398
		if ( $this->query_vars['count'] ) {
399
			// $comment_ids is actually a count in this case.
400
			return intval( $comment_ids );
401
		}
402
403
		$comment_ids = array_map( 'intval', $comment_ids );
404
405
		$this->comment_count = count( $this->comments );
0 ignored issues
show
Bug introduced by
The property comment_count does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
406
407
		if ( $comment_ids && $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $comment_ids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
408
			/**
409
			 * Filter the query used to retrieve found comment count.
410
			 *
411
			 * @since 4.4.0
412
			 *
413
			 * @param string           $found_comments_query SQL query. Default 'SELECT FOUND_ROWS()'.
414
			 * @param WP_Comment_Query $comment_query        The `WP_Comment_Query` instance.
415
			 */
416
			$found_comments_query = apply_filters( 'found_comments_query', 'SELECT FOUND_ROWS()', $this );
417
			$this->found_comments = (int) $wpdb->get_var( $found_comments_query );
418
419
			$this->max_num_pages = ceil( $this->found_comments / $this->query_vars['number'] );
0 ignored issues
show
Documentation Bug introduced by
The property $max_num_pages was declared of type integer, but ceil($this->found_commen...->query_vars['number']) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
420
		}
421
422
		if ( 'ids' == $this->query_vars['fields'] ) {
423
			$this->comments = $comment_ids;
424
			return $this->comments;
425
		}
426
427
		_prime_comment_caches( $comment_ids, $this->query_vars['update_comment_meta_cache'] );
428
429
		// Fetch full comment objects from the primed cache.
430
		$_comments = array();
431
		foreach ( $comment_ids as $comment_id ) {
432
			if ( $_comment = get_comment( $comment_id ) ) {
433
				$_comments[] = $_comment;
434
			}
435
		}
436
437
		// Prime comment post caches.
438
		if ( $this->query_vars['update_comment_post_cache'] ) {
439
			$comment_post_ids = array();
440
			foreach ( $_comments as $_comment ) {
441
				$comment_post_ids[] = $_comment->comment_post_ID;
442
			}
443
444
			_prime_post_caches( $comment_post_ids, false, false );
445
		}
446
447
		/**
448
		 * Filter the comment query results.
449
		 *
450
		 * @since 3.1.0
451
		 *
452
		 * @param array            $results  An array of comments.
453
		 * @param WP_Comment_Query &$this    Current instance of WP_Comment_Query, passed by reference.
454
		 */
455
		$_comments = apply_filters_ref_array( 'the_comments', array( $_comments, &$this ) );
456
457
		// Convert to WP_Comment instances
458
		$comments = array_map( 'get_comment', $_comments );
459
460
		if ( $this->query_vars['hierarchical'] ) {
461
			$comments = $this->fill_descendants( $comments );
462
		}
463
464
		$this->comments = $comments;
465
		return $this->comments;
466
	}
467
468
	/**
469
	 * Used internally to get a list of comment IDs matching the query vars.
470
	 *
471
	 * @since 4.4.0
472
	 * @access protected
473
	 *
474
	 * @global wpdb $wpdb WordPress database abstraction object.
475
	 */
476
	protected function get_comment_ids() {
477
		global $wpdb;
478
479
		// Assemble clauses related to 'comment_approved'.
480
		$approved_clauses = array();
481
482
		// 'status' accepts an array or a comma-separated string.
483
		$status_clauses = array();
484
		$statuses = $this->query_vars['status'];
485
		if ( ! is_array( $statuses ) ) {
486
			$statuses = preg_split( '/[\s,]+/', $statuses );
487
		}
488
489
		// 'any' overrides other statuses.
490
		if ( ! in_array( 'any', $statuses ) ) {
491
			foreach ( $statuses as $status ) {
492
				switch ( $status ) {
493
					case 'hold' :
494
						$status_clauses[] = "comment_approved = '0'";
495
						break;
496
497
					case 'approve' :
498
						$status_clauses[] = "comment_approved = '1'";
499
						break;
500
501
					case 'all' :
502
					case '' :
503
						$status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
504
						break;
505
506
					default :
507
						$status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
508
						break;
509
				}
510
			}
511
512
			if ( ! empty( $status_clauses ) ) {
513
				$approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
514
			}
515
		}
516
517
		// User IDs or emails whose unapproved comments are included, regardless of $status.
518
		if ( ! empty( $this->query_vars['include_unapproved'] ) ) {
519
			$include_unapproved = $this->query_vars['include_unapproved'];
520
521
			// Accepts arrays or comma-separated strings.
522
			if ( ! is_array( $include_unapproved ) ) {
523
				$include_unapproved = preg_split( '/[\s,]+/', $include_unapproved );
524
			}
525
526
			$unapproved_ids = $unapproved_emails = array();
527
			foreach ( $include_unapproved as $unapproved_identifier ) {
528
				// Numeric values are assumed to be user ids.
529
				if ( is_numeric( $unapproved_identifier ) ) {
530
					$approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
531
532
				// Otherwise we match against email addresses.
533
				} else {
534
					$approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
535
				}
536
			}
537
		}
538
539
		// Collapse comment_approved clauses into a single OR-separated clause.
540
		if ( ! empty( $approved_clauses ) ) {
541
			if ( 1 === count( $approved_clauses ) ) {
542
				$this->sql_clauses['where']['approved'] = $approved_clauses[0];
543
			} else {
544
				$this->sql_clauses['where']['approved'] = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
545
			}
546
		}
547
548
		$order = ( 'ASC' == strtoupper( $this->query_vars['order'] ) ) ? 'ASC' : 'DESC';
549
550
		// Disable ORDER BY with 'none', an empty array, or boolean false.
551
		if ( in_array( $this->query_vars['orderby'], array( 'none', array(), false ), true ) ) {
552
			$orderby = '';
553
		} elseif ( ! empty( $this->query_vars['orderby'] ) ) {
554
			$ordersby = is_array( $this->query_vars['orderby'] ) ?
555
				$this->query_vars['orderby'] :
556
				preg_split( '/[,\s]/', $this->query_vars['orderby'] );
557
558
			$orderby_array = array();
559
			$found_orderby_comment_ID = false;
560
			foreach ( $ordersby as $_key => $_value ) {
561
				if ( ! $_value ) {
562
					continue;
563
				}
564
565 View Code Duplication
				if ( is_int( $_key ) ) {
566
					$_orderby = $_value;
567
					$_order = $order;
568
				} else {
569
					$_orderby = $_key;
570
					$_order = $_value;
571
				}
572
573
				if ( ! $found_orderby_comment_ID && in_array( $_orderby, array( 'comment_ID', 'comment__in' ) ) ) {
574
					$found_orderby_comment_ID = true;
575
				}
576
577
				$parsed = $this->parse_orderby( $_orderby );
578
579
				if ( ! $parsed ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parsed of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
580
					continue;
581
				}
582
583
				if ( 'comment__in' === $_orderby ) {
584
					$orderby_array[] = $parsed;
585
					continue;
586
				}
587
588
				$orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
589
			}
590
591
			// If no valid clauses were found, order by comment_date_gmt.
592
			if ( empty( $orderby_array ) ) {
593
				$orderby_array[] = "$wpdb->comments.comment_date_gmt $order";
594
			}
595
596
			// To ensure determinate sorting, always include a comment_ID clause.
597
			if ( ! $found_orderby_comment_ID ) {
598
				$comment_ID_order = '';
599
600
				// Inherit order from comment_date or comment_date_gmt, if available.
601
				foreach ( $orderby_array as $orderby_clause ) {
602
					if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) {
603
						$comment_ID_order = $match[1];
604
						break;
605
					}
606
				}
607
608
				// If no date-related order is available, use the date from the first available clause.
609
				if ( ! $comment_ID_order ) {
610
					foreach ( $orderby_array as $orderby_clause ) {
611
						if ( false !== strpos( 'ASC', $orderby_clause ) ) {
612
							$comment_ID_order = 'ASC';
613
						} else {
614
							$comment_ID_order = 'DESC';
615
						}
616
617
						break;
618
					}
619
				}
620
621
				// Default to DESC.
622
				if ( ! $comment_ID_order ) {
623
					$comment_ID_order = 'DESC';
624
				}
625
626
				$orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order";
627
			}
628
629
			$orderby = implode( ', ', $orderby_array );
630
		} else {
631
			$orderby = "$wpdb->comments.comment_date_gmt $order";
632
		}
633
634
		$number = absint( $this->query_vars['number'] );
635
		$offset = absint( $this->query_vars['offset'] );
636
637 View Code Duplication
		if ( ! empty( $number ) ) {
638
			if ( $offset ) {
639
				$limits = 'LIMIT ' . $offset . ',' . $number;
640
			} else {
641
				$limits = 'LIMIT ' . $number;
642
			}
643
		}
644
645
		if ( $this->query_vars['count'] ) {
646
			$fields = 'COUNT(*)';
647
		} else {
648
			$fields = "$wpdb->comments.comment_ID";
649
		}
650
651
		$post_id = absint( $this->query_vars['post_id'] );
652
		if ( ! empty( $post_id ) ) {
653
			$this->sql_clauses['where']['post_id'] = $wpdb->prepare( 'comment_post_ID = %d', $post_id );
654
		}
655
656
		// Parse comment IDs for an IN clause.
657
		if ( ! empty( $this->query_vars['comment__in'] ) ) {
658
			$this->sql_clauses['where']['comment__in'] = "$wpdb->comments.comment_ID IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
659
		}
660
661
		// Parse comment IDs for a NOT IN clause.
662
		if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
663
			$this->sql_clauses['where']['comment__not_in'] = "$wpdb->comments.comment_ID NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
664
		}
665
666
		// Parse comment parent IDs for an IN clause.
667
		if ( ! empty( $this->query_vars['parent__in'] ) ) {
668
			$this->sql_clauses['where']['parent__in'] = 'comment_parent IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['parent__in'] ) ) . ' )';
669
		}
670
671
		// Parse comment parent IDs for a NOT IN clause.
672
		if ( ! empty( $this->query_vars['parent__not_in'] ) ) {
673
			$this->sql_clauses['where']['parent__not_in'] = 'comment_parent NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['parent__not_in'] ) ) . ' )';
674
		}
675
676
		// Parse comment post IDs for an IN clause.
677
		if ( ! empty( $this->query_vars['post__in'] ) ) {
678
			$this->sql_clauses['where']['post__in'] = 'comment_post_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__in'] ) ) . ' )';
679
		}
680
681
		// Parse comment post IDs for a NOT IN clause.
682
		if ( ! empty( $this->query_vars['post__not_in'] ) ) {
683
			$this->sql_clauses['where']['post__not_in'] = 'comment_post_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__not_in'] ) ) . ' )';
684
		}
685
686 View Code Duplication
		if ( '' !== $this->query_vars['author_email'] ) {
687
			$this->sql_clauses['where']['author_email'] = $wpdb->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
688
		}
689
690 View Code Duplication
		if ( '' !== $this->query_vars['author_url'] ) {
691
			$this->sql_clauses['where']['author_url'] = $wpdb->prepare( 'comment_author_url = %s', $this->query_vars['author_url'] );
692
		}
693
694 View Code Duplication
		if ( '' !== $this->query_vars['karma'] ) {
695
			$this->sql_clauses['where']['karma'] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
696
		}
697
698
		// Filtering by comment_type: 'type', 'type__in', 'type__not_in'.
699
		$raw_types = array(
700
			'IN' => array_merge( (array) $this->query_vars['type'], (array) $this->query_vars['type__in'] ),
701
			'NOT IN' => (array) $this->query_vars['type__not_in'],
702
		);
703
704
		$comment_types = array();
705
		foreach ( $raw_types as $operator => $_raw_types ) {
706
			$_raw_types = array_unique( $_raw_types );
707
708
			foreach ( $_raw_types as $type ) {
709
				switch ( $type ) {
710
					// An empty translates to 'all', for backward compatibility
711
					case '':
712
					case 'all' :
713
						break;
714
715
					case 'comment':
716
					case 'comments':
717
						$comment_types[ $operator ][] = "''";
718
						break;
719
720
					case 'pings':
721
						$comment_types[ $operator ][] = "'pingback'";
722
						$comment_types[ $operator ][] = "'trackback'";
723
						break;
724
725
					default:
726
						$comment_types[ $operator ][] = $wpdb->prepare( '%s', $type );
727
						break;
728
				}
729
			}
730
731
			if ( ! empty( $comment_types[ $operator ] ) ) {
732
				$types_sql = implode( ', ', $comment_types[ $operator ] );
733
				$this->sql_clauses['where']['comment_type__' . strtolower( str_replace( ' ', '_', $operator ) ) ] = "comment_type $operator ($types_sql)";
734
			}
735
		}
736
737
		if ( $this->query_vars['hierarchical'] && ! $this->query_vars['parent'] ) {
738
			$this->query_vars['parent'] = 0;
739
		}
740
741 View Code Duplication
		if ( '' !== $this->query_vars['parent'] ) {
742
			$this->sql_clauses['where']['parent'] = $wpdb->prepare( 'comment_parent = %d', $this->query_vars['parent'] );
743
		}
744
745
		if ( is_array( $this->query_vars['user_id'] ) ) {
746
			$this->sql_clauses['where']['user_id'] = 'user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
747 View Code Duplication
		} elseif ( '' !== $this->query_vars['user_id'] ) {
748
			$this->sql_clauses['where']['user_id'] = $wpdb->prepare( 'user_id = %d', $this->query_vars['user_id'] );
749
		}
750
751
		// Falsy search strings are ignored.
752
		if ( strlen( $this->query_vars['search'] ) ) {
753
			$search_sql = $this->get_search_sql(
754
				$this->query_vars['search'],
755
				array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' )
756
			);
757
758
			// Strip leading 'AND'.
759
			$this->sql_clauses['where']['search'] = preg_replace( '/^\s*AND\s*/', '', $search_sql );
760
		}
761
762
		// If any post-related query vars are passed, join the posts table.
763
		$join_posts_table = false;
764
		$plucked = wp_array_slice_assoc( $this->query_vars, array( 'post_author', 'post_name', 'post_parent' ) );
765
		$post_fields = array_filter( $plucked );
766
767
		if ( ! empty( $post_fields ) ) {
768
			$join_posts_table = true;
769
			foreach ( $post_fields as $field_name => $field_value ) {
770
				// $field_value may be an array.
771
				$esses = array_fill( 0, count( (array) $field_value ), '%s' );
772
				$this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value );
773
			}
774
		}
775
776
		// 'post_status' and 'post_type' are handled separately, due to the specialized behavior of 'any'.
777
		foreach ( array( 'post_status', 'post_type' ) as $field_name ) {
778
			$q_values = array();
779
			if ( ! empty( $this->query_vars[ $field_name ] ) ) {
780
				$q_values = $this->query_vars[ $field_name ];
781
				if ( ! is_array( $q_values ) ) {
782
					$q_values = explode( ',', $q_values );
783
				}
784
785
				// 'any' will cause the query var to be ignored.
786
				if ( in_array( 'any', $q_values, true ) || empty( $q_values ) ) {
787
					continue;
788
				}
789
790
				$join_posts_table = true;
791
792
				$esses = array_fill( 0, count( $q_values ), '%s' );
793
				$this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ")", $q_values );
794
			}
795
		}
796
797
		// Comment author IDs for an IN clause.
798
		if ( ! empty( $this->query_vars['author__in'] ) ) {
799
			$this->sql_clauses['where']['author__in'] = 'user_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__in'] ) ) . ' )';
800
		}
801
802
		// Comment author IDs for a NOT IN clause.
803
		if ( ! empty( $this->query_vars['author__not_in'] ) ) {
804
			$this->sql_clauses['where']['author__not_in'] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )';
805
		}
806
807
		// Post author IDs for an IN clause.
808 View Code Duplication
		if ( ! empty( $this->query_vars['post_author__in'] ) ) {
809
			$join_posts_table = true;
810
			$this->sql_clauses['where']['post_author__in'] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )';
811
		}
812
813
		// Post author IDs for a NOT IN clause.
814 View Code Duplication
		if ( ! empty( $this->query_vars['post_author__not_in'] ) ) {
815
			$join_posts_table = true;
816
			$this->sql_clauses['where']['post_author__not_in'] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )';
817
		}
818
819
		$join = '';
820
821
		if ( $join_posts_table ) {
822
			$join .= "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
823
		}
824
825
		if ( ! empty( $this->meta_query_clauses ) ) {
826
			$join .= $this->meta_query_clauses['join'];
827
828
			// Strip leading 'AND'.
829
			$this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $this->meta_query_clauses['where'] );
830
831
			if ( ! $this->query_vars['count'] ) {
832
				$groupby = "{$wpdb->comments}.comment_ID";
833
			}
834
		}
835
836
		$date_query = $this->query_vars['date_query'];
837 View Code Duplication
		if ( ! empty( $date_query ) && is_array( $date_query ) ) {
838
			$date_query_object = new WP_Date_Query( $date_query, 'comment_date' );
839
			$this->sql_clauses['where']['date_query'] = preg_replace( '/^\s*AND\s*/', '', $date_query_object->get_sql() );
840
		}
841
842
		$where = implode( ' AND ', $this->sql_clauses['where'] );
843
844
		$pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
845
		/**
846
		 * Filter the comment query clauses.
847
		 *
848
		 * @since 3.1.0
849
		 *
850
		 * @param array            $pieces A compacted array of comment query clauses.
851
		 * @param WP_Comment_Query &$this  Current instance of WP_Comment_Query, passed by reference.
852
		 */
853
		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
854
855
		$fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
856
		$join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
857
		$where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
858
		$orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
859
		$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
860
		$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
861
862
		$this->filtered_where_clause = $where;
863
864
		if ( $where ) {
865
			$where = 'WHERE ' . $where;
866
		}
867
868
		if ( $groupby ) {
869
			$groupby = 'GROUP BY ' . $groupby;
870
		}
871
872
		if ( $orderby ) {
873
			$orderby = "ORDER BY $orderby";
874
		}
875
876
		$found_rows = '';
877
		if ( ! $this->query_vars['no_found_rows'] ) {
878
			$found_rows = 'SQL_CALC_FOUND_ROWS';
879
		}
880
881
		$this->sql_clauses['select']  = "SELECT $found_rows $fields";
882
		$this->sql_clauses['from']    = "FROM $wpdb->comments $join";
883
		$this->sql_clauses['groupby'] = $groupby;
884
		$this->sql_clauses['orderby'] = $orderby;
885
		$this->sql_clauses['limits']  = $limits;
886
887
		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
888
889
		if ( $this->query_vars['count'] ) {
890
			return intval( $wpdb->get_var( $this->request ) );
891
		} else {
892
			$comment_ids = $wpdb->get_col( $this->request );
893
			return array_map( 'intval', $comment_ids );
894
		}
895
	}
896
897
	/**
898
	 * Fetch descendants for located comments.
899
	 *
900
	 * Instead of calling `get_children()` separately on each child comment, we do a single set of queries to fetch
901
	 * the descendant trees for all matched top-level comments.
902
	 *
903
	 * @since 4.4.0
904
	 *
905
	 * @param array $comments Array of top-level comments whose descendants should be filled in.
906
	 * @return array
907
	 */
908
	protected function fill_descendants( $comments ) {
909
		global $wpdb;
910
911
		$levels = array(
912
			0 => wp_list_pluck( $comments, 'comment_ID' ),
913
		);
914
915
		/*
916
		 * The WHERE clause for the descendant query is the same as for the top-level
917
		 * query, minus the `parent`, `parent__in`, and `parent__not_in` sub-clauses.
918
		 */
919
		$_where = $this->filtered_where_clause;
920
		$exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' );
921
		foreach ( $exclude_keys as $exclude_key ) {
922
			if ( isset( $this->sql_clauses['where'][ $exclude_key ] ) ) {
923
				$clause = $this->sql_clauses['where'][ $exclude_key ];
924
925
				// Strip the clause as well as any adjacent ANDs.
926
				$pattern = '|(?:AND)?\s*' . $clause . '\s*(?:AND)?|';
927
				$_where_parts = preg_split( $pattern, $_where );
928
929
				// Remove empties.
930
				$_where_parts = array_filter( array_map( 'trim', $_where_parts ) );
931
932
				// Reassemble with an AND.
933
				$_where = implode( ' AND ', $_where_parts );
934
			}
935
		}
936
937
		// Fetch an entire level of the descendant tree at a time.
938
		$level = 0;
939
		do {
940
			$parent_ids = $levels[ $level ];
941
			if ( ! $parent_ids ) {
942
				break;
943
			}
944
945
			$where = 'WHERE ' . $_where . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $parent_ids ) ) . ')';
946
			$comment_ids = $wpdb->get_col( "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} ORDER BY comment_date_gmt ASC, comment_ID ASC" );
947
948
			$level++;
949
			$levels[ $level ] = $comment_ids;
950
		} while ( $comment_ids );
951
952
		// Prime comment caches for non-top-level comments.
953
		$descendant_ids = array();
954
		for ( $i = 1; $i < count( $levels ); $i++ ) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
955
			$descendant_ids = array_merge( $descendant_ids, $levels[ $i ] );
956
		}
957
958
		_prime_comment_caches( $descendant_ids, $this->query_vars['update_comment_meta_cache'] );
959
960
		// Assemble a flat array of all comments + descendants.
961
		$all_comments = $comments;
962
		foreach ( $descendant_ids as $descendant_id ) {
963
			$all_comments[] = get_comment( $descendant_id );
964
		}
965
966
		// If a threaded representation was requested, build the tree.
967
		if ( 'threaded' === $this->query_vars['hierarchical'] ) {
968
			$threaded_comments = $ref = array();
969
			foreach ( $all_comments as $k => $c ) {
970
				$_c = get_comment( $c->comment_ID );
971
972
				// If the comment isn't in the reference array, it goes in the top level of the thread.
973
				if ( ! isset( $ref[ $c->comment_parent ] ) ) {
974
					$threaded_comments[ $_c->comment_ID ] = $_c;
975
					$ref[ $_c->comment_ID ] = $threaded_comments[ $_c->comment_ID ];
976
977
				// Otherwise, set it as a child of its parent.
978
				} else {
979
980
					$ref[ $_c->comment_parent ]->add_child( $_c );
981
					$ref[ $_c->comment_ID ] = $ref[ $_c->comment_parent ]->get_child( $_c->comment_ID );
982
				}
983
			}
984
985
			// Set the 'populated_children' flag, to ensure additional database queries aren't run.
986
			foreach ( $ref as $_ref ) {
987
				$_ref->populated_children( true );
988
			}
989
990
			$comments = $threaded_comments;
991
		} else {
992
			$comments = $all_comments;
993
		}
994
995
		return $comments;
996
	}
997
998
	/**
999
	 * Used internally to generate an SQL string for searching across multiple columns
1000
	 *
1001
	 * @since 3.1.0
1002
	 * @access protected
1003
	 *
1004
	 * @global wpdb $wpdb WordPress database abstraction object.
1005
	 *
1006
	 * @param string $string
1007
	 * @param array $cols
1008
	 * @return string
1009
	 */
1010
	protected function get_search_sql( $string, $cols ) {
1011
		global $wpdb;
1012
1013
		$like = '%' . $wpdb->esc_like( $string ) . '%';
1014
1015
		$searches = array();
1016
		foreach ( $cols as $col ) {
1017
			$searches[] = $wpdb->prepare( "$col LIKE %s", $like );
1018
		}
1019
1020
		return ' AND (' . implode(' OR ', $searches) . ')';
1021
	}
1022
1023
	/**
1024
	 * Parse and sanitize 'orderby' keys passed to the comment query.
1025
	 *
1026
	 * @since 4.2.0
1027
	 * @access protected
1028
	 *
1029
	 * @global wpdb $wpdb WordPress database abstraction object.
1030
	 *
1031
	 * @param string $orderby Alias for the field to order by.
1032
	 * @return string|false Value to used in the ORDER clause. False otherwise.
1033
	 */
1034
	protected function parse_orderby( $orderby ) {
1035
		global $wpdb;
1036
1037
		$allowed_keys = array(
1038
			'comment_agent',
1039
			'comment_approved',
1040
			'comment_author',
1041
			'comment_author_email',
1042
			'comment_author_IP',
1043
			'comment_author_url',
1044
			'comment_content',
1045
			'comment_date',
1046
			'comment_date_gmt',
1047
			'comment_ID',
1048
			'comment_karma',
1049
			'comment_parent',
1050
			'comment_post_ID',
1051
			'comment_type',
1052
			'user_id',
1053
		);
1054
1055
		if ( ! empty( $this->query_vars['meta_key'] ) ) {
1056
			$allowed_keys[] = $this->query_vars['meta_key'];
1057
			$allowed_keys[] = 'meta_value';
1058
			$allowed_keys[] = 'meta_value_num';
1059
		}
1060
1061
		$meta_query_clauses = $this->meta_query->get_clauses();
1062
		if ( $meta_query_clauses ) {
1063
			$allowed_keys = array_merge( $allowed_keys, array_keys( $meta_query_clauses ) );
1064
		}
1065
1066
		$parsed = false;
1067
		if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) {
1068
			$parsed = "$wpdb->commentmeta.meta_value";
1069
		} elseif ( $orderby == 'meta_value_num' ) {
1070
			$parsed = "$wpdb->commentmeta.meta_value+0";
1071
		} elseif ( $orderby == 'comment__in' ) {
1072
			$comment__in = implode( ',', array_map( 'absint', $this->query_vars['comment__in'] ) );
1073
			$parsed = "FIELD( {$wpdb->comments}.comment_ID, $comment__in )";
1074
		} elseif ( in_array( $orderby, $allowed_keys ) ) {
1075
1076
			if ( isset( $meta_query_clauses[ $orderby ] ) ) {
1077
				$meta_clause = $meta_query_clauses[ $orderby ];
1078
				$parsed = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
1079
			} else {
1080
				$parsed = "$wpdb->comments.$orderby";
1081
			}
1082
		}
1083
1084
		return $parsed;
1085
	}
1086
1087
	/**
1088
	 * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
1089
	 *
1090
	 * @since 4.2.0
1091
	 * @access protected
1092
	 *
1093
	 * @param string $order The 'order' query variable.
1094
	 * @return string The sanitized 'order' query variable.
1095
	 */
1096 View Code Duplication
	protected function parse_order( $order ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1097
		if ( ! is_string( $order ) || empty( $order ) ) {
1098
			return 'DESC';
1099
		}
1100
1101
		if ( 'ASC' === strtoupper( $order ) ) {
1102
			return 'ASC';
1103
		} else {
1104
			return 'DESC';
1105
		}
1106
	}
1107
}
1108