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/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/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/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( ', ' ); 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/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": { 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/php/class-wp-customize-posts-preview.php b/php/class-wp-customize-posts-preview.php index 7cb3dc7..94ccfee 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. + 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 ); + } } /** @@ -126,6 +134,102 @@ 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( 'is_amp_endpoint' ) + && + is_amp_endpoint() + ); + if ( $should_get_amp_content ) { + $post = get_post( $partial->post_id ); + + // 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 +1414,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 +1433,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', 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,