From 68c3484694b1f31a1788b85c2285653b872c334f Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Mon, 5 Aug 2024 16:22:26 -0400 Subject: [PATCH 1/9] Try setting targetHints automatically. --- .../rest-api/class-wp-rest-server.php | 28 +++++- tests/qunit/fixtures/wp-api-generated.js | 87 +++++++++++++++++-- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 0eedb0396bcc4..849011d86afa2 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -628,6 +628,8 @@ public static function get_response_links( $response ) { return array(); } + $server = rest_get_server(); + // Convert links to part of the data. $data = array(); foreach ( $links as $rel => $items ) { @@ -636,7 +638,31 @@ public static function get_response_links( $response ) { foreach ( $items as $item ) { $attributes = $item['attributes']; $attributes['href'] = $item['href']; - $data[ $rel ][] = $attributes; + + if ( 'self' === $rel ) { + $request = WP_REST_Request::from_url( $item['href'] ); + $match = $server->match_request_to_handler( $request ); + + if ( ! is_wp_error( $match ) ) { + $response = new WP_REST_Response(); + $response->set_matched_route( $match[0] ); + $response->set_matched_handler( $match[1] ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + + // Prefer targetHints that were specifically designated by the developer. + if ( isset( $attributes['targetHints'][ $name ] ) ) { + continue; + } + + $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); + } + } + } + + $data[ $rel ][] = $attributes; } } diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 7e97f19b18588..b3917a35eee93 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -12334,7 +12334,16 @@ mockedApiResponse.PostsCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/posts/4" + "href": "http://example.org/index.php?rest_route=/wp/v2/posts/4", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -12641,7 +12650,16 @@ mockedApiResponse.PagesCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/pages/7" + "href": "http://example.org/index.php?rest_route=/wp/v2/pages/7", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -12932,7 +12950,16 @@ mockedApiResponse.MediaCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/media/10" + "href": "http://example.org/index.php?rest_route=/wp/v2/media/10", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -13629,7 +13656,15 @@ mockedApiResponse.CategoriesCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/categories/1" + "href": "http://example.org/index.php?rest_route=/wp/v2/categories/1", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH" + ] + } } ], "collection": [ @@ -13694,7 +13729,16 @@ mockedApiResponse.TagsCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/tags/2" + "href": "http://example.org/index.php?rest_route=/wp/v2/tags/2", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -13758,7 +13802,16 @@ mockedApiResponse.UsersCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/users/1" + "href": "http://example.org/index.php?rest_route=/wp/v2/users/1", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -13786,7 +13839,16 @@ mockedApiResponse.UsersCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/users/2" + "href": "http://example.org/index.php?rest_route=/wp/v2/users/2", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ @@ -13859,7 +13921,16 @@ mockedApiResponse.CommentsCollection = [ "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/comments/2" + "href": "http://example.org/index.php?rest_route=/wp/v2/comments/2", + "targetHints": { + "allow": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ] + } } ], "collection": [ From 5fa7cd691ee304f21263896d5c1f8670ed54e9f0 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Mon, 2 Sep 2024 14:30:03 -0400 Subject: [PATCH 2/9] refresh with changes from GB --- .../rest-api/class-wp-rest-server.php | 40 ++++++----- tests/phpunit/tests/rest-api/rest-server.php | 66 +++++++++++++++++++ 2 files changed, 90 insertions(+), 16 deletions(-) diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 849011d86afa2..f92bfc674feb0 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -639,26 +639,34 @@ public static function get_response_links( $response ) { $attributes = $item['attributes']; $attributes['href'] = $item['href']; - if ( 'self' === $rel ) { - $request = WP_REST_Request::from_url( $item['href'] ); - $match = $server->match_request_to_handler( $request ); + if ( 'self' !== $rel ) { + $data[ $rel ][] = $attributes; + continue; + } - if ( ! is_wp_error( $match ) ) { - $response = new WP_REST_Response(); - $response->set_matched_route( $match[0] ); - $response->set_matched_handler( $match[1] ); - $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + // Prefer targetHints that were specifically designated by the developer. + if ( isset( $attributes['targetHints']['allow'] ) ) { + $data[ $rel ][] = $attributes; + continue; + } - foreach ( $headers as $name => $value ) { - $name = WP_REST_Request::canonicalize_header_name( $name ); + $request = WP_REST_Request::from_url( $item['href'] ); + if ( ! $request ) { + $data[ $rel ][] = $attributes; + continue; + } - // Prefer targetHints that were specifically designated by the developer. - if ( isset( $attributes['targetHints'][ $name ] ) ) { - continue; - } + $match = $server->match_request_to_handler( $request ); + if ( ! is_wp_error( $match ) ) { + $response = new WP_REST_Response(); + $response->set_matched_route( $match[0] ); + $response->set_matched_handler( $match[1] ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); - $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); - } + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + + $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); } } diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 7bcc6d68e7497..7c5b164cb034e 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -9,6 +9,8 @@ */ class Tests_REST_Server extends WP_Test_REST_TestCase { protected static $icon_id; + protected static $admin_id; + protected static $post_id; /** * Called before setting up all tests. @@ -23,10 +25,18 @@ public static function set_up_before_class() { public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { $filename = DIR_TESTDATA . '/images/test-image-large.jpg'; self::$icon_id = $factory->attachment->create_upload_object( $filename ); + self::$admin_id = $factory->user->create( + array( + 'role' => 'administrator', + ) + ); + self::$post_id = $factory->post->create(); } public static function tear_down_after_class() { wp_delete_attachment( self::$icon_id, true ); + self::delete_user( self::$admin_id ); + wp_delete_post( self::$post_id ); parent::tear_down_after_class(); } @@ -2431,6 +2441,62 @@ public function test_rest_allowed_cors_headers_filter_receives_request_object() $this->assertSame( '/test-allowed-cors-headers', $mock_hook->get_events()[0]['args'][1]->get_route() ); } + public function test_populates_target_hints_for_administrator() { + wp_set_current_user( self::$admin_id ); + $response = rest_do_request( '/wp/v2/posts' ); + $post = $response->get_data()[0]; + + $link = $post['_links']['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET', 'POST', 'PUT', 'PATCH', 'DELETE' ), $link['targetHints']['allow'] ); + } + + public function test_populates_target_hints_for_logged_out_user() { + $response = rest_do_request( '/wp/v2/posts' ); + $post = $response->get_data()[0]; + + $link = $post['_links']['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET' ), $link['targetHints']['allow'] ); + } + + public function test_does_not_error_on_invalid_urls() { + $response = new WP_REST_Response(); + $response->add_link( 'self', 'this is not a real URL' ); + + $links = rest_get_server()::get_response_links( $response ); + $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); + } + + public function test_does_not_error_on_bad_rest_api_routes() { + $response = new WP_REST_Response(); + $response->add_link( 'self', rest_url( '/this/is/not/a/real/route' ) ); + + $links = rest_get_server()::get_response_links( $response ); + $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); + } + + public function test_prefers_developer_defined_target_hints() { + $response = new WP_REST_Response(); + $response->add_link( + 'self', + '/wp/v2/posts/' . self::$post_id, + array( + 'targetHints' => array( + 'allow' => array( 'GET', 'PUT' ), + ), + ) + ); + + $links = rest_get_server()::get_response_links( $response ); + $link = $links['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET', 'PUT' ), $link['targetHints']['allow'] ); + } + public function _validate_as_integer_123( $value, $request, $key ) { if ( ! is_int( $value ) ) { return new WP_Error( 'some-error', 'This is not valid!' ); From 4d4917b78183113e57ce5d12c8bdb7a0e6ff40d2 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Mon, 2 Sep 2024 14:35:49 -0400 Subject: [PATCH 3/9] phpcs fixes --- tests/phpunit/tests/rest-api/rest-server.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 7c5b164cb034e..421bf2e3528e4 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -23,14 +23,14 @@ public static function set_up_before_class() { } public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { - $filename = DIR_TESTDATA . '/images/test-image-large.jpg'; - self::$icon_id = $factory->attachment->create_upload_object( $filename ); + $filename = DIR_TESTDATA . '/images/test-image-large.jpg'; + self::$icon_id = $factory->attachment->create_upload_object( $filename ); self::$admin_id = $factory->user->create( array( 'role' => 'administrator', ) ); - self::$post_id = $factory->post->create(); + self::$post_id = $factory->post->create(); } public static function tear_down_after_class() { From a2ffb2990881a7006d9f42e7b6200c95a84c06a0 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 10:04:18 -0700 Subject: [PATCH 4/9] Add validation and sanitization. --- .../rest-api/class-wp-rest-server.php | 78 +++++++++++++------ tests/phpunit/tests/rest-api/rest-server.php | 29 +++++++ 2 files changed, 82 insertions(+), 25 deletions(-) diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index f92bfc674feb0..87e6e351fd56d 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -628,8 +628,6 @@ public static function get_response_links( $response ) { return array(); } - $server = rest_get_server(); - // Convert links to part of the data. $data = array(); foreach ( $links as $rel => $items ) { @@ -644,37 +642,67 @@ public static function get_response_links( $response ) { continue; } - // Prefer targetHints that were specifically designated by the developer. - if ( isset( $attributes['targetHints']['allow'] ) ) { - $data[ $rel ][] = $attributes; - continue; + $target_hints = self::get_target_hints_for_link( $item['href'] ); + if ( $target_hints ) { + $attributes['targetHints'] = $target_hints; } - $request = WP_REST_Request::from_url( $item['href'] ); - if ( ! $request ) { - $data[ $rel ][] = $attributes; - continue; - } + $data[ $rel ][] = $attributes; + } + } - $match = $server->match_request_to_handler( $request ); - if ( ! is_wp_error( $match ) ) { - $response = new WP_REST_Response(); - $response->set_matched_route( $match[0] ); - $response->set_matched_handler( $match[1] ); - $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + return $data; + } - foreach ( $headers as $name => $value ) { - $name = WP_REST_Request::canonicalize_header_name( $name ); + /** + * Gets the target links for a REST API Link. + * + * @since 6.7.0 + * + * @param array $link + * + * @return array|null + */ + protected static function get_target_hints_for_link( $link ) { + // Prefer targetHints that were specifically designated by the developer. + if ( isset( $link['targetHints']['allow'] ) ) { + return null; + } - $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); - } - } + $request = WP_REST_Request::from_url( $link['href'] ); + if ( ! $request ) { + return null; + } - $data[ $rel ][] = $attributes; - } + $server = rest_get_server(); + $match = $server->match_request_to_handler( $request ); + + if ( is_wp_error( $match ) ) { + return null; } - return $data; + if ( is_wp_error( $request->has_valid_params() ) ) { + return null; + } + + if ( is_wp_error( $request->sanitize_params() ) ) { + return null; + } + + $target_hints = array(); + + $response = new WP_REST_Response(); + $response->set_matched_route( $match[0] ); + $response->set_matched_handler( $match[1] ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + + $target_hints[ $name ] = array_map( 'trim', explode( ',', $value ) ); + } + + return $target_hints; } /** diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 421bf2e3528e4..1aa19b4815a41 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -2441,6 +2441,35 @@ public function test_rest_allowed_cors_headers_filter_receives_request_object() $this->assertSame( '/test-allowed-cors-headers', $mock_hook->get_events()[0]['args'][1]->get_route() ); } + public function test_validates_request_when_building_target_hints() { + register_rest_route( + 'test-ns/v1', + '/test/(?P\d+)', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => static function () { + return new \WP_REST_Response(); + }, + 'permission_callback' => '__return_true', + 'args' => array( + 'id' => array( + 'type' => 'integer', + ), + ), + ), + ) + ); + + $response = new WP_REST_Response(); + $response->add_link( 'self', rest_url( 'test-ns/v1/test/garbage' ) ); + + $links = rest_get_server()::get_response_links( $response ); + + $this->assertArrayHasKey( 'self', $links['self'] ); + $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); + } + public function test_populates_target_hints_for_administrator() { wp_set_current_user( self::$admin_id ); $response = rest_do_request( '/wp/v2/posts' ); From ebf790860b54495f66c6055450a5c743d8e62f7a Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 10:26:51 -0700 Subject: [PATCH 5/9] facepalm --- src/wp-includes/rest-api/class-wp-rest-server.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 87e6e351fd56d..17d620f6fb6e0 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -642,7 +642,7 @@ public static function get_response_links( $response ) { continue; } - $target_hints = self::get_target_hints_for_link( $item['href'] ); + $target_hints = self::get_target_hints_for_link( $attributes ); if ( $target_hints ) { $attributes['targetHints'] = $target_hints; } @@ -675,7 +675,7 @@ protected static function get_target_hints_for_link( $link ) { } $server = rest_get_server(); - $match = $server->match_request_to_handler( $request ); + $match = $server->match_request_to_handler( $request ); if ( is_wp_error( $match ) ) { return null; From 0761afbbc9254fbfb04d86d495ab32cf185292f5 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 10:37:04 -0700 Subject: [PATCH 6/9] more face palming --- tests/phpunit/tests/rest-api/rest-server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 1aa19b4815a41..c1b4e1b1eafa5 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -2466,7 +2466,7 @@ public function test_validates_request_when_building_target_hints() { $links = rest_get_server()::get_response_links( $response ); - $this->assertArrayHasKey( 'self', $links['self'] ); + $this->assertArrayHasKey( 'self', $links ); $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); } From c774f15d93ecd8344bde3de228719ce882ad8c1e Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 11:28:06 -0700 Subject: [PATCH 7/9] add sanitization test, add ticket groups --- tests/phpunit/tests/rest-api/rest-server.php | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index c1b4e1b1eafa5..9fbcec03d24a1 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -2441,6 +2441,9 @@ public function test_rest_allowed_cors_headers_filter_receives_request_object() $this->assertSame( '/test-allowed-cors-headers', $mock_hook->get_events()[0]['args'][1]->get_route() ); } + /** + * @ticket 61739 + */ public function test_validates_request_when_building_target_hints() { register_rest_route( 'test-ns/v1', @@ -2470,6 +2473,45 @@ public function test_validates_request_when_building_target_hints() { $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); } + /** + * @ticket 61739 + */ + public function test_sanitizes_request_when_building_target_hints() { + register_rest_route( + 'test-ns/v1', + '/test/(?P\d+)', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => static function () { + return new \WP_REST_Response(); + }, + 'permission_callback' => function( WP_REST_Request $request ) { + $this->assertIsInt( $request['id'] ); + + return true; + }, + 'args' => array( + 'id' => array( + 'type' => 'integer', + ), + ), + ), + ) + ); + + $response = new WP_REST_Response(); + $response->add_link( 'self', rest_url( 'test-ns/v1/test/5' ) ); + + $links = rest_get_server()::get_response_links( $response ); + + $this->assertArrayHasKey( 'self', $links ); + $this->assertArrayHasKey( 'targetHints', $links['self'][0] ); + } + + /** + * @ticket 61739 + */ public function test_populates_target_hints_for_administrator() { wp_set_current_user( self::$admin_id ); $response = rest_do_request( '/wp/v2/posts' ); @@ -2481,6 +2523,9 @@ public function test_populates_target_hints_for_administrator() { $this->assertSame( array( 'GET', 'POST', 'PUT', 'PATCH', 'DELETE' ), $link['targetHints']['allow'] ); } + /** + * @ticket 61739 + */ public function test_populates_target_hints_for_logged_out_user() { $response = rest_do_request( '/wp/v2/posts' ); $post = $response->get_data()[0]; @@ -2491,6 +2536,9 @@ public function test_populates_target_hints_for_logged_out_user() { $this->assertSame( array( 'GET' ), $link['targetHints']['allow'] ); } + /** + * @ticket 61739 + */ public function test_does_not_error_on_invalid_urls() { $response = new WP_REST_Response(); $response->add_link( 'self', 'this is not a real URL' ); @@ -2499,6 +2547,9 @@ public function test_does_not_error_on_invalid_urls() { $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); } + /** + * @ticket 61739 + */ public function test_does_not_error_on_bad_rest_api_routes() { $response = new WP_REST_Response(); $response->add_link( 'self', rest_url( '/this/is/not/a/real/route' ) ); @@ -2507,6 +2558,9 @@ public function test_does_not_error_on_bad_rest_api_routes() { $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); } + /** + * @ticket 61739 + */ public function test_prefers_developer_defined_target_hints() { $response = new WP_REST_Response(); $response->add_link( From 3af640d0d546fb5bf73a1d32bdf4a820942805e1 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 11:31:37 -0700 Subject: [PATCH 8/9] phpcs --- tests/phpunit/tests/rest-api/rest-server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 9fbcec03d24a1..4a9ee14301475 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -2486,7 +2486,7 @@ public function test_sanitizes_request_when_building_target_hints() { 'callback' => static function () { return new \WP_REST_Response(); }, - 'permission_callback' => function( WP_REST_Request $request ) { + 'permission_callback' => function ( WP_REST_Request $request ) { $this->assertIsInt( $request['id'] ); return true; From 0ffd0eba9b17a6faa25e59d8e58de7a71c21871f Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Tue, 17 Sep 2024 13:43:41 -0700 Subject: [PATCH 9/9] Rework to test the parameter with other assertions --- tests/phpunit/tests/rest-api/rest-server.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 4a9ee14301475..378b51f606cc9 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -2477,6 +2477,7 @@ public function test_validates_request_when_building_target_hints() { * @ticket 61739 */ public function test_sanitizes_request_when_building_target_hints() { + $validated_param = null; register_rest_route( 'test-ns/v1', '/test/(?P\d+)', @@ -2486,8 +2487,8 @@ public function test_sanitizes_request_when_building_target_hints() { 'callback' => static function () { return new \WP_REST_Response(); }, - 'permission_callback' => function ( WP_REST_Request $request ) { - $this->assertIsInt( $request['id'] ); + 'permission_callback' => function ( WP_REST_Request $request ) use ( &$validated_param ) { + $validated_param = $request['id']; return true; }, @@ -2507,6 +2508,7 @@ public function test_sanitizes_request_when_building_target_hints() { $this->assertArrayHasKey( 'self', $links ); $this->assertArrayHasKey( 'targetHints', $links['self'][0] ); + $this->assertIsInt( $validated_param ); } /**