+ // 'any' overrides other statuses.
+ if ( ! in_array( 'any', $statuses ) ) {
+ foreach ( $statuses as $status ) {
+ switch ( $status ) {
+ case 'hold' :
+ $status_clauses[] = "comment_approved = '0'";
+ break;
+
+ case 'approve' :
+ $status_clauses[] = "comment_approved = '1'";
+ break;
+
+ case 'all' :
+ case '' :
+ $status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
+ break;
+
+ default :
+ $status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
+ break;
+ }
+ }
+
+ if ( ! empty( $status_clauses ) ) {
+ $approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
+ }
+ }
+
+ // User IDs or emails whose unapproved comments are included, regardless of $status.
+ if ( ! empty( $this->query_vars['include_unapproved'] ) ) {
+ $include_unapproved = $this->query_vars['include_unapproved'];
+
+ // Accepts arrays or comma-separated strings.
+ if ( ! is_array( $include_unapproved ) ) {
+ $include_unapproved = preg_split( '/[\s,]+/', $include_unapproved );
+ }
+
+ $unapproved_ids = $unapproved_emails = array();
+ foreach ( $include_unapproved as $unapproved_identifier ) {
+ // Numeric values are assumed to be user ids.
+ if ( is_numeric( $unapproved_identifier ) ) {
+ $approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
+
+ // Otherwise we match against email addresses.
+ } else {
+ $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
+ }
+ }
+ }
+
+ // Collapse comment_approved clauses into a single OR-separated clause.
+ if ( ! empty( $approved_clauses ) ) {
+ if ( 1 === count( $approved_clauses ) ) {
+ $where[] = $approved_clauses[0];
+ } else {
+ $where[] = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
+ }
+ }
+
+ $order = ( 'ASC' == strtoupper( $this->query_vars['order'] ) ) ? 'ASC' : 'DESC';
+
+ // Disable ORDER BY with 'none', an empty array, or boolean false.
+ if ( in_array( $this->query_vars['orderby'], array( 'none', array(), false ), true ) ) {
+ $orderby = '';
+ } elseif ( ! empty( $this->query_vars['orderby'] ) ) {
+ $ordersby = is_array( $this->query_vars['orderby'] ) ?
+ $this->query_vars['orderby'] :
+ preg_split( '/[,\s]/', $this->query_vars['orderby'] );
+
+ $orderby_array = array();
+ $found_orderby_comment_ID = false;
+ foreach ( $ordersby as $_key => $_value ) {
+ if ( ! $_value ) {
+ continue;
+ }
+
+ if ( is_int( $_key ) ) {
+ $_orderby = $_value;
+ $_order = $order;
+ } else {
+ $_orderby = $_key;
+ $_order = $_value;
+ }
+
+ if ( ! $found_orderby_comment_ID && 'comment_ID' === $_orderby ) {
+ $found_orderby_comment_ID = true;
+ }
+
+ $parsed = $this->parse_orderby( $_orderby );
+
+ if ( ! $parsed ) {
+ continue;
+ }
+
+ $orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
+ }
+
+ // If no valid clauses were found, order by comment_date_gmt.
+ if ( empty( $orderby_array ) ) {
+ $orderby_array[] = "$wpdb->comments.comment_date_gmt $order";
+ }
+
+ // To ensure determinate sorting, always include a comment_ID clause.
+ if ( ! $found_orderby_comment_ID ) {
+ $comment_ID_order = '';
+
+ // Inherit order from comment_date or comment_date_gmt, if available.
+ foreach ( $orderby_array as $orderby_clause ) {
+ if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) {
+ $comment_ID_order = $match[1];
+ break;
+ }
+ }
+
+ // If no date-related order is available, use the date from the first available clause.
+ if ( ! $comment_ID_order ) {
+ foreach ( $orderby_array as $orderby_clause ) {
+ if ( false !== strpos( 'ASC', $orderby_clause ) ) {
+ $comment_ID_order = 'ASC';
+ } else {
+ $comment_ID_order = 'DESC';
+ }
+
+ break;
+ }
+ }
+
+ // Default to DESC.
+ if ( ! $comment_ID_order ) {
+ $comment_ID_order = 'DESC';
+ }
+
+ $orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order";
+ }
+
+ $orderby = implode( ', ', $orderby_array );
+ } else {
+ $orderby = "$wpdb->comments.comment_date_gmt $order";
+ }
+
+ $number = absint( $this->query_vars['number'] );
+ $offset = absint( $this->query_vars['offset'] );
+
+ if ( ! empty( $number ) ) {
+ if ( $offset ) {
+ $limits = 'LIMIT ' . $offset . ',' . $number;
+ } else {
+ $limits = 'LIMIT ' . $number;
+ }
+ } else {
+ $limits = '';
+ }
+
+ if ( $this->query_vars['count'] ) {
+ $fields = 'COUNT(*)';
+ } else {
+ switch ( strtolower( $this->query_vars['fields'] ) ) {
+ case 'ids':
+ $fields = "$wpdb->comments.comment_ID";
+ break;
+ default:
+ $fields = "*";
+ break;
+ }
+ }
+
+ $join = '';
+
+ $post_id = absint( $this->query_vars['post_id'] );
+ if ( ! empty( $post_id ) ) {
+ $where[] = $wpdb->prepare( 'comment_post_ID = %d', $post_id );
+ }
+
+ // Parse comment IDs for an IN clause.
+ if ( ! empty( $this->query_vars['comment__in'] ) ) {
+ $where[] = 'comment_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
+ }
+
+ // Parse comment IDs for a NOT IN clause.
+ if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
+ $where[] = 'comment_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
+ }
+
+ // Parse comment post IDs for an IN clause.
+ if ( ! empty( $this->query_vars['post__in'] ) ) {
+ $where[] = 'comment_post_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__in'] ) ) . ' )';
+ }
+
+ // Parse comment post IDs for a NOT IN clause.
+ if ( ! empty( $this->query_vars['post__not_in'] ) ) {
+ $where[] = 'comment_post_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__not_in'] ) ) . ' )';
+ }
+
+ if ( '' !== $this->query_vars['author_email'] ) {
+ $where[] = $wpdb->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
+ }
+
+ if ( '' !== $this->query_vars['karma'] ) {
+ $where[] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
+ }
+
+ // Filtering by comment_type: 'type', 'type__in', 'type__not_in'.
+ $raw_types = array(
+ 'IN' => array_merge( (array) $this->query_vars['type'], (array) $this->query_vars['type__in'] ),
+ 'NOT IN' => (array) $this->query_vars['type__not_in'],
+ );
+
+ $comment_types = array();
+ foreach ( $raw_types as $operator => $_raw_types ) {
+ $_raw_types = array_unique( $_raw_types );
+
+ foreach ( $_raw_types as $type ) {
+ switch ( $type ) {
+ // An empty translates to 'all', for backward compatibility
+ case '':
+ case 'all' :
+ break;
+
+ case 'comment':
+ case 'comments':
+ $comment_types[ $operator ][] = "''";
+ break;
+
+ case 'pings':
+ $comment_types[ $operator ][] = "'pingback'";
+ $comment_types[ $operator ][] = "'trackback'";
+ break;
+
+ default:
+ $comment_types[ $operator ][] = $wpdb->prepare( '%s', $type );
+ break;
+ }
+ }
+
+ if ( ! empty( $comment_types[ $operator ] ) ) {
+ $types_sql = implode( ', ', $comment_types[ $operator ] );
+ $where[] = "comment_type $operator ($types_sql)";
+ }
+ }
+
+ if ( '' !== $this->query_vars['parent'] ) {
+ $where[] = $wpdb->prepare( 'comment_parent = %d', $this->query_vars['parent'] );
+ }
+
+ if ( is_array( $this->query_vars['user_id'] ) ) {
+ $where[] = 'user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
+ } elseif ( '' !== $this->query_vars['user_id'] ) {
+ $where[] = $wpdb->prepare( 'user_id = %d', $this->query_vars['user_id'] );
+ }
+
+ if ( '' !== $this->query_vars['search'] ) {
+ $search_sql = $this->get_search_sql(
+ $this->query_vars['search'],
+ array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' )
+ );
+
+ // Strip leading 'AND'.
+ $where[] = preg_replace( '/^\s*AND\s*/', '', $search_sql );
+ }
+
+ // If any post-related query vars are passed, join the posts table.
+ $join_posts_table = false;
+ $plucked = wp_array_slice_assoc( $this->query_vars, array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type' ) );
+ $post_fields = array_filter( $plucked );
+
+ if ( ! empty( $post_fields ) ) {
+ $join_posts_table = true;
+ foreach ( $post_fields as $field_name => $field_value ) {
+ // $field_value may be an array.
+ $esses = array_fill( 0, count( (array) $field_value ), '%s' );
+ $where[] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value );
+ }
+ }
+
+ // Comment author IDs for an IN clause.
+ if ( ! empty( $this->query_vars['author__in'] ) ) {
+ $where[] = 'user_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__in'] ) ) . ' )';
+ }
+
+ // Comment author IDs for a NOT IN clause.
+ if ( ! empty( $this->query_vars['author__not_in'] ) ) {
+ $where[] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )';
+ }
+
+ // Post author IDs for an IN clause.
+ if ( ! empty( $this->query_vars['post_author__in'] ) ) {
+ $join_posts_table = true;
+ $where[] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )';
+ }
+
+ // Post author IDs for a NOT IN clause.
+ if ( ! empty( $this->query_vars['post_author__not_in'] ) ) {
+ $join_posts_table = true;
+ $where[] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )';
+ }
+
+ if ( $join_posts_table ) {
+ $join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
+ }
+
+ if ( ! empty( $meta_query_clauses ) ) {
+ $join .= $meta_query_clauses['join'];
+
+ // Strip leading 'AND'.
+ $where[] = preg_replace( '/^\s*AND\s*/', '', $meta_query_clauses['where'] );
+
+ if ( ! $this->query_vars['count'] ) {
+ $groupby = "{$wpdb->comments}.comment_ID";
+ }
+ }
+
+ $date_query = $this->query_vars['date_query'];
+ if ( ! empty( $date_query ) && is_array( $date_query ) ) {
+ $date_query_object = new WP_Date_Query( $date_query, 'comment_date' );
+ $where[] = preg_replace( '/^\s*AND\s*/', '', $date_query_object->get_sql() );
+ }
+
+ $where = implode( ' AND ', $where );
+
+ $pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
+ /**
+ * Filter the comment query clauses.
+ *
+ * @since 3.1.0
+ *
+ * @param array $pieces A compacted array of comment query clauses.
+ * @param WP_Comment_Query &$this Current instance of WP_Comment_Query, passed by reference.
+ */
+ $clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
+
+ $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
+ $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
+ $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
+ $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
+ $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
+ $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
+
+ if ( $where ) {
+ $where = 'WHERE ' . $where;
+ }
+
+ if ( $groupby ) {
+ $groupby = 'GROUP BY ' . $groupby;
+ }
+
+ if ( $orderby ) {
+ $orderby = "ORDER BY $orderby";
+ }
+
+ $this->request = "SELECT $fields FROM $wpdb->comments $join $where $groupby $orderby $limits";
+
+ if ( $this->query_vars['count'] ) {
+ return $wpdb->get_var( $this->request );
+ }
+
+ if ( 'ids' == $this->query_vars['fields'] ) {
+ $this->comments = $wpdb->get_col( $this->request );
+ return array_map( 'intval', $this->comments );
+ }
+
+ $results = $wpdb->get_results( $this->request );
+ /**
+ * Filter the comment query results.
+ *
+ * @since 3.1.0
+ *
+ * @param array $results An array of comments.
+ * @param WP_Comment_Query &$this Current instance of WP_Comment_Query, passed by reference.
+ */
+ $comments = apply_filters_ref_array( 'the_comments', array( $results, &$this ) );
+
+ wp_cache_add( $cache_key, $comments, 'comment' );
+
+ $this->comments = $comments;
+ return $this->comments;