From 6df02a9ce231cb7231a5ff0db4fd72fbf5090a32 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Tue, 26 Jan 2021 18:26:13 +0000 Subject: [PATCH] REST API: Introduce `modified_before` and `modified_after` query parameters for the posts endpoints. These parameters work just the same as `before` and `after` except they operate on the post modified date instead of the post published date. Props claytoncollie, TimothyBlynJacobs, hellofromTonya Fixes #50617 git-svn-id: https://develop.svn.wordpress.org/trunk@50024 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-posts-controller.php | 40 +++++++++++-- .../rest-api/rest-attachments-controller.php | 56 +++++++++++++++++++ .../tests/rest-api/rest-pages-controller.php | 47 ++++++++++++++++ .../tests/rest-api/rest-posts-controller.php | 32 +++++++++++ tests/qunit/fixtures/wp-api-generated.js | 48 ++++++++++++++++ 5 files changed, 219 insertions(+), 4 deletions(-) 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 a0752c2534..dd0269ebf6 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 @@ -216,14 +216,32 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { // Check for & assign any parameters which require special handling or setting. $args['date_query'] = array(); - // Set before into date query. Date query must be specified as an array of an array. if ( isset( $registered['before'], $request['before'] ) ) { - $args['date_query'][0]['before'] = $request['before']; + $args['date_query'][] = array( + 'before' => $request['before'], + 'column' => 'post_date', + ); + } + + if ( isset( $registered['modified_before'], $request['modified_before'] ) ) { + $args['date_query'][] = array( + 'before' => $request['modified_before'], + 'column' => 'post_modified', + ); } - // Set after into date query. Date query must be specified as an array of an array. if ( isset( $registered['after'], $request['after'] ) ) { - $args['date_query'][0]['after'] = $request['after']; + $args['date_query'][] = array( + 'after' => $request['after'], + 'column' => 'post_date', + ); + } + + if ( isset( $registered['modified_after'], $request['modified_after'] ) ) { + $args['date_query'][] = array( + 'after' => $request['modified_after'], + 'column' => 'post_modified', + ); } // Ensure our per_page parameter overrides any provided posts_per_page filter. @@ -2628,6 +2646,8 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { * Retrieves the query params for the posts collection. * * @since 4.7.0 + * @since 5.4.0 The `tax_relation` query parameter was added. + * @since 5.7.0 The `modified_after` and `modified_before` query parameters were added. * * @return array Collection parameters. */ @@ -2642,6 +2662,12 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'format' => 'date-time', ); + $query_params['modified_after'] = array( + 'description' => __( 'Limit response to posts modified after a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + if ( post_type_supports( $this->post_type, 'author' ) ) { $query_params['author'] = array( 'description' => __( 'Limit result set to posts assigned to specific authors.' ), @@ -2667,6 +2693,12 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'format' => 'date-time', ); + $query_params['modified_before'] = array( + 'description' => __( 'Limit response to posts modified before a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.' ), 'type' => 'array', diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index ec560e9c00..2e32bed202 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -198,6 +198,8 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control 'include', 'media_type', 'mime_type', + 'modified_after', + 'modified_before', 'offset', 'order', 'orderby', @@ -566,6 +568,60 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control $this->assertSame( $id2, $data[0]['id'] ); } + /** + * @ticket 50617 + */ + public function test_get_items_invalid_modified_date() { + $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); + $request->set_param( 'modified_after', rand_str() ); + $request->set_param( 'modified_before', rand_str() ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + /** + * @ticket 50617 + */ + public function test_get_items_valid_modified_date() { + $id1 = $this->factory->attachment->create_object( + $this->test_file, + 0, + array( + 'post_date' => '2016-01-01 00:00:00', + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + $id2 = $this->factory->attachment->create_object( + $this->test_file, + 0, + array( + 'post_date' => '2016-01-02 00:00:00', + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + $id3 = $this->factory->attachment->create_object( + $this->test_file, + 0, + array( + 'post_date' => '2016-01-03 00:00:00', + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + $this->update_post_modified( $id1, '2016-01-15 00:00:00' ); + $this->update_post_modified( $id2, '2016-01-16 00:00:00' ); + $this->update_post_modified( $id3, '2016-01-17 00:00:00' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); + $request->set_param( 'modified_after', '2016-01-15T00:00:00Z' ); + $request->set_param( 'modified_before', '2016-01-17T00:00:00Z' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertSame( $id2, $data[0]['id'] ); + } + public function test_get_item() { $attachment_id = $this->factory->attachment->create_object( $this->test_file, diff --git a/tests/phpunit/tests/rest-api/rest-pages-controller.php b/tests/phpunit/tests/rest-api/rest-pages-controller.php index 1180fed889..902272d7a1 100644 --- a/tests/phpunit/tests/rest-api/rest-pages-controller.php +++ b/tests/phpunit/tests/rest-api/rest-pages-controller.php @@ -76,6 +76,8 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te 'exclude', 'include', 'menu_order', + 'modified_after', + 'modified_before', 'offset', 'order', 'orderby', @@ -361,6 +363,51 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertSame( $post2, $data[0]['id'] ); } + /** + * @ticket 50617 + */ + public function test_get_items_invalid_modified_date() { + $request = new WP_REST_Request( 'GET', '/wp/v2/pages' ); + $request->set_param( 'modified_after', rand_str() ); + $request->set_param( 'modified_before', rand_str() ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + /** + * @ticket 50617 + */ + public function test_get_items_valid_modified_date() { + $post1 = $this->factory->post->create( + array( + 'post_date' => '2016-01-01 00:00:00', + 'post_type' => 'page', + ) + ); + $post2 = $this->factory->post->create( + array( + 'post_date' => '2016-01-02 00:00:00', + 'post_type' => 'page', + ) + ); + $post3 = $this->factory->post->create( + array( + 'post_date' => '2016-01-03 00:00:00', + 'post_type' => 'page', + ) + ); + $this->update_post_modified( $post1, '2016-01-15 00:00:00' ); + $this->update_post_modified( $post2, '2016-01-16 00:00:00' ); + $this->update_post_modified( $post3, '2016-01-17 00:00:00' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/pages' ); + $request->set_param( 'modified_after', '2016-01-15T00:00:00Z' ); + $request->set_param( 'modified_before', '2016-01-17T00:00:00Z' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertSame( $post2, $data[0]['id'] ); + } + public function test_get_item() { } diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index d07347f973..f6470f5241 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -181,6 +181,8 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 'context', 'exclude', 'include', + 'modified_after', + 'modified_before', 'offset', 'order', 'orderby', @@ -1490,6 +1492,36 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertSame( $post2, $data[0]['id'] ); } + /** + * @ticket 50617 + */ + public function test_get_items_invalid_modified_date() { + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'modified_after', rand_str() ); + $request->set_param( 'modified_before', rand_str() ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + /** + * @ticket 50617 + */ + public function test_get_items_valid_modified_date() { + $post1 = $this->factory->post->create( array( 'post_date' => '2016-01-01 00:00:00' ) ); + $post2 = $this->factory->post->create( array( 'post_date' => '2016-01-02 00:00:00' ) ); + $post3 = $this->factory->post->create( array( 'post_date' => '2016-01-03 00:00:00' ) ); + $this->update_post_modified( $post1, '2016-01-15 00:00:00' ); + $this->update_post_modified( $post2, '2016-01-16 00:00:00' ); + $this->update_post_modified( $post3, '2016-01-17 00:00:00' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'modified_after', '2016-01-15T00:00:00Z' ); + $request->set_param( 'modified_before', '2016-01-17T00:00:00Z' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertSame( $post2, $data[0]['id'] ); + } + public function test_get_items_all_post_formats() { $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts' ); $response = rest_get_server()->dispatch( $request ); diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 6e705844a4..e9f6b11d9b 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -298,6 +298,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_after": { + "description": "Limit response to posts modified after a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "author": { "description": "Limit result set to posts assigned to specific authors.", "type": "array", @@ -322,6 +328,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_before": { + "description": "Limit response to posts modified before a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "exclude": { "description": "Ensure result set excludes specific IDs.", "type": "array", @@ -1476,6 +1488,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_after": { + "description": "Limit response to posts modified after a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "author": { "description": "Limit result set to posts assigned to specific authors.", "type": "array", @@ -1500,6 +1518,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_before": { + "description": "Limit response to posts modified before a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "exclude": { "description": "Ensure result set excludes specific IDs.", "type": "array", @@ -2539,6 +2563,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_after": { + "description": "Limit response to posts modified after a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "author": { "description": "Limit result set to posts assigned to specific authors.", "type": "array", @@ -2563,6 +2593,12 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_before": { + "description": "Limit response to posts modified before a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "exclude": { "description": "Ensure result set excludes specific IDs.", "type": "array", @@ -3188,12 +3224,24 @@ mockedApiResponse.Schema = { "format": "date-time", "required": false }, + "modified_after": { + "description": "Limit response to posts modified after a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "before": { "description": "Limit response to posts published before a given ISO8601 compliant date.", "type": "string", "format": "date-time", "required": false }, + "modified_before": { + "description": "Limit response to posts modified before a given ISO8601 compliant date.", + "type": "string", + "format": "date-time", + "required": false + }, "exclude": { "description": "Ensure result set excludes specific IDs.", "type": "array",