From a6d2904cb1005ae74faa0a89968760856b32e06c Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Fri, 17 Feb 2023 15:43:47 +0000 Subject: [PATCH] REST API: Normalize WP_REST_Server::dispatch() to return a response object. Previously, the `rest_pre_dispatch` filter could be used to return a `WP_Error` instance. This would cause a fatal error for `rest_post_dispath` filters that were rightly expecting a `WP_REST_Response` object to be passed instead. Props DaveFX, felipeelia. Fixes #56566. git-svn-id: https://develop.svn.wordpress.org/trunk@55361 602fd350-edb4-49c9-b593-d223f7449a82 --- .../rest-api/class-wp-rest-server.php | 9 ++++++ tests/phpunit/tests/rest-api/rest-server.php | 32 ++++++++++++++++--- 2 files changed, 37 insertions(+), 4 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 00c34cd621..4c017eeefa 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -984,6 +984,15 @@ class WP_REST_Server { $result = apply_filters( 'rest_pre_dispatch', null, $this, $request ); if ( ! empty( $result ) ) { + + // Normalize to either WP_Error or WP_REST_Response... + $result = rest_ensure_response( $result ); + + // ...then convert WP_Error across. + if ( is_wp_error( $result ) ) { + $result = $this->error_to_response( $result ); + } + return $result; } diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 8788a72445..19905cf614 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -922,11 +922,35 @@ class Tests_REST_Server extends WP_Test_REST_TestCase { $data = array( 'untouched' => 'data', ); - $result = rest_get_server()->embed_links( $data ); + $result = rest_get_server()->embed_links( $data, true ); - $this->assertArrayNotHasKey( '_links', $data ); - $this->assertArrayNotHasKey( '_embedded', $data ); - $this->assertSame( 'data', $data['untouched'] ); + $this->assertArrayNotHasKey( '_links', $result ); + $this->assertArrayNotHasKey( '_embedded', $result ); + $this->assertSame( 'data', $result['untouched'] ); + } + + /** + * Ensure embed_links handles WP_Error objects returned by dispatch + * + * @ticket 56566 + */ + public function test_link_embedding_returning_wp_error() { + $return_wp_error = function() { + return new WP_Error( 'some-error', 'This is not valid!' ); + }; + add_filter( 'rest_pre_dispatch', $return_wp_error ); + + $mock = new MockAction(); + add_filter( 'rest_post_dispatch', array( $mock, 'filter' ) ); + + $response = new WP_REST_Response(); + $response->add_link( 'author', rest_url( 'test' ), array( 'embeddable' => true ) ); + + $data = rest_get_server()->response_to_data( $response, true ); + + $this->assertArrayHasKey( '_links', $data ); + $this->assertCount( 1, $mock->get_events() ); + $this->assertSame( 'some-error', $data['_embedded']['author'][0]['code'] ); } public function embedded_response_callback( $request ) {