From baf52c815a7bb4725bc47c5e0915dbd0b3b08276 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Thu, 3 Nov 2016 02:17:39 +0000 Subject: [PATCH] REST API: Clean-up our validation callbacks and add missing array `items` properties in our endpoint schemas. Props joehoyle, jnylen0. Fixes #38617. git-svn-id: https://develop.svn.wordpress.org/trunk@39105 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-attachments-controller.php | 1 - .../class-wp-rest-comments-controller.php | 51 ++++----- .../class-wp-rest-posts-controller.php | 60 +++++----- .../class-wp-rest-taxonomies-controller.php | 1 - .../class-wp-rest-terms-controller.php | 20 +--- .../class-wp-rest-users-controller.php | 22 ++-- .../rest-api/rest-categories-controller.php | 9 ++ .../rest-api/rest-comments-controller.php | 108 ++++++++++++++++++ .../tests/rest-api/rest-pages-controller.php | 13 +++ .../tests/rest-api/rest-posts-controller.php | 45 +++++++- .../tests/rest-api/rest-tags-controller.php | 26 +++++ .../tests/rest-api/rest-users-controller.php | 27 +++++ 12 files changed, 294 insertions(+), 89 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index 42187df05b..9d8e7d438f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -594,7 +594,6 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 'description' => __( 'Limit result set to attachments of a particular media type.' ), 'type' => 'string', 'enum' => array_keys( $media_types ), - 'validate_callback' => 'rest_validate_request_arg', ); $params['mime_type'] = array( diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index bfd652db4b..b0a8bd790d 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -1114,9 +1114,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { 'type' => 'string', 'format' => 'ipv4', 'context' => array( 'edit' ), - 'arg_options' => array( - 'default' => '127.0.0.1', - ), + 'default' => '127.0.0.1', ), 'author_name' => array( 'description' => __( 'Display name for the object author.' ), @@ -1188,17 +1186,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { 'description' => __( 'The id for the parent of the object.' ), 'type' => 'integer', 'context' => array( 'view', 'edit', 'embed' ), - 'arg_options' => array( - 'default' => 0, - ), + 'default' => 0, ), 'post' => array( 'description' => __( 'The id of the associated post object.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), - 'arg_options' => array( - 'default' => 0, - ), + 'default' => 0, ), 'status' => array( 'description' => __( 'State of the object.' ), @@ -1264,26 +1258,28 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['author'] = array( 'description' => __( 'Limit result set to comments assigned to specific user ids. Requires authorization.' ), - 'sanitize_callback' => 'wp_parse_id_list', 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), ); $query_params['author_exclude'] = array( 'description' => __( 'Ensure result set excludes comments assigned to specific user ids. Requires authorization.' ), - 'sanitize_callback' => 'wp_parse_id_list', 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), ); $query_params['author_email'] = array( 'default' => null, 'description' => __( 'Limit result set to that from a specific author email. Requires authorization.' ), 'format' => 'email', - 'sanitize_callback' => 'sanitize_email', 'type' => 'string', ); @@ -1291,43 +1287,40 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $query_params['karma'] = array( 'default' => null, 'description' => __( 'Limit result set to that of a particular comment karma. Requires authorization.' ), - 'sanitize_callback' => 'absint', 'type' => 'integer', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of comments.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['order'] = array( 'description' => __( 'Order sort attribute ascending or descending.' ), 'type' => 'string', - 'sanitize_callback' => 'sanitize_key', - 'validate_callback' => 'rest_validate_request_arg', 'default' => 'desc', 'enum' => array( 'asc', @@ -1338,8 +1331,6 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { $query_params['orderby'] = array( 'description' => __( 'Sort collection by object attribute.' ), 'type' => 'string', - 'sanitize_callback' => 'sanitize_key', - 'validate_callback' => 'rest_validate_request_arg', 'default' => 'date_gmt', 'enum' => array( 'date', @@ -1355,22 +1346,28 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { $query_params['parent'] = array( 'default' => array(), 'description' => __( 'Limit result set to resources of specific parent ids.' ), - 'sanitize_callback' => 'wp_parse_id_list', 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), ); $query_params['parent_exclude'] = array( 'default' => array(), 'description' => __( 'Ensure result set excludes specific parent ids.' ), - 'sanitize_callback' => 'wp_parse_id_list', 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), ); $query_params['post'] = array( 'default' => array(), 'description' => __( 'Limit result set to resources assigned to specific post ids.' ), 'type' => 'array', - 'sanitize_callback' => 'wp_parse_id_list', + 'items' => array( + 'type' => 'integer', + ), ); $query_params['status'] = array( diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index 2eed29b69f..0afc6061b6 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -1975,20 +1975,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'items' => array( 'type' => 'integer', ), - 'arg_options' => array( - 'sanitize_callback' => 'wp_parse_id_list', - ), - 'context' => array( 'view', 'edit' ), - ); - $schema['properties'][ $base . '_exclude' ] = array( - 'description' => sprintf( __( 'The terms in the %s taxonomy that should not be assigned to the object.' ), $taxonomy->name ), - 'type' => 'array', - 'items' => array( - 'type' => 'integer', - ), - 'arg_options' => array( - 'sanitize_callback' => 'wp_parse_id_list', - ), 'context' => array( 'view', 'edit' ), ); } @@ -2013,21 +1999,24 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', - 'validate_callback' => 'rest_validate_request_arg', ); if ( post_type_supports( $this->post_type, 'author' ) ) { $params['author'] = array( 'description' => __( 'Limit result set to posts assigned to specific authors.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $params['author_exclude'] = array( 'description' => __( 'Ensure result set excludes posts assigned to specific authors.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); } @@ -2035,37 +2024,36 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', - 'validate_callback' => 'rest_validate_request_arg', ); $params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $params['include'] = array( 'description' => __( 'Limit result set to specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { $params['menu_order'] = array( 'description' => __( 'Limit result set to resources with a specific menu_order value.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); } $params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); $params['order'] = array( @@ -2073,7 +2061,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'type' => 'string', 'default' => 'desc', 'enum' => array( 'asc', 'desc' ), - 'validate_callback' => 'rest_validate_request_arg', ); $params['orderby'] = array( @@ -2088,7 +2075,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'title', 'slug', ), - 'validate_callback' => 'rest_validate_request_arg', ); if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { @@ -2101,13 +2087,17 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { $params['parent'] = array( 'description' => __( 'Limit result set to those of particular parent ids.' ), 'type' => 'array', - 'sanitize_callback' => 'wp_parse_id_list', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), ); $params['parent_exclude'] = array( 'description' => __( 'Limit result set to all items except those of a particular parent id.' ), 'type' => 'array', - 'sanitize_callback' => 'wp_parse_id_list', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), ); } @@ -2137,7 +2127,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { $params[ $base ] = array( 'description' => sprintf( __( 'Limit result set to all items that have the specified term assigned in the %s taxonomy.' ), $base ), 'type' => 'array', - 'sanitize_callback' => 'wp_parse_id_list', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + + $params[ $base . '_exclude' ] = array( + 'description' => sprintf( __( 'Limit result set to all items except those that have the specified term assigned in the %s taxonomy.' ), $base ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), ); } @@ -2146,7 +2147,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { $params['sticky'] = array( 'description' => __( 'Limit result set to items that are sticky.' ), 'type' => 'boolean', - 'sanitize_callback' => 'rest_parse_request_arg', ); } diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php index 5ae26212df..053bff537b 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php @@ -304,7 +304,6 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller { $new_params['type'] = array( 'description' => __( 'Limit results to resources associated with a specific post type.' ), 'type' => 'string', - 'validate_callback' => 'rest_validate_request_arg', ); return $new_params; } diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php index ceaa26bee7..c9f9f910a8 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php @@ -887,42 +887,41 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); if ( ! $taxonomy->hierarchical ) { $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); } $query_params['order'] = array( 'description' => __( 'Order sort attribute ascending or descending.' ), 'type' => 'string', - 'sanitize_callback' => 'sanitize_key', 'default' => 'asc', 'enum' => array( 'asc', 'desc', ), - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['orderby'] = array( 'description' => __( 'Sort collection by resource attribute.' ), 'type' => 'string', - 'sanitize_callback' => 'sanitize_key', 'default' => 'name', 'enum' => array( 'id', @@ -933,23 +932,18 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { 'description', 'count', ), - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['hide_empty'] = array( 'description' => __( 'Whether to hide resources not assigned to any posts.' ), 'type' => 'boolean', 'default' => false, - 'sanitize_callback' => 'rest_sanitize_request_arg', - 'validate_callback' => 'rest_validate_request_arg', ); if ( $taxonomy->hierarchical ) { $query_params['parent'] = array( 'description' => __( 'Limit result set to resources assigned to a specific parent.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); } @@ -957,13 +951,11 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { 'description' => __( 'Limit result set to resources assigned to a specific post.' ), 'type' => 'integer', 'default' => null, - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['slug'] = array( 'description' => __( 'Limit result set to resources with a specific slug.' ), 'type' => 'string', - 'validate_callback' => 'rest_validate_request_arg', ); return $query_params; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php index bb3737df0c..1256c6810d 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php @@ -1102,9 +1102,6 @@ class WP_REST_Users_Controller extends WP_REST_Controller { 'type' => 'string', ), 'context' => array( 'edit' ), - 'arg_options' => array( - 'sanitize_callback' => 'wp_parse_slug_list', - ), ), 'password' => array( 'description' => __( 'Password for the resource (never included).' ), @@ -1171,31 +1168,31 @@ class WP_REST_Users_Controller extends WP_REST_Controller { $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific ids.' ), 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), 'default' => array(), - 'sanitize_callback' => 'wp_parse_id_list', ); $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['order'] = array( 'default' => 'asc', 'description' => __( 'Order sort attribute ascending or descending.' ), 'enum' => array( 'asc', 'desc' ), - 'sanitize_callback' => 'sanitize_key', 'type' => 'string', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['orderby'] = array( @@ -1210,21 +1207,20 @@ class WP_REST_Users_Controller extends WP_REST_Controller { 'email', 'url', ), - 'sanitize_callback' => 'sanitize_key', 'type' => 'string', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['slug'] = array( 'description' => __( 'Limit result set to resources with a specific slug.' ), 'type' => 'string', - 'validate_callback' => 'rest_validate_request_arg', ); $query_params['roles'] = array( 'description' => __( 'Limit result set to resources matching at least one specific role provided. Accepts csv list or single role.' ), 'type' => 'array', - 'sanitize_callback' => 'wp_parse_slug_list', + 'items' => array( + 'type' => 'string', + ), ); return $query_params; diff --git a/tests/phpunit/tests/rest-api/rest-categories-controller.php b/tests/phpunit/tests/rest-api/rest-categories-controller.php index 440cb45967..4212f5f708 100644 --- a/tests/phpunit/tests/rest-api/rest-categories-controller.php +++ b/tests/phpunit/tests/rest-api/rest-categories-controller.php @@ -428,6 +428,15 @@ class WP_Test_REST_Categories_Controller extends WP_Test_REST_Controller_Testcas $this->assertEquals( 'Child', $data[0]['name'] ); } + public function test_get_terms_invalid_parent_arg() { + $category1 = $this->factory->category->create( array( 'name' => 'Parent' ) ); + $this->factory->category->create( array( 'name' => 'Child', 'parent' => $category1 ) ); + $request = new WP_REST_Request( 'GET', '/wp/v2/categories' ); + $request->set_param( 'parent', 'invalid-parent' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + public function test_get_terms_private_taxonomy() { register_taxonomy( 'robin', 'post', array( 'public' => false ) ); $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) ); diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 9372581f95..0775073fb7 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -300,6 +300,15 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( $id3, $data[0]['id'] ); + // Orderby=>invalid should fail. + $request->set_param( 'orderby', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + // fails on invalid id. + $request->set_param( 'orderby', array( 'include' ) ); + $request->set_param( 'include', array( 'invalid' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_exclude_query() { @@ -320,6 +329,11 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $data = $response->get_data(); $this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) ); $this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) ); + + // fails on invalid id. + $request->set_param( 'exclude', array( 'invalid' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_offset_query() { @@ -343,6 +357,10 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $request->set_param( 'page', 3 ); $response = $this->server->dispatch( $request ); $this->assertCount( 2, $response->get_data() ); + // 'offset' with invalid value errors. + $request->set_param( 'offset', 'moreplease' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_order_query() { @@ -364,6 +382,10 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $response = $this->server->dispatch( $request ); $data = $response->get_data(); $this->assertEquals( self::$approved_id, $data[0]['id'] ); + // order=>asc,id should fail + $request->set_param( 'order', 'asc,id' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_private_post_no_permissions() { @@ -402,8 +424,13 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $this->assertEquals( 200, $response->get_status() ); $comments = $response->get_data(); $this->assertCount( 2, $comments ); + // Invalid author param errors + $request->set_param( 'author', 'skippy' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); // Unavailable to unauthenticated; defaults to error wp_set_current_user( 0 ); + $request->set_param( 'author', array( self::$author_id, self::$subscriber_id ) ); $response = $this->server->dispatch( $request ); $this->assertErrorResponse( 'rest_forbidden_param', $response, 401 ); } @@ -441,8 +468,14 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $this->assertEquals( 200, $response->get_status() ); $comments = $response->get_data(); $this->assertCount( 2, $comments ); + // 'author_exclude' for both invalid author + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); + $request->set_param( 'author_exclude', 'skippy' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); // Unavailable to unauthenticated; defaults to error wp_set_current_user( 0 ); + $request->set_param( 'author_exclude', array( self::$author_id, self::$subscriber_id ) ); $response = $this->server->dispatch( $request ); $this->assertErrorResponse( 'rest_forbidden_param', $response, 401 ); } @@ -470,6 +503,10 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $request->set_param( 'parent', array( $parent_id, $parent_id2 ) ); $response = $this->server->dispatch( $request ); $this->assertCount( 2, $response->get_data() ); + // Invalid parent should error + $request->set_param( 'parent', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_parent_exclude_arg() { @@ -495,6 +532,10 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $request->set_param( 'parent_exclude', array( $parent_id, $parent_id2 ) ); $response = $this->server->dispatch( $request ); $this->assertCount( 3, $response->get_data() ); + // Invalid parent id should error + $request->set_param( 'parent_exclude', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_search_query() { @@ -957,6 +998,28 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $this->assertEquals( $comment_id, $collection_data[0]['id'] ); } + public function test_create_comment_invalid_email() { + $post_id = $this->factory->post->create(); + wp_set_current_user( self::$admin_id ); + + $params = array( + 'post' => $post_id, + 'author' => self::$admin_id, + 'author_name' => 'Comic Book Guy', + 'author_email' => 'hello:)', + 'author_url' => 'http://androidsdungeon.com', + 'content' => 'Worst Comment Ever!', + 'date' => '2014-11-07T10:14:25', + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); + $request->add_header( 'content-type', 'application/json' ); + $request->set_body( wp_json_encode( $params ) ); + + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + public function test_create_item_current_user() { $user_id = $this->factory->user->create( array( 'role' => 'subscriber', @@ -1057,6 +1120,47 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $this->assertErrorResponse( 'rest_comment_invalid_karma', $response, 403 ); } + public function test_create_comment_invalid_post() { + wp_set_current_user( self::$subscriber_id ); + + $params = array( + 'post' => 'some-slug', + 'author_name' => 'Homer Jay Simpson', + 'author_email' => 'chunkylover53@aol.com', + 'author_url' => 'http://compuglobalhypermeganet.com', + 'content' => 'Here\’s to alcohol: the cause of, and solution to, all of life\’s problems.', + 'author' => self::$subscriber_id, + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); + $request->add_header( 'content-type', 'application/json' ); + $request->set_body( wp_json_encode( $params ) ); + $response = $this->server->dispatch( $request ); + + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + public function test_create_comment_karma_invalid_value() { + wp_set_current_user( self::$subscriber_id ); + + $params = array( + 'post' => self::$post_id, + 'author_name' => 'Homer Jay Simpson', + 'author_email' => 'chunkylover53@aol.com', + 'author_url' => 'http://compuglobalhypermeganet.com', + 'content' => 'Here\’s to alcohol: the cause of, and solution to, all of life\’s problems.', + 'author' => self::$subscriber_id, + 'karma' => 'themostkarmaever', + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); + $request->add_header( 'content-type', 'application/json' ); + $request->set_body( wp_json_encode( $params ) ); + $response = $this->server->dispatch( $request ); + + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + public function test_create_comment_status_without_permission() { wp_set_current_user( self::$subscriber_id ); @@ -1893,6 +1997,10 @@ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase $this->assertArrayHasKey( 'post', $properties ); $this->assertArrayHasKey( 'status', $properties ); $this->assertArrayHasKey( 'type', $properties ); + + $this->assertEquals( '127.0.0.1', $properties['author_ip']['default'] ); + $this->assertEquals( 0, $properties['parent']['default'] ); + $this->assertEquals( 0, $properties['post']['default'] ); } public function test_get_item_schema_show_avatar() { diff --git a/tests/phpunit/tests/rest-api/rest-pages-controller.php b/tests/phpunit/tests/rest-api/rest-pages-controller.php index 2ce9afe394..a571803d12 100644 --- a/tests/phpunit/tests/rest-api/rest-pages-controller.php +++ b/tests/phpunit/tests/rest-api/rest-pages-controller.php @@ -95,6 +95,10 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te $data = $response->get_data(); $this->assertEquals( 1, count( $data ) ); $this->assertEquals( $id2, $data[0]['id'] ); + // Invalid parent should fail + $request->set_param( 'parent', 'some-slug' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_parents_query() { @@ -129,6 +133,10 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te $data = $response->get_data(); $this->assertEquals( 1, count( $data ) ); $this->assertEquals( $id1, $data[0]['id'] ); + // Invalid parent_exclude should error + $request->set_param( 'parent_exclude', 'some-slug' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_menu_order_query() { @@ -156,6 +164,11 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertEquals( $id4, $data[1]['id'] ); $this->assertEquals( $id2, $data[2]['id'] ); $this->assertEquals( $id3, $data[3]['id'] ); + // Invalid menu_order should fail + $request = new WP_REST_Request( 'GET', '/wp/v2/pages' ); + $request->set_param( 'menu_order', 'top-first' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_min_max_pages_query() { diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index 9b7206ffcb..078f7aa57f 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -92,6 +92,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 'author_exclude', 'before', 'categories', + 'categories_exclude', 'context', 'exclude', 'include', @@ -105,6 +106,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 'status', 'sticky', 'tags', + 'tags_exclude', ), $keys ); } @@ -183,6 +185,11 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertEquals( 2, count( $data ) ); $this->assertNotEquals( self::$editor_id, $data[0]['author'] ); $this->assertNotEquals( self::$editor_id, $data[1]['author'] ); + // invalid author_exclude errors + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'author_exclude', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_include_query() { @@ -202,6 +209,11 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( $id1, $data[0]['id'] ); + // Invalid include should error + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'include', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_exclude_query() { @@ -224,6 +236,10 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $data = $response->get_data(); $this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) ); $this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) ); + + $request->set_param( 'exclude', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_search_query() { @@ -406,6 +422,15 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $response = $this->server->dispatch( $request ); $data = $response->get_data(); $this->assertEquals( 'Apple Cobbler', $data[0]['title']['rendered'] ); + // order=>asc,id should fail + $request->set_param( 'order', 'asc,id' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + // orderby=>content should fail (invalid param test) + $request->set_param( 'order', 'asc' ); + $request->set_param( 'orderby', 'content' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_with_orderby_relevance() { @@ -456,6 +481,10 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $request->set_param( 'page', 3 ); $response = $this->server->dispatch( $request ); $this->assertCount( 2, $response->get_data() ); + // Invalid 'offset' should error + $request->set_param( 'offset', 'moreplease' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_tags_query() { @@ -512,6 +541,10 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $response = $this->server->dispatch( $request ); $this->assertCount( 1, $response->get_data() ); + + $request->set_param( 'tags', array( 'my-tag' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_tags_and_categories_exclude_query() { @@ -534,6 +567,10 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $data = $response->get_data(); $this->assertCount( 1, $data ); $this->assertEquals( $id2, $data[0]['id'] ); + + $request->set_param( 'tags_exclude', array( 'my-tag' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_sticky_query() { @@ -551,6 +588,10 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $posts = $response->get_data(); $post = $posts[0]; $this->assertEquals( $id2, $post['id'] ); + + $request->set_param( 'sticky', 'nothanks' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_sticky_with_post__in_query() { @@ -1989,7 +2030,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $response = $this->server->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertEquals( 25, count( $properties ) ); + $this->assertEquals( 23, count( $properties ) ); $this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'comment_status', $properties ); $this->assertArrayHasKey( 'content', $properties ); @@ -2012,9 +2053,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertArrayHasKey( 'title', $properties ); $this->assertArrayHasKey( 'type', $properties ); $this->assertArrayHasKey( 'tags', $properties ); - $this->assertArrayHasKey( 'tags_exclude', $properties ); $this->assertArrayHasKey( 'categories', $properties ); - $this->assertArrayHasKey( 'categories_exclude', $properties ); } public function test_status_array_enum_args() { diff --git a/tests/phpunit/tests/rest-api/rest-tags-controller.php b/tests/phpunit/tests/rest-api/rest-tags-controller.php index 0bdae855ae..568b15addf 100644 --- a/tests/phpunit/tests/rest-api/rest-tags-controller.php +++ b/tests/phpunit/tests/rest-api/rest-tags-controller.php @@ -98,6 +98,10 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $this->assertEquals( 2, count( $data ) ); $this->assertEquals( 'Season 5', $data[0]['name'] ); $this->assertEquals( 'The Be Sharps', $data[1]['name'] ); + // invalid value should fail + $request->set_param( 'hide_empty', 'nothanks' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_include_query() { @@ -117,6 +121,10 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( $id3, $data[0]['id'] ); + // Include invalid value shoud fail + $request->set_param( 'include', array( 'myterm' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_exclude_query() { @@ -132,6 +140,10 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) ); $this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) ); + // Invalid exclude value should fail + $request->set_param( 'exclude', array( 'invalid' ) ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_offset_query() { @@ -151,6 +163,10 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $request->set_param( 'page', 3 ); $response = $this->server->dispatch( $request ); $this->assertCount( 2, $response->get_data() ); + // 'offset' invalid value shoudl fail + $request->set_param( 'offset', 'moreplease' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } @@ -181,6 +197,10 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( 'Apple', $data[0]['name'] ); + // Invalid orderby should fail. + $request->set_param( 'orderby', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_orderby_id() { @@ -231,6 +251,12 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( 'DC', $data[0]['name'] ); + + // Invalid post should error. + $request = new WP_REST_Request( 'GET', '/wp/v2/tags' ); + $request->set_param( 'post', 'invalid-post' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_terms_post_args_paging() { diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php index 4f89ac2180..7dd254052e 100644 --- a/tests/phpunit/tests/rest-api/rest-users-controller.php +++ b/tests/phpunit/tests/rest-api/rest-users-controller.php @@ -363,6 +363,20 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $this->assertErrorResponse( 'rest_forbidden_orderby', $response, 401 ); } + public function test_get_items_invalid_order() { + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'order', 'asc,id' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + public function test_get_items_invalid_orderby() { + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'orderby', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + public function test_get_items_offset() { wp_set_current_user( self::$user ); // 2 users created in __construct(), plus default user @@ -379,6 +393,10 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $request->set_param( 'page', 3 ); $response = $this->server->dispatch( $request ); $this->assertCount( 2, $response->get_data() ); + // 'offset' invalid value should error + $request->set_param( 'offset', 'moreplease' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_include_query() { @@ -399,7 +417,12 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertEquals( 2, count( $data ) ); $this->assertEquals( $id3, $data[0]['id'] ); + // Invalid include should fail + $request->set_param( 'include', 'invalid' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); // No privileges + $request->set_param( 'include', array( $id3, $id1 ) ); wp_set_current_user( 0 ); $response = $this->server->dispatch( $request ); $data = $response->get_data(); @@ -421,6 +444,10 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $data = $response->get_data(); $this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) ); $this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) ); + // Invalid exlude value should error. + $request->set_param( 'exclude', 'none-of-those-please' ); + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_get_items_search() {