Make WordPress Core

Ticket #34059: 34059.5.diff

File 34059.5.diff, 27.5 KB (added by johnbillion, 8 years ago)
  • src/wp-comments-post.php

     
    1717
    1818nocache_headers();
    1919
    20 $comment_post_ID = isset($_POST['comment_post_ID']) ? (int) $_POST['comment_post_ID'] : 0;
    21 
    22 $post = get_post($comment_post_ID);
    23 
    24 if ( empty( $post->comment_status ) ) {
    25         /**
    26          * Fires when a comment is attempted on a post that does not exist.
    27          *
    28          * @since 1.5.0
    29          *
    30          * @param int $comment_post_ID Post ID.
    31          */
    32         do_action( 'comment_id_not_found', $comment_post_ID );
    33         exit;
    34 }
    35 
    36 // get_post_status() will get the parent status for attachments.
    37 $status = get_post_status($post);
    38 
    39 $status_obj = get_post_status_object($status);
    40 
    41 if ( ! comments_open( $comment_post_ID ) ) {
    42         /**
    43          * Fires when a comment is attempted on a post that has comments closed.
    44          *
    45          * @since 1.5.0
    46          *
    47          * @param int $comment_post_ID Post ID.
    48          */
    49         do_action( 'comment_closed', $comment_post_ID );
    50         wp_die( __( 'Sorry, comments are closed for this item.' ), 403 );
    51 } elseif ( 'trash' == $status ) {
    52         /**
    53          * Fires when a comment is attempted on a trashed post.
    54          *
    55          * @since 2.9.0
    56          *
    57          * @param int $comment_post_ID Post ID.
    58          */
    59         do_action( 'comment_on_trash', $comment_post_ID );
    60         exit;
    61 } elseif ( ! $status_obj->public && ! $status_obj->private ) {
    62         /**
    63          * Fires when a comment is attempted on a post in draft mode.
    64          *
    65          * @since 1.5.1
    66          *
    67          * @param int $comment_post_ID Post ID.
    68          */
    69         do_action( 'comment_on_draft', $comment_post_ID );
    70         exit;
    71 } elseif ( post_password_required( $comment_post_ID ) ) {
    72         /**
    73          * Fires when a comment is attempted on a password-protected post.
    74          *
    75          * @since 2.9.0
    76          *
    77          * @param int $comment_post_ID Post ID.
    78          */
    79         do_action( 'comment_on_password_protected', $comment_post_ID );
    80         exit;
    81 } else {
    82         /**
    83          * Fires before a comment is posted.
    84          *
    85          * @since 2.8.0
    86          *
    87          * @param int $comment_post_ID Post ID.
    88          */
    89         do_action( 'pre_comment_on_post', $comment_post_ID );
    90 }
    91 
    92 $comment_author       = ( isset( $_POST['author'] ) && is_string( $_POST['author'] ) ) ? trim( strip_tags( $_POST['author'] ) ) : null;
    93 $comment_author_email = ( isset( $_POST['email'] ) && is_string( $_POST['email'] ) ) ? trim( $_POST['email'] ) : null;
    94 $comment_author_url   = ( isset( $_POST['url'] ) && is_string( $_POST['url'] ) ) ? trim( $_POST['url'] ) : null;
    95 $comment_content      = ( isset( $_POST['comment'] ) && is_string( $_POST['comment'] ) ) ? trim( $_POST['comment'] ) : null;
    96 
    97 // If the user is logged in
    98 $user = wp_get_current_user();
    99 if ( $user->exists() ) {
    100         if ( empty( $user->display_name ) )
    101                 $user->display_name=$user->user_login;
    102         $comment_author       = wp_slash( $user->display_name );
    103         $comment_author_email = wp_slash( $user->user_email );
    104         $comment_author_url   = wp_slash( $user->user_url );
    105         if ( current_user_can( 'unfiltered_html' ) ) {
    106                 if ( ! isset( $_POST['_wp_unfiltered_html_comment'] )
    107                         || ! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_ID )
    108                 ) {
    109                         kses_remove_filters(); // start with a clean slate
    110                         kses_init_filters(); // set up the filters
    111                 }
    112         }
    113 } else {
    114         if ( get_option( 'comment_registration' ) || 'private' == $status ) {
    115                 wp_die( __( 'Sorry, you must be logged in to post a comment.' ), 403 );
     20$comment = wp_handle_comment_submission( wp_unslash( $_POST ) );
     21if ( is_wp_error( $comment ) ) {
     22        $data = $comment->get_error_data();
     23        if ( ! empty( $data ) ) {
     24                wp_die( $comment->get_error_message(), $data );
     25        } else {
     26                exit;
    11627        }
    11728}
    11829
    119 $comment_type = '';
    120 
    121 if ( get_option('require_name_email') && !$user->exists() ) {
    122         if ( 6 > strlen( $comment_author_email ) || '' == $comment_author ) {
    123                 wp_die( __( '<strong>ERROR</strong>: please fill the required fields (name, email).' ), 200 );
    124         } elseif ( ! is_email( $comment_author_email ) ) {
    125                 wp_die( __( '<strong>ERROR</strong>: please enter a valid email address.' ), 200 );
    126         }
    127 }
    128 
    129 if ( '' == $comment_content ) {
    130         wp_die( __( '<strong>ERROR</strong>: please type a comment.' ), 200 );
    131 }
    132 
    133 $comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0;
    134 
    135 $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
    136 
    137 $comment_id = wp_new_comment( $commentdata );
    138 if ( ! $comment_id ) {
    139         wp_die( __( "<strong>ERROR</strong>: The comment could not be saved. Please try again later." ) );
    140 }
    141 
    142 $comment = get_comment( $comment_id );
     30$user = wp_get_current_user();
    14331
    14432/**
    14533 * Perform other actions when comment cookies are set.
     
    15139 */
    15240do_action( 'set_comment_cookies', $comment, $user );
    15341
    154 $location = empty($_POST['redirect_to']) ? get_comment_link( $comment ) : $_POST['redirect_to'] . '#comment-' . $comment_id;
     42$location = empty( $_POST['redirect_to'] ) ? get_comment_link( $comment ) : $_POST['redirect_to'] . '#comment-' . $comment->comment_ID;
    15543
    15644/**
    15745 * Filter the location URI to send the commenter after posting.
  • tests/phpunit/tests/comment-submission.php

     
     1<?php
     2
     3/**
     4 * @group comment
     5 */
     6class Tests_Comment_Submission extends WP_UnitTestCase {
     7
     8        function setUp() {
     9                parent::setUp();
     10                require_once ABSPATH . WPINC . '/class-phpass.php';
     11        }
     12
     13        function tearDown() {
     14                wp_set_current_user( 0 );
     15                parent::tearDown();
     16        }
     17
     18        public function test_submitting_comment_to_invalid_post_returns_error() {
     19
     20                $error = 'comment_id_not_found';
     21
     22                $this->assertSame( 0, did_action( $error ) );
     23
     24                $data = array(
     25                        'comment_post_ID' => 0,
     26                );
     27                $comment = wp_handle_comment_submission( $data );
     28
     29                $this->assertSame( 1, did_action( $error ) );
     30                $this->assertWPError( $comment );
     31                $this->assertSame( $error, $comment->get_error_code() );
     32
     33        }
     34
     35        public function test_submitting_comment_to_post_with_closed_comments_returns_error() {
     36
     37                $error = 'comment_closed';
     38
     39                $this->assertSame( 0, did_action( $error ) );
     40
     41                $post = $this->factory->post->create_and_get( array(
     42                        'comment_status' => 'closed',
     43                ) );
     44                $data = array(
     45                        'comment_post_ID' => $post->ID,
     46                );
     47                $comment = wp_handle_comment_submission( $data );
     48
     49                $this->assertSame( 1, did_action( $error ) );
     50                $this->assertWPError( $comment );
     51                $this->assertSame( $error, $comment->get_error_code() );
     52
     53        }
     54
     55        public function test_submitting_comment_to_trashed_post_returns_error() {
     56
     57                $error = 'comment_on_trash';
     58
     59                $this->assertSame( 0, did_action( $error ) );
     60
     61                $post = $this->factory->post->create_and_get();
     62                wp_trash_post( $post );
     63                $data = array(
     64                        'comment_post_ID' => $post->ID,
     65                );
     66                $comment = wp_handle_comment_submission( $data );
     67
     68                $this->assertSame( 1, did_action( $error ) );
     69                $this->assertWPError( $comment );
     70                $this->assertSame( $error, $comment->get_error_code() );
     71
     72        }
     73
     74        public function test_submitting_comment_to_draft_post_returns_error() {
     75
     76                $error = 'comment_on_draft';
     77
     78                $this->assertSame( 0, did_action( $error ) );
     79
     80                $post = $this->factory->post->create_and_get( array(
     81                        'post_status' => 'draft',
     82                ) );
     83                $data = array(
     84                        'comment_post_ID' => $post->ID,
     85                );
     86                $comment = wp_handle_comment_submission( $data );
     87
     88                $this->assertSame( 1, did_action( $error ) );
     89                $this->assertWPError( $comment );
     90                $this->assertSame( $error, $comment->get_error_code() );
     91
     92        }
     93
     94        public function test_submitting_comment_to_scheduled_post_returns_error() {
     95
     96                // Same error as commenting on a draft
     97                $error = 'comment_on_draft';
     98
     99                $this->assertSame( 0, did_action( $error ) );
     100
     101                $post = $this->factory->post->create_and_get( array(
     102                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '+1 day' ) ),
     103                ) );
     104
     105                $this->assertSame( 'future', $post->post_status );
     106
     107                $data = array(
     108                        'comment_post_ID' => $post->ID,
     109                );
     110                $comment = wp_handle_comment_submission( $data );
     111
     112                $this->assertSame( 1, did_action( $error ) );
     113                $this->assertWPError( $comment );
     114                $this->assertSame( $error, $comment->get_error_code() );
     115
     116        }
     117
     118        public function test_submitting_comment_to_password_required_post_returns_error() {
     119
     120                $error = 'comment_on_password_protected';
     121
     122                $this->assertSame( 0, did_action( $error ) );
     123
     124                $post = $this->factory->post->create_and_get( array(
     125                        'post_password' => 'password',
     126                ) );
     127                $data = array(
     128                        'comment_post_ID' => $post->ID,
     129                );
     130                $comment = wp_handle_comment_submission( $data );
     131
     132                $this->assertSame( 1, did_action( $error ) );
     133                $this->assertWPError( $comment );
     134                $this->assertSame( $error, $comment->get_error_code() );
     135
     136        }
     137
     138        public function test_submitting_comment_to_password_protected_post_succeeds() {
     139
     140                $password = 'password';
     141                $hasher   = new PasswordHash( 8, true );
     142
     143                $_COOKIE['wp-postpass_' . COOKIEHASH] = $hasher->HashPassword( $password );
     144
     145                $post = $this->factory->post->create_and_get( array(
     146                        'post_password' => $password,
     147                ) );
     148                $data = array(
     149                        'comment_post_ID' => $post->ID,
     150                        'comment'         => 'Comment',
     151                        'author'          => 'Comment Author',
     152                        'email'           => 'comment@example.org',
     153                );
     154                $comment = wp_handle_comment_submission( $data );
     155
     156                unset( $_COOKIE['wp-postpass_' . COOKIEHASH] );
     157
     158                $this->assertNotWPError( $comment );
     159                $this->assertInstanceOf( 'WP_Comment', $comment );
     160
     161        }
     162
     163        public function test_submitting_valid_comment_as_logged_in_user_succeeds() {
     164
     165                $user = $this->factory->user->create_and_get( array(
     166                        'user_url' => 'http://user.example.org'
     167                ) );
     168
     169                wp_set_current_user( $user->ID );
     170
     171                $post = $this->factory->post->create_and_get();
     172                $data = array(
     173                        'comment_post_ID' => $post->ID,
     174                        'comment'         => 'Comment',
     175                );
     176                $comment = wp_handle_comment_submission( $data );
     177
     178                $this->assertNotWPError( $comment );
     179                $this->assertInstanceOf( 'WP_Comment', $comment );
     180
     181                $this->assertSame( 'Comment', $comment->comment_content);
     182                $this->assertSame( $user->display_name, $comment->comment_author );
     183                $this->assertSame( $user->user_email, $comment->comment_author_email );
     184                $this->assertSame( $user->user_url, $comment->comment_author_url );
     185
     186        }
     187
     188        public function test_submitting_valid_comment_anonymously_succeeds() {
     189
     190                $post = $this->factory->post->create_and_get();
     191                $data = array(
     192                        'comment_post_ID' => $post->ID,
     193                        'comment'         => 'Comment',
     194                        'author'          => 'Comment Author',
     195                        'email'           => 'comment@example.org',
     196                        'url'             => 'user.example.org'
     197                );
     198                $comment = wp_handle_comment_submission( $data );
     199
     200                $this->assertNotWPError( $comment );
     201                $this->assertInstanceOf( 'WP_Comment', $comment );
     202
     203                $this->assertSame( 'Comment', $comment->comment_content);
     204                $this->assertSame( 'Comment Author', $comment->comment_author );
     205                $this->assertSame( 'comment@example.org', $comment->comment_author_email );
     206                $this->assertSame( 'http://user.example.org', $comment->comment_author_url );
     207
     208        }
     209
     210        /**
     211         * wp_handle_comment_submission() expects un-slashed data.
     212         *
     213         * @group slashes
     214         */
     215        public function test_submitting_comment_handles_slashes_correctly_handles_slashes() {
     216
     217                $post = $this->factory->post->create_and_get();
     218                $data = array(
     219                        'comment_post_ID' => $post->ID,
     220                        'comment'         => 'Comment with 1 slash: \\',
     221                        'author'          => 'Comment Author with 1 slash: \\',
     222                        'email'           => 'comment@example.org',
     223                );
     224                $comment = wp_handle_comment_submission( $data );
     225
     226                $this->assertNotWPError( $comment );
     227                $this->assertInstanceOf( 'WP_Comment', $comment );
     228
     229                $this->assertSame( 'Comment with 1 slash: \\', $comment->comment_content);
     230                $this->assertSame( 'Comment Author with 1 slash: \\', $comment->comment_author );
     231                $this->assertSame( 'comment@example.org', $comment->comment_author_email );
     232
     233        }
     234
     235        public function test_submitting_comment_anonymously_to_private_post_returns_error() {
     236
     237                $error = 'not_logged_in';
     238
     239                $post = $this->factory->post->create_and_get( array(
     240                        'post_status' => 'private',
     241                ) );
     242                $data = array(
     243                        'comment_post_ID' => $post->ID,
     244                );
     245                $comment = wp_handle_comment_submission( $data );
     246
     247                $this->assertFalse( is_user_logged_in() );
     248                $this->assertWPError( $comment );
     249                $this->assertSame( $error, $comment->get_error_code() );
     250
     251        }
     252
     253        public function test_submitting_comment_to_own_private_post_succeeds() {
     254
     255                $user = $this->factory->user->create_and_get();
     256
     257                wp_set_current_user( $user->ID );
     258
     259                $post = $this->factory->post->create_and_get( array(
     260                        'post_status' => 'private',
     261                        'post_author' => $user->ID,
     262                ) );
     263                $data = array(
     264                        'comment_post_ID' => $post->ID,
     265                        'comment'         => 'Comment',
     266                );
     267                $comment = wp_handle_comment_submission( $data );
     268
     269                $this->assertTrue( current_user_can( 'read_post', $post->ID ) );
     270                $this->assertNotWPError( $comment );
     271                $this->assertInstanceOf( 'WP_Comment', $comment );
     272
     273        }
     274
     275        public function test_submitting_comment_to_accessible_private_post_succeeds() {
     276
     277                $author = $this->factory->user->create_and_get( array(
     278                        'role' => 'author',
     279                ) );
     280                $user = $this->factory->user->create_and_get( array(
     281                        'role' => 'editor',
     282                ) );
     283
     284                wp_set_current_user( $user->ID );
     285
     286                $post = $this->factory->post->create_and_get( array(
     287                        'post_status' => 'private',
     288                        'post_author' => $author->ID,
     289                ) );
     290                $data = array(
     291                        'comment_post_ID' => $post->ID,
     292                        'comment'         => 'Comment',
     293                );
     294                $comment = wp_handle_comment_submission( $data );
     295
     296                $this->assertTrue( current_user_can( 'read_post', $post->ID ) );
     297                $this->assertNotWPError( $comment );
     298                $this->assertInstanceOf( 'WP_Comment', $comment );
     299
     300        }
     301
     302        public function test_anonymous_user_cannot_comment_unfiltered_html() {
     303
     304                $post = $this->factory->post->create_and_get();
     305                $data = array(
     306                        'comment_post_ID' => $post->ID,
     307                        'comment'         => 'Comment <script>alert(document.cookie);</script>',
     308                        'author'          => 'Comment Author',
     309                        'email'           => 'comment@example.org',
     310                );
     311                $comment = wp_handle_comment_submission( $data );
     312
     313                $this->assertNotWPError( $comment );
     314                $this->assertInstanceOf( 'WP_Comment', $comment );
     315                $this->assertNotContains( '<script', $comment->comment_content );
     316
     317        }
     318
     319        public function test_unprivileged_user_cannot_comment_unfiltered_html() {
     320
     321                $user = $this->factory->user->create_and_get( array(
     322                        'role' => 'author',
     323                ) );
     324                wp_set_current_user( $user->ID );
     325
     326                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     327
     328                $post = $this->factory->post->create_and_get();
     329                $data = array(
     330                        'comment_post_ID' => $post->ID,
     331                        'comment'         => 'Comment <script>alert(document.cookie);</script>',
     332                );
     333                $comment = wp_handle_comment_submission( $data );
     334
     335                $this->assertNotWPError( $comment );
     336                $this->assertInstanceOf( 'WP_Comment', $comment );
     337                $this->assertNotContains( '<script', $comment->comment_content );
     338
     339        }
     340
     341        public function test_unprivileged_user_cannot_comment_unfiltered_html_even_with_valid_nonce() {
     342
     343                $user = $this->factory->user->create_and_get( array(
     344                        'role' => 'author',
     345                ) );
     346                wp_set_current_user( $user->ID );
     347
     348                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     349
     350                $post   = $this->factory->post->create_and_get();
     351                $action = 'unfiltered-html-comment_' . $post->ID;
     352                $nonce  = wp_create_nonce( $action );
     353
     354                $this->assertNotFalse( wp_verify_nonce( $nonce, $action ) );
     355
     356                $data = array(
     357                        'comment_post_ID'             => $post->ID,
     358                        'comment'                     => 'Comment <script>alert(document.cookie);</script>',
     359                        '_wp_unfiltered_html_comment' => $nonce,
     360                );
     361                $comment = wp_handle_comment_submission( $data );
     362
     363                $this->assertNotWPError( $comment );
     364                $this->assertInstanceOf( 'WP_Comment', $comment );
     365                $this->assertNotContains( '<script', $comment->comment_content );
     366
     367        }
     368
     369        public function test_privileged_user_can_comment_unfiltered_html_with_valid_nonce() {
     370
     371                $this->assertFalse( defined( 'DISALLOW_UNFILTERED_HTML' ) );
     372
     373                $user = $this->factory->user->create_and_get( array(
     374                        'role' => 'editor',
     375                ) );
     376
     377                if ( is_multisite() ) {
     378                        // In multisite, only Super Admins can post unfiltered HTML
     379                        $this->assertFalse( user_can( $user->ID, 'unfiltered_html' ) );
     380                        grant_super_admin( $user->ID );
     381                }
     382
     383                wp_set_current_user( $user->ID );
     384
     385                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     386
     387                $post   = $this->factory->post->create_and_get();
     388                $action = 'unfiltered-html-comment_' . $post->ID;
     389                $nonce  = wp_create_nonce( $action );
     390
     391                $this->assertNotFalse( wp_verify_nonce( $nonce, $action ) );
     392
     393                $data = array(
     394                        'comment_post_ID'             => $post->ID,
     395                        'comment'                     => 'Comment <script>alert(document.cookie);</script>',
     396                        '_wp_unfiltered_html_comment' => $nonce,
     397                );
     398                $comment = wp_handle_comment_submission( $data );
     399
     400                $this->assertNotWPError( $comment );
     401                $this->assertInstanceOf( 'WP_Comment', $comment );
     402                $this->assertContains( '<script', $comment->comment_content );
     403
     404        }
     405
     406        public function test_privileged_user_cannot_comment_unfiltered_html_without_valid_nonce() {
     407
     408                $user = $this->factory->user->create_and_get( array(
     409                        'role' => 'editor',
     410                ) );
     411
     412                if ( is_multisite() ) {
     413                        // In multisite, only Super Admins can post unfiltered HTML
     414                        $this->assertFalse( user_can( $user->ID, 'unfiltered_html' ) );
     415                        grant_super_admin( $user->ID );
     416                }
     417
     418                wp_set_current_user( $user->ID );
     419
     420                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     421
     422                $post   = $this->factory->post->create_and_get();
     423                $data = array(
     424                        'comment_post_ID' => $post->ID,
     425                        'comment'         => 'Comment <script>alert(document.cookie);</script>',
     426                );
     427                $comment = wp_handle_comment_submission( $data );
     428
     429                $this->assertNotWPError( $comment );
     430                $this->assertInstanceOf( 'WP_Comment', $comment );
     431                $this->assertNotContains( '<script', $comment->comment_content );
     432
     433        }
     434
     435        public function test_submitting_comment_as_anonymous_user_when_registration_required_returns_error() {
     436
     437                $error = 'not_logged_in';
     438
     439                $_comment_registration = get_option( 'comment_registration' );
     440                update_option( 'comment_registration', '1' );
     441
     442                $post = $this->factory->post->create_and_get();
     443                $data = array(
     444                        'comment_post_ID' => $post->ID,
     445                );
     446                $comment = wp_handle_comment_submission( $data );
     447
     448                update_option( 'comment_registration', $_comment_registration );
     449
     450                $this->assertWPError( $comment );
     451                $this->assertSame( $error, $comment->get_error_code() );
     452
     453        }
     454
     455        public function test_submitting_comment_with_no_name_when_name_email_required_returns_error() {
     456
     457                $error = 'require_name_email';
     458
     459                $_require_name_email = get_option( 'require_name_email' );
     460                update_option( 'require_name_email', '1' );
     461
     462                $post = $this->factory->post->create_and_get();
     463                $data = array(
     464                        'comment_post_ID' => $post->ID,
     465                        'comment'         => 'Comment',
     466                        'email'           => 'comment@example.org',
     467                );
     468                $comment = wp_handle_comment_submission( $data );
     469
     470                update_option( 'require_name_email', $_require_name_email );
     471
     472                $this->assertWPError( $comment );
     473                $this->assertSame( $error, $comment->get_error_code() );
     474
     475        }
     476
     477        public function test_submitting_comment_with_no_email_when_name_email_required_returns_error() {
     478
     479                $error = 'require_name_email';
     480
     481                $_require_name_email = get_option( 'require_name_email' );
     482                update_option( 'require_name_email', '1' );
     483
     484                $post = $this->factory->post->create_and_get();
     485                $data = array(
     486                        'comment_post_ID' => $post->ID,
     487                        'comment'         => 'Comment',
     488                        'author'          => 'Comment Author',
     489                );
     490                $comment = wp_handle_comment_submission( $data );
     491
     492                update_option( 'require_name_email', $_require_name_email );
     493
     494                $this->assertWPError( $comment );
     495                $this->assertSame( $error, $comment->get_error_code() );
     496
     497        }
     498
     499        public function test_submitting_comment_with_invalid_email_when_name_email_required_returns_error() {
     500
     501                $error = 'require_valid_email';
     502
     503                $_require_name_email = get_option( 'require_name_email' );
     504                update_option( 'require_name_email', '1' );
     505
     506                $post = $this->factory->post->create_and_get();
     507                $data = array(
     508                        'comment_post_ID' => $post->ID,
     509                        'comment'         => 'Comment',
     510                        'author'          => 'Comment Author',
     511                        'email'           => 'not_an_email',
     512                );
     513                $comment = wp_handle_comment_submission( $data );
     514
     515                update_option( 'require_name_email', $_require_name_email );
     516
     517                $this->assertWPError( $comment );
     518                $this->assertSame( $error, $comment->get_error_code() );
     519
     520        }
     521
     522        public function test_submitting_comment_with_no_comment_content_returns_error() {
     523
     524                $error = 'require_valid_comment';
     525
     526                $post = $this->factory->post->create_and_get();
     527                $data = array(
     528                        'comment_post_ID' => $post->ID,
     529                        'comment'         => '',
     530                        'author'          => 'Comment Author',
     531                        'email'           => 'comment@example.org',
     532                );
     533                $comment = wp_handle_comment_submission( $data );
     534
     535                $this->assertWPError( $comment );
     536                $this->assertSame( $error, $comment->get_error_code() );
     537
     538        }
     539
     540}
  • src/wp-includes/comment-functions.php

     
    25262526
    25272527        return $open;
    25282528}
     2529
     2530/**
     2531 * Handles the submission of a comment, usually posted to wp-comments-post.php via a comment form.
     2532 *
     2533 * This function expects unslashed data, as opposed to functions such as `wp_new_comment()` which
     2534 * expect slashed data.
     2535 *
     2536 * @since 4.4.0
     2537 *
     2538 * @param array $comment_data {
     2539 *     Comment data.
     2540 *
     2541 *     @type string|int $comment_post_ID             The ID of the post that relates to the comment.
     2542 *     @type string     $author                      The name of the comment author.
     2543 *     @type string     $email                       The comment author email address.
     2544 *     @type string     $url                         The comment author URL.
     2545 *     @type string     $comment                     The content of the comment.
     2546 *     @type string|int $comment_parent              The ID of this comment's parent, if any. Default 0.
     2547 *     @type string     $_wp_unfiltered_html_comment The nonce value for allowing unfiltered HTML.
     2548 * }
     2549 * @return WP_Comment|WP_Error A WP_Comment object on success, a WP_Error object on failure.
     2550 */
     2551function wp_handle_comment_submission( $comment_data ) {
     2552
     2553        $comment_post_ID = $comment_parent = 0;
     2554        $comment_author = $comment_author_email = $comment_author_url = $comment_content = $_wp_unfiltered_html_comment = null;
     2555
     2556        if ( isset( $comment_data['comment_post_ID'] ) ) {
     2557                $comment_post_ID = (int) $comment_data['comment_post_ID'];
     2558        }
     2559        if ( isset( $comment_data['author'] ) && is_string( $comment_data['author'] ) ) {
     2560                $comment_author = trim( strip_tags( $comment_data['author'] ) );
     2561        }
     2562        if ( isset( $comment_data['email'] ) && is_string( $comment_data['email'] ) ) {
     2563                $comment_author_email = trim( $comment_data['email'] );
     2564        }
     2565        if ( isset( $comment_data['url'] ) && is_string( $comment_data['url'] ) ) {
     2566                $comment_author_url = trim( $comment_data['url'] );
     2567        }
     2568        if ( isset( $comment_data['comment'] ) && is_string( $comment_data['comment'] ) ) {
     2569                $comment_content = trim( $comment_data['comment'] );
     2570        }
     2571        if ( isset( $comment_data['comment_parent'] ) ) {
     2572                $comment_parent = absint( $comment_data['comment_parent'] );
     2573        }
     2574        if ( isset( $comment_data['_wp_unfiltered_html_comment'] ) && is_string( $comment_data['_wp_unfiltered_html_comment'] ) ) {
     2575                $_wp_unfiltered_html_comment = trim( $comment_data['_wp_unfiltered_html_comment'] );
     2576        }
     2577
     2578        $post = get_post( $comment_post_ID );
     2579
     2580        if ( empty( $post->comment_status ) ) {
     2581
     2582                /**
     2583                 * Fires when a comment is attempted on a post that does not exist.
     2584                 *
     2585                 * @since 1.5.0
     2586                 *
     2587                 * @param int $comment_post_ID Post ID.
     2588                 */
     2589                do_action( 'comment_id_not_found', $comment_post_ID );
     2590
     2591                return new WP_Error( 'comment_id_not_found' );
     2592
     2593        }
     2594
     2595        // get_post_status() will get the parent status for attachments.
     2596        $status = get_post_status( $post );
     2597
     2598        $status_obj = get_post_status_object( $status );
     2599
     2600        if ( ! comments_open( $comment_post_ID ) ) {
     2601
     2602                /**
     2603                 * Fires when a comment is attempted on a post that has comments closed.
     2604                 *
     2605                 * @since 1.5.0
     2606                 *
     2607                 * @param int $comment_post_ID Post ID.
     2608                 */
     2609                do_action( 'comment_closed', $comment_post_ID );
     2610
     2611                return new WP_Error( 'comment_closed', __( 'Sorry, comments are closed for this item.' ), 403 );
     2612
     2613        } elseif ( 'trash' == $status ) {
     2614
     2615                /**
     2616                 * Fires when a comment is attempted on a trashed post.
     2617                 *
     2618                 * @since 2.9.0
     2619                 *
     2620                 * @param int $comment_post_ID Post ID.
     2621                 */
     2622                do_action( 'comment_on_trash', $comment_post_ID );
     2623
     2624                return new WP_Error( 'comment_on_trash' );
     2625
     2626        } elseif ( ! $status_obj->public && ! $status_obj->private ) {
     2627
     2628                /**
     2629                 * Fires when a comment is attempted on a post in draft mode.
     2630                 *
     2631                 * @since 1.5.1
     2632                 *
     2633                 * @param int $comment_post_ID Post ID.
     2634                 */
     2635                do_action( 'comment_on_draft', $comment_post_ID );
     2636
     2637                return new WP_Error( 'comment_on_draft' );
     2638
     2639        } elseif ( post_password_required( $comment_post_ID ) ) {
     2640
     2641                /**
     2642                 * Fires when a comment is attempted on a password-protected post.
     2643                 *
     2644                 * @since 2.9.0
     2645                 *
     2646                 * @param int $comment_post_ID Post ID.
     2647                 */
     2648                do_action( 'comment_on_password_protected', $comment_post_ID );
     2649
     2650                return new WP_Error( 'comment_on_password_protected' );
     2651
     2652        } else {
     2653
     2654                /**
     2655                 * Fires before a comment is posted.
     2656                 *
     2657                 * @since 2.8.0
     2658                 *
     2659                 * @param int $comment_post_ID Post ID.
     2660                 */
     2661                do_action( 'pre_comment_on_post', $comment_post_ID );
     2662
     2663        }
     2664
     2665        // If the user is logged in
     2666        $user = wp_get_current_user();
     2667        if ( $user->exists() ) {
     2668                if ( empty( $user->display_name ) ) {
     2669                        $user->display_name=$user->user_login;
     2670                }
     2671                $comment_author       = $user->display_name;
     2672                $comment_author_email = $user->user_email;
     2673                $comment_author_url   = $user->user_url;
     2674                if ( current_user_can( 'unfiltered_html' ) ) {
     2675                        if ( ! isset( $comment_data['_wp_unfiltered_html_comment'] )
     2676                                || ! wp_verify_nonce( $comment_data['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_ID )
     2677                        ) {
     2678                                kses_remove_filters(); // start with a clean slate
     2679                                kses_init_filters(); // set up the filters
     2680                        }
     2681                }
     2682        } else {
     2683                if ( get_option( 'comment_registration' ) || 'private' == $status ) {
     2684                        return new WP_Error( 'not_logged_in', __( 'Sorry, you must be logged in to post a comment.' ), 403 );
     2685                }
     2686        }
     2687
     2688        $comment_type = '';
     2689
     2690        if ( get_option( 'require_name_email' ) && ! $user->exists() ) {
     2691                if ( 6 > strlen( $comment_author_email ) || '' == $comment_author ) {
     2692                        return new WP_Error( 'require_name_email', __( '<strong>ERROR</strong>: please fill the required fields (name, email).' ), 200 );
     2693                } elseif ( ! is_email( $comment_author_email ) ) {
     2694                        return new WP_Error( 'require_valid_email', __( '<strong>ERROR</strong>: please enter a valid email address.' ), 200 );
     2695                }
     2696        }
     2697
     2698        if ( '' == $comment_content ) {
     2699                return new WP_Error( 'require_valid_comment', __( '<strong>ERROR</strong>: please type a comment.' ), 200 );
     2700        }
     2701
     2702        $commentdata = compact(
     2703                'comment_post_ID',
     2704                'comment_author',
     2705                'comment_author_email',
     2706                'comment_author_url',
     2707                'comment_content',
     2708                'comment_type',
     2709                'comment_parent',
     2710                'user_ID'
     2711        );
     2712
     2713        $comment_id = wp_new_comment( wp_slash( $commentdata ) );
     2714        if ( ! $comment_id ) {
     2715                return new WP_Error( 'comment_save_error', __( '<strong>ERROR</strong>: The comment could not be saved. Please try again later.' ), 500 );
     2716        }
     2717
     2718        return get_comment( $comment_id );
     2719
     2720}