WordPress.org

Make WordPress Core

Ticket #36901: 36901.2.diff

File 36901.2.diff, 9.8 KB (added by boonebgorges, 3 years ago)
  • src/wp-includes/comment.php

    diff --git src/wp-includes/comment.php src/wp-includes/comment.php
    index 861ad6b..de42864 100644
    function sanitize_comment_cookies() { 
    581581 * Validates whether this comment is allowed to be made.
    582582 *
    583583 * @since 2.0.0
     584 * @since 4.7.0 The `$avoid_die` parameter was added.
    584585 *
    585586 * @global wpdb $wpdb WordPress database abstraction object.
    586587 *
    587  * @param array $commentdata Contains information on the comment
    588  * @return int|string Signifies the approval status (0|1|'spam')
     588 * @param array   $commentdata Contains information on the comment.
     589 * @param boolean $avoid_die   Should errors be returned as WP_Error objects
     590 *                             instead of executing wp_die()? Default false.
     591 * @return int|string|WP_Error Allowed comments return the approval status (0|1|'spam').
     592 *                             If $avoid_die is true, unallowed comments return a WP_Error.
    589593 */
    590 function wp_allow_comment( $commentdata ) {
     594function wp_allow_comment( $commentdata, $avoid_die = false ) {
    591595        global $wpdb;
    592596
    593597        // Simple duplicate check
    function wp_allow_comment( $commentdata ) { 
    632636                 * @param array $commentdata Comment data.
    633637                 */
    634638                do_action( 'comment_duplicate_trigger', $commentdata );
    635                 if ( wp_doing_ajax() ) {
    636                         die( __('Duplicate comment detected; it looks as though you’ve already said that!') );
     639                if ( true === $avoid_die ) {
     640                        return new WP_Error( 'comment_duplicate', __( 'Duplicate comment detected; it looks as though you’ve already said that!' ), 409 );
     641                } else {
     642                        if ( wp_doing_ajax() ) {
     643                                die( __('Duplicate comment detected; it looks as though you’ve already said that!') );
     644                        }
     645
     646                        wp_die( __( 'Duplicate comment detected; it looks as though you’ve already said that!' ), 409 );
    637647                }
    638                 wp_die( __( 'Duplicate comment detected; it looks as though you’ve already said that!' ), 409 );
    639648        }
    640649
    641650        /**
    function wp_allow_comment( $commentdata ) { 
    656665                $commentdata['comment_date_gmt']
    657666        );
    658667
     668        $is_flood = apply_filters(
     669                'wp_is_comment_flood',
     670                $commentdata['comment_author_IP'],
     671                $commentdata['comment_author_email'],
     672                $commentdata['comment_date_gmt'],
     673                $avoid_die
     674        );
     675
     676        $is_flood = check_comment_flood_db( $commentdata['comment_author_IP'], $commentdata['comment_author_email'], $commentdata['comment_date_gmt'], $avoid_die );
     677        if ( $is_flood ) {
     678                return new WP_Error( 'comment_flood', __( 'You are posting comments too quickly. Slow down.' ), 429 );
     679        }
     680
    659681        if ( ! empty( $commentdata['user_id'] ) ) {
    660682                $user = get_userdata( $commentdata['user_id'] );
    661683                $post_author = $wpdb->get_var( $wpdb->prepare(
    function wp_allow_comment( $commentdata ) { 
    708730}
    709731
    710732/**
     733 * Hooks WP's native database-based comment-flood check.
     734 *
     735 * @since 2.3.0
     736 * @since 4.7.0 Converted to be an add_filter() wrapper.
     737 */
     738function check_comment_flood_db() {
     739        add_filter( 'wp_is_comment_flood', 'wp_check_comment_flood', 10, 4 );
     740}
     741
     742/**
    711743 * Check whether comment flooding is occurring.
    712744 *
    713745 * Won't run, if current user can manage options, so to not block
    714746 * administrators.
    715747 *
    716  * @since 2.3.0
     748 * @since 4.7.0 The `$avoid_die` parameter was added.
    717749 *
    718750 * @global wpdb $wpdb WordPress database abstraction object.
    719751 *
    720  * @param string $ip Comment IP.
    721  * @param string $email Comment author email address.
    722  * @param string $date MySQL time string.
     752 * @param string  $ip        Comment IP.
     753 * @param string  $email     Comment author email address.
     754 * @param string  $date      MySQL time string.
     755 * @param boolean $avoid_die Prevent executing wp_die() or die() if a
     756 *                           comment flood is occuring. Default is false.
     757 * @return boolean|WP_Error True or a WP_Error if a comment flood is occuring,
     758 *                          otherwise false.
    723759 */
    724 function check_comment_flood_db( $ip, $email, $date ) {
     760function wp_check_comment_flood( $ip, $email, $date, $avoid_die = false ) {
     761
    725762        global $wpdb;
    726763        // don't throttle admins or moderators
    727764        if ( current_user_can( 'manage_options' ) || current_user_can( 'moderate_comments' ) ) {
    function check_comment_flood_db( $ip, $email, $date ) { 
    767804                         * @param int $time_newcomment  Timestamp of when the new comment was posted.
    768805                         */
    769806                        do_action( 'comment_flood_trigger', $time_lastcomment, $time_newcomment );
     807                        if ( true === $avoid_die ) {
     808                                return true;
     809                        } else {
     810                                if ( wp_doing_ajax() ) {
     811                                        die( __('You are posting comments too quickly. Slow down.') );
     812                                }
    770813
    771                         if ( wp_doing_ajax() )
    772                                 die( __('You are posting comments too quickly. Slow down.') );
    773 
    774                         wp_die( __( 'You are posting comments too quickly. Slow down.' ), 429 );
     814                                wp_die( __( 'You are posting comments too quickly. Slow down.' ), 429 );
     815                        }
    775816                }
    776817        }
     818
     819        return false;
    777820}
    778821
    779822/**
    function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) 
    17171760 *
    17181761 * @since 1.5.0
    17191762 * @since 4.3.0 'comment_agent' and 'comment_author_IP' can be set via `$commentdata`.
     1763 * @since 4.7.0 The `$avoid_die` parameter was added.
    17201764 *
    17211765 * @see wp_insert_comment()
    17221766 * @global wpdb $wpdb WordPress database abstraction object.
    function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) 
    17401784 *     @type string $comment_author_IP    Comment author IP address in IPv4 format. Default is the value of
    17411785 *                                        'REMOTE_ADDR' in the `$_SERVER` superglobal sent in the original request.
    17421786 * }
    1743  * @return int|false The ID of the comment on success, false on failure.
     1787 * @param boolean $avoid_die Should errors be returned as WP_Error objects instead of
     1788 *                           executing wp_die()? Default false.
     1789 * @return int|false|WP_Error The ID of the comment on success, false or WP_Error on failure.
    17441790 */
    1745 function wp_new_comment( $commentdata ) {
     1791function wp_new_comment( $commentdata, $avoid_die = false ) {
    17461792        global $wpdb;
    17471793
    17481794        if ( isset( $commentdata['user_ID'] ) ) {
    function wp_new_comment( $commentdata ) { 
    17911837
    17921838        $commentdata = wp_filter_comment($commentdata);
    17931839
    1794         $commentdata['comment_approved'] = wp_allow_comment($commentdata);
     1840        $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $avoid_die );
     1841        if ( is_wp_error( $commentdata['comment_approved'] ) ) {
     1842                return $commentdata['comment_approved'];
     1843        }
    17951844
    17961845        $comment_ID = wp_insert_comment($commentdata);
    17971846        if ( ! $comment_ID ) {
    function wp_new_comment( $commentdata ) { 
    18051854
    18061855                $commentdata = wp_filter_comment( $commentdata );
    18071856
    1808                 $commentdata['comment_approved'] = wp_allow_comment( $commentdata );
     1857                $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $avoid_die );
     1858                if ( is_wp_error( $commentdata['comment_approved'] ) ) {
     1859                        return $commentdata['comment_approved'];
     1860                }
    18091861
    18101862                $comment_ID = wp_insert_comment( $commentdata );
    18111863                if ( ! $comment_ID ) {
    function wp_handle_comment_submission( $comment_data ) { 
    29272979                'user_ID'
    29282980        );
    29292981
    2930         $comment_id = wp_new_comment( wp_slash( $commentdata ) );
     2982        $comment_id = wp_new_comment( wp_slash( $commentdata ), true );
     2983        if ( is_wp_error( $comment_id ) ) {
     2984                return $comment_id;
     2985        }
     2986
    29312987        if ( ! $comment_id ) {
    29322988                return new WP_Error( 'comment_save_error', __( '<strong>ERROR</strong>: The comment could not be saved. Please try again later.' ), 500 );
    29332989        }
    29342990
    29352991        return get_comment( $comment_id );
    2936 
    29372992}
  • tests/phpunit/tests/comment-submission.php

    diff --git tests/phpunit/tests/comment-submission.php tests/phpunit/tests/comment-submission.php
    index 8c42db9..256966b 100644
    class Tests_Comment_Submission extends WP_UnitTestCase { 
    714714                return $commentdata;
    715715        }
    716716
     717        /**
     718         * @ticket 36901
     719         */
     720        public function test_submitting_duplicate_comments() {
     721                $post = self::factory()->post->create_and_get( array(
     722                        'post_status' => 'publish',
     723                ) );
     724                $data = array(
     725                        'comment_post_ID'       => $post->ID,
     726                        'comment'               => 'Did I say that?',
     727                        'author'                => 'Repeat myself',
     728                        'email'                 => 'mail@example.com',
     729                );
     730                $first_comment = wp_handle_comment_submission( $data );
     731                $second_comment = wp_handle_comment_submission( $data );
     732                $this->assertWPError( $second_comment );
     733                $this->assertSame( 'comment_duplicate', $second_comment->get_error_code() );
     734        }
     735
     736        /**
     737         * @ticket 36901
     738         */
     739        public function test_comments_flood() {
     740                $post = self::factory()->post->create_and_get( array(
     741                        'post_status' => 'publish',
     742                ) );
     743                $data = array(
     744                        'comment_post_ID'       => $post->ID,
     745                        'comment'               => 'Did I say that?',
     746                        'author'                => 'Repeat myself',
     747                        'email'                 => 'mail@example.com',
     748                );
     749                $first_comment = wp_handle_comment_submission( $data );
     750
     751                $data['comment'] = 'Wow! I am quick!';
     752                $second_comment = wp_handle_comment_submission( $data );
     753
     754                $this->assertWPError( $second_comment );
     755                $this->assertSame( 'comment_flood', $second_comment->get_error_code() );
     756        }
     757
     758        /**
     759         * @ticket 36901
     760         */
     761        public function test_comments_flood_user_is_admin() {
     762                $user = self::factory()->user->create_and_get( array(
     763                        'role' => 'administrator',
     764                ) );
     765                wp_set_current_user( $user->ID );
     766
     767                $post = self::factory()->post->create_and_get( array(
     768                        'post_status' => 'publish',
     769                ) );
     770                $data = array(
     771                        'comment_post_ID'       => $post->ID,
     772                        'comment'               => 'Did I say that?',
     773                        'author'                => 'Repeat myself',
     774                        'email'                 => 'mail@example.com',
     775                );
     776                $first_comment = wp_handle_comment_submission( $data );
     777
     778                $data['comment'] = 'Wow! I am quick!';
     779                $second_comment = wp_handle_comment_submission( $data );
     780
     781                $this->assertNotWPError( $second_comment );
     782                $this->assertEquals( $post->ID, $second_comment->comment_post_ID );
     783        }
     784
    717785}