From c5355eeb8fcd8afdb12ae2ca38f4338c153ded01 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 20:42:10 -0800 Subject: [PATCH 1/7] Improve handling of post preview from edit screen for AMP compat Remove WP<5.7 compat code --- css/edit-post-preview-admin.css | 4 +- js/edit-post-preview-admin.js | 88 ++++++++++--------- php/class-edit-post-preview.php | 18 +--- .../test-ajax-class-wp-customize-posts.php | 10 +-- 4 files changed, 53 insertions(+), 67 deletions(-) diff --git a/css/edit-post-preview-admin.css b/css/edit-post-preview-admin.css index e6588e1..fc5fe48 100644 --- a/css/edit-post-preview-admin.css +++ b/css/edit-post-preview-admin.css @@ -1,3 +1,3 @@ -#preview-action .spinner:not(.is-active-preview) { - visibility: hidden !important; +#preview-action .button.loading { + cursor: progress; } diff --git a/js/edit-post-preview-admin.js b/js/edit-post-preview-admin.js index da0ebbe..77013aa 100644 --- a/js/edit-post-preview-admin.js +++ b/js/edit-post-preview-admin.js @@ -8,7 +8,6 @@ var EditPostPreviewAdmin = (function( $ ) { var component = { data: { customize_url: null, - is_compat: false, previewed_post: null, customize_posts_update_changeset_nonce: null } @@ -18,17 +17,23 @@ var EditPostPreviewAdmin = (function( $ ) { $.extend( component.data, _editPostPreviewAdminExports ); } + /** + * Init. + * + * @returns {void} + */ component.init = function() { - component.previewButton = $( '#post-preview' ); - component.previewButtonSpinner = $( 'span.spinner' ).first().clone(); - component.previewButton.after( component.previewButtonSpinner ); - component.previewButton - .off( 'click.post-preview' ) - .on( 'click.post-preview', component.onClickPreviewBtn ); + $( 'form#post' ).on( 'submit', component.onPreviewSubmitPostForm ); }; - component.onClickPreviewBtn = function( event ) { - var $btn = $( this ), + /** + * Handle submitting form from preview button. + * + * @param {jQuery.Event} event - Event. + * @returns {void} + */ + component.onPreviewSubmitPostForm = function( event ) { + var $btn, postId = $( '#post_ID' ).val(), postType = $( '#post_type' ).val(), postSettingId, @@ -38,7 +43,13 @@ var EditPostPreviewAdmin = (function( $ ) { wasMobile, parentId, menuOrder, - request; + request, + customizeUrl; + + $btn = $( document.activeElement ); + if ( ! $btn.is( 'a.preview' ) || 'dopreview' !== $( '#wp-preview' ).val() ) { + return; + } event.preventDefault(); @@ -46,6 +57,8 @@ var EditPostPreviewAdmin = (function( $ ) { return; } + customizeUrl = component.data.customize_url + '&url=' + encodeURIComponent( $btn.prop( 'href' ) ); + wp.customize.Loader.link = $btn; // Prevent loader from navigating to new URL. @@ -81,41 +94,30 @@ var EditPostPreviewAdmin = (function( $ ) { // Allow plugins to inject additional settings to preview. wp.customize.trigger( 'settings-from-edit-post-screen', settings ); - // For backward compatibility send the current input fields from the edit post page to the Customizer via sessionStorage. - if ( component.data.is_compat ) { - sessionStorage.setItem( 'previewedCustomizePostSettings[' + postId + ']', JSON.stringify( settings ) ); - wp.customize.Loader.open( component.data.customize_url ); + $btn.addClass( 'disabled' ).addClass( 'loading' ); + request = wp.ajax.post( 'customize_posts_update_changeset', { + customize_posts_update_changeset_nonce: component.data.customize_posts_update_changeset_nonce, + previewed_post: component.data.previewed_post, + input_data: postSettingValue + } ); + + request.fail( function( resp ) { + var error = JSON.parse( resp.responseText ), errorText; + if ( error.data ) { + errorText = error.data.replace( /_/g, ' ' ); + alert( errorText.charAt( 0 ).toUpperCase() + errorText.slice( 1 ) ); // eslint-disable-line no-alert + } + } ); + + request.done( function( resp ) { + wp.customize.Loader.open( customizeUrl + '&changeset_uuid=' + encodeURIComponent( resp.changeset_uuid ) ); wp.customize.Loader.settings.browser.mobile = wasMobile; component.bindChangesFromCustomizer( postSettingId, editor ); - } else { - $btn.addClass( 'disabled' ); - component.previewButtonSpinner.addClass( 'is-active is-active-preview' ); - request = wp.ajax.post( 'customize_posts_update_changeset', { - customize_posts_update_changeset_nonce: component.data.customize_posts_update_changeset_nonce, - previewed_post: component.data.previewed_post, - customize_url: component.data.customize_url, - input_data: postSettingValue - } ); - - request.fail( function( resp ) { - var error = JSON.parse( resp.responseText ), errorText; - if ( error.data ) { - errorText = error.data.replace( /_/g, ' ' ); - alert( errorText.charAt( 0 ).toUpperCase() + errorText.slice( 1 ) ); // eslint-disable-line no-alert - } - } ); - - request.done( function( resp ) { - wp.customize.Loader.open( resp.customize_url ); - wp.customize.Loader.settings.browser.mobile = wasMobile; - component.bindChangesFromCustomizer( postSettingId, editor ); - } ); - - request.always( function() { - $btn.removeClass( 'disabled' ); - component.previewButtonSpinner.removeClass( 'is-active is-active-preview' ); - } ); - } + } ); + + request.always( function() { + $btn.removeClass( 'disabled' ).removeClass( 'loading' ); + } ); }; /** diff --git a/php/class-edit-post-preview.php b/php/class-edit-post-preview.php index 3cdf47d..3b3a407 100644 --- a/php/class-edit-post-preview.php +++ b/php/class-edit-post-preview.php @@ -134,7 +134,6 @@ public function enqueue_admin_scripts() { $customize_url = add_query_arg( array( - 'url' => urlencode( self::get_preview_post_link( $post ) ), 'previewed_post' => $post->ID, 'autofocus[section]' => sprintf( 'post[%s][%d]', $post->post_type, $post->ID ), self::PREVIEW_POST_NONCE_QUERY_VAR => wp_create_nonce( self::PREVIEW_POST_NONCE_ACTION ), @@ -146,7 +145,6 @@ public function enqueue_admin_scripts() { 'customize_url' => $customize_url, self::UPDATE_CHANGESET_NONCE => wp_create_nonce( self::UPDATE_CHANGESET_NONCE_ACTION ), 'previewed_post' => $post->ID, - 'is_compat' => version_compare( strtok( get_bloginfo( 'version' ), '-' ), '4.7', '<' ), ); wp_scripts()->add_data( 'edit-post-preview-admin', 'data', sprintf( 'var _editPostPreviewAdminExports = %s;', wp_json_encode( $data ) ) ); @@ -224,9 +222,6 @@ public function update_post_changeset() { } elseif ( ! isset( $_POST['previewed_post'] ) ) { status_header( 400 ); wp_send_json_error( 'missing_previewed_post' ); - } elseif ( empty( $_POST['customize_url'] ) ) { - status_header( 400 ); - wp_send_json_error( 'missing_customize_url' ); } elseif ( empty( $_POST['input_data'] ) || ! is_array( $_POST['input_data'] ) ) { status_header( 400 ); wp_send_json_error( 'missing_input_data' ); @@ -249,9 +244,9 @@ public function update_post_changeset() { } if ( $changeset_uuid ) { - $wp_customize = new \WP_Customize_Manager( array( + $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $changeset_uuid, - ) ); + ) ); // WPCS: override ok. $changeset_post_id = $wp_customize->changeset_post_id(); if ( $changeset_post_id ) { @@ -272,16 +267,11 @@ public function update_post_changeset() { status_header( 403 ); wp_send_json_error( 'cannot_create_changeset_post' ); } - $wp_customize = new \WP_Customize_Manager(); + $wp_customize = new WP_Customize_Manager(); // WPCS: override ok. $changeset_uuid = $wp_customize->changeset_uuid(); update_post_meta( $previewed_post_id, '_preview_changeset_uuid', $changeset_uuid ); } - $customize_url = add_query_arg( - compact( 'changeset_uuid' ), - wp_unslash( $_POST['customize_url'] ) - ); - if ( ! isset( $wp_customize->posts ) || ! ( $wp_customize->posts instanceof WP_Customize_Posts ) ) { wp_send_json_error( 'missing_posts_component' ); } @@ -317,6 +307,6 @@ public function update_post_changeset() { wp_send_json_error( $response->get_error_code() ); } - wp_send_json_success( compact( 'customize_url', 'response' ) ); + wp_send_json_success( compact( 'changeset_uuid', 'response' ) ); } } diff --git a/tests/php/test-ajax-class-wp-customize-posts.php b/tests/php/test-ajax-class-wp-customize-posts.php index 4ac164c..3b4b17c 100644 --- a/tests/php/test-ajax-class-wp-customize-posts.php +++ b/tests/php/test-ajax-class-wp-customize-posts.php @@ -490,27 +490,21 @@ public function test_update_post_changeset_successes() { $_POST = wp_slash( array( 'customize_posts_update_changeset_nonce' => wp_create_nonce( 'customize_posts_update_changeset' ), 'previewed_post' => $post_id, - 'customize_url' => wp_customize_url(), 'input_data' => $input_data, ) ); $this->make_ajax_call( 'customize_posts_update_changeset' ); $response = json_decode( $this->_last_response, true ); $this->assertTrue( $response['success'] ); - $this->assertArrayHasKey( 'customize_url', $response['data'] ); + $this->assertArrayHasKey( 'changeset_uuid', $response['data'] ); $this->assertArrayHasKey( 'response', $response['data'] ); $this->assertArrayHasKey( 'setting_validities', $response['data']['response'] ); $setting_key = "post[post][$post_id]"; $this->assertTrue( $response['data']['response']['setting_validities'][ $setting_key ] ); - $customize_url_parts = parse_url( $response['data']['customize_url'] ); - parse_str( $customize_url_parts['query'], $url_query ); - $this->assertNotEmpty( $url_query['changeset_uuid'] ); - $this->assertEquals( get_post_meta( $post_id, '_preview_changeset_uuid', true ), $url_query['changeset_uuid'] ); - $query = new WP_Query( array( - 'post_name' => $url_query['changeset_uuid'], + 'post_name' => $response['data']['changeset_uuid'], 'post_type' => 'customize_changeset', 'post_status' => 'auto-draft', 'no_found_rows' => true, From 3b9b2e76219d8391028279f330962528ea75905e Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 20:53:23 -0800 Subject: [PATCH 2/7] Add support for selective refresh previewing in AMP --- php/class-wp-customize-posts-preview.php | 112 ++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/php/class-wp-customize-posts-preview.php b/php/class-wp-customize-posts-preview.php index 7cb3dc7..1b4223f 100644 --- a/php/class-wp-customize-posts-preview.php +++ b/php/class-wp-customize-posts-preview.php @@ -101,6 +101,14 @@ public function customize_preview_init() { add_filter( 'customize_render_partials_response', array( $this, 'amend_with_queried_post_ids' ) ); add_filter( 'customize_render_partials_response', array( $this, 'amend_partials_response_with_rest_resources' ), 10, 3 ); remove_filter( 'get_edit_post_link', '__return_empty_string' ); // See . + + // Support for AMP. + add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'enqueue_scripts' ) ); + if ( false === has_action( 'amp_post_template_footer', array( $this->component->manager->selective_refresh, 'export_preview_data' ) ) ) { + add_action( 'amp_post_template_footer', array( $this->component->manager->selective_refresh, 'export_preview_data' ) ); + } + add_filter( 'amp_post_template_data', array( $this, 'filter_amp_post_template_data' ), 10, 2 ); + add_filter( 'customize_partial_render', array( $this, 'sanitize_amp_rendered_content_partial' ), 10, 3 ); } /** @@ -126,6 +134,106 @@ public function add_preview_filters() { return true; } + /** + * Filter AMP post template data to add body classes. + * + * @param array $data Data. + * @param WP_Post $post Post. + * + * @return array Data. + */ + public function filter_amp_post_template_data( $data, $post ) { + if ( 'page' === $post->post_type ) { + $data['body_class'] .= sprintf( 'page-id-%d', $post->ID ); + } else { + $data['body_class'] .= sprintf( 'postid-%d', $post->ID ); + } + return $data; + } + + /** + * Sanitize rendered content field partial for AMP. + * + * @param string|array|false $rendered The partial value. Default false. + * @param WP_Customize_Partial $partial WP_Customize_Setting instance. + * @return string Rendered partial. + */ + public function sanitize_amp_rendered_content_partial( $rendered, $partial ) { + $should_get_amp_content = ( + $partial instanceof WP_Customize_Post_Field_Partial + && + 'post_content' === $partial->field_id + && + function_exists( 'amp_load_classes' ) + && + defined( 'AMP_QUERY_VAR' ) + && + false !== get_query_var( AMP_QUERY_VAR, false ) + ); + if ( $should_get_amp_content ) { + $post = get_post( $partial->post_id ); + + amp_load_classes(); + + // The following is copied from AMP_Post_Template::__construct(). See . + $content_max_width = AMP_Post_Template::CONTENT_MAX_WIDTH; + if ( isset( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 0 ) { + $content_max_width = $GLOBALS['content_width']; + } + $content_max_width = apply_filters( 'amp_content_max_width', $content_max_width ); + + // The following is adapted from AMP_Post_Template::build_post_content(). See . + $amp_content = new AMP_Content( $rendered, + apply_filters( + 'amp_content_embed_handlers', array( + 'AMP_Twitter_Embed_Handler' => array(), + 'AMP_YouTube_Embed_Handler' => array(), + 'AMP_DailyMotion_Embed_Handler' => array(), + 'AMP_Vimeo_Embed_Handler' => array(), + 'AMP_SoundCloud_Embed_Handler' => array(), + 'AMP_Instagram_Embed_Handler' => array(), + 'AMP_Vine_Embed_Handler' => array(), + 'AMP_Facebook_Embed_Handler' => array(), + 'AMP_Pinterest_Embed_Handler' => array(), + 'AMP_Gallery_Embed_Handler' => array(), + ), + $post + ), + apply_filters( + 'amp_content_sanitizers', array( + 'AMP_Style_Sanitizer' => array(), + 'AMP_Img_Sanitizer' => array(), + 'AMP_Video_Sanitizer' => array(), + 'AMP_Audio_Sanitizer' => array(), + 'AMP_Playbuzz_Sanitizer' => array(), + 'AMP_Iframe_Sanitizer' => array( + 'add_placeholder' => true, + ), + 'AMP_Tag_And_Attribute_Sanitizer' => array(), + ), + $post + ), + array( + 'content_max_width' => $content_max_width, + ) + ); + $rendered = $amp_content->get_amp_content(); + foreach ( $amp_content->get_amp_scripts() as $id => $src ) { + $rendered .= sprintf( '', esc_attr( $id ), esc_url( $src ) ); + } + $styles = $amp_content->get_amp_styles(); + if ( ! empty( $styles ) ) { + $rendered .= ''; + } + } + return $rendered; + } + /** * Enqueue scripts for the customizer preview. */ @@ -1310,7 +1418,7 @@ function filter_get_avatar( $avatar, $id_or_email, $size, $default, $alt, $args public function get_post_field_partial_schema( $field_id = '' ) { $schema = array( 'post_title' => array( - 'selector' => '.entry-title', + 'selector' => '.entry-title, .amp-wp-title', ), 'post_name' => array( 'fallback_refresh' => false, @@ -1329,7 +1437,7 @@ public function get_post_field_partial_schema( $field_id = '' ) { 'fallback_refresh' => false, ), 'post_content' => array( - 'selector' => '.entry-content', + 'selector' => '.entry-content, .amp-wp-article-content', ), 'post_excerpt' => array( 'selector' => '.entry-summary', From 60622f153c4980b7b40392c54c9da666c0764739 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 20:54:12 -0800 Subject: [PATCH 3/7] Bump version to 0.9.2-alpha --- composer.json | 2 +- customize-posts.php | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index d7087d2..5051116 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "xwp/wp-customize-posts", "description": "Manage posts and postmeta via the Customizer.", - "version": "0.9.1", + "version": "0.9.2", "type": "wordpress-plugin", "keywords": [ "customizer", "customize", "posts", "postmeta", "preview", "featured-image", "page-template" ], "homepage": "https://github.com/xwp/wp-customize-posts/", diff --git a/customize-posts.php b/customize-posts.php index be6370c..1524066 100644 --- a/customize-posts.php +++ b/customize-posts.php @@ -3,7 +3,7 @@ * Plugin Name: Customize Posts * Description: Manage posts and postmeta via the Customizer. * Plugin URI: https://github.com/xwp/wp-customize-posts/ - * Version: 0.9.1 + * Version: 0.9.2-alpha * Author: XWP * Author URI: https://make.xwp.co/ * License: GPLv2+ diff --git a/package.json b/package.json index eb89545..e4f09e5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/xwp/wp-customize-posts.git" }, - "version": "0.9.1", + "version": "0.9.2", "license": "GPL-2.0+", "private": true, "devDependencies": { From cdc70809983088fd45a0def9099555630282ea83 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 7 Dec 2017 15:47:12 -0800 Subject: [PATCH 4/7] Use is_amp_endpoint() instead of looking at query var directly --- php/class-wp-customize-posts-preview.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/class-wp-customize-posts-preview.php b/php/class-wp-customize-posts-preview.php index 1b4223f..6183e58 100644 --- a/php/class-wp-customize-posts-preview.php +++ b/php/class-wp-customize-posts-preview.php @@ -166,9 +166,9 @@ public function sanitize_amp_rendered_content_partial( $rendered, $partial ) { && function_exists( 'amp_load_classes' ) && - defined( 'AMP_QUERY_VAR' ) + function_exists( 'is_amp_endpoint' ) && - false !== get_query_var( AMP_QUERY_VAR, false ) + is_amp_endpoint() ); if ( $should_get_amp_content ) { $post = get_post( $partial->post_id ); From 5a303063f75e2513e5293b8f07ce2f8a5089b54e Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 14 Dec 2017 23:26:19 -0800 Subject: [PATCH 5/7] Remove AMP plugin code that is part of 0.6 --- php/class-wp-customize-posts-preview.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/php/class-wp-customize-posts-preview.php b/php/class-wp-customize-posts-preview.php index 6183e58..c44c8a3 100644 --- a/php/class-wp-customize-posts-preview.php +++ b/php/class-wp-customize-posts-preview.php @@ -104,9 +104,7 @@ public function customize_preview_init() { // Support for AMP. add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'enqueue_scripts' ) ); - if ( false === has_action( 'amp_post_template_footer', array( $this->component->manager->selective_refresh, 'export_preview_data' ) ) ) { - add_action( 'amp_post_template_footer', array( $this->component->manager->selective_refresh, 'export_preview_data' ) ); - } + add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'export_preview_data' ) ); add_filter( 'amp_post_template_data', array( $this, 'filter_amp_post_template_data' ), 10, 2 ); add_filter( 'customize_partial_render', array( $this, 'sanitize_amp_rendered_content_partial' ), 10, 3 ); } @@ -164,8 +162,6 @@ public function sanitize_amp_rendered_content_partial( $rendered, $partial ) { && 'post_content' === $partial->field_id && - function_exists( 'amp_load_classes' ) - && function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() @@ -173,8 +169,6 @@ function_exists( 'is_amp_endpoint' ) if ( $should_get_amp_content ) { $post = get_post( $partial->post_id ); - amp_load_classes(); - // The following is copied from AMP_Post_Template::__construct(). See . $content_max_width = AMP_Post_Template::CONTENT_MAX_WIDTH; if ( isset( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 0 ) { From 7887cdc2a3ce805272fb6d0839518828a12ee370 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 14 Dec 2017 23:39:05 -0800 Subject: [PATCH 6/7] Limit AMP support to v0.6+ --- php/class-wp-customize-posts-preview.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/php/class-wp-customize-posts-preview.php b/php/class-wp-customize-posts-preview.php index c44c8a3..94ccfee 100644 --- a/php/class-wp-customize-posts-preview.php +++ b/php/class-wp-customize-posts-preview.php @@ -103,10 +103,12 @@ public function customize_preview_init() { remove_filter( 'get_edit_post_link', '__return_empty_string' ); // See . // Support for AMP. - add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'enqueue_scripts' ) ); - add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'export_preview_data' ) ); - add_filter( 'amp_post_template_data', array( $this, 'filter_amp_post_template_data' ), 10, 2 ); - add_filter( 'customize_partial_render', array( $this, 'sanitize_amp_rendered_content_partial' ), 10, 3 ); + if ( defined( 'AMP__VERSION' ) && version_compare( strtok( AMP__VERSION, '-' ), '0.6', '>=' ) ) { + add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'enqueue_scripts' ) ); + add_action( 'amp_customizer_enqueue_preview_scripts', array( $this, 'export_preview_data' ) ); + add_filter( 'amp_post_template_data', array( $this, 'filter_amp_post_template_data' ), 10, 2 ); + add_filter( 'customize_partial_render', array( $this, 'sanitize_amp_rendered_content_partial' ), 10, 3 ); + } } /** From bef654df631b1b73fd1f437c6fa6bbadb1a886a0 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 14 Dec 2017 23:41:27 -0800 Subject: [PATCH 7/7] Support post field partial selectors containing multiple --- js/customize-preview-posts.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/customize-preview-posts.js b/js/customize-preview-posts.js index f796a43..44f2d84 100644 --- a/js/customize-preview-posts.js +++ b/js/customize-preview-posts.js @@ -129,7 +129,9 @@ selectorBases.push( 'body.postid-' + String( postId ) ); } schema.params.selector = _.map( selectorBases, function( selectorBase ) { - var selector = selectorBase + ' ' + schema.params.selector; + var selector = schema.params.selector.split( /,/ ).map( function( subSelector ) { + return selectorBase + ' ' + subSelector; + } ).join( ',' ); selector = selector.replace( /%d/g, String( postId ) ); return selector; } ).join( ', ' );