From d2630e00cd6f2300bcd9f161051c255b1c60b3bb Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 15 Jan 2025 18:34:35 +0000 Subject: [PATCH] REST API: Fix PHP warning about undefined `paged` argument in various REST API endpoints. This bug could occur in `WP_REST_Posts_Controller`, `WP_REST_Global_Styles_Revisions_Controller`, `WP_REST_Revisions_Controller`, and any of their child classes. This changeset fixes it throughout. Props apermo, pbearne, hemant-ahir, flixos90. Fixes #62292. git-svn-id: https://develop.svn.wordpress.org/trunk@59630 602fd350-edb4-49c9-b593-d223f7449a82 --- ...est-global-styles-revisions-controller.php | 2 +- .../class-wp-rest-posts-controller.php | 2 +- .../class-wp-rest-revisions-controller.php | 2 +- ...est-global-styles-revisions-controller.php | 41 +++++++++++++++++++ .../tests/rest-api/rest-posts-controller.php | 39 ++++++++++++++++++ .../rest-api/rest-revisions-controller.php | 40 ++++++++++++++++++ .../wpRestTemplateRevisionsController.php | 40 ++++++++++++++++++ 7 files changed, 163 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php index 54285fa560..4108f9711c 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php @@ -189,7 +189,7 @@ class WP_REST_Global_Styles_Revisions_Controller extends WP_REST_Revisions_Contr $revisions_query = new WP_Query(); $revisions = $revisions_query->query( $query_args ); $offset = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0; - $page = (int) $query_args['paged']; + $page = isset( $query_args['paged'] ) ? (int) $query_args['paged'] : 0; $total_revisions = $revisions_query->found_posts; if ( $total_revisions < 1 ) { 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 95851199c6..6f872be3df 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 @@ -457,7 +457,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { remove_filter( 'post_password_required', array( $this, 'check_password_required' ) ); } - $page = (int) $query_args['paged']; + $page = isset( $query_args['paged'] ) ? (int) $query_args['paged'] : 0; $total_posts = $posts_query->found_posts; if ( $total_posts < 1 && $page > 1 ) { diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php index fb5fa29231..1dbc611631 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php @@ -294,7 +294,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller { $revisions_query = new WP_Query(); $revisions = $revisions_query->query( $query_args ); $offset = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0; - $page = (int) $query_args['paged']; + $page = isset( $query_args['paged'] ) ? (int) $query_args['paged'] : 0; $total_revisions = $revisions_query->found_posts; if ( $total_revisions < 1 ) { diff --git a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php index b01ada9be2..5fd97a7a71 100644 --- a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php +++ b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php @@ -826,6 +826,47 @@ class WP_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Contr $this->assertCount( $expected_count, $response->get_data() ); } + + /** + * Tests for the pagination. + * + * @ticket 62292 + * + * @covers WP_REST_Global_Styles_Controller::get_items + */ + public function test_get_global_styles_revisions_pagination() { + wp_set_current_user( self::$admin_id ); + + // Test offset + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' ); + $request->set_param( 'offset', 1 ); + $request->set_param( 'per_page', 1 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( 3, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 3, $response->get_headers()['X-WP-TotalPages'] ); + + // Test paged + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' ); + $request->set_param( 'page', 2 ); + $request->set_param( 'per_page', 2 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( 3, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 2, $response->get_headers()['X-WP-TotalPages'] ); + + // Test out of bounds + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' ); + $request->set_param( 'page', 4 ); + $request->set_param( 'per_page', 6 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_revision_invalid_page_number', $response, 400 ); + } + /** * @doesNotPerformAssertions */ diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index e2fd7139f3..a1b8de0474 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -5676,6 +5676,45 @@ Shankle pork chop prosciutto ribeye ham hock pastrami. T-bone shank brisket baco $this->assertCount( 2, $response->get_data(), 'Two posts are expected to be returned' ); } + /** + * Tests for the pagination. + * + * @ticket 62292 + * + * @covers WP_REST_Posts_Controller::get_items + */ + public function test_get_posts_with_pagination() { + + // Test offset + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'offset', 1 ); + $request->set_param( 'per_page', 1 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( 30, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 30, $response->get_headers()['X-WP-TotalPages'] ); + + // Test paged + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'page', 2 ); + $request->set_param( 'per_page', 2 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 2, $data ); + $this->assertEquals( 30, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 15, $response->get_headers()['X-WP-TotalPages'] ); + + // Test out of bounds + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'page', 4 ); + $request->set_param( 'per_page', 10 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_post_invalid_page_number', $response, 400 ); + } + /** * Internal function used to disable an insert query which * will trigger a wpdb error for testing purposes. diff --git a/tests/phpunit/tests/rest-api/rest-revisions-controller.php b/tests/phpunit/tests/rest-api/rest-revisions-controller.php index d2650d31fa..cdb886c4e4 100644 --- a/tests/phpunit/tests/rest-api/rest-revisions-controller.php +++ b/tests/phpunit/tests/rest-api/rest-revisions-controller.php @@ -864,4 +864,44 @@ class WP_Test_REST_Revisions_Controller extends WP_Test_REST_Controller_Testcase $response = rest_get_server()->dispatch( $request ); $this->assertCount( $expected_count, $response->get_data() ); } + + /** + * Tests for the pagination. + * + * @ticket 62292 + * + * @covers WP_REST_Revisions_Controller::get_items + */ + public function test_get_template_revisions_pagination() { + wp_set_current_user( self::$editor_id ); + + // Test offset + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' ); + $request->set_param( 'offset', 1 ); + $request->set_param( 'per_page', 1 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( $this->total_revisions, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( $this->total_revisions, $response->get_headers()['X-WP-TotalPages'] ); + + // Test paged + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' ); + $request->set_param( 'page', 2 ); + $request->set_param( 'per_page', 2 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( $this->total_revisions, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( (int) ceil( $this->total_revisions / 2 ), $response->get_headers()['X-WP-TotalPages'] ); + + // Test out of bounds + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' ); + $request->set_param( 'page', $this->total_revisions + 1 ); + $request->set_param( 'per_page', 1 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_revision_invalid_page_number', $response, 400 ); + } } diff --git a/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php b/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php index 2391a92478..23352879f3 100644 --- a/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php +++ b/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php @@ -1065,4 +1065,44 @@ class Tests_REST_wpRestTemplateRevisionsController extends WP_Test_REST_Controll ), ); } + + /** + * Tests for the pagination. + * + * @ticket 62292 + * + * @covers WP_REST_Template_Revisions_Controller::get_items + */ + public function test_get_template_revisions_pagination() { + wp_set_current_user( self::$admin_id ); + + // Test offset + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/revisions' ); + $request->set_param( 'offset', 1 ); + $request->set_param( 'per_page', 1 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertEquals( 4, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 4, $response->get_headers()['X-WP-TotalPages'] ); + + // Test paged + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/revisions' ); + $request->set_param( 'page', 2 ); + $request->set_param( 'per_page', 2 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertCount( 2, $data ); + $this->assertEquals( 4, $response->get_headers()['X-WP-Total'] ); + $this->assertEquals( 2, $response->get_headers()['X-WP-TotalPages'] ); + + // Test out of bounds + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/revisions' ); + $request->set_param( 'page', 4 ); + $request->set_param( 'per_page', 6 ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_revision_invalid_page_number', $response, 400 ); + } }