diff --git a/editor/store/selectors.js b/editor/store/selectors.js index 4928ec226ba16e..ea5d7d8180b4cd 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-version', 0, 'id' ], null ); } /** diff --git a/editor/store/test/selectors.js b/editor/store/test/selectors.js index 4e65b55a661bec..42e2b917e39d3c 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-version': [ + { + 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..37c7abc62733b8 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 ( ! 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' ); + + $revisions = wp_get_post_revisions( $post->ID, array( 'fields' => 'ids' ) ); + $revisions_count = count( $revisions ); + + $new_links['version-history'] = array( + 'href' => $version_history_link['href'], + 'count' => $revisions_count, + ); + + if ( $revisions_count > 0 ) { + $last_revision = array_shift( $revisions ); + + $new_links['predecessor-version'] = array( + 'href' => $version_history_link['href'] . '/' . $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..e8fcb33d558e86 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_version() { + $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-version'][0]['href'] ); + $this->assertEquals( $revision_1->ID, $links['predecessor-version'][0]['attributes']['id'] ); + } }