From 7d3698a9e94f0dcd28bb50a11185c85b5fc0f7d9 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Fri, 22 Jun 2018 12:12:55 -0700 Subject: [PATCH 1/3] Implement core style of including revisions data on Post response --- editor/store/selectors.js | 4 +- editor/store/test/selectors.js | 16 +++-- lib/rest-api.php | 83 ++++++++++++----------- phpunit/class-gutenberg-rest-api-test.php | 23 +++++++ 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/editor/store/selectors.js b/editor/store/selectors.js index 4928ec226ba16e..37f42ec6fdf966 100644 --- a/editor/store/selectors.js +++ b/editor/store/selectors.js @@ -155,7 +155,7 @@ export function getCurrentPostId( state ) { * @return {number} Number of revisions. */ export function getCurrentPostRevisionsCount( state ) { - return get( getCurrentPost( state ), [ 'revisions', 'count' ], 0 ); + return get( getCurrentPost( state ), [ '_links', 'version-history', 0, 'count' ], 0 ); } /** @@ -167,7 +167,7 @@ export function getCurrentPostRevisionsCount( state ) { * @return {?number} ID of the last revision. */ export function getCurrentPostLastRevisionId( state ) { - return get( getCurrentPost( state ), [ 'revisions', 'last_id' ], null ); + return get( getCurrentPost( state ), [ '_links', 'predecessor', 0, 'id' ], null ); } /** diff --git a/editor/store/test/selectors.js b/editor/store/test/selectors.js index 4e65b55a661bec..d87334ecd5906f 100644 --- a/editor/store/test/selectors.js +++ b/editor/store/test/selectors.js @@ -515,8 +515,12 @@ describe( 'selectors', () => { it( 'should return the last revision ID', () => { const state = { currentPost: { - revisions: { - last_id: 123, + _links: { + predecessor: [ + { + id: 123, + }, + ], }, }, }; @@ -537,8 +541,12 @@ describe( 'selectors', () => { it( 'should return the number of revisions', () => { const state = { currentPost: { - revisions: { - count: 5, + _links: { + 'version-history': [ + { + count: 5, + }, + ], }, }, }; diff --git a/lib/rest-api.php b/lib/rest-api.php index bae0f3c58560cd..9ad9ecdc929bae 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -338,6 +338,48 @@ function gutenberg_add_target_schema_to_links( $response, $post, $request ) { return $response; } +/** + * Include revisions data on post response links. + * + * @see https://core.trac.wordpress.org/ticket/44321 + * + * @param WP_REST_Response $response WP REST API response of a post. + * @param WP_Post $post The post being returned. + * @param WP_REST_Request $request WP REST API request. + * @return WP_REST_Response Response containing the new links. + */ +function gutenberg_add_revisions_data_to_links( $response, $post, $request ) { + + $new_links = array(); + $orig_links = $response->get_links(); + + if ( in_array( $post->post_type, array( 'post', 'page' ), true ) || post_type_supports( $post->post_type, 'revisions' ) ) { + // 'version-history' already exists and we don't want to duplicate it. + $response->remove_link( 'version-history' ); + + $orig_href = ! empty( $orig_links['self'][0]['href'] ) ? $orig_links['self'][0]['href'] : null; + $revisions = wp_get_post_revisions( $post->ID, array( 'fields' => 'ids' ) ); + $revisions_count = count( $revisions ); + + $new_links['version-history'] = array( + 'href' => $orig_href . '/revisions', + 'count' => $revisions_count, + ); + + if ( $revisions_count > 0 ) { + $last_revision = array_shift( $revisions ); + + $new_links['predecessor'] = array( + 'href' => $orig_href . '/revisions/' . $last_revision, + 'id' => $last_revision, + ); + } + } + + $response->add_links( $new_links ); + return $response; +} + /** * Whenever a post type is registered, ensure we're hooked into it's WP REST API response. * @@ -348,6 +390,7 @@ function gutenberg_register_post_prepare_functions( $post_type ) { add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_permalink_template_to_posts', 10, 3 ); add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_block_format_to_post_content', 10, 3 ); add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_target_schema_to_links', 10, 3 ); + add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_revisions_data_to_links', 10, 3 ); add_filter( "rest_{$post_type}_collection_params", 'gutenberg_filter_post_collection_parameters', 10, 2 ); add_filter( "rest_{$post_type}_query", 'gutenberg_filter_post_query_arguments', 10, 2 ); return $post_type; @@ -365,46 +408,6 @@ function gutenberg_register_taxonomy_prepare_functions( $taxonomy ) { } add_filter( 'registered_taxonomy', 'gutenberg_register_taxonomy_prepare_functions' ); -/** - * Gets revisions details for the selected post. - * - * @since 1.6.0 - * - * @param array $post The post object from the response. - * @return array|null Revisions details or null when no revisions present. - */ -function gutenberg_get_post_revisions( $post ) { - $revisions = wp_get_post_revisions( $post['id'] ); - $revisions_count = count( $revisions ); - if ( 0 === $revisions_count ) { - return null; - } - - $last_revision = array_shift( $revisions ); - - return array( - 'count' => $revisions_count, - 'last_id' => $last_revision->ID, - ); -} - -/** - * Adds the custom field `revisions` to the REST API response of post. - * - * TODO: This is a temporary solution. Next step would be to find a solution that is limited to the editor. - * - * @since 1.6.0 - */ -function gutenberg_register_rest_api_post_revisions() { - register_rest_field( get_post_types( '', 'names' ), - 'revisions', - array( - 'get_callback' => 'gutenberg_get_post_revisions', - ) - ); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_api_post_revisions' ); - /** * Ensure that the wp-json index contains the 'theme-supports' setting as * part of its site info elements. diff --git a/phpunit/class-gutenberg-rest-api-test.php b/phpunit/class-gutenberg-rest-api-test.php index ed07d5af7dfe61..71299a0d01b5eb 100644 --- a/phpunit/class-gutenberg-rest-api-test.php +++ b/phpunit/class-gutenberg-rest-api-test.php @@ -414,4 +414,27 @@ public function test_get_pages_unbounded_per_page_unauthorized() { $data = $response->get_data(); $this->assertEquals( 'rest_forbidden_per_page', $data['code'] ); } + + public function test_get_post_links_predecessor() { + $post_id = $this->factory->post->create(); + wp_update_post( + array( + 'post_content' => 'This content is marvelous.', + 'ID' => $post_id, + ) + ); + $revisions = wp_get_post_revisions( $post_id ); + $revision_1 = array_pop( $revisions ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $post_id ) ); + $response = rest_get_server()->dispatch( $request ); + + $links = $response->get_links(); + + $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions' ), $links['version-history'][0]['href'] ); + $this->assertEquals( 1, $links['version-history'][0]['attributes']['count'] ); + + $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions/' . $revision_1->ID ), $links['predecessor'][0]['href'] ); + $this->assertEquals( $revision_1->ID, $links['predecessor'][0]['attributes']['id'] ); + } } From 9823c743fc33cfda40e29a9cc941723a08c1e6d1 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 25 Jun 2018 06:40:36 -0700 Subject: [PATCH 2/3] Rename `predecessor` to `predecessor-version` --- editor/store/selectors.js | 2 +- editor/store/test/selectors.js | 2 +- lib/rest-api.php | 2 +- phpunit/class-gutenberg-rest-api-test.php | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/store/selectors.js b/editor/store/selectors.js index 37f42ec6fdf966..ea5d7d8180b4cd 100644 --- a/editor/store/selectors.js +++ b/editor/store/selectors.js @@ -167,7 +167,7 @@ export function getCurrentPostRevisionsCount( state ) { * @return {?number} ID of the last revision. */ export function getCurrentPostLastRevisionId( state ) { - return get( getCurrentPost( state ), [ '_links', 'predecessor', 0, 'id' ], null ); + return get( getCurrentPost( state ), [ '_links', 'predecessor-version', 0, 'id' ], null ); } /** diff --git a/editor/store/test/selectors.js b/editor/store/test/selectors.js index d87334ecd5906f..42e2b917e39d3c 100644 --- a/editor/store/test/selectors.js +++ b/editor/store/test/selectors.js @@ -516,7 +516,7 @@ describe( 'selectors', () => { const state = { currentPost: { _links: { - predecessor: [ + 'predecessor-version': [ { id: 123, }, diff --git a/lib/rest-api.php b/lib/rest-api.php index 9ad9ecdc929bae..a2956a17ad2d56 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -369,7 +369,7 @@ function gutenberg_add_revisions_data_to_links( $response, $post, $request ) { if ( $revisions_count > 0 ) { $last_revision = array_shift( $revisions ); - $new_links['predecessor'] = array( + $new_links['predecessor-version'] = array( 'href' => $orig_href . '/revisions/' . $last_revision, 'id' => $last_revision, ); diff --git a/phpunit/class-gutenberg-rest-api-test.php b/phpunit/class-gutenberg-rest-api-test.php index 71299a0d01b5eb..e8fcb33d558e86 100644 --- a/phpunit/class-gutenberg-rest-api-test.php +++ b/phpunit/class-gutenberg-rest-api-test.php @@ -415,7 +415,7 @@ public function test_get_pages_unbounded_per_page_unauthorized() { $this->assertEquals( 'rest_forbidden_per_page', $data['code'] ); } - public function test_get_post_links_predecessor() { + public function test_get_post_links_predecessor_version() { $post_id = $this->factory->post->create(); wp_update_post( array( @@ -434,7 +434,7 @@ public function test_get_post_links_predecessor() { $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions' ), $links['version-history'][0]['href'] ); $this->assertEquals( 1, $links['version-history'][0]['attributes']['count'] ); - $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions/' . $revision_1->ID ), $links['predecessor'][0]['href'] ); - $this->assertEquals( $revision_1->ID, $links['predecessor'][0]['attributes']['id'] ); + $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions/' . $revision_1->ID ), $links['predecessor-version'][0]['href'] ); + $this->assertEquals( $revision_1->ID, $links['predecessor-version'][0]['attributes']['id'] ); } } From 874d8b79ef3fd91d0b4668da2c610eaa71f66cf6 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 25 Jun 2018 06:47:58 -0700 Subject: [PATCH 3/3] Base inclusion of `version-history` count on existing link --- lib/rest-api.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rest-api.php b/lib/rest-api.php index a2956a17ad2d56..37c7abc62733b8 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -353,16 +353,16 @@ function gutenberg_add_revisions_data_to_links( $response, $post, $request ) { $new_links = array(); $orig_links = $response->get_links(); - if ( in_array( $post->post_type, array( 'post', 'page' ), true ) || post_type_supports( $post->post_type, 'revisions' ) ) { + if ( ! empty( $orig_links['version-history'] ) ) { + $version_history_link = array_shift( $orig_links['version-history'] ); // 'version-history' already exists and we don't want to duplicate it. $response->remove_link( 'version-history' ); - $orig_href = ! empty( $orig_links['self'][0]['href'] ) ? $orig_links['self'][0]['href'] : null; $revisions = wp_get_post_revisions( $post->ID, array( 'fields' => 'ids' ) ); $revisions_count = count( $revisions ); $new_links['version-history'] = array( - 'href' => $orig_href . '/revisions', + 'href' => $version_history_link['href'], 'count' => $revisions_count, ); @@ -370,7 +370,7 @@ function gutenberg_add_revisions_data_to_links( $response, $post, $request ) { $last_revision = array_shift( $revisions ); $new_links['predecessor-version'] = array( - 'href' => $orig_href . '/revisions/' . $last_revision, + 'href' => $version_history_link['href'] . '/' . $last_revision, 'id' => $last_revision, ); }