116 /** |
116 /** |
117 * Make private/protected methods readable for backward compatibility. |
117 * Make private/protected methods readable for backward compatibility. |
118 * |
118 * |
119 * @since 4.0.0 |
119 * @since 4.0.0 |
120 * |
120 * |
121 * @param callable $name Method to call. |
121 * @param string $name Method to call. |
122 * @param array $arguments Arguments to pass when calling. |
122 * @param array $arguments Arguments to pass when calling. |
123 * @return mixed|false Return value of the callback, false otherwise. |
123 * @return mixed|false Return value of the callback, false otherwise. |
124 */ |
124 */ |
125 public function __call( $name, $arguments ) { |
125 public function __call( $name, $arguments ) { |
126 if ( 'get_search_sql' === $name ) { |
126 if ( 'get_search_sql' === $name ) { |
220 * Default empty. |
220 * Default empty. |
221 * @type int $post_parent Post parent ID to retrieve affiliated comments for. |
221 * @type int $post_parent Post parent ID to retrieve affiliated comments for. |
222 * Default empty. |
222 * Default empty. |
223 * @type string $search Search term(s) to retrieve matching comments for. |
223 * @type string $search Search term(s) to retrieve matching comments for. |
224 * Default empty. |
224 * Default empty. |
225 * @type string $status Comment status to limit results by. Accepts 'hold' |
225 * @type string|array $status Comment stati to limit results by. Accepts an array |
226 * (`comment_status=0`), 'approve' (`comment_status=1`), |
226 * or space/comma-separated list of 'hold' (`comment_status=0`), |
227 * 'all', or a custom comment status. Default 'all'. |
227 * 'approve' (`comment_status=1`), 'all', or a custom |
|
228 * comment status. Default 'all'. |
228 * @type string|array $type Include comments of a given type, or array of types. |
229 * @type string|array $type Include comments of a given type, or array of types. |
229 * Accepts 'comment', 'pings' (includes 'pingback' and |
230 * Accepts 'comment', 'pings' (includes 'pingback' and |
230 * 'trackback'), or anycustom type string. Default empty. |
231 * 'trackback'), or anycustom type string. Default empty. |
231 * @type array $type__in Include comments from a given array of comment types. |
232 * @type array $type__in Include comments from a given array of comment types. |
232 * Default empty. |
233 * Default empty. |
239 * object. 'flat' returns a flat array of found comments plus |
240 * object. 'flat' returns a flat array of found comments plus |
240 * their children. Pass `false` to leave out descendants. |
241 * their children. Pass `false` to leave out descendants. |
241 * The parameter is ignored (forced to `false`) when |
242 * The parameter is ignored (forced to `false`) when |
242 * `$fields` is 'ids' or 'counts'. Accepts 'threaded', |
243 * `$fields` is 'ids' or 'counts'. Accepts 'threaded', |
243 * 'flat', or false. Default: false. |
244 * 'flat', or false. Default: false. |
244 * @type string $cache_domain Unique cache key to be produced when this query is stored in |
245 * @type string $cache_domain Unique cache key to be produced when this query is stored in |
245 * an object cache. Default is 'core'. |
246 * an object cache. Default is 'core'. |
246 * @type bool $update_comment_meta_cache Whether to prime the metadata cache for found comments. |
247 * @type bool $update_comment_meta_cache Whether to prime the metadata cache for found comments. |
247 * Default true. |
248 * Default true. |
248 * @type bool $update_comment_post_cache Whether to prime the cache for comment posts. |
249 * @type bool $update_comment_post_cache Whether to prime the cache for comment posts. |
249 * Default false. |
250 * Default false. |
250 * } |
251 * } |
251 */ |
252 */ |
252 public function __construct( $query = '' ) { |
253 public function __construct( $query = '' ) { |
253 $this->query_var_defaults = array( |
254 $this->query_var_defaults = array( |
254 'author_email' => '', |
255 'author_email' => '', |
255 'author_url' => '', |
256 'author_url' => '', |
256 'author__in' => '', |
257 'author__in' => '', |
257 'author__not_in' => '', |
258 'author__not_in' => '', |
258 'include_unapproved' => '', |
259 'include_unapproved' => '', |
259 'fields' => '', |
260 'fields' => '', |
260 'ID' => '', |
261 'ID' => '', |
261 'comment__in' => '', |
262 'comment__in' => '', |
262 'comment__not_in' => '', |
263 'comment__not_in' => '', |
263 'karma' => '', |
264 'karma' => '', |
264 'number' => '', |
265 'number' => '', |
265 'offset' => '', |
266 'offset' => '', |
266 'no_found_rows' => true, |
267 'no_found_rows' => true, |
267 'orderby' => '', |
268 'orderby' => '', |
268 'order' => 'DESC', |
269 'order' => 'DESC', |
269 'paged' => 1, |
270 'paged' => 1, |
270 'parent' => '', |
271 'parent' => '', |
271 'parent__in' => '', |
272 'parent__in' => '', |
272 'parent__not_in' => '', |
273 'parent__not_in' => '', |
273 'post_author__in' => '', |
274 'post_author__in' => '', |
274 'post_author__not_in' => '', |
275 'post_author__not_in' => '', |
275 'post_ID' => '', |
276 'post_ID' => '', |
276 'post_id' => 0, |
277 'post_id' => 0, |
277 'post__in' => '', |
278 'post__in' => '', |
278 'post__not_in' => '', |
279 'post__not_in' => '', |
279 'post_author' => '', |
280 'post_author' => '', |
280 'post_name' => '', |
281 'post_name' => '', |
281 'post_parent' => '', |
282 'post_parent' => '', |
282 'post_status' => '', |
283 'post_status' => '', |
283 'post_type' => '', |
284 'post_type' => '', |
284 'status' => 'all', |
285 'status' => 'all', |
285 'type' => '', |
286 'type' => '', |
286 'type__in' => '', |
287 'type__in' => '', |
287 'type__not_in' => '', |
288 'type__not_in' => '', |
288 'user_id' => '', |
289 'user_id' => '', |
289 'search' => '', |
290 'search' => '', |
290 'count' => false, |
291 'count' => false, |
291 'meta_key' => '', |
292 'meta_key' => '', |
292 'meta_value' => '', |
293 'meta_value' => '', |
293 'meta_query' => '', |
294 'meta_query' => '', |
294 'date_query' => null, // See WP_Date_Query |
295 'date_query' => null, // See WP_Date_Query |
295 'hierarchical' => false, |
296 'hierarchical' => false, |
296 'cache_domain' => 'core', |
297 'cache_domain' => 'core', |
297 'update_comment_meta_cache' => true, |
298 'update_comment_meta_cache' => true, |
298 'update_comment_post_cache' => false, |
299 'update_comment_post_cache' => false, |
299 ); |
300 ); |
300 |
301 |
301 if ( ! empty( $query ) ) { |
302 if ( ! empty( $query ) ) { |
384 * but ignore 'fields', which does not affect query results. |
384 * but ignore 'fields', which does not affect query results. |
385 */ |
385 */ |
386 $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ); |
386 $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ); |
387 unset( $_args['fields'] ); |
387 unset( $_args['fields'] ); |
388 |
388 |
389 $key = md5( serialize( $_args ) ); |
389 $key = md5( serialize( $_args ) ); |
390 $last_changed = wp_cache_get_last_changed( 'comment' ); |
390 $last_changed = wp_cache_get_last_changed( 'comment' ); |
391 |
391 |
392 $cache_key = "get_comments:$key:$last_changed"; |
392 $cache_key = "get_comments:$key:$last_changed"; |
393 $cache_value = wp_cache_get( $cache_key, 'comment' ); |
393 $cache_value = wp_cache_get( $cache_key, 'comment' ); |
394 if ( false === $cache_value ) { |
394 if ( false === $cache_value ) { |
447 /** |
447 /** |
448 * Filters the comment query results. |
448 * Filters the comment query results. |
449 * |
449 * |
450 * @since 3.1.0 |
450 * @since 3.1.0 |
451 * |
451 * |
452 * @param array $_comments An array of comments. |
452 * @param WP_Comment[] $_comments An array of comments. |
453 * @param WP_Comment_Query $this Current instance of WP_Comment_Query (passed by reference). |
453 * @param WP_Comment_Query $this Current instance of WP_Comment_Query (passed by reference). |
454 */ |
454 */ |
455 $_comments = apply_filters_ref_array( 'the_comments', array( $_comments, &$this ) ); |
455 $_comments = apply_filters_ref_array( 'the_comments', array( $_comments, &$this ) ); |
456 |
456 |
457 // Convert to WP_Comment instances |
457 // Convert to WP_Comment instances |
458 $comments = array_map( 'get_comment', $_comments ); |
458 $comments = array_map( 'get_comment', $_comments ); |
469 * Used internally to get a list of comment IDs matching the query vars. |
469 * Used internally to get a list of comment IDs matching the query vars. |
470 * |
470 * |
471 * @since 4.4.0 |
471 * @since 4.4.0 |
472 * |
472 * |
473 * @global wpdb $wpdb WordPress database abstraction object. |
473 * @global wpdb $wpdb WordPress database abstraction object. |
|
474 * |
|
475 * @return int|array A single count of comment IDs if a count query. An array of comment IDs if a full query. |
474 */ |
476 */ |
475 protected function get_comment_ids() { |
477 protected function get_comment_ids() { |
476 global $wpdb; |
478 global $wpdb; |
477 |
479 |
478 // Assemble clauses related to 'comment_approved'. |
480 // Assemble clauses related to 'comment_approved'. |
479 $approved_clauses = array(); |
481 $approved_clauses = array(); |
480 |
482 |
481 // 'status' accepts an array or a comma-separated string. |
483 // 'status' accepts an array or a comma-separated string. |
482 $status_clauses = array(); |
484 $status_clauses = array(); |
483 $statuses = $this->query_vars['status']; |
485 $statuses = wp_parse_list( $this->query_vars['status'] ); |
484 if ( ! is_array( $statuses ) ) { |
486 |
485 $statuses = preg_split( '/[\s,]+/', $statuses ); |
487 // Empty 'status' should be interpreted as 'all'. |
|
488 if ( empty( $statuses ) ) { |
|
489 $statuses = array( 'all' ); |
486 } |
490 } |
487 |
491 |
488 // 'any' overrides other statuses. |
492 // 'any' overrides other statuses. |
489 if ( ! in_array( 'any', $statuses ) ) { |
493 if ( ! in_array( 'any', $statuses ) ) { |
490 foreach ( $statuses as $status ) { |
494 foreach ( $statuses as $status ) { |
491 switch ( $status ) { |
495 switch ( $status ) { |
492 case 'hold' : |
496 case 'hold': |
493 $status_clauses[] = "comment_approved = '0'"; |
497 $status_clauses[] = "comment_approved = '0'"; |
494 break; |
498 break; |
495 |
499 |
496 case 'approve' : |
500 case 'approve': |
497 $status_clauses[] = "comment_approved = '1'"; |
501 $status_clauses[] = "comment_approved = '1'"; |
498 break; |
502 break; |
499 |
503 |
500 case 'all' : |
504 case 'all': |
501 case '' : |
505 case '': |
502 $status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )"; |
506 $status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )"; |
503 break; |
507 break; |
504 |
508 |
505 default : |
509 default: |
506 $status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status ); |
510 $status_clauses[] = $wpdb->prepare( 'comment_approved = %s', $status ); |
507 break; |
511 break; |
508 } |
512 } |
509 } |
513 } |
510 |
514 |
511 if ( ! empty( $status_clauses ) ) { |
515 if ( ! empty( $status_clauses ) ) { |
513 } |
517 } |
514 } |
518 } |
515 |
519 |
516 // User IDs or emails whose unapproved comments are included, regardless of $status. |
520 // User IDs or emails whose unapproved comments are included, regardless of $status. |
517 if ( ! empty( $this->query_vars['include_unapproved'] ) ) { |
521 if ( ! empty( $this->query_vars['include_unapproved'] ) ) { |
518 $include_unapproved = $this->query_vars['include_unapproved']; |
522 $include_unapproved = wp_parse_list( $this->query_vars['include_unapproved'] ); |
519 |
523 |
520 // Accepts arrays or comma-separated strings. |
524 $unapproved_ids = array(); |
521 if ( ! is_array( $include_unapproved ) ) { |
525 $unapproved_emails = array(); |
522 $include_unapproved = preg_split( '/[\s,]+/', $include_unapproved ); |
|
523 } |
|
524 |
|
525 $unapproved_ids = $unapproved_emails = array(); |
|
526 foreach ( $include_unapproved as $unapproved_identifier ) { |
526 foreach ( $include_unapproved as $unapproved_identifier ) { |
527 // Numeric values are assumed to be user ids. |
527 // Numeric values are assumed to be user ids. |
528 if ( is_numeric( $unapproved_identifier ) ) { |
528 if ( is_numeric( $unapproved_identifier ) ) { |
529 $approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier ); |
529 $approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier ); |
530 |
530 |
531 // Otherwise we match against email addresses. |
531 // Otherwise we match against email addresses. |
532 } else { |
532 } else { |
533 $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier ); |
533 $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier ); |
534 } |
534 } |
535 } |
535 } |
536 } |
536 } |
552 } elseif ( ! empty( $this->query_vars['orderby'] ) ) { |
552 } elseif ( ! empty( $this->query_vars['orderby'] ) ) { |
553 $ordersby = is_array( $this->query_vars['orderby'] ) ? |
553 $ordersby = is_array( $this->query_vars['orderby'] ) ? |
554 $this->query_vars['orderby'] : |
554 $this->query_vars['orderby'] : |
555 preg_split( '/[,\s]/', $this->query_vars['orderby'] ); |
555 preg_split( '/[,\s]/', $this->query_vars['orderby'] ); |
556 |
556 |
557 $orderby_array = array(); |
557 $orderby_array = array(); |
558 $found_orderby_comment_ID = false; |
558 $found_orderby_comment_id = false; |
559 foreach ( $ordersby as $_key => $_value ) { |
559 foreach ( $ordersby as $_key => $_value ) { |
560 if ( ! $_value ) { |
560 if ( ! $_value ) { |
561 continue; |
561 continue; |
562 } |
562 } |
563 |
563 |
564 if ( is_int( $_key ) ) { |
564 if ( is_int( $_key ) ) { |
565 $_orderby = $_value; |
565 $_orderby = $_value; |
566 $_order = $order; |
566 $_order = $order; |
567 } else { |
567 } else { |
568 $_orderby = $_key; |
568 $_orderby = $_key; |
569 $_order = $_value; |
569 $_order = $_value; |
570 } |
570 } |
571 |
571 |
572 if ( ! $found_orderby_comment_ID && in_array( $_orderby, array( 'comment_ID', 'comment__in' ) ) ) { |
572 if ( ! $found_orderby_comment_id && in_array( $_orderby, array( 'comment_ID', 'comment__in' ) ) ) { |
573 $found_orderby_comment_ID = true; |
573 $found_orderby_comment_id = true; |
574 } |
574 } |
575 |
575 |
576 $parsed = $this->parse_orderby( $_orderby ); |
576 $parsed = $this->parse_orderby( $_orderby ); |
577 |
577 |
578 if ( ! $parsed ) { |
578 if ( ! $parsed ) { |
591 if ( empty( $orderby_array ) ) { |
591 if ( empty( $orderby_array ) ) { |
592 $orderby_array[] = "$wpdb->comments.comment_date_gmt $order"; |
592 $orderby_array[] = "$wpdb->comments.comment_date_gmt $order"; |
593 } |
593 } |
594 |
594 |
595 // To ensure determinate sorting, always include a comment_ID clause. |
595 // To ensure determinate sorting, always include a comment_ID clause. |
596 if ( ! $found_orderby_comment_ID ) { |
596 if ( ! $found_orderby_comment_id ) { |
597 $comment_ID_order = ''; |
597 $comment_id_order = ''; |
598 |
598 |
599 // Inherit order from comment_date or comment_date_gmt, if available. |
599 // Inherit order from comment_date or comment_date_gmt, if available. |
600 foreach ( $orderby_array as $orderby_clause ) { |
600 foreach ( $orderby_array as $orderby_clause ) { |
601 if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) { |
601 if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) { |
602 $comment_ID_order = $match[1]; |
602 $comment_id_order = $match[1]; |
603 break; |
603 break; |
604 } |
604 } |
605 } |
605 } |
606 |
606 |
607 // If no date-related order is available, use the date from the first available clause. |
607 // If no date-related order is available, use the date from the first available clause. |
608 if ( ! $comment_ID_order ) { |
608 if ( ! $comment_id_order ) { |
609 foreach ( $orderby_array as $orderby_clause ) { |
609 foreach ( $orderby_array as $orderby_clause ) { |
610 if ( false !== strpos( 'ASC', $orderby_clause ) ) { |
610 if ( false !== strpos( 'ASC', $orderby_clause ) ) { |
611 $comment_ID_order = 'ASC'; |
611 $comment_id_order = 'ASC'; |
612 } else { |
612 } else { |
613 $comment_ID_order = 'DESC'; |
613 $comment_id_order = 'DESC'; |
614 } |
614 } |
615 |
615 |
616 break; |
616 break; |
617 } |
617 } |
618 } |
618 } |
619 |
619 |
620 // Default to DESC. |
620 // Default to DESC. |
621 if ( ! $comment_ID_order ) { |
621 if ( ! $comment_id_order ) { |
622 $comment_ID_order = 'DESC'; |
622 $comment_id_order = 'DESC'; |
623 } |
623 } |
624 |
624 |
625 $orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order"; |
625 $orderby_array[] = "$wpdb->comments.comment_ID $comment_id_order"; |
626 } |
626 } |
627 |
627 |
628 $orderby = implode( ', ', $orderby_array ); |
628 $orderby = implode( ', ', $orderby_array ); |
629 } else { |
629 } else { |
630 $orderby = "$wpdb->comments.comment_date_gmt $order"; |
630 $orderby = "$wpdb->comments.comment_date_gmt $order"; |
631 } |
631 } |
632 |
632 |
633 $number = absint( $this->query_vars['number'] ); |
633 $number = absint( $this->query_vars['number'] ); |
634 $offset = absint( $this->query_vars['offset'] ); |
634 $offset = absint( $this->query_vars['offset'] ); |
635 $paged = absint( $this->query_vars['paged'] ); |
635 $paged = absint( $this->query_vars['paged'] ); |
|
636 $limits = ''; |
636 |
637 |
637 if ( ! empty( $number ) ) { |
638 if ( ! empty( $number ) ) { |
638 if ( $offset ) { |
639 if ( $offset ) { |
639 $limits = 'LIMIT ' . $offset . ',' . $number; |
640 $limits = 'LIMIT ' . $offset . ',' . $number; |
640 } else { |
641 } else { |
695 $this->sql_clauses['where']['karma'] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] ); |
696 $this->sql_clauses['where']['karma'] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] ); |
696 } |
697 } |
697 |
698 |
698 // Filtering by comment_type: 'type', 'type__in', 'type__not_in'. |
699 // Filtering by comment_type: 'type', 'type__in', 'type__not_in'. |
699 $raw_types = array( |
700 $raw_types = array( |
700 'IN' => array_merge( (array) $this->query_vars['type'], (array) $this->query_vars['type__in'] ), |
701 '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 'NOT IN' => (array) $this->query_vars['type__not_in'], |
702 ); |
703 ); |
703 |
704 |
704 $comment_types = array(); |
705 $comment_types = array(); |
705 foreach ( $raw_types as $operator => $_raw_types ) { |
706 foreach ( $raw_types as $operator => $_raw_types ) { |
728 } |
729 } |
729 } |
730 } |
730 |
731 |
731 if ( ! empty( $comment_types[ $operator ] ) ) { |
732 if ( ! empty( $comment_types[ $operator ] ) ) { |
732 $types_sql = implode( ', ', $comment_types[ $operator ] ); |
733 $types_sql = implode( ', ', $comment_types[ $operator ] ); |
733 $this->sql_clauses['where']['comment_type__' . strtolower( str_replace( ' ', '_', $operator ) ) ] = "comment_type $operator ($types_sql)"; |
734 $this->sql_clauses['where'][ 'comment_type__' . strtolower( str_replace( ' ', '_', $operator ) ) ] = "comment_type $operator ($types_sql)"; |
734 } |
735 } |
735 } |
736 } |
736 |
737 |
737 $parent = $this->query_vars['parent']; |
738 $parent = $this->query_vars['parent']; |
738 if ( $this->query_vars['hierarchical'] && ! $parent ) { |
739 if ( $this->query_vars['hierarchical'] && ! $parent ) { |
760 $this->sql_clauses['where']['search'] = preg_replace( '/^\s*AND\s*/', '', $search_sql ); |
761 $this->sql_clauses['where']['search'] = preg_replace( '/^\s*AND\s*/', '', $search_sql ); |
761 } |
762 } |
762 |
763 |
763 // If any post-related query vars are passed, join the posts table. |
764 // If any post-related query vars are passed, join the posts table. |
764 $join_posts_table = false; |
765 $join_posts_table = false; |
765 $plucked = wp_array_slice_assoc( $this->query_vars, array( 'post_author', 'post_name', 'post_parent' ) ); |
766 $plucked = wp_array_slice_assoc( $this->query_vars, array( 'post_author', 'post_name', 'post_parent' ) ); |
766 $post_fields = array_filter( $plucked ); |
767 $post_fields = array_filter( $plucked ); |
767 |
768 |
768 if ( ! empty( $post_fields ) ) { |
769 if ( ! empty( $post_fields ) ) { |
769 $join_posts_table = true; |
770 $join_posts_table = true; |
770 foreach ( $post_fields as $field_name => $field_value ) { |
771 foreach ( $post_fields as $field_name => $field_value ) { |
771 // $field_value may be an array. |
772 // $field_value may be an array. |
772 $esses = array_fill( 0, count( (array) $field_value ), '%s' ); |
773 $esses = array_fill( 0, count( (array) $field_value ), '%s' ); |
773 $this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value ); |
774 $this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value ); |
774 } |
775 } |
775 } |
776 } |
776 |
777 |
777 // 'post_status' and 'post_type' are handled separately, due to the specialized behavior of 'any'. |
778 // 'post_status' and 'post_type' are handled separately, due to the specialized behavior of 'any'. |
788 continue; |
789 continue; |
789 } |
790 } |
790 |
791 |
791 $join_posts_table = true; |
792 $join_posts_table = true; |
792 |
793 |
793 $esses = array_fill( 0, count( $q_values ), '%s' ); |
794 $esses = array_fill( 0, count( $q_values ), '%s' ); |
794 $this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ")", $q_values ); |
795 $this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $q_values ); |
795 } |
796 } |
796 } |
797 } |
797 |
798 |
798 // Comment author IDs for an IN clause. |
799 // Comment author IDs for an IN clause. |
799 if ( ! empty( $this->query_vars['author__in'] ) ) { |
800 if ( ! empty( $this->query_vars['author__in'] ) ) { |
805 $this->sql_clauses['where']['author__not_in'] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )'; |
806 $this->sql_clauses['where']['author__not_in'] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )'; |
806 } |
807 } |
807 |
808 |
808 // Post author IDs for an IN clause. |
809 // Post author IDs for an IN clause. |
809 if ( ! empty( $this->query_vars['post_author__in'] ) ) { |
810 if ( ! empty( $this->query_vars['post_author__in'] ) ) { |
810 $join_posts_table = true; |
811 $join_posts_table = true; |
811 $this->sql_clauses['where']['post_author__in'] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )'; |
812 $this->sql_clauses['where']['post_author__in'] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )'; |
812 } |
813 } |
813 |
814 |
814 // Post author IDs for a NOT IN clause. |
815 // Post author IDs for a NOT IN clause. |
815 if ( ! empty( $this->query_vars['post_author__not_in'] ) ) { |
816 if ( ! empty( $this->query_vars['post_author__not_in'] ) ) { |
816 $join_posts_table = true; |
817 $join_posts_table = true; |
817 $this->sql_clauses['where']['post_author__not_in'] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )'; |
818 $this->sql_clauses['where']['post_author__not_in'] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )'; |
818 } |
819 } |
819 |
820 |
820 $join = ''; |
821 $join = ''; |
|
822 $groupby = ''; |
821 |
823 |
822 if ( $join_posts_table ) { |
824 if ( $join_posts_table ) { |
823 $join .= "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID"; |
825 $join .= "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID"; |
824 } |
826 } |
825 |
827 |
833 $groupby = "{$wpdb->comments}.comment_ID"; |
835 $groupby = "{$wpdb->comments}.comment_ID"; |
834 } |
836 } |
835 } |
837 } |
836 |
838 |
837 if ( ! empty( $this->query_vars['date_query'] ) && is_array( $this->query_vars['date_query'] ) ) { |
839 if ( ! empty( $this->query_vars['date_query'] ) && is_array( $this->query_vars['date_query'] ) ) { |
838 $this->date_query = new WP_Date_Query( $this->query_vars['date_query'], 'comment_date' ); |
840 $this->date_query = new WP_Date_Query( $this->query_vars['date_query'], 'comment_date' ); |
839 $this->sql_clauses['where']['date_query'] = preg_replace( '/^\s*AND\s*/', '', $this->date_query->get_sql() ); |
841 $this->sql_clauses['where']['date_query'] = preg_replace( '/^\s*AND\s*/', '', $this->date_query->get_sql() ); |
840 } |
842 } |
841 |
843 |
842 $where = implode( ' AND ', $this->sql_clauses['where'] ); |
844 $where = implode( ' AND ', $this->sql_clauses['where'] ); |
843 |
845 |
845 /** |
847 /** |
846 * Filters the comment query clauses. |
848 * Filters the comment query clauses. |
847 * |
849 * |
848 * @since 3.1.0 |
850 * @since 3.1.0 |
849 * |
851 * |
850 * @param array $pieces A compacted array of comment query clauses. |
852 * @param string[] $pieces An associative array of comment query clauses. |
851 * @param WP_Comment_Query $this Current instance of WP_Comment_Query (passed by reference). |
853 * @param WP_Comment_Query $this Current instance of WP_Comment_Query (passed by reference). |
852 */ |
854 */ |
853 $clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) ); |
855 $clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) ); |
854 |
856 |
855 $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : ''; |
857 $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; |
856 $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : ''; |
858 $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; |
857 $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : ''; |
859 $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; |
858 $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : ''; |
860 $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : ''; |
859 $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : ''; |
861 $limits = isset( $clauses['limits'] ) ? $clauses['limits'] : ''; |
860 $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : ''; |
862 $groupby = isset( $clauses['groupby'] ) ? $clauses['groupby'] : ''; |
861 |
863 |
862 $this->filtered_where_clause = $where; |
864 $this->filtered_where_clause = $where; |
863 |
865 |
864 if ( $where ) { |
866 if ( $where ) { |
865 $where = 'WHERE ' . $where; |
867 $where = 'WHERE ' . $where; |
928 * |
930 * |
929 * @since 4.4.0 |
931 * @since 4.4.0 |
930 * |
932 * |
931 * @global wpdb $wpdb WordPress database abstraction object. |
933 * @global wpdb $wpdb WordPress database abstraction object. |
932 * |
934 * |
933 * @param array $comments Array of top-level comments whose descendants should be filled in. |
935 * @param WP_Comment[] $comments Array of top-level comments whose descendants should be filled in. |
934 * @return array |
936 * @return array |
935 */ |
937 */ |
936 protected function fill_descendants( $comments ) { |
938 protected function fill_descendants( $comments ) { |
937 global $wpdb; |
939 global $wpdb; |
938 |
940 |
939 $levels = array( |
941 $levels = array( |
940 0 => wp_list_pluck( $comments, 'comment_ID' ), |
942 0 => wp_list_pluck( $comments, 'comment_ID' ), |
941 ); |
943 ); |
942 |
944 |
943 $key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) ); |
945 $key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) ); |
944 $last_changed = wp_cache_get_last_changed( 'comment' ); |
946 $last_changed = wp_cache_get_last_changed( 'comment' ); |
945 |
947 |
946 // Fetch an entire level of the descendant tree at a time. |
948 // Fetch an entire level of the descendant tree at a time. |
947 $level = 0; |
949 $level = 0; |
948 $exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' ); |
950 $exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' ); |
949 do { |
951 do { |
950 // Parent-child relationships may be cached. Only query for those that are not. |
952 // Parent-child relationships may be cached. Only query for those that are not. |
951 $child_ids = $uncached_parent_ids = array(); |
953 $child_ids = $uncached_parent_ids = array(); |
952 $_parent_ids = $levels[ $level ]; |
954 $_parent_ids = $levels[ $level ]; |
953 foreach ( $_parent_ids as $parent_id ) { |
955 foreach ( $_parent_ids as $parent_id ) { |
954 $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; |
956 $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; |
955 $parent_child_ids = wp_cache_get( $cache_key, 'comment' ); |
957 $parent_child_ids = wp_cache_get( $cache_key, 'comment' ); |
956 if ( false !== $parent_child_ids ) { |
958 if ( false !== $parent_child_ids ) { |
957 $child_ids = array_merge( $child_ids, $parent_child_ids ); |
959 $child_ids = array_merge( $child_ids, $parent_child_ids ); |
958 } else { |
960 } else { |
959 $uncached_parent_ids[] = $parent_id; |
961 $uncached_parent_ids[] = $parent_id; |
976 |
978 |
977 // Cache parent-child relationships. |
979 // Cache parent-child relationships. |
978 $parent_map = array_fill_keys( $uncached_parent_ids, array() ); |
980 $parent_map = array_fill_keys( $uncached_parent_ids, array() ); |
979 foreach ( $level_comments as $level_comment ) { |
981 foreach ( $level_comments as $level_comment ) { |
980 $parent_map[ $level_comment->comment_parent ][] = $level_comment->comment_ID; |
982 $parent_map[ $level_comment->comment_parent ][] = $level_comment->comment_ID; |
981 $child_ids[] = $level_comment->comment_ID; |
983 $child_ids[] = $level_comment->comment_ID; |
982 } |
984 } |
983 |
985 |
984 foreach ( $parent_map as $parent_id => $children ) { |
986 foreach ( $parent_map as $parent_id => $children ) { |
985 $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; |
987 $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; |
986 wp_cache_set( $cache_key, $children, 'comment' ); |
988 wp_cache_set( $cache_key, $children, 'comment' ); |
1012 $_c = get_comment( $c->comment_ID ); |
1014 $_c = get_comment( $c->comment_ID ); |
1013 |
1015 |
1014 // If the comment isn't in the reference array, it goes in the top level of the thread. |
1016 // If the comment isn't in the reference array, it goes in the top level of the thread. |
1015 if ( ! isset( $ref[ $c->comment_parent ] ) ) { |
1017 if ( ! isset( $ref[ $c->comment_parent ] ) ) { |
1016 $threaded_comments[ $_c->comment_ID ] = $_c; |
1018 $threaded_comments[ $_c->comment_ID ] = $_c; |
1017 $ref[ $_c->comment_ID ] = $threaded_comments[ $_c->comment_ID ]; |
1019 $ref[ $_c->comment_ID ] = $threaded_comments[ $_c->comment_ID ]; |
1018 |
1020 |
1019 // Otherwise, set it as a child of its parent. |
1021 // Otherwise, set it as a child of its parent. |
1020 } else { |
1022 } else { |
1021 |
1023 |
1022 $ref[ $_c->comment_parent ]->add_child( $_c ); |
1024 $ref[ $_c->comment_parent ]->add_child( $_c ); |
1023 $ref[ $_c->comment_ID ] = $ref[ $_c->comment_parent ]->get_child( $_c->comment_ID ); |
1025 $ref[ $_c->comment_ID ] = $ref[ $_c->comment_parent ]->get_child( $_c->comment_ID ); |
1024 } |
1026 } |
1108 $parsed = "$wpdb->commentmeta.meta_value"; |
1110 $parsed = "$wpdb->commentmeta.meta_value"; |
1109 } elseif ( $orderby == 'meta_value_num' ) { |
1111 } elseif ( $orderby == 'meta_value_num' ) { |
1110 $parsed = "$wpdb->commentmeta.meta_value+0"; |
1112 $parsed = "$wpdb->commentmeta.meta_value+0"; |
1111 } elseif ( $orderby == 'comment__in' ) { |
1113 } elseif ( $orderby == 'comment__in' ) { |
1112 $comment__in = implode( ',', array_map( 'absint', $this->query_vars['comment__in'] ) ); |
1114 $comment__in = implode( ',', array_map( 'absint', $this->query_vars['comment__in'] ) ); |
1113 $parsed = "FIELD( {$wpdb->comments}.comment_ID, $comment__in )"; |
1115 $parsed = "FIELD( {$wpdb->comments}.comment_ID, $comment__in )"; |
1114 } elseif ( in_array( $orderby, $allowed_keys ) ) { |
1116 } elseif ( in_array( $orderby, $allowed_keys ) ) { |
1115 |
1117 |
1116 if ( isset( $meta_query_clauses[ $orderby ] ) ) { |
1118 if ( isset( $meta_query_clauses[ $orderby ] ) ) { |
1117 $meta_clause = $meta_query_clauses[ $orderby ]; |
1119 $meta_clause = $meta_query_clauses[ $orderby ]; |
1118 $parsed = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) ); |
1120 $parsed = sprintf( 'CAST(%s.meta_value AS %s)', esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) ); |
1119 } else { |
1121 } else { |
1120 $parsed = "$wpdb->comments.$orderby"; |
1122 $parsed = "$wpdb->comments.$orderby"; |
1121 } |
1123 } |
1122 } |
1124 } |
1123 |
1125 |