From 578c345f0e9eca512b22baaa072525495833aa39 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 6 Jun 2018 14:24:36 -0400 Subject: [PATCH 01/13] REST API: Move preview_link to autosaves controller --- lib/class-wp-rest-autosaves-controller.php | 24 +++++++++++- lib/rest-api.php | 39 ------------------- phpunit/class-gutenberg-rest-api-test.php | 15 ------- .../class-rest-autosaves-controller-test.php | 3 +- 4 files changed, 25 insertions(+), 56 deletions(-) diff --git a/lib/class-wp-rest-autosaves-controller.php b/lib/class-wp-rest-autosaves-controller.php index 4fcd571d15f143..dd057c7f107613 100644 --- a/lib/class-wp-rest-autosaves-controller.php +++ b/lib/class-wp-rest-autosaves-controller.php @@ -265,7 +265,17 @@ public function get_items( $request ) { * @return array Item schema data. */ public function get_item_schema() { - return $this->revisions_controller->get_item_schema(); + $schema = $this->revisions_controller->get_item_schema(); + + $schema['properties']['preview_link'] = array( + 'description' => __( 'Preview link for the post.', 'gutenberg' ), + 'type' => 'string', + 'format' => 'uri', + 'context' => array( 'edit' ), + 'readonly' => true, + ); + + return $schema; } /** @@ -339,6 +349,18 @@ public function prepare_item_for_response( $post, $request ) { $response = $this->revisions_controller->prepare_item_for_response( $post, $request ); + $schema = $this->get_item_schema(); + + if ( ! empty( $schema['properties']['preview_link'] ) ) { + $response->data['preview_link'] = get_preview_post_link( $post->post_parent, array( + 'preview_id' => $post->post_parent, + 'preview_nonce' => wp_create_nonce( 'post_preview_' . $post->post_parent ) + ) ); + } + + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $response->data = $this->filter_response_by_context( $response->data, $context ); + /** * Filters a revision returned from the API. * diff --git a/lib/rest-api.php b/lib/rest-api.php index 8317cdf1e3a163..2e6b0cdcb068a5 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -438,45 +438,6 @@ function gutenberg_register_rest_api_post_revisions() { } add_action( 'rest_api_init', 'gutenberg_register_rest_api_post_revisions' ); -/** - * Get the preview link for the post object. - * - * @see https://github.com/WordPress/gutenberg/issues/4555 - * - * @param WP_Post $post Post object. - * @return string - */ -function gutenberg_get_post_preview_link( $post ) { - return get_preview_post_link( $post['id'] ); -} - -/** - * Adds the 'preview_link' attribute to the REST API response of a post. - * - * @see https://github.com/WordPress/gutenberg/issues/4555 - */ -function gutenberg_register_rest_api_post_preview_link() { - foreach ( get_post_types( array( 'show_in_rest' => true ), 'names' ) as $post_type ) { - if ( ! is_post_type_viewable( $post_type ) ) { - continue; - } - register_rest_field( $post_type, - 'preview_link', - array( - 'get_callback' => 'gutenberg_get_post_preview_link', - 'schema' => array( - 'description' => __( 'Preview link for the post.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'uri', - 'context' => array( 'edit' ), - 'readonly' => true, - ), - ) - ); - } -} -add_action( 'rest_api_init', 'gutenberg_register_rest_api_post_preview_link' ); - /** * 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 9bdaf81a2bd9b5..5fb617fc6634de 100644 --- a/phpunit/class-gutenberg-rest-api-test.php +++ b/phpunit/class-gutenberg-rest-api-test.php @@ -445,19 +445,4 @@ 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_page_edit_context_includes_preview() { - wp_set_current_user( $this->editor ); - $page_id = $this->factory->post->create( array( - 'post_type' => 'page', - 'post_status' => 'draft', - ) ); - $page = get_post( $page_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/pages/' . $page_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - $this->assertEquals( get_preview_post_link( $page ), $data['preview_link'] ); - } } diff --git a/phpunit/class-rest-autosaves-controller-test.php b/phpunit/class-rest-autosaves-controller-test.php index 20f61f1d2ede49..2acc91295070c5 100644 --- a/phpunit/class-rest-autosaves-controller-test.php +++ b/phpunit/class-rest-autosaves-controller-test.php @@ -239,7 +239,7 @@ public function test_get_item_schema() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertEquals( 12, count( $properties ) ); + $this->assertEquals( 13, count( $properties ) ); $this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'content', $properties ); $this->assertArrayHasKey( 'date', $properties ); @@ -252,6 +252,7 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'parent', $properties ); $this->assertArrayHasKey( 'slug', $properties ); $this->assertArrayHasKey( 'title', $properties ); + $this->assertArrayHasKey( 'preview_link', $properties ); } public function test_create_item() { From 2134269c32463587eca7dcd000f271374357cbf9 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 6 Jun 2018 14:25:22 -0400 Subject: [PATCH 02/13] Post Preview: Redirect to preview by autosave property availability --- .../components/post-preview-button/index.js | 50 ++++++------ .../post-preview-button/test/index.js | 22 ++---- editor/store/effects.js | 41 +--------- editor/store/reducer.js | 7 +- editor/store/selectors.js | 43 +++++++++- editor/store/test/reducer.js | 2 + editor/store/test/selectors.js | 79 +++++++++++++++++++ 7 files changed, 163 insertions(+), 81 deletions(-) diff --git a/editor/components/post-preview-button/index.js b/editor/components/post-preview-button/index.js index 00244ec04afd16..d0ad6111bf6636 100644 --- a/editor/components/post-preview-button/index.js +++ b/editor/components/post-preview-button/index.js @@ -16,24 +16,32 @@ export class PostPreviewButton extends Component { super( ...arguments ); this.saveForPreview = this.saveForPreview.bind( this ); - - this.state = { - isAwaitingSave: false, - }; } - componentWillReceiveProps( nextProps ) { - const { modified, link } = nextProps; - const { isAwaitingSave } = this.state; - const hasFinishedSaving = ( - isAwaitingSave && - modified !== this.props.modified - ); + componentDidUpdate( prevProps ) { + const { previewLink } = this.props; + + // This relies on the window being responsible to unset itself when + // navigation occurs or a new preview window is opened, to avoid + // unintentional forceful redirects. + if ( previewLink && ! prevProps.previewLink ) { + this.setPreviewWindowLink( previewLink ); + } + } - if ( hasFinishedSaving && this.previewWindow ) { - this.previewWindow.location = link; - this.setState( { isAwaitingSave: false } ); + /** + * Sets the preview window's location to the given URL, if a preview window + * exists and is not already at that location. + * + * @param {string} url URL to assign as preview window location. + */ + setPreviewWindowLink( url ) { + const { previewWindow } = this; + if ( ! previewWindow || previewWindow.location === url ) { + return; } + + previewWindow.location = url; } getWindowTarget() { @@ -50,9 +58,6 @@ export class PostPreviewButton extends Component { // Save post prior to opening window this.props.autosave(); - this.setState( { - isAwaitingSave: true, - } ); // Open a popup, BUT: Set it to a blank page until save completes. This // is necessary because popups can only be opened in response to user @@ -95,13 +100,13 @@ export class PostPreviewButton extends Component { } render() { - const { link, isSaveable } = this.props; + const { currentPostLink, isSaveable } = this.props; return (