WordPress.org

Make WordPress Core

Changeset 39349


Ignore:
Timestamp:
11/23/16 16:14:08 (5 months ago)
Author:
joehoyle
Message:

REST API: Add support for comments of password-protected posts.

Core requires the post password to view and create comments on password protected posts, so we must support a “password” param on the comments endpoint when fetch comments for a specific post and creating a comment on a password protected post.

Props flixos90, jnylen0.
Fixes #38692.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

    r39348 r39349  
    7070                'args'     => array( 
    7171                    'context'          => $this->get_context_param( array( 'default' => 'view' ) ), 
     72                    'password' => array( 
     73                        'description' => __( 'The password for the post if it is password protected.' ), 
     74                        'type'        => 'string', 
     75                    ), 
    7276                ), 
    7377            ), 
     
    8892                        'description' => __( 'Whether to bypass trash and force deletion.' ), 
    8993                    ), 
     94                    'password' => array( 
     95                        'description' => __( 'The password for the post if it is password protected.' ), 
     96                        'type'        => 'string', 
     97                    ), 
    9098                ), 
    9199            ), 
     
    109117                $post = get_post( $post_id ); 
    110118 
    111                 if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post ) ) { 
     119                if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post, $request ) ) { 
    112120                    return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
    113121                } elseif ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) { 
     
    243251 
    244252        foreach ( $query_result as $comment ) { 
    245             if ( ! $this->check_read_permission( $comment ) ) { 
     253            if ( ! $this->check_read_permission( $comment, $request ) ) { 
    246254                continue; 
    247255            } 
     
    310318        } 
    311319 
    312         if ( ! $this->check_read_permission( $comment ) ) { 
    313             return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
    314         } 
    315  
    316         $post = get_post( $comment->comment_post_ID ); 
    317  
    318         if ( $post && ! $this->check_read_post_permission( $post ) ) { 
    319             return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
    320         } 
    321  
    322320        if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) { 
    323321            return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit comments.' ), array( 'status' => rest_authorization_required_code() ) ); 
     322        } 
     323 
     324        $post = get_post( $comment->comment_post_ID ); 
     325 
     326        if ( ! $this->check_read_permission( $comment, $request ) ) { 
     327            return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
     328        } 
     329 
     330        if ( $post && ! $this->check_read_post_permission( $post, $request ) ) { 
     331            return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
    324332        } 
    325333 
     
    434442        } 
    435443 
    436         if ( ! $this->check_read_post_permission( $post ) ) { 
     444        if ( ! $this->check_read_post_permission( $post, $request ) ) { 
    437445            return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) ); 
    438446        } 
     
    14111419            'type'              => 'string', 
    14121420            'validate_callback' => 'rest_validate_request_arg', 
     1421        ); 
     1422 
     1423        $query_params['password'] = array( 
     1424            'description' => __( 'The password for the post if it is password protected.' ), 
     1425            'type'        => 'string', 
    14131426        ); 
    14141427 
     
    14821495     * @access protected 
    14831496     * 
    1484      * @param WP_Post $post Post Object. 
     1497     * @param WP_Post         $post    Post object. 
     1498     * @param WP_REST_Request $request Request data to check. 
    14851499     * @return bool Whether post can be read. 
    14861500     */ 
    1487     protected function check_read_post_permission( $post ) { 
     1501    protected function check_read_post_permission( $post, $request ) { 
    14881502        $posts_controller = new WP_REST_Posts_Controller( $post->post_type ); 
    14891503        $post_type = get_post_type_object( $post->post_type ); 
    14901504 
     1505        $has_password_filter = false; 
     1506 
     1507        // Only check password if a specific post was queried for or a single comment 
     1508        $requested_post = ! empty( $request['post'] ) && 1 === count( $request['post'] ); 
     1509        $requested_comment = ! empty( $request['id'] ); 
     1510        if ( ( $requested_post || $requested_comment ) && $posts_controller->can_access_password_content( $post, $request ) ) { 
     1511            add_filter( 'post_password_required', '__return_false' ); 
     1512 
     1513            $has_password_filter = true; 
     1514        } 
     1515 
    14911516        if ( post_password_required( $post ) ) { 
    1492             return current_user_can( $post_type->cap->edit_post, $post->ID ); 
    1493         } 
    1494  
    1495         return $posts_controller->check_read_permission( $post ); 
     1517            $result = current_user_can( $post_type->cap->edit_post, $post->ID ); 
     1518        } else { 
     1519            $result = $posts_controller->check_read_permission( $post ); 
     1520        } 
     1521 
     1522        if ( $has_password_filter ) { 
     1523            remove_filter( 'post_password_required', '__return_false' ); 
     1524        } 
     1525 
     1526        return $result; 
    14961527    } 
    14971528 
     
    15021533     * @access protected 
    15031534     * 
    1504      * @param WP_Comment $comment Comment object. 
     1535     * @param WP_Comment      $comment Comment object. 
     1536     * @param WP_REST_Request $request Request data to check. 
    15051537     * @return bool Whether the comment can be read. 
    15061538     */ 
    1507     protected function check_read_permission( $comment ) { 
     1539    protected function check_read_permission( $comment, $request ) { 
    15081540        if ( ! empty( $comment->comment_post_ID ) ) { 
    15091541            $post = get_post( $comment->comment_post_ID ); 
    15101542            if ( $post ) { 
    1511                 if ( $this->check_read_post_permission( $post ) && 1 === (int) $comment->comment_approved ) { 
     1543                if ( $this->check_read_post_permission( $post, $request ) && 1 === (int) $comment->comment_approved ) { 
    15121544                    return true; 
    15131545                } 
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r39348 r39349  
    384384     * 
    385385     * @since 4.7.0 
    386      * @access protected 
     386     * @access public 
    387387     * 
    388388     * @param WP_Post         $post    Post to check against. 
     
    390390     * @return bool True if the user can access password-protected content, otherwise false. 
    391391     */ 
    392     protected function can_access_password_content( $post, $request ) { 
     392    public function can_access_password_content( $post, $request ) { 
    393393        if ( empty( $post->post_password ) ) { 
    394394            // No filter required. 
  • trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php

    r39337 r39349  
    147147            'parent', 
    148148            'parent_exclude', 
     149            'password', 
    149150            'per_page', 
    150151            'post', 
     
    166167        // We created 6 comments in this method, plus self::$approved_id. 
    167168        $this->assertCount( 7, $comments ); 
     169    } 
     170 
     171    /** 
     172     * @ticket 38692 
     173     */ 
     174    public function test_get_items_with_password() { 
     175        wp_set_current_user( 0 ); 
     176 
     177        $args = array( 
     178            'comment_approved' => 1, 
     179            'comment_post_ID'  => self::$password_id, 
     180        ); 
     181        $password_comment = $this->factory->comment->create( $args ); 
     182 
     183        $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); 
     184        $request->set_param( 'password', 'toomanysecrets' ); 
     185        $request->set_param( 'post', self::$password_id ); 
     186 
     187        $response = $this->server->dispatch( $request ); 
     188        $this->assertEquals( 200, $response->get_status() ); 
     189 
     190        $collection_data = $response->get_data(); 
     191        $this->assertTrue( in_array( $password_comment, wp_list_pluck( $collection_data, 'id' ), true ) ); 
     192    } 
     193 
     194    /** 
     195     * @ticket 38692 
     196     */ 
     197    public function test_get_items_with_password_without_post() { 
     198        wp_set_current_user( 0 ); 
     199        $args = array( 
     200            'comment_approved' => 1, 
     201            'comment_post_ID'  => self::$password_id, 
     202        ); 
     203        $password_comment = $this->factory->comment->create( $args ); 
     204 
     205        $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); 
     206        $request->set_param( 'password', 'toomanysecrets' ); 
     207 
     208        $response = $this->server->dispatch( $request ); 
     209        $this->assertEquals( 200, $response->get_status() ); 
     210 
     211        $collection_data = $response->get_data(); 
     212        $this->assertFalse( in_array( $password_comment, wp_list_pluck( $collection_data, 'id' ), true ) ); 
     213    } 
     214 
     215    /** 
     216     * @ticket 38692 
     217     */ 
     218    public function test_get_items_with_password_with_multiple_post() { 
     219        wp_set_current_user( 0 ); 
     220        $args = array( 
     221            'comment_approved' => 1, 
     222            'comment_post_ID'  => self::$password_id, 
     223        ); 
     224        $password_comment = $this->factory->comment->create( $args ); 
     225 
     226        $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); 
     227        $request->set_param( 'password', 'toomanysecrets' ); 
     228        $request->set_param( 'post', array( self::$password_id, self::$post_id ) ); 
     229 
     230        $response = $this->server->dispatch( $request ); 
     231        $this->assertErrorResponse( 'rest_cannot_read_post', $response, 401 ); 
    168232    } 
    169233 
     
    854918    } 
    855919 
     920    /** 
     921     * @ticket 38692 
     922     */ 
     923    public function test_get_comment_with_password_with_valid_password() { 
     924        wp_set_current_user( self::$subscriber_id ); 
     925 
     926        $args = array( 
     927            'comment_approved' => 1, 
     928            'comment_post_ID'  => self::$password_id, 
     929        ); 
     930        $password_comment = $this->factory->comment->create( $args ); 
     931 
     932        $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%s', $password_comment ) ); 
     933        $request->set_param( 'password', 'toomanysecrets' ); 
     934 
     935        $response = $this->server->dispatch( $request ); 
     936        $this->assertEquals( 200, $response->get_status() ); 
     937    } 
     938 
    856939    public function test_create_item() { 
    857940        wp_set_current_user( self::$admin_id ); 
     
    17261809 
    17271810        $this->assertErrorResponse( 'comment_content_column_length', $response, 400 ); 
     1811    } 
     1812 
     1813    public function test_create_comment_without_password() { 
     1814        wp_set_current_user( self::$subscriber_id ); 
     1815 
     1816        $params = array( 
     1817            'post'         => self::$password_id, 
     1818            'author_name'  => 'Bleeding Gums Murphy', 
     1819            'author_email' => 'murphy@gingivitis.com', 
     1820            'author_url'   => 'http://jazz.gingivitis.com', 
     1821            'content'      => 'This isn\'t a saxophone. It\'s an umbrella.', 
     1822        ); 
     1823        $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); 
     1824 
     1825        $request->add_header( 'content-type', 'application/json' ); 
     1826        $request->set_body( wp_json_encode( $params ) ); 
     1827        $response = $this->server->dispatch( $request ); 
     1828 
     1829        $this->assertErrorResponse( 'rest_cannot_read_post', $response, 403 ); 
     1830    } 
     1831 
     1832    public function test_create_comment_with_password() { 
     1833        add_filter( 'rest_allow_anonymous_comments', '__return_true' ); 
     1834 
     1835        $params = array( 
     1836            'post'         => self::$password_id, 
     1837            'author_name'  => 'Bleeding Gums Murphy', 
     1838            'author_email' => 'murphy@gingivitis.com', 
     1839            'author_url'   => 'http://jazz.gingivitis.com', 
     1840            'content'      => 'This isn\'t a saxophone. It\'s an umbrella.', 
     1841            'password'     => 'toomanysecrets', 
     1842        ); 
     1843        $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); 
     1844 
     1845        $request->add_header( 'content-type', 'application/json' ); 
     1846        $request->set_body( wp_json_encode( $params ) ); 
     1847        $response = $this->server->dispatch( $request ); 
     1848        $this->assertEquals( 201, $response->get_status() ); 
    17281849    } 
    17291850 
Note: See TracChangeset for help on using the changeset viewer.