Make WordPress Core

Changeset 30084


Ignore:
Timestamp:
10/29/2014 02:21:10 AM (12 years ago)
Author:
boonebgorges
Message:

Support multiple 'status' values in WP_Comment_Query.

This change required turning the SQL concatenation into the generation of an
array, for greater flexibility.

Props karpstrucking, ebinnion.
Fixes #29612.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/comment.php

    r30026 r30084  
    303303                        'post_status' => '',
    304304                        'post_type' => '',
    305                         'status' => '',
     305                        'status' => 'all',
    306306                        'type' => '',
    307307                        'user_id' => '',
     
    344344                }
    345345
     346                $where = array();
     347
    346348                // Assemble clauses related to 'comment_approved'.
    347349                $approved_clauses = array();
    348                 $status = $this->query_vars['status'];
    349                 if ( 'hold' == $status ) {
    350                         $approved_clauses[] = "comment_approved = '0'";
    351                 } elseif ( 'approve' == $status ) {
    352                         $approved_clauses[] = "comment_approved = '1'";
    353                 } elseif ( ! empty( $status ) && 'all' != $status ) {
    354                         $approved_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
    355                 } else {
    356                         $approved_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
     350
     351                // 'status' accepts an array or a comma-separated string.
     352                $status_clauses = array();
     353                $statuses = $this->query_vars['status'];
     354                if ( ! is_array( $statuses ) ) {
     355                        $statuses = preg_split( '/[\s,]+/', $statuses );
     356                }
     357
     358                // Remove empty statuses.
     359                $statuses = array_filter( $statuses );
     360
     361                // 'any' overrides other statuses.
     362                if ( ! in_array( 'any', $statuses ) ) {
     363                        foreach ( $statuses as $status ) {
     364                                switch ( $status ) {
     365                                        case 'hold' :
     366                                                $status_clauses[] = "comment_approved = '0'";
     367                                                break;
     368
     369                                        case 'approve' :
     370                                                $status_clauses[] = "comment_approved = '1'";
     371                                                break;
     372
     373                                        case 'all' :
     374                                                $status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
     375                                                break;
     376
     377                                        default :
     378                                                $status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
     379                                                break;
     380                                }
     381                        }
     382
     383                        if ( ! empty( $status_clauses ) ) {
     384                                $approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
     385                        }
    357386                }
    358387
     
    380409
    381410                // Collapse comment_approved clauses into a single OR-separated clause.
    382                 if ( 1 === count( $approved_clauses ) ) {
    383                         $approved = $approved_clauses[0];
    384                 } else {
    385                         $approved = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
     411                if ( ! empty( $approved_clauses ) ) {
     412                        if ( 1 === count( $approved_clauses ) ) {
     413                                $where[] = $approved_clauses[0];
     414                        } else {
     415                                $where[] = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
     416                        }
    386417                }
    387418
     
    458489
    459490                $join = '';
    460                 $where = $approved;
    461491
    462492                $post_id = absint( $this->query_vars['post_id'] );
    463493                if ( ! empty( $post_id ) ) {
    464                         $where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
     494                        $where[] = $wpdb->prepare( 'comment_post_ID = %d', $post_id );
    465495                }
    466496
    467497                // Parse comment IDs for an IN clause.
    468498                if ( ! empty( $this->query_vars['comment__in'] ) ) {
    469                         $where .= ' AND comment_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
     499                        $where[] = 'comment_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
    470500                }
    471501
    472502                // Parse comment IDs for a NOT IN clause.
    473503                if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
    474                         $where .= ' AND comment_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
     504                        $where[] = 'comment_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
    475505                }
    476506
    477507                // Parse comment post IDs for an IN clause.
    478508                if ( ! empty( $this->query_vars['post__in'] ) ) {
    479                         $where .= ' AND comment_post_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__in'] ) ) . ' )';
     509                        $where[] = 'comment_post_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__in'] ) ) . ' )';
    480510                }
    481511
    482512                // Parse comment post IDs for a NOT IN clause.
    483513                if ( ! empty( $this->query_vars['post__not_in'] ) ) {
    484                         $where .= ' AND comment_post_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__not_in'] ) ) . ' )';
     514                        $where[] = 'comment_post_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__not_in'] ) ) . ' )';
    485515                }
    486516
    487517                if ( '' !== $this->query_vars['author_email'] ) {
    488                         $where .= $wpdb->prepare( ' AND comment_author_email = %s', $this->query_vars['author_email'] );
     518                        $where[] = $wpdb->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
    489519                }
    490520
    491521                if ( '' !== $this->query_vars['karma'] ) {
    492                         $where .= $wpdb->prepare( ' AND comment_karma = %d', $this->query_vars['karma'] );
     522                        $where[] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
    493523                }
    494524
    495525                if ( 'comment' == $this->query_vars['type'] ) {
    496                         $where .= " AND comment_type = ''";
     526                        $where[] = "comment_type = ''";
    497527                } elseif( 'pings' == $this->query_vars['type'] ) {
    498                         $where .= ' AND comment_type IN ("pingback", "trackback")';
     528                        $where[] = 'comment_type IN ("pingback", "trackback")';
    499529                } elseif ( ! empty( $this->query_vars['type'] ) ) {
    500                         $where .= $wpdb->prepare( ' AND comment_type = %s', $this->query_vars['type'] );
     530                        $where[] = $wpdb->prepare( 'comment_type = %s', $this->query_vars['type'] );
    501531                }
    502532
    503533                if ( '' !== $this->query_vars['parent'] ) {
    504                         $where .= $wpdb->prepare( ' AND comment_parent = %d', $this->query_vars['parent'] );
     534                        $where[] = $wpdb->prepare( 'comment_parent = %d', $this->query_vars['parent'] );
    505535                }
    506536
    507537                if ( is_array( $this->query_vars['user_id'] ) ) {
    508                         $where .= ' AND user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
     538                        $where[] = 'user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
    509539                } elseif ( '' !== $this->query_vars['user_id'] ) {
    510                         $where .= $wpdb->prepare( ' AND user_id = %d', $this->query_vars['user_id'] );
     540                        $where[] = $wpdb->prepare( 'user_id = %d', $this->query_vars['user_id'] );
    511541                }
    512542
    513543                if ( '' !== $this->query_vars['search'] ) {
    514                         $where .= $this->get_search_sql(
     544                        $search_sql = $this->get_search_sql(
    515545                                $this->query_vars['search'],
    516546                                array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' )
    517547                        );
     548
     549                        // Strip leading 'AND'.
     550                        $where[] = preg_replace( '/^\s*AND\s*/', '', $search_sql );
    518551                }
    519552
     
    526559                        $join_posts_table = true;
    527560                        foreach ( $post_fields as $field_name => $field_value ) {
    528                                 $where .= $wpdb->prepare( " AND {$wpdb->posts}.{$field_name} = %s", $field_value );
     561                                $where[] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} = %s", $field_value );
    529562                        }
    530563                }
     
    532565                // Comment author IDs for an IN clause.
    533566                if ( ! empty( $this->query_vars['author__in'] ) ) {
    534                         $where .= ' AND user_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__in'] ) ) . ' )';
     567                        $where[] = 'user_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__in'] ) ) . ' )';
    535568                }
    536569
    537570                // Comment author IDs for a NOT IN clause.
    538571                if ( ! empty( $this->query_vars['author__not_in'] ) ) {
    539                         $where .= ' AND user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )';
     572                        $where[] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )';
    540573                }
    541574
     
    543576                if ( ! empty( $this->query_vars['post_author__in'] ) ) {
    544577                        $join_posts_table = true;
    545                         $where .= ' AND post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )';
     578                        $where[] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )';
    546579                }
    547580
     
    549582                if ( ! empty( $this->query_vars['post_author__not_in'] ) ) {
    550583                        $join_posts_table = true;
    551                         $where .= ' AND post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )';
     584                        $where[] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )';
    552585                }
    553586
     
    559592                        $clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
    560593                        $join .= $clauses['join'];
    561                         $where .= $clauses['where'];
     594
     595                        // Strip leading 'AND'.
     596                        $where[] = preg_replace( '/^\s*AND\s*/', '', $clauses['where'] );
    562597
    563598                        if ( ! $this->query_vars['count'] ) {
     
    569604                if ( ! empty( $date_query ) && is_array( $date_query ) ) {
    570605                        $date_query_object = new WP_Date_Query( $date_query, 'comment_date' );
    571                         $where .= $date_query_object->get_sql();
    572                 }
     606                        $where[] = preg_replace( '/^\s*AND\s*/', '', $date_query_object->get_sql() );
     607                }
     608
     609                $where = implode( ' AND ', $where );
    573610
    574611                $pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits', 'groupby' );
     
    591628                $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
    592629
     630                if ( $where ) {
     631                        $where = 'WHERE ' . $where;
     632                }
     633
    593634                if ( $groupby ) {
    594635                        $groupby = 'GROUP BY ' . $groupby;
     
    599640                }
    600641
    601                 $this->request = "SELECT $fields FROM $wpdb->comments $join WHERE $where $groupby $orderby $limits";
     642                $this->request = "SELECT $fields FROM $wpdb->comments $join $where $groupby $orderby $limits";
    602643
    603644                if ( $this->query_vars['count'] ) {
  • trunk/tests/phpunit/tests/comment/query.php

    r30026 r30084  
    7474
    7575                $this->assertEqualSets( array( $c1, $c3 ), $found );
     76        }
     77
     78        public function test_status_default_to_all() {
     79                $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '1' ) );
     80                $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => 'foo' ) );
     81                $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '0' ) );
     82
     83                $q = new WP_Comment_Query();
     84                $found = $q->query( array(
     85                        'fields' => 'ids',
     86                ) );
     87
     88                $this->assertEqualSets( array( $c1, $c3 ), $found );
     89        }
     90
     91        /**
     92         * @ticket 29612
     93         */
     94        public function test_status_comma_any() {
     95                $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '1' ) );
     96                $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => 'foo' ) );
     97                $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '0' ) );
     98
     99                $q = new WP_Comment_Query();
     100                $found = $q->query( array(
     101                        'status' => 'any',
     102                        'fields' => 'ids',
     103                ) );
     104
     105                $this->assertEqualSets( array( $c1, $c2, $c3 ), $found );
     106        }
     107
     108        /**
     109         * @ticket 29612
     110         */
     111        public function test_status_comma_separated() {
     112                $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '1' ) );
     113                $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => 'foo' ) );
     114                $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '0' ) );
     115
     116                $q = new WP_Comment_Query();
     117                $found = $q->query( array(
     118                        'status' => 'approve,foo,bar',
     119                        'fields' => 'ids',
     120                ) );
     121
     122                $this->assertEqualSets( array( $c1, $c2 ), $found );
     123        }
     124
     125        /**
     126         * @ticket 29612
     127         */
     128        public function test_status_array() {
     129                $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '1' ) );
     130                $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => 'foo' ) );
     131                $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'comment_approved' => '0' ) );
     132
     133                $q = new WP_Comment_Query();
     134                $found = $q->query( array(
     135                        'status' => array( 'approve', 'foo', 'bar', ),
     136                        'fields' => 'ids',
     137                ) );
     138
     139                $this->assertEqualSets( array( $c1, $c2 ), $found );
    76140        }
    77141
Note: See TracChangeset for help on using the changeset viewer.