From 4f0367ef886e9a8b49d4ff9126be5e5ea032aa38 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Sat, 6 Jun 2020 09:59:56 +0000 Subject: [PATCH] Comments: Ensure that unmoderated comments won't be search indexed. After a comment is submitted, only allow a brief window where the comment is live on the site. Props jonkolbert, ayeshrajans, Asif2BD, peterwilsoncc, imath, audrasjb, jonoaldersonwp, whyisjake, SergeyBiryukov. Merges [47887] and [47889] to the 5.2 branch. See #49956. Built from https://develop.svn.wordpress.org/branches/5.2@47917 git-svn-id: http://core.svn.wordpress.org/branches/5.2@47691 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-comments-post.php | 4 +- wp-includes/class-walker-comment.php | 105 ++++++++++++++++++------- wp-includes/class-wp-comment-query.php | 11 ++- wp-includes/class-wp.php | 4 + wp-includes/comment-template.php | 2 +- wp-includes/comment.php | 7 +- 6 files changed, 98 insertions(+), 35 deletions(-) diff --git a/wp-comments-post.php b/wp-comments-post.php index fe03cb7296..a3ea760c62 100644 --- a/wp-comments-post.php +++ b/wp-comments-post.php @@ -56,8 +56,8 @@ do_action( 'set_comment_cookies', $comment, $user, $cookies_consent ); $location = empty( $_POST['redirect_to'] ) ? get_comment_link( $comment ) : $_POST['redirect_to'] . '#comment-' . $comment->comment_ID; -// Add specific query arguments to display the awaiting moderation message. -if ( 'unapproved' === wp_get_comment_status( $comment ) && ! empty( $comment->comment_author_email ) ) { +// If user didn't consent to cookies, add specific query arguments to display the awaiting moderation message. +if ( ! $cookies_consent && 'unapproved' === wp_get_comment_status( $comment ) && ! empty( $comment->comment_author_email ) ) { $location = add_query_arg( array( 'unapproved' => $comment->comment_ID, diff --git a/wp-includes/class-walker-comment.php b/wp-includes/class-walker-comment.php index 87834f52be..8fe85fb0c2 100644 --- a/wp-includes/class-walker-comment.php +++ b/wp-includes/class-walker-comment.php @@ -181,7 +181,11 @@ class Walker_Comment extends Walker { return; } - if ( ( 'pingback' == $comment->comment_type || 'trackback' == $comment->comment_type ) && $args['short_ping'] ) { + if ( 'comment' === $comment->comment_type ) { + add_filter( 'comment_text', array( $this, 'filter_comment_text' ), 40, 2 ); + } + + if ( ( 'pingback' === $comment->comment_type || 'trackback' === $comment->comment_type ) && $args['short_ping'] ) { ob_start(); $this->ping( $comment, $depth, $args ); $output .= ob_get_clean(); @@ -194,6 +198,10 @@ class Walker_Comment extends Walker { $this->comment( $comment, $depth, $args ); $output .= ob_get_clean(); } + + if ( 'comment' === $comment->comment_type ) { + remove_filter( 'comment_text', array( $this, 'filter_comment_text' ), 40, 2 ); + } } /** @@ -244,6 +252,29 @@ class Walker_Comment extends Walker { comment_approved && ! $show_pending_links ) { + $comment_text = wp_kses( $comment_text, array() ); + } + + return $comment_text; + } + /** * Outputs a single comment. * @@ -264,13 +295,14 @@ class Walker_Comment extends Walker { $add_below = 'div-comment'; } - $commenter = wp_get_current_commenter(); + $commenter = wp_get_current_commenter(); + $show_pending_links = isset( $commenter['comment_author'] ) && $commenter['comment_author']; + if ( $commenter['comment_author_email'] ) { $moderation_note = __( 'Your comment is awaiting moderation.' ); } else { $moderation_note = __( 'Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.' ); } - ?> < has_children ? 'parent' : '', $comment ); ?> id="comment-"> @@ -279,14 +311,21 @@ class Walker_Comment extends Walker {
says:' ), - sprintf( '%s', get_comment_author_link( $comment ) ) - ); + $comment_author = get_comment_author_link( $comment ); + + if ( '0' == $comment->comment_approved && ! $show_pending_links ) { + $comment_author = get_comment_author( $comment ); + } + + printf( + /* translators: %s: Comment author link. */ + __( '%s says:' ), + sprintf( '%s', $comment_author ) + ); ?>
comment_approved ) : ?> @@ -354,13 +393,14 @@ class Walker_Comment extends Walker { protected function html5_comment( $comment, $depth, $args ) { $tag = ( 'div' === $args['style'] ) ? 'div' : 'li'; - $commenter = wp_get_current_commenter(); + $commenter = wp_get_current_commenter(); + $show_pending_links = ! empty( $commenter['comment_author'] ); + if ( $commenter['comment_author_email'] ) { $moderation_note = __( 'Your comment is awaiting moderation.' ); } else { $moderation_note = __( 'Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.' ); } - ?> < id="comment-" has_children ? 'parent' : '', $comment ); ?>>
@@ -368,14 +408,21 @@ class Walker_Comment extends Walker {
says:' ), - sprintf( '%s', get_comment_author_link( $comment ) ) - ); + $comment_author = get_comment_author_link( $comment ); + + if ( '0' == $comment->comment_approved && ! $show_pending_links ) { + $comment_author = get_comment_author( $comment ); + } + + printf( + /* translators: %s: Comment author link. */ + __( '%s says:' ), + sprintf( '%s', $comment_author ) + ); ?>
@@ -401,18 +448,20 @@ class Walker_Comment extends Walker { 'div-comment', - 'depth' => $depth, - 'max_depth' => $args['max_depth'], - 'before' => '
', - 'after' => '
', + if ( '1' == $comment->comment_approved || $show_pending_links ) { + comment_reply_link( + array_merge( + $args, + array( + 'add_below' => 'div-comment', + 'depth' => $depth, + 'max_depth' => $args['max_depth'], + 'before' => '
', + 'after' => '
', + ) ) - ) - ); + ); + } ?>
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 ); + // Otherwise we match against email addresses. + if ( ! empty( $_GET['unapproved'] ) && ! empty( $_GET['moderation-hash'] ) ) { + // Only include requested comment. + $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' AND comment_ID = %d )", $unapproved_identifier, (int) $_GET['unapproved'] ); + } else { + // Include all of the author's unapproved comments. + $approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier ); + } } } } diff --git a/wp-includes/class-wp.php b/wp-includes/class-wp.php index 5824463a1e..cfac3b71aa 100644 --- a/wp-includes/class-wp.php +++ b/wp-includes/class-wp.php @@ -403,6 +403,10 @@ class WP { if ( is_user_logged_in() ) { $headers = array_merge( $headers, wp_get_nocache_headers() ); + } elseif ( ! empty( $_GET['unapproved'] ) && ! empty( $_GET['moderation-hash'] ) ) { + // Unmoderated comments are only visible for one minute via the moderation hash. + $headers['Expires'] = gmdate( 'D, d M Y H:i:s', time() + MINUTE_IN_SECONDS ); + $headers['Cache-Control'] = 'max-age=60, must-revalidate'; } if ( ! empty( $this->query_vars['error'] ) ) { $status = (int) $this->query_vars['error']; diff --git a/wp-includes/comment-template.php b/wp-includes/comment-template.php index 41031cba93..a4372269ad 100644 --- a/wp-includes/comment-template.php +++ b/wp-includes/comment-template.php @@ -999,7 +999,7 @@ function comment_text( $comment_ID = 0, $args = array() ) { * @see Walker_Comment::comment() * * @param string $comment_text Text of the current comment. - * @param WP_Comment|null $comment The comment object. + * @param WP_Comment|null $comment The comment object. Null if not found. * @param array $args An array of arguments. */ echo apply_filters( 'comment_text', $comment_text, $comment, $args ); diff --git a/wp-includes/comment.php b/wp-includes/comment.php index 5e89ef7695..3c15b0d6a6 100644 --- a/wp-includes/comment.php +++ b/wp-includes/comment.php @@ -1808,7 +1808,12 @@ function wp_get_unapproved_comment_author_email() { $comment = get_comment( $comment_id ); if ( $comment && hash_equals( $_GET['moderation-hash'], wp_hash( $comment->comment_date_gmt ) ) ) { - $commenter_email = $comment->comment_author_email; + // The comment will only be viewable by the comment author for 1 minute. + $comment_preview_expires = strtotime( $comment->comment_date_gmt . '+1 minute' ); + + if ( time() < $comment_preview_expires ) { + $commenter_email = $comment->comment_author_email; + } } }