Ticket #33717: 33717.16.diff
| File 33717.16.diff, 15.5 KB (added by , 6 years ago) |
|---|
-
package-lock.json
3922 3922 "tar-fs": "^2.0.0", 3923 3923 "unbzip2-stream": "^1.3.3", 3924 3924 "ws": "^7.2.3" 3925 }, 3926 "dependencies": { 3927 "devtools-protocol": { 3928 "version": "0.0.818844", 3929 "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", 3930 "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==", 3931 "dev": true 3932 } 3925 3933 } 3926 3934 }, 3927 3935 "rimraf": { … … 5631 5639 "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", 5632 5640 "dev": true 5633 5641 }, 5634 "browser-resolve": {5635 "version": "1.11.3",5636 "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",5637 "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",5638 "dev": true,5639 "requires": {5640 "resolve": "1.1.7"5641 },5642 "dependencies": {5643 "resolve": {5644 "version": "1.1.7",5645 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",5646 "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",5647 "dev": true5648 }5649 }5650 },5651 5642 "browserify-aes": { 5652 5643 "version": "1.2.0", 5653 "resolved": "http ://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",5644 "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", 5654 5645 "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", 5655 5646 "dev": true, 5656 5647 "requires": { … … 7959 7950 "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", 7960 7951 "dev": true 7961 7952 }, 7962 "devtools-protocol": {7963 "version": "0.0.818844",7964 "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz",7965 "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==",7966 "dev": true7967 },7968 7953 "diff": { 7969 7954 "version": "4.0.2", 7970 7955 "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", -
src/wp-comments-post.php
22 22 23 23 nocache_headers(); 24 24 25 if ( isset( $_POST['wp-comment-approved-notification-optin'], $_POST['comment_ID'], $_POST['moderation-hash'] ) ) { 26 $comment = get_comment( $_POST['comment_ID'] ); 27 28 if ( $comment && hash_equals( $_POST['moderation-hash'], wp_hash( $comment->comment_date_gmt ) ) ) { 29 update_comment_meta( $comment->comment_ID, '_wp_comment_author_notification_optin', true ); 30 } else { 31 wp_die( 32 '<p>' . __( 'Invalid comment ID.' ) . '</p>', 33 __( 'Comment Notification Opt-in Failure' ), 34 array( 35 'response' => 404, 36 'back_link' => true, 37 ) 38 ); 39 } 40 } else { 25 41 $comment = wp_handle_comment_submission( wp_unslash( $_POST ) ); 26 42 if ( is_wp_error( $comment ) ) { 27 43 $data = (int) $comment->get_error_data(); … … 53 69 * @param bool $cookies_consent Comment author's consent to store cookies. 54 70 */ 55 71 do_action( 'set_comment_cookies', $comment, $user, $cookies_consent ); 72 } 56 73 57 74 $location = empty( $_POST['redirect_to'] ) ? get_comment_link( $comment ) : $_POST['redirect_to'] . '#comment-' . $comment->comment_ID; 58 75 -
src/wp-includes/class-walker-comment.php
41 41 ); 42 42 43 43 /** 44 * Backward compability checks. 45 * 46 * @since 5.7.0 47 * 48 * @var bool 49 */ 50 protected $needs_comment_approval_notification_output = true; 51 52 /** 44 53 * Starts the list before the elements are added. 45 54 * 46 55 * @since 2.7.0 … … 255 264 /** 256 265 * Filters the comment text. 257 266 * 258 * Removes links from the pending comment's text if the commenter did not consent 259 * to the comment cookies. 267 * - Removes links from the pending comment's text if the commenter did not consent 268 * to the comment cookies 269 * - Prepends the approval notification opt-in form or message to pending comments 260 270 * 261 271 * @since 5.4.2 272 * @since 5.7.0 Adds backcompatibilty output if needed. 262 273 * 263 274 * @param string $comment_text Text of the current comment. 264 275 * @param WP_Comment|null $comment The comment object. Null if not found. … … 272 283 $comment_text = wp_kses( $comment_text, array() ); 273 284 } 274 285 286 /* 287 * Checks if we need to output the comment approval notification/form. 288 */ 289 if ( $this->needs_comment_approval_notification_output ) { 290 $comment_text = $this->comment_approval_notification_form( $comment ) . "\n" . $comment_text; 291 } 292 275 293 return $comment_text; 276 294 } 277 295 278 296 /** 297 * Outputs the awaiting moderation text. 298 * 299 * @since 5.7.0 300 * 301 * @param WP_Comment $comment Comment to display. 302 */ 303 protected function awaiting_moderation_text( $comment ) { 304 if ( '0' !== $comment->comment_approved ) { 305 return; 306 } 307 308 $commenter = wp_get_current_commenter(); 309 310 if ( $commenter['comment_author_email'] ) { 311 $moderation_note = __( 'Your comment is awaiting moderation.' ); 312 } else { 313 $moderation_note = __( 'Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.' ); 314 } 315 316 printf( 317 '<em class="comment-awaiting-moderation">%s</em>', 318 esc_html( $moderation_note ) 319 ); 320 } 321 322 /** 323 * Gets the approval notification message for a comment, or the form for opting in. 324 * 325 * @since 5.7.0 326 * 327 * @param WP_Comment $comment Comment to display. 328 * @return string HTML output. 329 */ 330 protected function comment_approval_notification_form( $comment ) { 331 $comment_approval_output = ''; 332 333 if ( '0' === $comment->comment_approved && has_action( 'comment_unapproved_to_approved', 'wp_new_comment_notify_comment_author' ) ) { 334 if ( get_comment_meta( $comment->comment_ID, '_wp_comment_author_notification_optin', true ) ) { 335 $comment_approval_output = sprintf( 336 '<p><em class="wp-comment-approved-notification-optedin">%s</em></p>', 337 esc_html__( 'You will receive an email when your comment is approved.' ) 338 ); 339 } else { 340 $comment_approval_output = sprintf( 341 '<form action="%1$s" method="post"> 342 <p> 343 <label for="wp-comment-approved-notification-optin"> 344 <input type="checkbox" id="wp-comment-approved-notification-optin" name="wp-comment-approved-notification-optin"> 345 %2$s 346 </label> 347 </p> 348 <input type="hidden" name="comment_ID" value="%3$s"> 349 <input type="hidden" name="moderation-hash" value="%4$s"> 350 <input type="submit" class="button" value="%5$s"> 351 </form>', 352 esc_url( site_url( '/wp-comments-post.php' ) ), 353 esc_html__( 'I want to be notified by email when my comment is approved.' ), 354 absint( $comment->comment_ID ), 355 wp_hash( $comment->comment_date_gmt ), 356 esc_html_x( 'Save', 'comment approval notification form' ) 357 ); 358 } 359 } 360 361 // Skip the backcompat output. 362 $this->needs_comment_approval_notification_output = false; 363 364 // Return the approval notification form. 365 return $comment_approval_output; 366 } 367 368 /** 279 369 * Outputs a single comment. 280 370 * 281 371 * @since 3.6.0 … … 297 387 298 388 $commenter = wp_get_current_commenter(); 299 389 $show_pending_links = isset( $commenter['comment_author'] ) && $commenter['comment_author']; 300 301 if ( $commenter['comment_author_email'] ) {302 $moderation_note = __( 'Your comment is awaiting moderation.' );303 } else {304 $moderation_note = __( 'Your comment is awaiting moderation. This is a preview; your comment will be visible after it has been approved.' );305 }306 390 ?> 307 391 <<?php echo $tag; ?> <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?> id="comment-<?php comment_ID(); ?>"> 308 392 <?php if ( 'div' !== $args['style'] ) : ?> … … 328 412 ); 329 413 ?> 330 414 </div> 331 <?php if ( '0' == $comment->comment_approved ) : ?> 332 <em class="comment-awaiting-moderation"><?php echo $moderation_note; ?></em> 333 <br /> 334 <?php endif; ?> 415 416 <?php 417 // Output the comment moderation feedback if needed. 418 $this->awaiting_moderation_text( $comment ); 419 420 // Output the comment approval notification form if needed. 421 echo $this->comment_approval_notification_form( $comment ); 422 ?> 335 423 336 424 <div class="comment-meta commentmetadata"> 337 425 <?php … … 401 489 402 490 $commenter = wp_get_current_commenter(); 403 491 $show_pending_links = ! empty( $commenter['comment_author'] ); 404 405 if ( $commenter['comment_author_email'] ) {406 $moderation_note = __( 'Your comment is awaiting moderation.' );407 } else {408 $moderation_note = __( 'Your comment is awaiting moderation. This is a preview; your comment will be visible after it has been approved.' );409 }410 492 ?> 411 493 <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>> 412 494 <article id="div-comment-<?php comment_ID(); ?>" class="comment-body"> … … 450 532 ?> 451 533 </div><!-- .comment-metadata --> 452 534 453 <?php if ( '0' == $comment->comment_approved ) : ?> 454 <em class="comment-awaiting-moderation"><?php echo $moderation_note; ?></em> 455 <?php endif; ?> 535 <?php 536 // Output the comment moderation feedback if needed. 537 $this->awaiting_moderation_text( $comment ); 538 539 // Output the comment approval notification form if needed. 540 echo $this->comment_approval_notification_form( $comment ); 541 ?> 456 542 </footer><!-- .comment-meta --> 457 543 458 544 <div class="comment-content"> -
src/wp-includes/comment.php
2349 2349 } 2350 2350 2351 2351 /** 2352 * Notifies the comment author when their comment gets approved. 2353 * 2354 * This notification is only sent once when the comment status 2355 * changes from unapproved to approved. 2356 * 2357 * @since 5.7.0 2358 * 2359 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. 2360 * @return bool Whether the email was sent. 2361 */ 2362 function wp_new_comment_notify_comment_author( $comment_id ) { 2363 $comment = get_comment( $comment_id ); 2364 2365 if ( ! $comment ) { 2366 return false; 2367 } 2368 2369 $post = get_post( $comment->comment_post_ID ); 2370 2371 if ( ! $post ) { 2372 return false; 2373 } 2374 2375 // Make sure the comment author can be notified by email. 2376 if ( empty( $comment->comment_author_email ) ) { 2377 return false; 2378 } 2379 2380 if ( ! get_comment_meta( $comment->comment_ID, '_wp_comment_author_notification_optin', true ) ) { 2381 return false; 2382 } 2383 2384 /** 2385 * The blogname option is escaped with esc_html when 2386 * saved into the database, we need to reverse this for 2387 * the plain text area of the email. 2388 */ 2389 $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); 2390 2391 $subject = sprintf( 2392 /* translators: 1: blog name, 2: post title */ 2393 __( '[%1$s] Your comment on "%2$s" has been approved' ), 2394 $blogname, 2395 $post->post_title 2396 ); 2397 2398 if ( ! empty( $comment->comment_author ) ) { 2399 $notify_message = sprintf( 2400 /* translators: 1: comment author's name */ 2401 __( 'Howdy %s,' ), 2402 $comment->comment_author 2403 ) . "\r\n\r\n"; 2404 } else { 2405 $notify_message = __( 'Howdy,' ) . "\r\n\r\n"; 2406 } 2407 2408 $notify_message .= sprintf( 2409 /* translators: 1: post title */ 2410 __( 'Your comment on "%s" has been approved.' ), 2411 $post->post_title 2412 ) . "\r\n\r\n"; 2413 2414 $notify_message .= sprintf( 2415 /* translators: 1: comment permalink */ 2416 __( 'View comment: %s' ), 2417 get_comment_link( $comment ) 2418 ) . "\r\n"; 2419 2420 $email = array( 2421 'to' => $comment->comment_author_email, 2422 'subject' => $subject, 2423 'message' => $notify_message, 2424 'headers' => '', 2425 ); 2426 2427 /** 2428 * Filters the contents of the email sent to notify a comment author that their comment was approved. 2429 * 2430 * Content should be formatted for transmission via wp_mail(). 2431 * 2432 * @since 5.7.0 2433 * 2434 * @param array $email { 2435 * Used to build wp_mail(). 2436 * 2437 * @type string $to The email address of the comment author. 2438 * @type string $subject The subject of the email. 2439 * @type string $message The content of the email. 2440 * @type string $headers Headers. 2441 * } 2442 * @param WP_Comment $comment Comment object. 2443 */ 2444 $email = apply_filters( 'comment_approval_notification', $email, $comment ); 2445 2446 $sent = wp_mail( 2447 $email['to'], 2448 wp_specialchars_decode( $email['subject'] ), 2449 $email['message'], 2450 $email['headers'] 2451 ); 2452 2453 // Delete the opt-in now the notification has been sent. 2454 delete_comment_meta( $comment->comment_ID, '_wp_comment_author_notification_optin' ); 2455 2456 return $sent; 2457 } 2458 2459 /** 2352 2460 * Sets the status of a comment. 2353 2461 * 2354 2462 * The {@see 'wp_set_comment_status'} action is called after the comment is handled. -
src/wp-includes/default-filters.php
468 468 add_action( 'after_password_reset', 'wp_password_change_notification' ); 469 469 add_action( 'register_new_user', 'wp_send_new_user_notifications' ); 470 470 add_action( 'edit_user_created_user', 'wp_send_new_user_notifications', 10, 2 ); 471 add_action( 'comment_unapproved_to_approved', 'wp_new_comment_notify_comment_author' ); 471 472 472 473 // REST API actions. 473 474 add_action( 'init', 'rest_api_init' ); -
tests/phpunit/tests/comment.php
555 555 } 556 556 557 557 /** 558 * @ticket 33717 559 */ 560 public function test_wp_new_comment_notify_comment_author_once_only() { 561 $c = self::factory()->comment->create( 562 array( 563 'comment_post_ID' => self::$post_id, 564 'comment_approved' => '0', 565 'comment_author_email' => 'foo@bar.mail', 566 ) 567 ); 568 569 // The comment author subscribed to receive an email once comment is approved. 570 update_comment_meta( $c, '_wp_comment_author_notification_optin', true ); 571 572 // For the purpose of the test we are removing this hook to directly use the function to notify the comment author. 573 remove_action( 'comment_unapproved_to_approved', 'wp_new_comment_notify_comment_author' ); 574 575 // Approve the comment. 576 wp_set_comment_status( $c, 'approve' ); 577 578 $sent = wp_new_comment_notify_comment_author( $c ); 579 $resent = wp_new_comment_notify_comment_author( $c ); 580 581 $this->assertTrue( $sent ); 582 $this->assertFalse( $resent ); 583 } 584 585 /** 586 * @ticket 33717 587 */ 588 public function test_wp_new_comment_notify_comment_author_has_not_opted_in() { 589 $c = self::factory()->comment->create( 590 array( 591 'comment_post_ID' => self::$post_id, 592 'comment_approved' => '0', 593 'comment_author_email' => 'bat@man.mail', 594 ) 595 ); 596 597 // For the purpose of the test we are removing this hook to directly use the function to notify the comment author. 598 remove_action( 'comment_unapproved_to_approved', 'wp_new_comment_notify_comment_author' ); 599 600 // Approve the comment. 601 wp_set_comment_status( $c, 'approve' ); 602 603 $sent = wp_new_comment_notify_comment_author( $c ); 604 605 // The comment author hasn't subscribed to receive an email, no email should be sent. 606 $this->assertFalse( $sent ); 607 } 608 609 /** 558 610 * @ticket 12431 559 611 */ 560 612 public function test_wp_new_comment_with_meta() {
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)