wp/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    38 
    38 
    39 	/**
    39 	/**
    40 	 * Registers the routes for the objects of the controller.
    40 	 * Registers the routes for the objects of the controller.
    41 	 *
    41 	 *
    42 	 * @since 4.7.0
    42 	 * @since 4.7.0
       
    43 	 *
       
    44 	 * @see register_rest_route()
    43 	 */
    45 	 */
    44 	public function register_routes() {
    46 	public function register_routes() {
    45 
    47 
    46 		register_rest_route(
    48 		register_rest_route(
    47 			$this->namespace,
    49 			$this->namespace,
    97 					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
    99 					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
    98 					'args'                => array(
   100 					'args'                => array(
    99 						'force'    => array(
   101 						'force'    => array(
   100 							'type'        => 'boolean',
   102 							'type'        => 'boolean',
   101 							'default'     => false,
   103 							'default'     => false,
   102 							'description' => __( 'Whether to bypass trash and force deletion.' ),
   104 							'description' => __( 'Whether to bypass Trash and force deletion.' ),
   103 						),
   105 						),
   104 						'password' => array(
   106 						'password' => array(
   105 							'description' => __( 'The password for the parent post of the comment (if the post is password protected).' ),
   107 							'description' => __( 'The password for the parent post of the comment (if the post is password protected).' ),
   106 							'type'        => 'string',
   108 							'type'        => 'string',
   107 						),
   109 						),
   116 	 * Checks if a given request has access to read comments.
   118 	 * Checks if a given request has access to read comments.
   117 	 *
   119 	 *
   118 	 * @since 4.7.0
   120 	 * @since 4.7.0
   119 	 *
   121 	 *
   120 	 * @param WP_REST_Request $request Full details about the request.
   122 	 * @param WP_REST_Request $request Full details about the request.
   121 	 * @return WP_Error|bool True if the request has read access, error object otherwise.
   123 	 * @return true|WP_Error True if the request has read access, error object otherwise.
   122 	 */
   124 	 */
   123 	public function get_items_permissions_check( $request ) {
   125 	public function get_items_permissions_check( $request ) {
   124 
   126 
   125 		if ( ! empty( $request['post'] ) ) {
   127 		if ( ! empty( $request['post'] ) ) {
   126 			foreach ( (array) $request['post'] as $post_id ) {
   128 			foreach ( (array) $request['post'] as $post_id ) {
   127 				$post = get_post( $post_id );
   129 				$post = get_post( $post_id );
   128 
   130 
   129 				if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post, $request ) ) {
   131 				if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post, $request ) ) {
   130 					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() ) );
   132 					return new WP_Error(
       
   133 						'rest_cannot_read_post',
       
   134 						__( 'Sorry, you are not allowed to read the post for this comment.' ),
       
   135 						array( 'status' => rest_authorization_required_code() )
       
   136 					);
   131 				} elseif ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) {
   137 				} elseif ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) {
   132 					return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read comments without a post.' ), array( 'status' => rest_authorization_required_code() ) );
   138 					return new WP_Error(
       
   139 						'rest_cannot_read',
       
   140 						__( 'Sorry, you are not allowed to read comments without a post.' ),
       
   141 						array( 'status' => rest_authorization_required_code() )
       
   142 					);
   133 				}
   143 				}
   134 			}
   144 			}
   135 		}
   145 		}
   136 
   146 
   137 		if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
   147 		if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
   138 			return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit comments.' ), array( 'status' => rest_authorization_required_code() ) );
   148 			return new WP_Error(
       
   149 				'rest_forbidden_context',
       
   150 				__( 'Sorry, you are not allowed to edit comments.' ),
       
   151 				array( 'status' => rest_authorization_required_code() )
       
   152 			);
   139 		}
   153 		}
   140 
   154 
   141 		if ( ! current_user_can( 'edit_posts' ) ) {
   155 		if ( ! current_user_can( 'edit_posts' ) ) {
   142 			$protected_params = array( 'author', 'author_exclude', 'author_email', 'type', 'status' );
   156 			$protected_params = array( 'author', 'author_exclude', 'author_email', 'type', 'status' );
   143 			$forbidden_params = array();
   157 			$forbidden_params = array();
   155 					$forbidden_params[] = $param;
   169 					$forbidden_params[] = $param;
   156 				}
   170 				}
   157 			}
   171 			}
   158 
   172 
   159 			if ( ! empty( $forbidden_params ) ) {
   173 			if ( ! empty( $forbidden_params ) ) {
   160 				return new WP_Error( 'rest_forbidden_param', sprintf( __( 'Query parameter not permitted: %s' ), implode( ', ', $forbidden_params ) ), array( 'status' => rest_authorization_required_code() ) );
   174 				return new WP_Error(
       
   175 					'rest_forbidden_param',
       
   176 					/* translators: %s: List of forbidden parameters. */
       
   177 					sprintf( __( 'Query parameter not permitted: %s' ), implode( ', ', $forbidden_params ) ),
       
   178 					array( 'status' => rest_authorization_required_code() )
       
   179 				);
   161 			}
   180 			}
   162 		}
   181 		}
   163 
   182 
   164 		return true;
   183 		return true;
   165 	}
   184 	}
   168 	 * Retrieves a list of comment items.
   187 	 * Retrieves a list of comment items.
   169 	 *
   188 	 *
   170 	 * @since 4.7.0
   189 	 * @since 4.7.0
   171 	 *
   190 	 *
   172 	 * @param WP_REST_Request $request Full details about the request.
   191 	 * @param WP_REST_Request $request Full details about the request.
   173 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
   192 	 * @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
   174 	 */
   193 	 */
   175 	public function get_items( $request ) {
   194 	public function get_items( $request ) {
   176 
   195 
   177 		// Retrieve the list of registered collection query parameters.
   196 		// Retrieve the list of registered collection query parameters.
   178 		$registered = $this->get_collection_params();
   197 		$registered = $this->get_collection_params();
   315 	 *
   334 	 *
   316 	 * @param int $id Supplied ID.
   335 	 * @param int $id Supplied ID.
   317 	 * @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
   336 	 * @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
   318 	 */
   337 	 */
   319 	protected function get_comment( $id ) {
   338 	protected function get_comment( $id ) {
   320 		$error = new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
   339 		$error = new WP_Error(
       
   340 			'rest_comment_invalid_id',
       
   341 			__( 'Invalid comment ID.' ),
       
   342 			array( 'status' => 404 )
       
   343 		);
       
   344 
   321 		if ( (int) $id <= 0 ) {
   345 		if ( (int) $id <= 0 ) {
   322 			return $error;
   346 			return $error;
   323 		}
   347 		}
   324 
   348 
   325 		$id      = (int) $id;
   349 		$id      = (int) $id;
   328 			return $error;
   352 			return $error;
   329 		}
   353 		}
   330 
   354 
   331 		if ( ! empty( $comment->comment_post_ID ) ) {
   355 		if ( ! empty( $comment->comment_post_ID ) ) {
   332 			$post = get_post( (int) $comment->comment_post_ID );
   356 			$post = get_post( (int) $comment->comment_post_ID );
       
   357 
   333 			if ( empty( $post ) ) {
   358 			if ( empty( $post ) ) {
   334 				return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
   359 				return new WP_Error(
       
   360 					'rest_post_invalid_id',
       
   361 					__( 'Invalid post ID.' ),
       
   362 					array( 'status' => 404 )
       
   363 				);
   335 			}
   364 			}
   336 		}
   365 		}
   337 
   366 
   338 		return $comment;
   367 		return $comment;
   339 	}
   368 	}
   342 	 * Checks if a given request has access to read the comment.
   371 	 * Checks if a given request has access to read the comment.
   343 	 *
   372 	 *
   344 	 * @since 4.7.0
   373 	 * @since 4.7.0
   345 	 *
   374 	 *
   346 	 * @param WP_REST_Request $request Full details about the request.
   375 	 * @param WP_REST_Request $request Full details about the request.
   347 	 * @return WP_Error|bool True if the request has read access for the item, error object otherwise.
   376 	 * @return true|WP_Error True if the request has read access for the item, error object otherwise.
   348 	 */
   377 	 */
   349 	public function get_item_permissions_check( $request ) {
   378 	public function get_item_permissions_check( $request ) {
   350 		$comment = $this->get_comment( $request['id'] );
   379 		$comment = $this->get_comment( $request['id'] );
   351 		if ( is_wp_error( $comment ) ) {
   380 		if ( is_wp_error( $comment ) ) {
   352 			return $comment;
   381 			return $comment;
   353 		}
   382 		}
   354 
   383 
   355 		if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
   384 		if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
   356 			return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit comments.' ), array( 'status' => rest_authorization_required_code() ) );
   385 			return new WP_Error(
       
   386 				'rest_forbidden_context',
       
   387 				__( 'Sorry, you are not allowed to edit comments.' ),
       
   388 				array( 'status' => rest_authorization_required_code() )
       
   389 			);
   357 		}
   390 		}
   358 
   391 
   359 		$post = get_post( $comment->comment_post_ID );
   392 		$post = get_post( $comment->comment_post_ID );
   360 
   393 
   361 		if ( ! $this->check_read_permission( $comment, $request ) ) {
   394 		if ( ! $this->check_read_permission( $comment, $request ) ) {
   362 			return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read this comment.' ), array( 'status' => rest_authorization_required_code() ) );
   395 			return new WP_Error(
       
   396 				'rest_cannot_read',
       
   397 				__( 'Sorry, you are not allowed to read this comment.' ),
       
   398 				array( 'status' => rest_authorization_required_code() )
       
   399 			);
   363 		}
   400 		}
   364 
   401 
   365 		if ( $post && ! $this->check_read_post_permission( $post, $request ) ) {
   402 		if ( $post && ! $this->check_read_post_permission( $post, $request ) ) {
   366 			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() ) );
   403 			return new WP_Error(
       
   404 				'rest_cannot_read_post',
       
   405 				__( 'Sorry, you are not allowed to read the post for this comment.' ),
       
   406 				array( 'status' => rest_authorization_required_code() )
       
   407 			);
   367 		}
   408 		}
   368 
   409 
   369 		return true;
   410 		return true;
   370 	}
   411 	}
   371 
   412 
   373 	 * Retrieves a comment.
   414 	 * Retrieves a comment.
   374 	 *
   415 	 *
   375 	 * @since 4.7.0
   416 	 * @since 4.7.0
   376 	 *
   417 	 *
   377 	 * @param WP_REST_Request $request Full details about the request.
   418 	 * @param WP_REST_Request $request Full details about the request.
   378 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
   419 	 * @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
   379 	 */
   420 	 */
   380 	public function get_item( $request ) {
   421 	public function get_item( $request ) {
   381 		$comment = $this->get_comment( $request['id'] );
   422 		$comment = $this->get_comment( $request['id'] );
   382 		if ( is_wp_error( $comment ) ) {
   423 		if ( is_wp_error( $comment ) ) {
   383 			return $comment;
   424 			return $comment;
   393 	 * Checks if a given request has access to create a comment.
   434 	 * Checks if a given request has access to create a comment.
   394 	 *
   435 	 *
   395 	 * @since 4.7.0
   436 	 * @since 4.7.0
   396 	 *
   437 	 *
   397 	 * @param WP_REST_Request $request Full details about the request.
   438 	 * @param WP_REST_Request $request Full details about the request.
   398 	 * @return WP_Error|bool True if the request has access to create items, error object otherwise.
   439 	 * @return true|WP_Error True if the request has access to create items, error object otherwise.
   399 	 */
   440 	 */
   400 	public function create_item_permissions_check( $request ) {
   441 	public function create_item_permissions_check( $request ) {
   401 		if ( ! is_user_logged_in() ) {
   442 		if ( ! is_user_logged_in() ) {
   402 			if ( get_option( 'comment_registration' ) ) {
   443 			if ( get_option( 'comment_registration' ) ) {
   403 				return new WP_Error( 'rest_comment_login_required', __( 'Sorry, you must be logged in to comment.' ), array( 'status' => 401 ) );
   444 				return new WP_Error(
       
   445 					'rest_comment_login_required',
       
   446 					__( 'Sorry, you must be logged in to comment.' ),
       
   447 					array( 'status' => 401 )
       
   448 				);
   404 			}
   449 			}
   405 
   450 
   406 			/**
   451 			/**
   407 			 * Filter whether comments can be created without authentication.
   452 			 * Filter whether comments can be created without authentication.
   408 			 *
   453 			 *
   414 			 *                              be created. Default `false`.
   459 			 *                              be created. Default `false`.
   415 			 * @param WP_REST_Request $request Request used to generate the
   460 			 * @param WP_REST_Request $request Request used to generate the
   416 			 *                                 response.
   461 			 *                                 response.
   417 			 */
   462 			 */
   418 			$allow_anonymous = apply_filters( 'rest_allow_anonymous_comments', false, $request );
   463 			$allow_anonymous = apply_filters( 'rest_allow_anonymous_comments', false, $request );
       
   464 
   419 			if ( ! $allow_anonymous ) {
   465 			if ( ! $allow_anonymous ) {
   420 				return new WP_Error( 'rest_comment_login_required', __( 'Sorry, you must be logged in to comment.' ), array( 'status' => 401 ) );
   466 				return new WP_Error(
       
   467 					'rest_comment_login_required',
       
   468 					__( 'Sorry, you must be logged in to comment.' ),
       
   469 					array( 'status' => 401 )
       
   470 				);
   421 			}
   471 			}
   422 		}
   472 		}
   423 
   473 
   424 		// Limit who can set comment `author`, `author_ip` or `status` to anything other than the default.
   474 		// Limit who can set comment `author`, `author_ip` or `status` to anything other than the default.
   425 		if ( isset( $request['author'] ) && get_current_user_id() !== $request['author'] && ! current_user_can( 'moderate_comments' ) ) {
   475 		if ( isset( $request['author'] ) && get_current_user_id() !== $request['author'] && ! current_user_can( 'moderate_comments' ) ) {
   426 			return new WP_Error(
   476 			return new WP_Error(
   427 				'rest_comment_invalid_author',
   477 				'rest_comment_invalid_author',
   428 				/* translators: %s: request parameter */
   478 				/* translators: %s: Request parameter. */
   429 				sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author' ),
   479 				sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author' ),
   430 				array( 'status' => rest_authorization_required_code() )
   480 				array( 'status' => rest_authorization_required_code() )
   431 			);
   481 			);
   432 		}
   482 		}
   433 
   483 
   434 		if ( isset( $request['author_ip'] ) && ! current_user_can( 'moderate_comments' ) ) {
   484 		if ( isset( $request['author_ip'] ) && ! current_user_can( 'moderate_comments' ) ) {
   435 			if ( empty( $_SERVER['REMOTE_ADDR'] ) || $request['author_ip'] !== $_SERVER['REMOTE_ADDR'] ) {
   485 			if ( empty( $_SERVER['REMOTE_ADDR'] ) || $request['author_ip'] !== $_SERVER['REMOTE_ADDR'] ) {
   436 				return new WP_Error(
   486 				return new WP_Error(
   437 					'rest_comment_invalid_author_ip',
   487 					'rest_comment_invalid_author_ip',
   438 					/* translators: %s: request parameter */
   488 					/* translators: %s: Request parameter. */
   439 					sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author_ip' ),
   489 					sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author_ip' ),
   440 					array( 'status' => rest_authorization_required_code() )
   490 					array( 'status' => rest_authorization_required_code() )
   441 				);
   491 				);
   442 			}
   492 			}
   443 		}
   493 		}
   444 
   494 
   445 		if ( isset( $request['status'] ) && ! current_user_can( 'moderate_comments' ) ) {
   495 		if ( isset( $request['status'] ) && ! current_user_can( 'moderate_comments' ) ) {
   446 			return new WP_Error(
   496 			return new WP_Error(
   447 				'rest_comment_invalid_status',
   497 				'rest_comment_invalid_status',
   448 				/* translators: %s: request parameter */
   498 				/* translators: %s: Request parameter. */
   449 				sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'status' ),
   499 				sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'status' ),
   450 				array( 'status' => rest_authorization_required_code() )
   500 				array( 'status' => rest_authorization_required_code() )
   451 			);
   501 			);
   452 		}
   502 		}
   453 
   503 
   454 		if ( empty( $request['post'] ) ) {
   504 		if ( empty( $request['post'] ) ) {
   455 			return new WP_Error( 'rest_comment_invalid_post_id', __( 'Sorry, you are not allowed to create this comment without a post.' ), array( 'status' => 403 ) );
   505 			return new WP_Error(
       
   506 				'rest_comment_invalid_post_id',
       
   507 				__( 'Sorry, you are not allowed to create this comment without a post.' ),
       
   508 				array( 'status' => 403 )
       
   509 			);
   456 		}
   510 		}
   457 
   511 
   458 		$post = get_post( (int) $request['post'] );
   512 		$post = get_post( (int) $request['post'] );
       
   513 
   459 		if ( ! $post ) {
   514 		if ( ! $post ) {
   460 			return new WP_Error( 'rest_comment_invalid_post_id', __( 'Sorry, you are not allowed to create this comment without a post.' ), array( 'status' => 403 ) );
   515 			return new WP_Error(
       
   516 				'rest_comment_invalid_post_id',
       
   517 				__( 'Sorry, you are not allowed to create this comment without a post.' ),
       
   518 				array( 'status' => 403 )
       
   519 			);
   461 		}
   520 		}
   462 
   521 
   463 		if ( 'draft' === $post->post_status ) {
   522 		if ( 'draft' === $post->post_status ) {
   464 			return new WP_Error( 'rest_comment_draft_post', __( 'Sorry, you are not allowed to create a comment on this post.' ), array( 'status' => 403 ) );
   523 			return new WP_Error(
       
   524 				'rest_comment_draft_post',
       
   525 				__( 'Sorry, you are not allowed to create a comment on this post.' ),
       
   526 				array( 'status' => 403 )
       
   527 			);
   465 		}
   528 		}
   466 
   529 
   467 		if ( 'trash' === $post->post_status ) {
   530 		if ( 'trash' === $post->post_status ) {
   468 			return new WP_Error( 'rest_comment_trash_post', __( 'Sorry, you are not allowed to create a comment on this post.' ), array( 'status' => 403 ) );
   531 			return new WP_Error(
       
   532 				'rest_comment_trash_post',
       
   533 				__( 'Sorry, you are not allowed to create a comment on this post.' ),
       
   534 				array( 'status' => 403 )
       
   535 			);
   469 		}
   536 		}
   470 
   537 
   471 		if ( ! $this->check_read_post_permission( $post, $request ) ) {
   538 		if ( ! $this->check_read_post_permission( $post, $request ) ) {
   472 			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() ) );
   539 			return new WP_Error(
       
   540 				'rest_cannot_read_post',
       
   541 				__( 'Sorry, you are not allowed to read the post for this comment.' ),
       
   542 				array( 'status' => rest_authorization_required_code() )
       
   543 			);
   473 		}
   544 		}
   474 
   545 
   475 		if ( ! comments_open( $post->ID ) ) {
   546 		if ( ! comments_open( $post->ID ) ) {
   476 			return new WP_Error( 'rest_comment_closed', __( 'Sorry, comments are closed for this item.' ), array( 'status' => 403 ) );
   547 			return new WP_Error(
       
   548 				'rest_comment_closed',
       
   549 				__( 'Sorry, comments are closed for this item.' ),
       
   550 				array( 'status' => 403 )
       
   551 			);
   477 		}
   552 		}
   478 
   553 
   479 		return true;
   554 		return true;
   480 	}
   555 	}
   481 
   556 
   483 	 * Creates a comment.
   558 	 * Creates a comment.
   484 	 *
   559 	 *
   485 	 * @since 4.7.0
   560 	 * @since 4.7.0
   486 	 *
   561 	 *
   487 	 * @param WP_REST_Request $request Full details about the request.
   562 	 * @param WP_REST_Request $request Full details about the request.
   488 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
   563 	 * @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
   489 	 */
   564 	 */
   490 	public function create_item( $request ) {
   565 	public function create_item( $request ) {
   491 		if ( ! empty( $request['id'] ) ) {
   566 		if ( ! empty( $request['id'] ) ) {
   492 			return new WP_Error( 'rest_comment_exists', __( 'Cannot create existing comment.' ), array( 'status' => 400 ) );
   567 			return new WP_Error(
       
   568 				'rest_comment_exists',
       
   569 				__( 'Cannot create existing comment.' ),
       
   570 				array( 'status' => 400 )
       
   571 			);
   493 		}
   572 		}
   494 
   573 
   495 		// Do not allow comments to be created with a non-default type.
   574 		// Do not allow comments to be created with a non-default type.
   496 		if ( ! empty( $request['type'] ) && 'comment' !== $request['type'] ) {
   575 		if ( ! empty( $request['type'] ) && 'comment' !== $request['type'] ) {
   497 			return new WP_Error( 'rest_invalid_comment_type', __( 'Cannot create a comment with that type.' ), array( 'status' => 400 ) );
   576 			return new WP_Error(
       
   577 				'rest_invalid_comment_type',
       
   578 				__( 'Cannot create a comment with that type.' ),
       
   579 				array( 'status' => 400 )
       
   580 			);
   498 		}
   581 		}
   499 
   582 
   500 		$prepared_comment = $this->prepare_item_for_database( $request );
   583 		$prepared_comment = $this->prepare_item_for_database( $request );
   501 		if ( is_wp_error( $prepared_comment ) ) {
   584 		if ( is_wp_error( $prepared_comment ) ) {
   502 			return $prepared_comment;
   585 			return $prepared_comment;
   503 		}
   586 		}
   504 
   587 
   505 		$prepared_comment['comment_type'] = '';
   588 		$prepared_comment['comment_type'] = 'comment';
   506 
   589 
   507 		/*
   590 		/*
   508 		 * Do not allow a comment to be created with missing or empty
   591 		 * Do not allow a comment to be created with missing or empty
   509 		 * comment_content. See wp_handle_comment_submission().
   592 		 * comment_content. See wp_handle_comment_submission().
   510 		 */
   593 		 */
   511 		if ( empty( $prepared_comment['comment_content'] ) ) {
   594 		if ( empty( $prepared_comment['comment_content'] ) ) {
   512 			return new WP_Error( 'rest_comment_content_invalid', __( 'Invalid comment content.' ), array( 'status' => 400 ) );
   595 			return new WP_Error(
       
   596 				'rest_comment_content_invalid',
       
   597 				__( 'Invalid comment content.' ),
       
   598 				array( 'status' => 400 )
       
   599 			);
   513 		}
   600 		}
   514 
   601 
   515 		// Setting remaining values before wp_insert_comment so we can use wp_allow_comment().
   602 		// Setting remaining values before wp_insert_comment so we can use wp_allow_comment().
   516 		if ( ! isset( $prepared_comment['comment_date_gmt'] ) ) {
   603 		if ( ! isset( $prepared_comment['comment_date_gmt'] ) ) {
   517 			$prepared_comment['comment_date_gmt'] = current_time( 'mysql', true );
   604 			$prepared_comment['comment_date_gmt'] = current_time( 'mysql', true );
   533 		}
   620 		}
   534 
   621 
   535 		// Honor the discussion setting that requires a name and email address of the comment author.
   622 		// Honor the discussion setting that requires a name and email address of the comment author.
   536 		if ( get_option( 'require_name_email' ) ) {
   623 		if ( get_option( 'require_name_email' ) ) {
   537 			if ( empty( $prepared_comment['comment_author'] ) || empty( $prepared_comment['comment_author_email'] ) ) {
   624 			if ( empty( $prepared_comment['comment_author'] ) || empty( $prepared_comment['comment_author_email'] ) ) {
   538 				return new WP_Error( 'rest_comment_author_data_required', __( 'Creating a comment requires valid author name and email values.' ), array( 'status' => 400 ) );
   625 				return new WP_Error(
       
   626 					'rest_comment_author_data_required',
       
   627 					__( 'Creating a comment requires valid author name and email values.' ),
       
   628 					array( 'status' => 400 )
       
   629 				);
   539 			}
   630 			}
   540 		}
   631 		}
   541 
   632 
   542 		if ( ! isset( $prepared_comment['comment_author_email'] ) ) {
   633 		if ( ! isset( $prepared_comment['comment_author_email'] ) ) {
   543 			$prepared_comment['comment_author_email'] = '';
   634 			$prepared_comment['comment_author_email'] = '';
   550 		if ( ! isset( $prepared_comment['comment_agent'] ) ) {
   641 		if ( ! isset( $prepared_comment['comment_agent'] ) ) {
   551 			$prepared_comment['comment_agent'] = '';
   642 			$prepared_comment['comment_agent'] = '';
   552 		}
   643 		}
   553 
   644 
   554 		$check_comment_lengths = wp_check_comment_data_max_lengths( $prepared_comment );
   645 		$check_comment_lengths = wp_check_comment_data_max_lengths( $prepared_comment );
       
   646 
   555 		if ( is_wp_error( $check_comment_lengths ) ) {
   647 		if ( is_wp_error( $check_comment_lengths ) ) {
   556 			$error_code = $check_comment_lengths->get_error_code();
   648 			$error_code = $check_comment_lengths->get_error_code();
   557 			return new WP_Error( $error_code, __( 'Comment field exceeds maximum length allowed.' ), array( 'status' => 400 ) );
   649 			return new WP_Error(
       
   650 				$error_code,
       
   651 				__( 'Comment field exceeds maximum length allowed.' ),
       
   652 				array( 'status' => 400 )
       
   653 			);
   558 		}
   654 		}
   559 
   655 
   560 		$prepared_comment['comment_approved'] = wp_allow_comment( $prepared_comment, true );
   656 		$prepared_comment['comment_approved'] = wp_allow_comment( $prepared_comment, true );
   561 
   657 
   562 		if ( is_wp_error( $prepared_comment['comment_approved'] ) ) {
   658 		if ( is_wp_error( $prepared_comment['comment_approved'] ) ) {
   563 			$error_code    = $prepared_comment['comment_approved']->get_error_code();
   659 			$error_code    = $prepared_comment['comment_approved']->get_error_code();
   564 			$error_message = $prepared_comment['comment_approved']->get_error_message();
   660 			$error_message = $prepared_comment['comment_approved']->get_error_message();
   565 
   661 
   566 			if ( 'comment_duplicate' === $error_code ) {
   662 			if ( 'comment_duplicate' === $error_code ) {
   567 				return new WP_Error( $error_code, $error_message, array( 'status' => 409 ) );
   663 				return new WP_Error(
       
   664 					$error_code,
       
   665 					$error_message,
       
   666 					array( 'status' => 409 )
       
   667 				);
   568 			}
   668 			}
   569 
   669 
   570 			if ( 'comment_flood' === $error_code ) {
   670 			if ( 'comment_flood' === $error_code ) {
   571 				return new WP_Error( $error_code, $error_message, array( 'status' => 400 ) );
   671 				return new WP_Error(
       
   672 					$error_code,
       
   673 					$error_message,
       
   674 					array( 'status' => 400 )
       
   675 				);
   572 			}
   676 			}
   573 
   677 
   574 			return $prepared_comment['comment_approved'];
   678 			return $prepared_comment['comment_approved'];
   575 		}
   679 		}
   576 
   680 
   577 		/**
   681 		/**
   578 		 * Filters a comment before it is inserted via the REST API.
   682 		 * Filters a comment before it is inserted via the REST API.
   579 		 *
   683 		 *
   580 		 * Allows modification of the comment right before it is inserted via wp_insert_comment().
   684 		 * Allows modification of the comment right before it is inserted via wp_insert_comment().
   581 		 * Returning a WP_Error value from the filter will shortcircuit insertion and allow
   685 		 * Returning a WP_Error value from the filter will short-circuit insertion and allow
   582 		 * skipping further processing.
   686 		 * skipping further processing.
   583 		 *
   687 		 *
   584 		 * @since 4.7.0
   688 		 * @since 4.7.0
   585 		 * @since 4.8.0 `$prepared_comment` can now be a WP_Error to shortcircuit insertion.
   689 		 * @since 4.8.0 `$prepared_comment` can now be a WP_Error to short-circuit insertion.
   586 		 *
   690 		 *
   587 		 * @param array|WP_Error  $prepared_comment The prepared comment data for wp_insert_comment().
   691 		 * @param array|WP_Error  $prepared_comment The prepared comment data for wp_insert_comment().
   588 		 * @param WP_REST_Request $request          Request used to insert the comment.
   692 		 * @param WP_REST_Request $request          Request used to insert the comment.
   589 		 */
   693 		 */
   590 		$prepared_comment = apply_filters( 'rest_pre_insert_comment', $prepared_comment, $request );
   694 		$prepared_comment = apply_filters( 'rest_pre_insert_comment', $prepared_comment, $request );
   593 		}
   697 		}
   594 
   698 
   595 		$comment_id = wp_insert_comment( wp_filter_comment( wp_slash( (array) $prepared_comment ) ) );
   699 		$comment_id = wp_insert_comment( wp_filter_comment( wp_slash( (array) $prepared_comment ) ) );
   596 
   700 
   597 		if ( ! $comment_id ) {
   701 		if ( ! $comment_id ) {
   598 			return new WP_Error( 'rest_comment_failed_create', __( 'Creating comment failed.' ), array( 'status' => 500 ) );
   702 			return new WP_Error(
       
   703 				'rest_comment_failed_create',
       
   704 				__( 'Creating comment failed.' ),
       
   705 				array( 'status' => 500 )
       
   706 			);
   599 		}
   707 		}
   600 
   708 
   601 		if ( isset( $request['status'] ) ) {
   709 		if ( isset( $request['status'] ) ) {
   602 			$this->handle_status_param( $request['status'], $comment_id );
   710 			$this->handle_status_param( $request['status'], $comment_id );
   603 		}
   711 		}
   660 	 * Checks if a given REST request has access to update a comment.
   768 	 * Checks if a given REST request has access to update a comment.
   661 	 *
   769 	 *
   662 	 * @since 4.7.0
   770 	 * @since 4.7.0
   663 	 *
   771 	 *
   664 	 * @param WP_REST_Request $request Full details about the request.
   772 	 * @param WP_REST_Request $request Full details about the request.
   665 	 * @return WP_Error|bool True if the request has access to update the item, error object otherwise.
   773 	 * @return true|WP_Error True if the request has access to update the item, error object otherwise.
   666 	 */
   774 	 */
   667 	public function update_item_permissions_check( $request ) {
   775 	public function update_item_permissions_check( $request ) {
   668 		$comment = $this->get_comment( $request['id'] );
   776 		$comment = $this->get_comment( $request['id'] );
   669 		if ( is_wp_error( $comment ) ) {
   777 		if ( is_wp_error( $comment ) ) {
   670 			return $comment;
   778 			return $comment;
   671 		}
   779 		}
   672 
   780 
   673 		if ( ! $this->check_edit_permission( $comment ) ) {
   781 		if ( ! $this->check_edit_permission( $comment ) ) {
   674 			return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this comment.' ), array( 'status' => rest_authorization_required_code() ) );
   782 			return new WP_Error(
       
   783 				'rest_cannot_edit',
       
   784 				__( 'Sorry, you are not allowed to edit this comment.' ),
       
   785 				array( 'status' => rest_authorization_required_code() )
       
   786 			);
   675 		}
   787 		}
   676 
   788 
   677 		return true;
   789 		return true;
   678 	}
   790 	}
   679 
   791 
   681 	 * Updates a comment.
   793 	 * Updates a comment.
   682 	 *
   794 	 *
   683 	 * @since 4.7.0
   795 	 * @since 4.7.0
   684 	 *
   796 	 *
   685 	 * @param WP_REST_Request $request Full details about the request.
   797 	 * @param WP_REST_Request $request Full details about the request.
   686 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
   798 	 * @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
   687 	 */
   799 	 */
   688 	public function update_item( $request ) {
   800 	public function update_item( $request ) {
   689 		$comment = $this->get_comment( $request['id'] );
   801 		$comment = $this->get_comment( $request['id'] );
   690 		if ( is_wp_error( $comment ) ) {
   802 		if ( is_wp_error( $comment ) ) {
   691 			return $comment;
   803 			return $comment;
   692 		}
   804 		}
   693 
   805 
   694 		$id = $comment->comment_ID;
   806 		$id = $comment->comment_ID;
   695 
   807 
   696 		if ( isset( $request['type'] ) && get_comment_type( $id ) !== $request['type'] ) {
   808 		if ( isset( $request['type'] ) && get_comment_type( $id ) !== $request['type'] ) {
   697 			return new WP_Error( 'rest_comment_invalid_type', __( 'Sorry, you are not allowed to change the comment type.' ), array( 'status' => 404 ) );
   809 			return new WP_Error(
       
   810 				'rest_comment_invalid_type',
       
   811 				__( 'Sorry, you are not allowed to change the comment type.' ),
       
   812 				array( 'status' => 404 )
       
   813 			);
   698 		}
   814 		}
   699 
   815 
   700 		$prepared_args = $this->prepare_item_for_database( $request );
   816 		$prepared_args = $this->prepare_item_for_database( $request );
   701 
   817 
   702 		if ( is_wp_error( $prepared_args ) ) {
   818 		if ( is_wp_error( $prepared_args ) ) {
   703 			return $prepared_args;
   819 			return $prepared_args;
   704 		}
   820 		}
   705 
   821 
   706 		if ( ! empty( $prepared_args['comment_post_ID'] ) ) {
   822 		if ( ! empty( $prepared_args['comment_post_ID'] ) ) {
   707 			$post = get_post( $prepared_args['comment_post_ID'] );
   823 			$post = get_post( $prepared_args['comment_post_ID'] );
       
   824 
   708 			if ( empty( $post ) ) {
   825 			if ( empty( $post ) ) {
   709 				return new WP_Error( 'rest_comment_invalid_post_id', __( 'Invalid post ID.' ), array( 'status' => 403 ) );
   826 				return new WP_Error(
       
   827 					'rest_comment_invalid_post_id',
       
   828 					__( 'Invalid post ID.' ),
       
   829 					array( 'status' => 403 )
       
   830 				);
   710 			}
   831 			}
   711 		}
   832 		}
   712 
   833 
   713 		if ( empty( $prepared_args ) && isset( $request['status'] ) ) {
   834 		if ( empty( $prepared_args ) && isset( $request['status'] ) ) {
   714 			// Only the comment status is being changed.
   835 			// Only the comment status is being changed.
   715 			$change = $this->handle_status_param( $request['status'], $id );
   836 			$change = $this->handle_status_param( $request['status'], $id );
   716 
   837 
   717 			if ( ! $change ) {
   838 			if ( ! $change ) {
   718 				return new WP_Error( 'rest_comment_failed_edit', __( 'Updating comment status failed.' ), array( 'status' => 500 ) );
   839 				return new WP_Error(
       
   840 					'rest_comment_failed_edit',
       
   841 					__( 'Updating comment status failed.' ),
       
   842 					array( 'status' => 500 )
       
   843 				);
   719 			}
   844 			}
   720 		} elseif ( ! empty( $prepared_args ) ) {
   845 		} elseif ( ! empty( $prepared_args ) ) {
   721 			if ( is_wp_error( $prepared_args ) ) {
   846 			if ( is_wp_error( $prepared_args ) ) {
   722 				return $prepared_args;
   847 				return $prepared_args;
   723 			}
   848 			}
   724 
   849 
   725 			if ( isset( $prepared_args['comment_content'] ) && empty( $prepared_args['comment_content'] ) ) {
   850 			if ( isset( $prepared_args['comment_content'] ) && empty( $prepared_args['comment_content'] ) ) {
   726 				return new WP_Error( 'rest_comment_content_invalid', __( 'Invalid comment content.' ), array( 'status' => 400 ) );
   851 				return new WP_Error(
       
   852 					'rest_comment_content_invalid',
       
   853 					__( 'Invalid comment content.' ),
       
   854 					array( 'status' => 400 )
       
   855 				);
   727 			}
   856 			}
   728 
   857 
   729 			$prepared_args['comment_ID'] = $id;
   858 			$prepared_args['comment_ID'] = $id;
   730 
   859 
   731 			$check_comment_lengths = wp_check_comment_data_max_lengths( $prepared_args );
   860 			$check_comment_lengths = wp_check_comment_data_max_lengths( $prepared_args );
       
   861 
   732 			if ( is_wp_error( $check_comment_lengths ) ) {
   862 			if ( is_wp_error( $check_comment_lengths ) ) {
   733 				$error_code = $check_comment_lengths->get_error_code();
   863 				$error_code = $check_comment_lengths->get_error_code();
   734 				return new WP_Error( $error_code, __( 'Comment field exceeds maximum length allowed.' ), array( 'status' => 400 ) );
   864 				return new WP_Error(
   735 			}
   865 					$error_code,
   736 
   866 					__( 'Comment field exceeds maximum length allowed.' ),
   737 			$updated = wp_update_comment( wp_slash( (array) $prepared_args ) );
   867 					array( 'status' => 400 )
   738 
   868 				);
   739 			if ( false === $updated ) {
   869 			}
   740 				return new WP_Error( 'rest_comment_failed_edit', __( 'Updating comment failed.' ), array( 'status' => 500 ) );
   870 
       
   871 			$updated = wp_update_comment( wp_slash( (array) $prepared_args ), true );
       
   872 
       
   873 			if ( is_wp_error( $updated ) ) {
       
   874 				return new WP_Error(
       
   875 					'rest_comment_failed_edit',
       
   876 					__( 'Updating comment failed.' ),
       
   877 					array( 'status' => 500 )
       
   878 				);
   741 			}
   879 			}
   742 
   880 
   743 			if ( isset( $request['status'] ) ) {
   881 			if ( isset( $request['status'] ) ) {
   744 				$this->handle_status_param( $request['status'], $id );
   882 				$this->handle_status_param( $request['status'], $id );
   745 			}
   883 			}
   780 	 * Checks if a given request has access to delete a comment.
   918 	 * Checks if a given request has access to delete a comment.
   781 	 *
   919 	 *
   782 	 * @since 4.7.0
   920 	 * @since 4.7.0
   783 	 *
   921 	 *
   784 	 * @param WP_REST_Request $request Full details about the request.
   922 	 * @param WP_REST_Request $request Full details about the request.
   785 	 * @return WP_Error|bool True if the request has access to delete the item, error object otherwise.
   923 	 * @return true|WP_Error True if the request has access to delete the item, error object otherwise.
   786 	 */
   924 	 */
   787 	public function delete_item_permissions_check( $request ) {
   925 	public function delete_item_permissions_check( $request ) {
   788 		$comment = $this->get_comment( $request['id'] );
   926 		$comment = $this->get_comment( $request['id'] );
   789 		if ( is_wp_error( $comment ) ) {
   927 		if ( is_wp_error( $comment ) ) {
   790 			return $comment;
   928 			return $comment;
   791 		}
   929 		}
   792 
   930 
   793 		if ( ! $this->check_edit_permission( $comment ) ) {
   931 		if ( ! $this->check_edit_permission( $comment ) ) {
   794 			return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this comment.' ), array( 'status' => rest_authorization_required_code() ) );
   932 			return new WP_Error(
       
   933 				'rest_cannot_delete',
       
   934 				__( 'Sorry, you are not allowed to delete this comment.' ),
       
   935 				array( 'status' => rest_authorization_required_code() )
       
   936 			);
   795 		}
   937 		}
   796 		return true;
   938 		return true;
   797 	}
   939 	}
   798 
   940 
   799 	/**
   941 	/**
   800 	 * Deletes a comment.
   942 	 * Deletes a comment.
   801 	 *
   943 	 *
   802 	 * @since 4.7.0
   944 	 * @since 4.7.0
   803 	 *
   945 	 *
   804 	 * @param WP_REST_Request $request Full details about the request.
   946 	 * @param WP_REST_Request $request Full details about the request.
   805 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
   947 	 * @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
   806 	 */
   948 	 */
   807 	public function delete_item( $request ) {
   949 	public function delete_item( $request ) {
   808 		$comment = $this->get_comment( $request['id'] );
   950 		$comment = $this->get_comment( $request['id'] );
   809 		if ( is_wp_error( $comment ) ) {
   951 		if ( is_wp_error( $comment ) ) {
   810 			return $comment;
   952 			return $comment;
   813 		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
   955 		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
   814 
   956 
   815 		/**
   957 		/**
   816 		 * Filters whether a comment can be trashed.
   958 		 * Filters whether a comment can be trashed.
   817 		 *
   959 		 *
   818 		 * Return false to disable trash support for the post.
   960 		 * Return false to disable Trash support for the post.
   819 		 *
   961 		 *
   820 		 * @since 4.7.0
   962 		 * @since 4.7.0
   821 		 *
   963 		 *
   822 		 * @param bool    $supports_trash Whether the post type support trashing.
   964 		 * @param bool    $supports_trash Whether the post type support trashing.
   823 		 * @param WP_Post $comment        The comment object being considered for trashing support.
   965 		 * @param WP_Post $comment        The comment object being considered for trashing support.
   837 				)
   979 				)
   838 			);
   980 			);
   839 		} else {
   981 		} else {
   840 			// If this type doesn't support trashing, error out.
   982 			// If this type doesn't support trashing, error out.
   841 			if ( ! $supports_trash ) {
   983 			if ( ! $supports_trash ) {
   842 				/* translators: %s: force=true */
   984 				return new WP_Error(
   843 				return new WP_Error( 'rest_trash_not_supported', sprintf( __( "The comment does not support trashing. Set '%s' to delete." ), 'force=true' ), array( 'status' => 501 ) );
   985 					'rest_trash_not_supported',
       
   986 					/* translators: %s: force=true */
       
   987 					sprintf( __( "The comment does not support trashing. Set '%s' to delete." ), 'force=true' ),
       
   988 					array( 'status' => 501 )
       
   989 				);
   844 			}
   990 			}
   845 
   991 
   846 			if ( 'trash' === $comment->comment_approved ) {
   992 			if ( 'trash' === $comment->comment_approved ) {
   847 				return new WP_Error( 'rest_already_trashed', __( 'The comment has already been trashed.' ), array( 'status' => 410 ) );
   993 				return new WP_Error(
       
   994 					'rest_already_trashed',
       
   995 					__( 'The comment has already been trashed.' ),
       
   996 					array( 'status' => 410 )
       
   997 				);
   848 			}
   998 			}
   849 
   999 
   850 			$result   = wp_trash_comment( $comment->comment_ID );
  1000 			$result   = wp_trash_comment( $comment->comment_ID );
   851 			$comment  = get_comment( $comment->comment_ID );
  1001 			$comment  = get_comment( $comment->comment_ID );
   852 			$response = $this->prepare_item_for_response( $comment, $request );
  1002 			$response = $this->prepare_item_for_response( $comment, $request );
   853 		}
  1003 		}
   854 
  1004 
   855 		if ( ! $result ) {
  1005 		if ( ! $result ) {
   856 			return new WP_Error( 'rest_cannot_delete', __( 'The comment cannot be deleted.' ), array( 'status' => 500 ) );
  1006 			return new WP_Error(
       
  1007 				'rest_cannot_delete',
       
  1008 				__( 'The comment cannot be deleted.' ),
       
  1009 				array( 'status' => 500 )
       
  1010 			);
   857 		}
  1011 		}
   858 
  1012 
   859 		/**
  1013 		/**
   860 		 * Fires after a comment is deleted via the REST API.
  1014 		 * Fires after a comment is deleted via the REST API.
   861 		 *
  1015 		 *
   947 		if ( in_array( 'type', $fields, true ) ) {
  1101 		if ( in_array( 'type', $fields, true ) ) {
   948 			$data['type'] = get_comment_type( $comment->comment_ID );
  1102 			$data['type'] = get_comment_type( $comment->comment_ID );
   949 		}
  1103 		}
   950 
  1104 
   951 		if ( in_array( 'author_avatar_urls', $fields, true ) ) {
  1105 		if ( in_array( 'author_avatar_urls', $fields, true ) ) {
   952 			$data['author_avatar_urls'] = rest_get_avatar_urls( $comment->comment_author_email );
  1106 			$data['author_avatar_urls'] = rest_get_avatar_urls( $comment );
   953 		}
  1107 		}
   954 
  1108 
   955 		if ( in_array( 'meta', $fields, true ) ) {
  1109 		if ( in_array( 'meta', $fields, true ) ) {
   956 			$data['meta'] = $this->meta->get_value( $comment->comment_ID, $request );
  1110 			$data['meta'] = $this->meta->get_value( $comment->comment_ID, $request );
   957 		}
  1111 		}
  1148 				$prepared_comment['user_id']              = $user->ID;
  1302 				$prepared_comment['user_id']              = $user->ID;
  1149 				$prepared_comment['comment_author']       = $user->display_name;
  1303 				$prepared_comment['comment_author']       = $user->display_name;
  1150 				$prepared_comment['comment_author_email'] = $user->user_email;
  1304 				$prepared_comment['comment_author_email'] = $user->user_email;
  1151 				$prepared_comment['comment_author_url']   = $user->user_url;
  1305 				$prepared_comment['comment_author_url']   = $user->user_url;
  1152 			} else {
  1306 			} else {
  1153 				return new WP_Error( 'rest_comment_author_invalid', __( 'Invalid comment author ID.' ), array( 'status' => 400 ) );
  1307 				return new WP_Error(
       
  1308 					'rest_comment_author_invalid',
       
  1309 					__( 'Invalid comment author ID.' ),
       
  1310 					array( 'status' => 400 )
       
  1311 				);
  1154 			}
  1312 			}
  1155 		}
  1313 		}
  1156 
  1314 
  1157 		if ( isset( $request['author_name'] ) ) {
  1315 		if ( isset( $request['author_name'] ) ) {
  1158 			$prepared_comment['comment_author'] = $request['author_name'];
  1316 			$prepared_comment['comment_author'] = $request['author_name'];
  1213 	 * @since 4.7.0
  1371 	 * @since 4.7.0
  1214 	 *
  1372 	 *
  1215 	 * @return array
  1373 	 * @return array
  1216 	 */
  1374 	 */
  1217 	public function get_item_schema() {
  1375 	public function get_item_schema() {
       
  1376 		if ( $this->schema ) {
       
  1377 			return $this->add_additional_fields_schema( $this->schema );
       
  1378 		}
       
  1379 
  1218 		$schema = array(
  1380 		$schema = array(
  1219 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
  1381 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
  1220 			'title'      => 'comment',
  1382 			'title'      => 'comment',
  1221 			'type'       => 'object',
  1383 			'type'       => 'object',
  1222 			'properties' => array(
  1384 			'properties' => array(
  1236 					'type'        => 'string',
  1398 					'type'        => 'string',
  1237 					'format'      => 'email',
  1399 					'format'      => 'email',
  1238 					'context'     => array( 'edit' ),
  1400 					'context'     => array( 'edit' ),
  1239 					'arg_options' => array(
  1401 					'arg_options' => array(
  1240 						'sanitize_callback' => array( $this, 'check_comment_author_email' ),
  1402 						'sanitize_callback' => array( $this, 'check_comment_author_email' ),
  1241 						'validate_callback' => null, // skip built-in validation of 'email'.
  1403 						'validate_callback' => null, // Skip built-in validation of 'email'.
  1242 					),
  1404 					),
  1243 				),
  1405 				),
  1244 				'author_ip'         => array(
  1406 				'author_ip'         => array(
  1245 					'description' => __( 'IP address for the object author.' ),
  1407 					'description' => __( 'IP address for the object author.' ),
  1246 					'type'        => 'string',
  1408 					'type'        => 'string',
  1272 				'content'           => array(
  1434 				'content'           => array(
  1273 					'description' => __( 'The content for the object.' ),
  1435 					'description' => __( 'The content for the object.' ),
  1274 					'type'        => 'object',
  1436 					'type'        => 'object',
  1275 					'context'     => array( 'view', 'edit', 'embed' ),
  1437 					'context'     => array( 'view', 'edit', 'embed' ),
  1276 					'arg_options' => array(
  1438 					'arg_options' => array(
  1277 						'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
  1439 						'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database().
  1278 						'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
  1440 						'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database().
  1279 					),
  1441 					),
  1280 					'properties'  => array(
  1442 					'properties'  => array(
  1281 						'raw'      => array(
  1443 						'raw'      => array(
  1282 							'description' => __( 'Content for the object, as it exists in the database.' ),
  1444 							'description' => __( 'Content for the object, as it exists in the database.' ),
  1283 							'type'        => 'string',
  1445 							'type'        => 'string',
  1341 
  1503 
  1342 		if ( get_option( 'show_avatars' ) ) {
  1504 		if ( get_option( 'show_avatars' ) ) {
  1343 			$avatar_properties = array();
  1505 			$avatar_properties = array();
  1344 
  1506 
  1345 			$avatar_sizes = rest_get_avatar_sizes();
  1507 			$avatar_sizes = rest_get_avatar_sizes();
       
  1508 
  1346 			foreach ( $avatar_sizes as $size ) {
  1509 			foreach ( $avatar_sizes as $size ) {
  1347 				$avatar_properties[ $size ] = array(
  1510 				$avatar_properties[ $size ] = array(
  1348 					/* translators: %d: avatar image size in pixels */
  1511 					/* translators: %d: Avatar image size in pixels. */
  1349 					'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ),
  1512 					'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ),
  1350 					'type'        => 'string',
  1513 					'type'        => 'string',
  1351 					'format'      => 'uri',
  1514 					'format'      => 'uri',
  1352 					'context'     => array( 'embed', 'view', 'edit' ),
  1515 					'context'     => array( 'embed', 'view', 'edit' ),
  1353 				);
  1516 				);
  1362 			);
  1525 			);
  1363 		}
  1526 		}
  1364 
  1527 
  1365 		$schema['properties']['meta'] = $this->meta->get_field_schema();
  1528 		$schema['properties']['meta'] = $this->meta->get_field_schema();
  1366 
  1529 
  1367 		return $this->add_additional_fields_schema( $schema );
  1530 		$this->schema = $schema;
       
  1531 
       
  1532 		return $this->add_additional_fields_schema( $this->schema );
  1368 	}
  1533 	}
  1369 
  1534 
  1370 	/**
  1535 	/**
  1371 	 * Retrieves the query params for collections.
  1536 	 * Retrieves the query params for collections.
  1372 	 *
  1537 	 *
  1580 	 * @param WP_Post         $post    Post object.
  1745 	 * @param WP_Post         $post    Post object.
  1581 	 * @param WP_REST_Request $request Request data to check.
  1746 	 * @param WP_REST_Request $request Request data to check.
  1582 	 * @return bool Whether post can be read.
  1747 	 * @return bool Whether post can be read.
  1583 	 */
  1748 	 */
  1584 	protected function check_read_post_permission( $post, $request ) {
  1749 	protected function check_read_post_permission( $post, $request ) {
  1585 		$posts_controller = new WP_REST_Posts_Controller( $post->post_type );
  1750 		$post_type = get_post_type_object( $post->post_type );
  1586 		$post_type        = get_post_type_object( $post->post_type );
  1751 
       
  1752 		// Return false if custom post type doesn't exist
       
  1753 		if ( ! $post_type ) {
       
  1754 			return false;
       
  1755 		}
       
  1756 
       
  1757 		$posts_controller = $post_type->get_rest_controller();
       
  1758 
       
  1759 		// Ensure the posts controller is specifically a WP_REST_Posts_Controller instance
       
  1760 		// before using methods specific to that controller.
       
  1761 		if ( ! $posts_controller instanceof WP_REST_Posts_Controller ) {
       
  1762 			$posts_controller = new WP_REST_Posts_Controller( $post->post_type );
       
  1763 		}
  1587 
  1764 
  1588 		$has_password_filter = false;
  1765 		$has_password_filter = false;
  1589 
  1766 
  1590 		// Only check password if a specific post was queried for or a single comment
  1767 		// Only check password if a specific post was queried for or a single comment
  1591 		$requested_post    = ! empty( $request['post'] ) && ( ! is_array( $request['post'] ) || 1 === count( $request['post'] ) );
  1768 		$requested_post    = ! empty( $request['post'] ) && ( ! is_array( $request['post'] ) || 1 === count( $request['post'] ) );
  1595 
  1772 
  1596 			$has_password_filter = true;
  1773 			$has_password_filter = true;
  1597 		}
  1774 		}
  1598 
  1775 
  1599 		if ( post_password_required( $post ) ) {
  1776 		if ( post_password_required( $post ) ) {
  1600 			$result = current_user_can( $post_type->cap->edit_post, $post->ID );
  1777 			$result = current_user_can( 'edit_post', $post->ID );
  1601 		} else {
  1778 		} else {
  1602 			$result = $posts_controller->check_read_permission( $post );
  1779 			$result = $posts_controller->check_read_permission( $post );
  1603 		}
  1780 		}
  1604 
  1781 
  1605 		if ( $has_password_filter ) {
  1782 		if ( $has_password_filter ) {
  1646 	/**
  1823 	/**
  1647 	 * Checks if a comment can be edited or deleted.
  1824 	 * Checks if a comment can be edited or deleted.
  1648 	 *
  1825 	 *
  1649 	 * @since 4.7.0
  1826 	 * @since 4.7.0
  1650 	 *
  1827 	 *
  1651 	 * @param object $comment Comment object.
  1828 	 * @param WP_Comment $comment Comment object.
  1652 	 * @return bool Whether the comment can be edited or deleted.
  1829 	 * @return bool Whether the comment can be edited or deleted.
  1653 	 */
  1830 	 */
  1654 	protected function check_edit_permission( $comment ) {
  1831 	protected function check_edit_permission( $comment ) {
  1655 		if ( 0 === (int) get_current_user_id() ) {
  1832 		if ( 0 === (int) get_current_user_id() ) {
  1656 			return false;
  1833 			return false;
  1657 		}
  1834 		}
  1658 
  1835 
  1659 		if ( ! current_user_can( 'moderate_comments' ) ) {
  1836 		if ( current_user_can( 'moderate_comments' ) ) {
  1660 			return false;
  1837 			return true;
  1661 		}
  1838 		}
  1662 
  1839 
  1663 		return current_user_can( 'edit_comment', $comment->comment_ID );
  1840 		return current_user_can( 'edit_comment', $comment->comment_ID );
  1664 	}
  1841 	}
  1665 
  1842 
  1673 	 * @since 4.7.0
  1850 	 * @since 4.7.0
  1674 	 *
  1851 	 *
  1675 	 * @param string          $value   Author email value submitted.
  1852 	 * @param string          $value   Author email value submitted.
  1676 	 * @param WP_REST_Request $request Full details about the request.
  1853 	 * @param WP_REST_Request $request Full details about the request.
  1677 	 * @param string          $param   The parameter name.
  1854 	 * @param string          $param   The parameter name.
  1678 	 * @return WP_Error|string The sanitized email address, if valid,
  1855 	 * @return string|WP_Error The sanitized email address, if valid,
  1679 	 *                         otherwise an error.
  1856 	 *                         otherwise an error.
  1680 	 */
  1857 	 */
  1681 	public function check_comment_author_email( $value, $request, $param ) {
  1858 	public function check_comment_author_email( $value, $request, $param ) {
  1682 		$email = (string) $value;
  1859 		$email = (string) $value;
  1683 		if ( empty( $email ) ) {
  1860 		if ( empty( $email ) ) {