wip
This commit is contained in:
@@ -123,6 +123,10 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
* @return true|WP_Error True if the request has read access, error object otherwise.
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
$is_note = 'note' === $request['type'];
|
||||
$is_edit_context = 'edit' === $request['context'];
|
||||
$protected_params = array( 'author', 'author_exclude', 'author_email', 'type', 'status' );
|
||||
$forbidden_params = array();
|
||||
|
||||
if ( ! empty( $request['post'] ) ) {
|
||||
foreach ( (array) $request['post'] as $post_id ) {
|
||||
@@ -141,10 +145,51 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
array( 'status' => rest_authorization_required_code() )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $post && $is_note && ! $this->check_post_type_supports_notes( $post->post_type ) ) {
|
||||
if ( current_user_can( 'edit_post', $post->ID ) ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_not_supported_post_type',
|
||||
__( 'Sorry, this post type does not support notes.' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
|
||||
foreach ( $protected_params as $param ) {
|
||||
if ( 'status' === $param ) {
|
||||
if ( 'approve' !== $request[ $param ] ) {
|
||||
$forbidden_params[] = $param;
|
||||
}
|
||||
} elseif ( 'type' === $param ) {
|
||||
if ( 'comment' !== $request[ $param ] ) {
|
||||
$forbidden_params[] = $param;
|
||||
}
|
||||
} elseif ( ! empty( $request[ $param ] ) ) {
|
||||
$forbidden_params[] = $param;
|
||||
}
|
||||
}
|
||||
return new WP_Error(
|
||||
'rest_forbidden_param',
|
||||
/* translators: %s: List of forbidden parameters. */
|
||||
sprintf( __( 'Query parameter not permitted: %s' ), implode( ', ', $forbidden_params ) ),
|
||||
array( 'status' => rest_authorization_required_code() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
|
||||
// Re-map edit context capabilities when requesting `note` for a post.
|
||||
if ( $is_edit_context && $is_note && ! empty( $request['post'] ) ) {
|
||||
foreach ( (array) $request['post'] as $post_id ) {
|
||||
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
||||
return new WP_Error(
|
||||
'rest_forbidden_context',
|
||||
__( 'Sorry, you are not allowed to edit comments.' ),
|
||||
array( 'status' => rest_authorization_required_code() )
|
||||
);
|
||||
}
|
||||
}
|
||||
} elseif ( $is_edit_context && ! current_user_can( 'moderate_comments' ) ) {
|
||||
return new WP_Error(
|
||||
'rest_forbidden_context',
|
||||
__( 'Sorry, you are not allowed to edit comments.' ),
|
||||
@@ -153,9 +198,6 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_posts' ) ) {
|
||||
$protected_params = array( 'author', 'author_exclude', 'author_email', 'type', 'status' );
|
||||
$forbidden_params = array();
|
||||
|
||||
foreach ( $protected_params as $param ) {
|
||||
if ( 'status' === $param ) {
|
||||
if ( 'approve' !== $request[ $param ] ) {
|
||||
@@ -302,12 +344,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
$max_pages = (int) $query->max_num_pages;
|
||||
|
||||
if ( $total_comments < 1 ) {
|
||||
// Out-of-bounds, run the query again without LIMIT for total count.
|
||||
// Out-of-bounds, run the query without pagination/offset to get the total count.
|
||||
unset( $prepared_args['number'], $prepared_args['offset'] );
|
||||
|
||||
$query = new WP_Comment_Query();
|
||||
$prepared_args['count'] = true;
|
||||
$prepared_args['orderby'] = 'none';
|
||||
$query = new WP_Comment_Query();
|
||||
$prepared_args['count'] = true;
|
||||
$prepared_args['orderby'] = 'none';
|
||||
$prepared_args['update_comment_meta_cache'] = false;
|
||||
|
||||
$total_comments = $query->query( $prepared_args );
|
||||
$max_pages = (int) ceil( $total_comments / $request['per_page'] );
|
||||
@@ -394,7 +437,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
return $comment;
|
||||
}
|
||||
|
||||
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
|
||||
// Re-map edit context capabilities when requesting `note` type.
|
||||
$edit_cap = 'note' === $comment->comment_type ? array( 'edit_comment', $comment->comment_ID ) : array( 'moderate_comments' );
|
||||
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( ...$edit_cap ) ) {
|
||||
return new WP_Error(
|
||||
'rest_forbidden_context',
|
||||
__( 'Sorry, you are not allowed to edit comments.' ),
|
||||
@@ -452,6 +497,16 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
* @return true|WP_Error True if the request has access to create items, error object otherwise.
|
||||
*/
|
||||
public function create_item_permissions_check( $request ) {
|
||||
$is_note = ! empty( $request['type'] ) && 'note' === $request['type'];
|
||||
|
||||
if ( ! is_user_logged_in() && $is_note ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_login_required',
|
||||
__( 'Sorry, you must be logged in to comment.' ),
|
||||
array( 'status' => 401 )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! is_user_logged_in() ) {
|
||||
if ( get_option( 'comment_registration' ) ) {
|
||||
return new WP_Error(
|
||||
@@ -505,7 +560,8 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $request['status'] ) && ! current_user_can( 'moderate_comments' ) ) {
|
||||
$edit_cap = $is_note ? array( 'edit_post', (int) $request['post'] ) : array( 'moderate_comments' );
|
||||
if ( isset( $request['status'] ) && ! current_user_can( ...$edit_cap ) ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_invalid_status',
|
||||
/* translators: %s: Request parameter. */
|
||||
@@ -532,7 +588,15 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'draft' === $post->post_status ) {
|
||||
if ( $is_note && ! $this->check_post_type_supports_notes( $post->post_type ) ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_not_supported_post_type',
|
||||
__( 'Sorry, this post type does not support notes.' ),
|
||||
array( 'status' => 403 )
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'draft' === $post->post_status && ! $is_note ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_draft_post',
|
||||
__( 'Sorry, you are not allowed to create a comment on this post.' ),
|
||||
@@ -556,7 +620,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! comments_open( $post->ID ) ) {
|
||||
if ( ! comments_open( $post->ID ) && ! $is_note ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_closed',
|
||||
__( 'Sorry, comments are closed for this item.' ),
|
||||
@@ -584,8 +648,8 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
);
|
||||
}
|
||||
|
||||
// Do not allow comments to be created with a non-default type.
|
||||
if ( ! empty( $request['type'] ) && 'comment' !== $request['type'] ) {
|
||||
// Do not allow comments to be created with a non-core type.
|
||||
if ( ! empty( $request['type'] ) && ! in_array( $request['type'], array( 'comment', 'note' ), true ) ) {
|
||||
return new WP_Error(
|
||||
'rest_invalid_comment_type',
|
||||
__( 'Cannot create a comment with that type.' ),
|
||||
@@ -598,12 +662,17 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
return $prepared_comment;
|
||||
}
|
||||
|
||||
$prepared_comment['comment_type'] = 'comment';
|
||||
$prepared_comment['comment_type'] = $request['type'];
|
||||
|
||||
if ( ! isset( $prepared_comment['comment_content'] ) ) {
|
||||
$prepared_comment['comment_content'] = '';
|
||||
}
|
||||
|
||||
// Include note metadata into check_is_comment_content_allowed.
|
||||
if ( isset( $request['meta']['_wp_note_status'] ) ) {
|
||||
$prepared_comment['meta']['_wp_note_status'] = $request['meta']['_wp_note_status'];
|
||||
}
|
||||
|
||||
if ( ! $this->check_is_comment_content_allowed( $prepared_comment ) ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_content_invalid',
|
||||
@@ -666,7 +735,11 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
);
|
||||
}
|
||||
|
||||
$prepared_comment['comment_approved'] = wp_allow_comment( $prepared_comment, true );
|
||||
// Don't check for duplicates or flooding for notes.
|
||||
$prepared_comment['comment_approved'] =
|
||||
'note' === $prepared_comment['comment_type'] ?
|
||||
'1' :
|
||||
wp_allow_comment( $prepared_comment, true );
|
||||
|
||||
if ( is_wp_error( $prepared_comment['comment_approved'] ) ) {
|
||||
$error_code = $prepared_comment['comment_approved']->get_error_code();
|
||||
@@ -859,8 +932,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
if ( is_wp_error( $prepared_args ) ) {
|
||||
return $prepared_args;
|
||||
}
|
||||
|
||||
if ( isset( $prepared_args['comment_content'] ) && empty( $prepared_args['comment_content'] ) ) {
|
||||
if ( ! $this->check_is_comment_content_allowed( $prepared_args ) ) {
|
||||
return new WP_Error(
|
||||
'rest_comment_content_invalid',
|
||||
__( 'Invalid comment content.' ),
|
||||
@@ -1207,6 +1279,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
array(
|
||||
'count' => true,
|
||||
'orderby' => 'none',
|
||||
'type' => 'all',
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1223,6 +1296,22 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
);
|
||||
}
|
||||
|
||||
// Embedding children for notes requires `type` and `status` inheritance.
|
||||
if ( isset( $links['children'] ) && 'note' === $comment->comment_type ) {
|
||||
$args = array(
|
||||
'parent' => $comment->comment_ID,
|
||||
'type' => $comment->comment_type,
|
||||
'status' => 'all',
|
||||
);
|
||||
|
||||
$rest_url = add_query_arg( $args, rest_url( $this->namespace . '/' . $this->rest_base ) );
|
||||
|
||||
$links['children'] = array(
|
||||
'href' => $rest_url,
|
||||
'embeddable' => true,
|
||||
);
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
@@ -1520,6 +1609,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit', 'embed' ),
|
||||
'readonly' => true,
|
||||
'default' => 'comment',
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -1821,7 +1911,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
* @return bool Whether the comment can be read.
|
||||
*/
|
||||
protected function check_read_permission( $comment, $request ) {
|
||||
if ( ! empty( $comment->comment_post_ID ) ) {
|
||||
if ( 'note' !== $comment->comment_type && ! empty( $comment->comment_post_ID ) ) {
|
||||
$post = get_post( $comment->comment_post_ID );
|
||||
if ( $post ) {
|
||||
if ( $this->check_read_post_permission( $post, $request ) && 1 === (int) $comment->comment_approved ) {
|
||||
@@ -1903,6 +1993,10 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
* @return bool True if the content is allowed, false otherwise.
|
||||
*/
|
||||
protected function check_is_comment_content_allowed( $prepared_comment ) {
|
||||
if ( ! isset( $prepared_comment['comment_content'] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$check = wp_parse_args(
|
||||
$prepared_comment,
|
||||
array(
|
||||
@@ -1922,10 +2016,42 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow empty notes only when resolution metadata is valid.
|
||||
if (
|
||||
isset( $check['comment_type'] ) &&
|
||||
'note' === $check['comment_type'] &&
|
||||
isset( $check['meta']['_wp_note_status'] ) &&
|
||||
in_array( $check['meta']['_wp_note_status'], array( 'resolved', 'reopen' ), true )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not allow a comment to be created with missing or empty
|
||||
* comment_content. See wp_handle_comment_submission().
|
||||
*/
|
||||
return '' !== $check['comment_content'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if post type supports notes.
|
||||
*
|
||||
* @param string $post_type Post type name.
|
||||
* @return bool True if post type supports notes, false otherwise.
|
||||
*/
|
||||
private function check_post_type_supports_notes( $post_type ) {
|
||||
$supports = get_all_post_type_supports( $post_type );
|
||||
if ( ! isset( $supports['editor'] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! is_array( $supports['editor'] ) ) {
|
||||
return false;
|
||||
}
|
||||
foreach ( $supports['editor'] as $item ) {
|
||||
if ( ! empty( $item['notes'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user