Skip to content

Commit e357195

Browse files
committed
REST API: Unify object access handling for simplicity.
Rather than repeating ourselves, unifying the access into a single method keeps everything tidy. While we're at it, add in additional schema handling for common parameters. See #38792. Built from https://develop.svn.wordpress.org/trunk@39954 git-svn-id: http://core.svn.wordpress.org/trunk@39891 1a063a9b-81f0-0310-95a4-ce76da25c4cd
1 parent 8538429 commit e357195

10 files changed

+353
-149
lines changed

Diff for: wp-includes/rest-api.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
4646
return false;
4747
}
4848

49+
if ( isset( $args['args'] ) ) {
50+
$common_args = $args['args'];
51+
unset( $args['args'] );
52+
} else {
53+
$common_args = array();
54+
}
55+
4956
if ( isset( $args['callback'] ) ) {
5057
// Upgrade a single set to multiple.
5158
$args = array( $args );
@@ -57,12 +64,13 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
5764
'args' => array(),
5865
);
5966
foreach ( $args as $key => &$arg_group ) {
60-
if ( ! is_numeric( $arg_group ) ) {
67+
if ( ! is_numeric( $key ) ) {
6168
// Route option, skip here.
6269
continue;
6370
}
6471

6572
$arg_group = array_merge( $defaults, $arg_group );
73+
$arg_group['args'] = array_merge( $common_args, $arg_group['args'] );
6674
}
6775

6876
$full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );

Diff for: wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

+60-41
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ public function register_routes() {
6363
) );
6464

