WordPress.org

Make WordPress Core

Changeset 29965


Ignore:
Timestamp:
10/19/2014 07:38:16 PM (5 years ago)
Author:
boonebgorges
Message:

Use the comment API rather than direct SQL queries in comments_template().

comments_template() is used by most themes to display a post's comments. It
shows all comments that have been approved, and also shows all pending comments
by the current visitor (as determined by the comment cookies). However, the
comments API previously had no way of querying for "all comments that are
either approved, or are unapproved but written by foo@…". The
workaround was a direct SQL query: uncached, not subject to the same filters as
other comment queries, and just generally icky.

The new include_unapproved parameter for WP_Comment_Query accepts an array
of user IDs or email addresses. Pending comments associated with users in this
array will be included in query results, regardless of the value of the 'status'
parameter. In comments_template(), we leap from direct SQL queries to
get_comments() plus `include_unapproved', striving to put right what once
went wrong.

Props boonebgorges, simonwheatley, hardy101, jesin.
Fixes #19623.

Location:
trunk
Files:
3 edited

Legend:

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

    r29908 r29965  
    11131113    $comment_author_url = esc_url($commenter['comment_author_url']);
    11141114
    1115     /** @todo Use API instead of SELECTs. */
    1116     if ( $user_ID) {
    1117         $comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND (comment_approved = '1' OR ( user_id = %d AND comment_approved = '0' ) )  ORDER BY comment_date_gmt", $post->ID, $user_ID));
    1118     } else if ( empty($comment_author) ) {
    1119         $comments = get_comments( array('post_id' => $post->ID, 'status' => 'approve', 'order' => 'ASC') );
    1120     } else {
    1121         $comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND ( comment_approved = '1' OR ( comment_author = %s AND comment_author_email = %s AND comment_approved = '0' ) ) ORDER BY comment_date_gmt", $post->ID, wp_specialchars_decode($comment_author,ENT_QUOTES), $comment_author_email));
    1122     }
     1115    $comment_args = array(
     1116        'order'   => 'ASC',
     1117        'orderby' => 'comment_date_gmt',
     1118        'status'  => 'approve',
     1119        'post_id' => $post->ID,
     1120    );
     1121
     1122    if ( $user_ID ) {
     1123        $comment_args['include_unapproved'] = array( $user_ID );
     1124    } else if ( ! empty( $comment_author ) ) {
     1125        $comment_args['include_unapproved'] = array( $comment_author_email );
     1126    }
     1127
     1128    $comments = get_comments( $comment_args );
    11231129
    11241130    /**
  • trunk/src/wp-includes/comment.php

    r29935 r29965  
    260260     * @since 4.1.0 Introduced 'comment__in', 'comment__not_in', 'post_author__in',
    261261     *              'post_author__not_in', 'author__in', 'author__not_in',
    262      *              'post__in', and 'post__not_in' to $query_vars.
     262     *              'post__in', 'post__not_in', and 'include_unapproved' to $query_vars.
    263263     *
    264264     * @param string|array $query_vars
     
    272272            'author__in' => '',
    273273            'author__not_in' => '',
     274            'include_unapproved' => '',
    274275            'fields' => '',
    275276            'ID' => '',
     
    334335        }
    335336
     337        // Assemble clauses related to 'comment_approved'.
     338        $approved_clauses = array();
    336339        $status = $this->query_vars['status'];
    337340        if ( 'hold' == $status ) {
    338             $approved = "comment_approved = '0'";
     341            $approved_clauses[] = "comment_approved = '0'";
    339342        } elseif ( 'approve' == $status ) {
    340             $approved = "comment_approved = '1'";
     343            $approved_clauses[] = "comment_approved = '1'";
    341344        } elseif ( ! empty( $status ) && 'all' != $status ) {
    342             $approved = $wpdb->prepare( "comment_approved = %s", $status );
     345            $approved_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
    343346        } else {
    344             $approved = "( comment_approved = '0' OR comment_approved = '1' )";
    345         }
     347            $approved_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
     348        }
     349
     350        // User IDs or emails whose unapproved comments are included, regardless of $status.
     351        if ( ! empty( $this->query_vars['include_unapproved'] ) ) {
     352            $include_unapproved = $this->query_vars['include_unapproved'];
     353
     354            // Accepts arrays or comma-separated strings.
     355            if ( ! is_array( $include_unapproved ) ) {
     356                $include_unapproved = preg_split( '/[\s,]+/', $include_unapproved );
     357            }
     358
     359            $unapproved_ids = $unapproved_emails = array();
     360            foreach ( $include_unapproved as $unapproved_identifier ) {
     361                // Numeric values are assumed to be user ids.
     362                if ( is_numeric( $unapproved_identifier ) ) {
     363                    $approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
     364
     365                // Otherwise we match against email addresses.
     366                } else {
     367                    $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
     368                }
     369            }
     370        }
     371
     372        // Collapse comment_approved clauses into a single OR-separated clause.
     373        if ( 1 === count( $approved_clauses ) ) {
     374            $approved = $approved_clauses[0];
     375        } else {
     376            $approved = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
     377        }
     378
    346379        $order = ( 'ASC' == strtoupper( $this->query_vars['order'] ) ) ? 'ASC' : 'DESC';
    347380
  • trunk/tests/phpunit/tests/comment/query.php

    r29935 r29965  
    361361        $this->assertEqualSets( array( $c3, $c4 ), $comment_ids );
    362362    }
     363
     364    /**
     365     * @ticket 19623
     366     */
     367    public function test_get_comments_with_status_all() {
     368        $comment_1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     369        $comment_2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '1' ) );
     370        $comment_3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '0' ) );
     371        $comments_approved_1 = get_comments( array( 'status' => 'all' ) );
     372
     373        $comment_ids = get_comments( array( 'fields' => 'ids' ) );
     374        $this->assertEqualSets( array( $comment_1, $comment_2, $comment_3 ), $comment_ids );
     375    }
     376
     377    /**
     378     * @ticket 19623
     379     */
     380    public function test_get_comments_with_include_unapproved_user_id() {
     381        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     382        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '1' ) );
     383        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '0' ) );
     384        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 6, 'comment_approved' => '0' ) );
     385
     386        $found = get_comments( array(
     387            'fields' => 'ids',
     388            'include_unapproved' => 1,
     389            'status' => 'approve',
     390        ) );
     391
     392        $this->assertEqualSets( array( $c1, $c2, $c3 ), $found );
     393    }
     394
     395    /**
     396     * @ticket 19623
     397     */
     398    public function test_get_comments_with_include_unapproved_user_id_array() {
     399        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     400        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '1' ) );
     401        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '0' ) );
     402        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 6, 'comment_approved' => '0' ) );
     403        $c5 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 8, 'comment_approved' => '0' ) );
     404
     405        $found = get_comments( array(
     406            'fields' => 'ids',
     407            'include_unapproved' => array( 1, 8 ),
     408            'status' => 'approve',
     409        ) );
     410
     411        $this->assertEqualSets( array( $c1, $c2, $c3, $c5 ), $found );
     412    }
     413
     414    /**
     415     * @ticket 19623
     416     */
     417    public function test_get_comments_with_include_unapproved_user_id_comma_separated() {
     418        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     419        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '1' ) );
     420        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 1, 'comment_approved' => '0' ) );
     421        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 6, 'comment_approved' => '0' ) );
     422        $c5 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 8, 'comment_approved' => '0' ) );
     423
     424        $found = get_comments( array(
     425            'fields' => 'ids',
     426            'include_unapproved' => '1,8',
     427            'status' => 'approve',
     428        ) );
     429
     430        $this->assertEqualSets( array( $c1, $c2, $c3, $c5 ), $found );
     431    }
     432
     433    /**
     434     * @ticket 19623
     435     */
     436    public function test_get_comments_with_include_unapproved_author_email() {
     437        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     438        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '1', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     439        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     440        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'bar@example.com' ) );
     441
     442        $found = get_comments( array(
     443            'fields' => 'ids',
     444            'include_unapproved' => 'foo@example.com',
     445            'status' => 'approve',
     446        ) );
     447
     448        $this->assertEqualSets( array( $c1, $c2, $c3 ), $found );
     449    }
     450
     451    /**
     452     * @ticket 19623
     453     */
     454    public function test_get_comments_with_include_unapproved_mixed_array() {
     455        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     456        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '1', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     457        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     458        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'bar@example.com' ) );
     459        $c5 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 4, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'bar@example.com' ) );
     460
     461        $found = get_comments( array(
     462            'fields' => 'ids',
     463            'include_unapproved' => array( 'foo@example.com', 4 ),
     464            'status' => 'approve',
     465        ) );
     466
     467        $this->assertEqualSets( array( $c1, $c2, $c3, $c5 ), $found );
     468    }
     469
     470    /**
     471     * @ticket 19623
     472     */
     473    public function test_get_comments_with_include_unapproved_mixed_comma_separated() {
     474        $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7, 'comment_approved' => '1' ) );
     475        $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '1', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     476        $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'foo@example.com' ) );
     477        $c4 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 0, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'bar@example.com' ) );
     478        $c5 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 4, 'comment_approved' => '0', 'comment_author' => 'foo', 'comment_author_email' => 'bar@example.com' ) );
     479
     480        $found = get_comments( array(
     481            'fields' => 'ids',
     482            'include_unapproved' => 'foo@example.com, 4',
     483            'status' => 'approve',
     484        ) );
     485
     486        $this->assertEqualSets( array( $c1, $c2, $c3, $c5 ), $found );
     487    }
    363488}
Note: See TracChangeset for help on using the changeset viewer.