diff --git a/src/wp-includes/class-wp-xmlrpc-server.php b/src/wp-includes/class-wp-xmlrpc-server.php index e7b8d64fbe..3011b7a8e3 100644 --- a/src/wp-includes/class-wp-xmlrpc-server.php +++ b/src/wp-includes/class-wp-xmlrpc-server.php @@ -3155,17 +3155,20 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $comment_id = (int) $args[3]; - if ( !$user = $this->login($username, $password) ) + if ( ! $user = $this->login( $username, $password ) ) { return $this->error; - - if ( !current_user_can( 'moderate_comments' ) ) - return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + } /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.getComment' ); - if ( ! $comment = get_comment($comment_id) ) + if ( ! $comment = get_comment( $comment_id ) ) { return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + } + + if ( ! current_user_can( 'edit_comment', $comment_id ) ) { + return new IXR_Error( 403, __( 'You are not allowed to moderate or edit this comment.' ) ); + } return $this->_prepare_comment( $comment ); } @@ -3203,20 +3206,21 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $struct = isset( $args[3] ) ? $args[3] : array(); - if ( !$user = $this->login($username, $password) ) + if ( ! $user = $this->login($username, $password ) ) return $this->error; - if ( !current_user_can( 'moderate_comments' ) ) - return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) ); - /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.getComments' ); - if ( isset($struct['status']) ) + if ( isset( $struct['status'] ) ) $status = $struct['status']; else $status = ''; + if ( ! current_user_can( 'moderate_comments' ) && 'approve' !== $status ) { + return new IXR_Error( 401, __( 'Invalid comment status.' ) ); + } + $post_id = ''; if ( isset($struct['post_id']) ) $post_id = absint($struct['post_id']); @@ -3260,24 +3264,24 @@ class wp_xmlrpc_server extends IXR_Server { * } * @return bool|IXR_Error {@link wp_delete_comment()} */ - public function wp_deleteComment($args) { + public function wp_deleteComment( $args ) { $this->escape($args); $username = $args[1]; $password = $args[2]; $comment_ID = (int) $args[3]; - if ( !$user = $this->login($username, $password) ) + if ( ! $user = $this->login( $username, $password ) ) { return $this->error; + } - if ( !current_user_can( 'moderate_comments' ) ) - return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); - - if ( ! get_comment($comment_ID) ) + if ( ! get_comment( $comment_ID ) ) { return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + } - if ( !current_user_can( 'edit_comment', $comment_ID ) ) - return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + if ( !current_user_can( 'edit_comment', $comment_ID ) ) { + return new IXR_Error( 403, __( 'You are not allowed to moderate or edit this comment.' ) ); + } /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.deleteComment' ); @@ -3334,17 +3338,17 @@ class wp_xmlrpc_server extends IXR_Server { $comment_ID = (int) $args[3]; $content_struct = $args[4]; - if ( !$user = $this->login($username, $password) ) + if ( !$user = $this->login( $username, $password ) ) { return $this->error; + } - if ( !current_user_can( 'moderate_comments' ) ) - return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); - - if ( ! get_comment($comment_ID) ) + if ( ! get_comment( $comment_ID ) ) { return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + } - if ( !current_user_can( 'edit_comment', $comment_ID ) ) - return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + if ( ! current_user_can( 'edit_comment', $comment_ID ) ) { + return new IXR_Error( 403, __( 'You are not allowed to moderate or edit this comment.' ) ); + } /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.editComment' ); @@ -3536,17 +3540,19 @@ class wp_xmlrpc_server extends IXR_Server { * } * @return array|IXR_Error */ - public function wp_getCommentStatusList($args) { + public function wp_getCommentStatusList( $args ) { $this->escape( $args ); $username = $args[1]; $password = $args[2]; - if ( !$user = $this->login($username, $password) ) + if ( ! $user = $this->login( $username, $password ) ) { return $this->error; + } - if ( !current_user_can( 'moderate_comments' ) ) + if ( ! current_user_can( 'publish_posts' ) ) { return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + } /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.getCommentStatusList' ); @@ -3576,16 +3582,24 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $post_id = (int) $args[3]; - if ( !$user = $this->login($username, $password) ) + if ( ! $user = $this->login( $username, $password ) ) { return $this->error; + } - if ( !current_user_can( 'edit_posts' ) ) - return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) ); + $post = get_post( $post_id, ARRAY_A ); + if ( empty( $post['ID'] ) ) { + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + } + + if ( ! current_user_can( 'edit_post', $post_id ) ) { + return new IXR_Error( 403, __( 'You are not allowed access to details of this post.' ) ); + } /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ do_action( 'xmlrpc_call', 'wp.getCommentCount' ); $count = wp_count_comments( $post_id ); + return array( 'approved' => $count->approved, 'awaiting_moderation' => $count->moderated, diff --git a/tests/phpunit/tests/xmlrpc/wp/editComment.php b/tests/phpunit/tests/xmlrpc/wp/editComment.php index d6ba91fdfc..868e369124 100644 --- a/tests/phpunit/tests/xmlrpc/wp/editComment.php +++ b/tests/phpunit/tests/xmlrpc/wp/editComment.php @@ -4,6 +4,49 @@ * @group xmlrpc */ class Tests_XMLRPC_wp_editComment extends WP_XMLRPC_UnitTestCase { + + function test_author_can_edit_own_comment() { + $author_id = $this->make_user_by_role( 'author' ); + $post_id = $this->factory->post->create( array( + 'post_title' => 'Post test by author', + 'post_author' => $author_id + ) ); + + $comment_id = wp_insert_comment(array( + 'comment_post_ID' => $post_id, + 'comment_author' => 'Commenter 1', + 'comment_author_url' => "http://example.com/1/", + 'comment_approved' => 1, + )); + + $result = $this->myxmlrpcserver->wp_editComment( array( 1, 'author', 'author', $comment_id, array( + 'status' => 'hold' + ) ) ); + $this->assertNotInstanceOf( 'IXR_Error', $result ); + $this->assertTrue( $result ); + } + + function test_author_cannot_edit_others_comment() { + $this->make_user_by_role( 'author' ); + $editor_id = $this->make_user_by_role( 'editor' ); + $post_id = $this->factory->post->create( array( + 'post_title' => 'Post test by editor', + 'post_author' => $editor_id + ) ); + + $comment_id = wp_insert_comment( array( + 'comment_post_ID' => $post_id, + 'comment_author' => 'Commenter 2', + 'comment_author_url' => 'http://example.com/2/', + 'comment_approved' => 0, + ) ); + + $result = $this->myxmlrpcserver->wp_editComment( array( 1, 'author', 'author', $comment_id, array( 'status' => 'hold' ) ) ); + $this->assertInstanceOf( 'IXR_Error', $result ); + $this->assertEquals( 403, $result->code ); + $this->assertEquals( __( 'You are not allowed to moderate or edit this comment.' ), $result->message ); + } + function test_trash_comment() { $this->make_user_by_role( 'administrator' ); $post_id = $this->factory->post->create(); diff --git a/tests/phpunit/tests/xmlrpc/wp/getComments.php b/tests/phpunit/tests/xmlrpc/wp/getComments.php index 59970dc6b4..bda7ed0271 100644 --- a/tests/phpunit/tests/xmlrpc/wp/getComments.php +++ b/tests/phpunit/tests/xmlrpc/wp/getComments.php @@ -42,10 +42,9 @@ class Tests_XMLRPC_wp_getComments extends WP_XMLRPC_UnitTestCase { function test_post_filter() { $this->make_user_by_role( 'editor' ); - $filter = array( + $results = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', array( 'post_id' => $this->post_id - ); - $results = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', $filter ) ); + ) ) ); $this->assertNotInstanceOf( 'IXR_Error', $results ); foreach( $results as $result ) { @@ -56,19 +55,154 @@ class Tests_XMLRPC_wp_getComments extends WP_XMLRPC_UnitTestCase { function test_number_filter() { $this->make_user_by_role( 'editor' ); - $filter = array( + $results = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', array( 'post_id' => $this->post_id, - ); - $results = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', $filter ) ); + ) ) ); $this->assertNotInstanceOf( 'IXR_Error', $results ); // if no 'number' filter is specified, default should be 10 - $this->assertEquals( 10, count( $results ) ); + $this->assertCount( 10, $results ); - // explicitly set a 'number' filter and verify that only that many are returned - $filter['number'] = 5; - $results2 = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', $filter ) ); + $results2 = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', array( + 'post_id' => $this->post_id, + 'number' => 5 + ) ) ); $this->assertNotInstanceOf( 'IXR_Error', $results2 ); - $this->assertEquals( 5, count( $results2 ) ); + $this->assertCount( 5, $results2 ); + } + + function test_contributor_capabilities() { + $this->make_user_by_role( 'contributor' ); + $author_id = $this->make_user_by_role( 'author' ); + $author_post_id = $this->factory->post->create( array( + 'post_title' => 'Author', + 'post_author' => $author_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create( array( + 'comment_post_ID' => $author_post_id, + 'comment_author' => "Commenter 1", + 'comment_author_url' => "http://example.com/1/", + 'comment_approved' => 0, + ) ); + + $editor_id = $this->make_user_by_role( 'editor' ); + $editor_post_id = $this->factory->post->create( array( + 'post_title' => 'Editor', + 'post_author' => $editor_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create( array( + 'comment_post_ID' => $editor_post_id, + 'comment_author' => 'Commenter 2', + 'comment_author_url' => 'http://example.com/2/', + 'comment_approved' => 0, + ) ); + + $result = $this->myxmlrpcserver->wp_getComments( array( 1, 'contributor', 'contributor' ) ); + $this->assertInstanceOf( 'IXR_Error', $result ); + $this->assertEquals( 401, $result->code ); + } + + function test_author_capabilities() { + $author_id = $this->make_user_by_role( 'author' ); + $author_post_id = $this->factory->post->create( array( + 'post_title' => 'Author', + 'post_author' => $author_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create( array( + 'comment_post_ID' => $author_post_id, + 'comment_author' => 'Commenter 1', + 'comment_author_url' => 'http://example.com/1/', + 'comment_approved' => 1, + ) ); + + $editor_id = $this->make_user_by_role( 'editor' ); + $editor_post_id = $this->factory->post->create( array( + 'post_title' => 'Editor', + 'post_author' => $editor_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create( array( + 'comment_post_ID' => $editor_post_id, + 'comment_author' => 'Commenter 2', + 'comment_author_url' => 'http://example.com/2/', + 'comment_approved' => 0, + ) ); + + $result1 = $this->myxmlrpcserver->wp_getComments( array( 1, 'author', 'author', array( + 'post_id' => $author_post_id + ) ) ); + $this->assertInstanceOf( 'IXR_Error', $result1 ); + + $result2 = $this->myxmlrpcserver->wp_getComments( array( 1, 'author', 'author', array( + 'status' => 'approve', + 'post_id' => $author_post_id + ) ) ); + + $this->assertInternalType( 'array', $result2 ); + $this->assertCount( 1, $result2 ); + + $result3 = $this->myxmlrpcserver->wp_getComments( array( 1, 'author', 'author', array( + 'post_id' => $editor_post_id + ) ) ); + $this->assertInstanceOf( 'IXR_Error', $result3 ); + + $result4 = $this->myxmlrpcserver->wp_getComments( array( 1, 'author', 'author', array( + 'status' => 'approve', + 'post_id' => $author_post_id + ) ) ); + + $this->assertInternalType( 'array', $result4 ); + $this->assertCount( 1, $result4 ); + } + + function test_editor_capabilities() { + $author_id = $this->make_user_by_role( 'author' ); + $author_post_id = $this->factory->post->create( array( + 'post_title' => 'Author', + 'post_author' => $author_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create( array( + 'comment_post_ID' => $author_post_id, + 'comment_author' => 'Commenter 1', + 'comment_author_url' => 'http://example.com/1/', + 'comment_approved' => 1, + )); + + $editor_id = $this->make_user_by_role( 'editor' ); + $editor_post_id = $this->factory->post->create( array( + 'post_title' => 'Editor', + 'post_author' => $editor_id, + 'post_status' => 'publish' + ) ); + + $this->factory->comment->create(array( + 'comment_post_ID' => $editor_post_id, + 'comment_author' => 'Commenter 2', + 'comment_author_url' => 'http://example.com/2/', + 'comment_approved' => 0, + )); + + $result = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', array( + 'post_id' => $author_post_id + ) ) ); + $this->assertInternalType( 'array', $result ); + $this->assertCount( 1, $result ); + + $result2 = $this->myxmlrpcserver->wp_getComments( array( 1, 'editor', 'editor', array( + 'status' => 'approve', + 'post_id' => $author_post_id + ) ) ); + + $this->assertInternalType( 'array', $result2 ); + $this->assertCount( 1, $result2 ); } } \ No newline at end of file