diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 20303dc1e7e17..a29edfc4b9fe8 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -2462,25 +2462,42 @@ function wp_new_comment_notify_moderator( $comment_id ) { /** * Sends a notification of a new comment to the post author. * - * @since 4.4.0 - * * Uses the {@see 'notify_post_author'} filter to determine whether the post author * should be notified when a new comment is added, overriding site setting. * + * @since 4.4.0 + * @since 7.1.0 The comment approval status is now checked before the + * {@see 'notify_post_author'} filter, and invalid comment IDs + * return false without firing the filter. + * * @param int $comment_id Comment ID. * @return bool True on success, false on failure. */ function wp_new_comment_notify_postauthor( $comment_id ) { $comment = get_comment( $comment_id ); - $is_note = ( $comment && 'note' === $comment->comment_type ); + if ( ! ( $comment instanceof WP_Comment ) ) { + return false; + } + $comment_id = (int) $comment->comment_ID; + $is_note = ( 'note' === $comment->comment_type ); - $maybe_notify = $is_note ? get_option( 'wp_notes_notify', 1 ) : get_option( 'comments_notify' ); + // By default, only notify for approved comments and notes. + if ( '1' !== $comment->comment_approved && ! $is_note ) { + $maybe_notify = false; + } elseif ( $is_note ) { + $maybe_notify = get_option( 'wp_notes_notify', 1 ); + } else { + $maybe_notify = get_option( 'comments_notify' ); + } /** - * Filters whether to send the post author new comment notification emails, - * overriding the site setting. + * Filters whether to send the post author new comment and note notification emails, + * overriding the site settings and defaults. By default, notifications are sent for + * all notes and for approved comments. * * @since 4.4.0 + * @since 7.1.0 Comment approval status is checked before this filter, + * and the filter no longer fires for invalid comment IDs. * * @param bool $maybe_notify Whether to notify the post author about the new comment. * @param int $comment_id The ID of the comment for the notification. @@ -2495,13 +2512,6 @@ function wp_new_comment_notify_postauthor( $comment_id ) { return false; } - // Send notifications for approved comments and all notes. - if ( - ! isset( $comment->comment_approved ) || - ( '1' !== $comment->comment_approved && ! $is_note ) ) { - return false; - } - return wp_notify_postauthor( $comment_id ); } diff --git a/tests/phpunit/tests/comment.php b/tests/phpunit/tests/comment.php index 11e78140f1020..2b7a704e2808e 100644 --- a/tests/phpunit/tests/comment.php +++ b/tests/phpunit/tests/comment.php @@ -1109,6 +1109,137 @@ public function test_wp_new_comment_notify_postauthor_should_not_send_email_when $this->assertFalse( $sent ); } + /** + * @ticket 64217 + * + * @covers ::wp_new_comment_notify_postauthor + */ + public function test_wp_new_comment_notify_postauthor_filter_should_receive_false_for_unapproved_comment() { + $c = self::factory()->comment->create( + array( + 'comment_post_ID' => self::$post_id, + 'comment_approved' => '0', + ) + ); + + update_option( 'comments_notify', 1 ); + + $maybe_notify = null; + add_filter( + 'notify_post_author', + static function ( $value ) use ( &$maybe_notify ) { + $maybe_notify = $value; + return $value; + } + ); + + $sent = wp_new_comment_notify_postauthor( $c ); + + $this->assertFalse( $maybe_notify, 'The filter should receive a default of false for an unapproved comment.' ); + $this->assertFalse( $sent, 'No notification should be sent for an unapproved comment by default.' ); + } + + /** + * @ticket 64217 + * + * @covers ::wp_new_comment_notify_postauthor + */ + public function test_wp_new_comment_notify_postauthor_filter_should_override_unapproved_comment() { + $c = self::factory()->comment->create( + array( + 'comment_post_ID' => self::$post_id, + 'comment_approved' => '0', + ) + ); + + add_filter( 'notify_post_author', '__return_true' ); + + $sent = wp_new_comment_notify_postauthor( $c ); + + $this->assertTrue( $sent, 'The notify_post_author filter should be able to force a notification for an unapproved comment.' ); + } + + /** + * @ticket 64217 + * + * @covers ::wp_new_comment_notify_postauthor + */ + public function test_wp_new_comment_notify_postauthor_should_not_send_email_for_invalid_comment() { + $filter_fired = false; + add_filter( + 'notify_post_author', + static function ( $value ) use ( &$filter_fired ) { + $filter_fired = true; + return $value; + } + ); + + // An empty ID such as 0 would fall back to the global comment in get_comment(). + $sent = wp_new_comment_notify_postauthor( PHP_INT_MAX ); + + $this->assertFalse( $sent, 'No notification should be sent for an invalid comment ID.' ); + $this->assertFalse( $filter_fired, 'The notify_post_author filter should not fire for an invalid comment ID.' ); + } + + /** + * @ticket 64217 + * + * @covers ::wp_new_comment_notify_postauthor + */ + public function test_wp_new_comment_notify_postauthor_filter_should_receive_truthy_default_for_unapproved_note() { + $c = self::factory()->comment->create( + array( + 'comment_post_ID' => self::$post_id, + 'comment_type' => 'note', + 'comment_approved' => '0', + ) + ); + + update_option( 'wp_notes_notify', 1 ); + + $maybe_notify = null; + add_filter( + 'notify_post_author', + static function ( $value ) use ( &$maybe_notify ) { + $maybe_notify = $value; + return false; + } + ); + + wp_new_comment_notify_postauthor( $c ); + + $this->assertTrue( (bool) $maybe_notify, 'The filter should receive a truthy default for an unapproved note.' ); + } + + /** + * @ticket 64217 + * + * @covers ::wp_new_comment_notify_postauthor + */ + public function test_wp_new_comment_notify_postauthor_filter_should_receive_option_value_for_approved_comment() { + $c = self::factory()->comment->create( + array( + 'comment_post_ID' => self::$post_id, + ) + ); + + update_option( 'comments_notify', 0 ); + + $maybe_notify = null; + add_filter( + 'notify_post_author', + static function ( $value ) use ( &$maybe_notify ) { + $maybe_notify = $value; + return $value; + } + ); + + $sent = wp_new_comment_notify_postauthor( $c ); + + $this->assertFalse( (bool) $maybe_notify, 'The filter should receive the comments_notify option value as the default for an approved comment.' ); + $this->assertFalse( $sent, 'No notification should be sent for an approved comment when comments_notify is disabled.' ); + } + /** * @ticket 43805 *