6565
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
66+
'args' => array(
67+
'id' => array(
68+
'description' => __( 'Unique identifier for the object.' ),
69+
'type' => 'integer',
70+
),
71+
),
6672
array(
6773
'methods' => WP_REST_Server::READABLE,
6874
'callback' => array( $this, 'get_item' ),
@@ -299,6 +305,36 @@ public function get_items( $request ) {
299305
return $response;
300306
}
301307

308+
/**
309+
* Get the comment, if the ID is valid.
310+
*
311+
* @since 4.7.2
312+
*
313+
* @param int $id Supplied ID.
314+
* @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
315+
*/
316+
protected function get_comment( $id ) {
317+
$error = new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
318+
if ( (int) $id <= 0 ) {
319+
return $error;
320+
}
321+
322+
$id = (int) $id;
323+
$comment = get_comment( $id );
324+
if ( empty( $comment ) ) {
325+
return $error;
326+
}
327+
328+
if ( ! empty( $comment->comment_post_ID ) ) {
329+
$post = get_post( (int) $comment->comment_post_ID );
330+
if ( empty( $post ) ) {
331+
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
332+
}
333+
}
334+
335+
return $comment;
336+
}
337+
302338
/**
303339
* Checks if a given request has access to read the comment.
304340
*
@@ -309,12 +345,9 @@ public function get_items( $request ) {
309345
* @return WP_Error|bool True if the request has read access for the item, error object otherwise.
310346
*/
311347
public function get_item_permissions_check( $request ) {
312-
$id = (int) $request['id'];
313-
314-
$comment = get_comment( $id );
315-
316-
if ( ! $comment ) {
317-
return true;
348+
$comment = $this->get_comment( $request['id'] );
349+
if ( is_wp_error( $comment ) ) {
350+
return $comment;
318351
}
319352

320353
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
@@ -344,18 +377,9 @@ public function get_item_permissions_check( $request ) {
344377
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
345378
*/
346379
public function get_item( $request ) {
347-
$id = (int) $request['id'];
348-
349-
$comment = get_comment( $id );
350-
if ( empty( $comment ) ) {
351-
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
352-
}
353-
354-
if ( ! empty( $comment->comment_post_ID ) ) {
355-
$post = get_post( $comment->comment_post_ID );
356-
if ( empty( $post ) ) {
357-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
358-
}
380+
$comment = $this->get_comment( $request['id'] );
381+
if ( is_wp_error( $comment ) ) {
382+
return $comment;
359383
}
360384

361385
$data = $this->prepare_item_for_response( $comment, $request );
@@ -630,12 +654,12 @@ public function create_item( $request ) {
630654
* @return WP_Error|bool True if the request has access to update the item, error object otherwise.
631655
*/
632656
public function update_item_permissions_check( $request ) {
657+
$comment = $this->get_comment( $request['id'] );
658+
if ( is_wp_error( $comment ) ) {
659+
return $comment;
660+
}
633661

634-
$id = (int) $request['id'];
635-
636-
$comment = get_comment( $id );
637-
638-
if ( $comment && ! $this->check_edit_permission( $comment ) ) {
662+
if ( ! $this->check_edit_permission( $comment ) ) {
639663
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this comment.' ), array( 'status' => rest_authorization_required_code() ) );
640664
}
641665

@@ -652,14 +676,13 @@ public function update_item_permissions_check( $request ) {
652676
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
653677
*/
654678
public function update_item( $request ) {
655-
$id = (int) $request['id'];
656-
657-
$comment = get_comment( $id );
658-
659-
if ( empty( $comment ) ) {
660-
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
679+
$comment = $this->get_comment( $request['id'] );
680+
if ( is_wp_error( $comment ) ) {
681+
return $comment;
661682
}
662683

684+
$id = $comment->comment_ID;
685+
663686
if ( isset( $request['type'] ) && get_comment_type( $id ) !== $request['type'] ) {
664687
return new WP_Error( 'rest_comment_invalid_type', __( 'Sorry, you are not allowed to change the comment type.' ), array( 'status' => 404 ) );
665688
}
@@ -750,11 +773,9 @@ public function update_item( $request ) {
750773
* @return WP_Error|bool True if the request has access to delete the item, error object otherwise.
751774
*/
752775
public function delete_item_permissions_check( $request ) {
753-
$id = (int) $request['id'];
754-
$comment = get_comment( $id );
755-
756-
if ( ! $comment ) {
757-
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
776+
$comment = $this->get_comment( $request['id'] );
777+
if ( is_wp_error( $comment ) ) {
778+
return $comment;
758779
}
759780

760781
if ( ! $this->check_edit_permission( $comment ) ) {
@@ -773,15 +794,13 @@ public function delete_item_permissions_check( $request ) {
773794
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
774795
*/
775796
public function delete_item( $request ) {
776-
$id = (int) $request['id'];
777-
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
778-
779-
$comment = get_comment( $id );
780-
781-
if ( empty( $comment ) ) {
782-
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
797+
$comment = $this->get_comment( $request['id'] );
798+
if ( is_wp_error( $comment ) ) {
799+
return $comment;
783800
}
784801

802+
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
803+
785804
/**
786805
* Filters whether a comment can be trashed.
787806
*

Diff for: wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ public function register_routes() {
4848
) );
4949

5050
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<status>[\w-]+)', array(
51+
'args' => array(
52+
'status' => array(
53+
'description' => __( 'An alphanumeric identifier for the status.' ),
54+
'type' => 'string',
55+
),
56+
),
5157
array(
5258
'methods' => WP_REST_Server::READABLE,
5359
'callback' => array( $this, 'get_item' ),

Diff for: wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ public function register_routes() {
4848
) );
4949

5050
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<type>[\w-]+)', array(
51+
'args' => array(
52+
'type' => array(
53+
'description' => __( 'An alphanumeric identifier for the post type.' ),
54+
'type' => 'string',
55+
),
56+
),
5157
array(
5258
'methods' => WP_REST_Server::READABLE,
5359
'callback' => array( $this, 'get_item' ),

Diff for: wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

+62-24
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ public function register_routes() {
8888
);
8989
}
9090
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
91+
'args' => array(
92+
'id' => array(
93+
'description' => __( 'Unique identifier for the object.' ),
94+
'type' => 'integer',
95+
),
96+
),
9197
array(
9298
'methods' => WP_REST_Server::READABLE,
9399
'callback' => array( $this, 'get_item' ),
@@ -349,6 +355,28 @@ public function get_items( $request ) {
349355
return $response;
350356
}
351357

358+
/**
359+
* Get the post, if the ID is valid.
360+
*
361+
* @since 4.7.2
362+
*
363+
* @param int $id Supplied ID.
364+
* @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
365+
*/
366+
protected function get_post( $id ) {
367+
$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
368+
if ( (int) $id <= 0 ) {
369+
return $error;
370+
}
371+
372+
$post = get_post( (int) $id );
373+
if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
374+
return $error;
375+
}
376+
377+
return $post;
378+
}
379+
352380
/**
353381
* Checks if a given request has access to read a post.
354382
*
@@ -359,8 +387,10 @@ public function get_items( $request ) {
359387
* @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise.
360388
*/
361389
public function get_item_permissions_check( $request ) {
362-
363-
$post = get_post( (int) $request['id'] );
390+
$post = $this->get_post( $request['id'] );
391+
if ( is_wp_error( $post ) ) {
392+
return $post;
393+
}
364394

365395
if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) {
366396
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -428,18 +458,16 @@ public function can_access_password_content( $post, $request ) {
428458
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
429459
*/
430460
public function get_item( $request ) {
431-
$id = (int) $request['id'];
432-
$post = get_post( $id );
433-
434-
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
435-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
461+
$post = $this->get_post( $request['id'] );
462+
if ( is_wp_error( $post ) ) {
463+
return $post;
436464
}
437465

438466
$data = $this->prepare_item_for_response( $post, $request );
439467
$response = rest_ensure_response( $data );
440468

441469
if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) {
442-
$response->link_header( 'alternate', get_permalink( $id ), array( 'type' => 'text/html' ) );
470+
$response->link_header( 'alternate', get_permalink( $post->ID ), array( 'type' => 'text/html' ) );
443471
}
444472

445473
return $response;
@@ -455,6 +483,9 @@ public function get_item( $request ) {
455483
* @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
456484
*/
457485
public function create_item_permissions_check( $request ) {
486+
if ( ! empty( $request['id'] ) ) {
487+
return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
488+
}
458489

459490
$post_type = get_post_type_object( $this->post_type );
460491

@@ -591,8 +622,11 @@ public function create_item( $request ) {
591622
* @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
592623
*/
593624
public function update_item_permissions_check( $request ) {
625+
$post = $this->get_post( $request['id'] );
626+
if ( is_wp_error( $post ) ) {
627+
return $post;
628+
}
594629

595-
$post = get_post( $request['id'] );
596630
$post_type = get_post_type_object( $this->post_type );
597631

598632
if ( $post && ! $this->check_update_permission( $post ) ) {
@@ -624,11 +658,9 @@ public function update_item_permissions_check( $request ) {
624658
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
625659
*/
626660
public function update_item( $request ) {
627-
$id = (int) $request['id'];
628-
$post = get_post( $id );
629-
630-
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
631-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
661+
$valid_check = $this->get_post( $request['id'] );
662+
if ( is_wp_error( $valid_check ) ) {
663+
return $valid_check;
632664
}
633665

634666
$post = $this->prepare_item_for_database( $request );
@@ -714,8 +746,10 @@ public function update_item( $request ) {
714746
* @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
715747
*/
716748
public function delete_item_permissions_check( $request ) {
717-
718-
$post = get_post( $request['id'] );
749+
$post = $this->get_post( $request['id'] );
750+
if ( is_wp_error( $post ) ) {
751+
return $post;
752+
}
719753

720754
if ( $post && ! $this->check_delete_permission( $post ) ) {
721755
return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this post.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -734,15 +768,14 @@ public function delete_item_permissions_check( $request ) {
734768
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
735769
*/
736770
public function delete_item( $request ) {
737-
$id = (int) $request['id'];
738-
$force = (bool) $request['force'];
739-
740-
$post = get_post( $id );
741-
742-
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
743-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
771+
$post = $this->get_post( $request['id'] );
772+
if ( is_wp_error( $post ) ) {
773+
return $post;
744774
}
745775

776+
$id = $post->ID;
777+
$force = (bool) $request['force'];
778+
746779
$supports_trash = ( EMPTY_TRASH_DAYS > 0 );
747780

748781
if ( 'attachment' === $post->post_type ) {
@@ -901,7 +934,12 @@ protected function prepare_item_for_database( $request ) {
901934

902935
// Post ID.
903936
if ( isset( $request['id'] ) ) {
904-
$prepared_post->ID = absint( $request['id'] );
937+
$existing_post = $this->get_post( $request['id'] );
938+
if ( is_wp_error( $existing_post ) ) {
939+
return $existing_post;
940+
}
941+
942+
$prepared_post->ID = $existing_post->ID;
905943
}
906944

907945
$schema = $this->get_item_schema();

0 commit comments

Comments
 (0)