From c647dcf25a012a037777fd1927b672329a462655 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Fri, 24 Nov 2017 17:11:30 +0100 Subject: [PATCH 01/14] Add post AMP preview button --- amp.php | 1 + assets/css/amp-post-meta-box.css | 22 +++++++ assets/images/amp-icon.svg | 7 +++ assets/js/amp-post-meta-box.js | 57 ++++++++++++++++++ includes/admin/class-amp-post-meta-box.php | 67 ++++++++++++++++++++++ includes/admin/functions.php | 13 +++++ tests/test-class-amp-meta-box.php | 67 ++++++++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 assets/css/amp-post-meta-box.css create mode 100644 assets/images/amp-icon.svg create mode 100644 assets/js/amp-post-meta-box.js create mode 100644 includes/admin/class-amp-post-meta-box.php create mode 100644 tests/test-class-amp-meta-box.php diff --git a/amp.php b/amp.php index 1cbd389113c..174a8c84d93 100644 --- a/amp.php +++ b/amp.php @@ -19,6 +19,7 @@ require_once( AMP__DIR__ . '/includes/amp-helper-functions.php' ); require_once( AMP__DIR__ . '/includes/admin/functions.php' ); require_once( AMP__DIR__ . '/includes/admin/class-amp-customizer.php' ); +require_once AMP__DIR__ . '/includes/admin/class-amp-post-meta-box.php'; require_once( AMP__DIR__ . '/includes/settings/class-amp-customizer-settings.php' ); require_once( AMP__DIR__ . '/includes/settings/class-amp-customizer-design-settings.php' ); diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css new file mode 100644 index 00000000000..c5957275e25 --- /dev/null +++ b/assets/css/amp-post-meta-box.css @@ -0,0 +1,22 @@ +/** +* 1.0 AMP preview. +* +* Submit box preview buttons. +*/ + +/* Core preview button */ +#preview-action.has-next-sibling .preview:first-of-type { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + float: none; +} + +/* AMP preview button */ +#preview-action.has-next-sibling .preview.amp-preview { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + text-indent: -9999px; + width: 30px; + background: #f7f7f7 url( '../images/amp-icon.svg' ) no-repeat center; + background-size: 14px; +} diff --git a/assets/images/amp-icon.svg b/assets/images/amp-icon.svg new file mode 100644 index 00000000000..9e59350b584 --- /dev/null +++ b/assets/images/amp-icon.svg @@ -0,0 +1,7 @@ + + + AMP-Icon + + + + diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js new file mode 100644 index 00000000000..1effe40ff14 --- /dev/null +++ b/assets/js/amp-post-meta-box.js @@ -0,0 +1,57 @@ +/* exported AmpPostMetaBox */ + +/** + * AMP Post Meta Box. + * + * @since 0.6 + */ +var AmpPostMetaBox = ( function( $ ) { + 'use strict'; + + // Exports. + return { + /** + * Holds data. + * + * @since 0.6 + */ + data: {}, + + /** + * Boot plugin. + * + * @since 0.6 + * @param {Object} data Object data. + * @return {void} + */ + boot: function( data ) { + this.data = data; + + $( document ).ready( function() { + this.addPreviewButton(); + }.bind( this ) ); + }, + + /** + * Add AMP Preview button. + * + * @since 0.6 + * @return {void} + */ + addPreviewButton: function() { + var $previewBtn = $( '#preview-action a.preview' ); + + $previewBtn + .clone() + .insertAfter( $previewBtn ) + .addClass( 'amp-preview' ) + .prop( { + 'href': this.data.previewLink, + 'id': 'amp-' + $previewBtn.prop( 'id' ), + 'target': 'amp-' + $previewBtn.prop( 'target' ) + } ) + .parent() + .addClass( 'has-next-sibling' ); + } + }; +})( window.jQuery ); diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php new file mode 100644 index 00000000000..bf7a2c4de76 --- /dev/null +++ b/includes/admin/class-amp-post-meta-box.php @@ -0,0 +1,67 @@ +post_type ) || true !== post_supports_amp( $post ) ) { + return; + } + + // Styles. + wp_enqueue_style( + self::ASSETS_HANDLE, + amp_get_asset_url( 'css/amp-post-meta-box.css' ), + false, + AMP__VERSION + ); + + // Scripts. + wp_enqueue_script( + self::ASSETS_HANDLE, + amp_get_asset_url( 'js/amp-post-meta-box.js' ), + array( 'jquery' ), + AMP__VERSION + ); + wp_add_inline_script( self::ASSETS_HANDLE, sprintf( 'AmpPostMetaBox.boot( %s );', + wp_json_encode( array( + 'previewLink' => esc_url_raw( add_query_arg( AMP_QUERY_VAR, true, get_preview_post_link( $post ) ) ), + ) ) + ) ); + } + +} diff --git a/includes/admin/functions.php b/includes/admin/functions.php index fd21e348385..e27034fd5fd 100644 --- a/includes/admin/functions.php +++ b/includes/admin/functions.php @@ -115,3 +115,16 @@ function amp_add_custom_analytics( $analytics ) { return $analytics; } add_filter( 'amp_post_template_analytics', 'amp_add_custom_analytics' ); + +/** + * Bootstrap AMP post meta box. + * + * This function must be invoked only once through the 'wp_loaded' action. + * + * @since 0.6 + */ +function amp_post_meta_box() { + $post_meta_box = new AMP_Post_Meta_Box(); + $post_meta_box->init(); +} +add_action( 'wp_loaded', 'amp_post_meta_box' ); diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php new file mode 100644 index 00000000000..588dbd43219 --- /dev/null +++ b/tests/test-class-amp-meta-box.php @@ -0,0 +1,67 @@ +instance = new AMP_Post_Meta_Box(); + } + + /** + * Test init. + * + * @see AMP_Settings::init() + */ + public function test_init() { + $this->instance->init(); + $this->assertEquals( 10, has_action( 'admin_enqueue_scripts', array( $this->instance, 'enqueue_admin_assets' ) ) ); + } + + /** + * Test enqueue_admin_assets. + * + * @see AMP_Settings::enqueue_admin_assets() + */ + public function test_enqueue_admin_assets() { + // Test enqueue outside of a post with AMP support. + $this->assertFalse( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); + $this->assertFalse( wp_script_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); + + // Test enqueue on a post with AMP support. + $post = self::factory()->post->create_and_get(); + $GLOBALS['post'] = $post; + $this->instance->enqueue_admin_assets(); + $this->assertTrue( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); + $this->assertTrue( wp_script_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); + $script_data = wp_scripts()->get_data( AMP_Post_Meta_Box::ASSETS_HANDLE, 'after' ); + + if ( empty( $script_data ) ) { + $this->markTestIncomplete( 'Script data could not be found.' ); + } + + // Test inline script boot. + $this->assertNotFalse( stripos( wp_json_encode( $script_data ), 'AmpPostMetaBox.boot(' ) ); + unset( $GLOBALS['post'] ); + } + +} From 600281d282333dd1dc88650d46e68ff9190696ce Mon Sep 17 00:00:00 2001 From: ThierryA Date: Fri, 24 Nov 2017 17:29:53 +0100 Subject: [PATCH 02/14] Fix unit test for legacy WP env --- tests/test-class-amp-meta-box.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index 588dbd43219..4c361399e8f 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -60,7 +60,7 @@ public function test_enqueue_admin_assets() { } // Test inline script boot. - $this->assertNotFalse( stripos( wp_json_encode( $script_data ), 'AmpPostMetaBox.boot(' ) ); + $this->assertTrue( false !== stripos( wp_json_encode( $script_data ), 'AmpPostMetaBox.boot(' ) ); unset( $GLOBALS['post'] ); } From ae8a3bb9d56796288dcfdcd3f6eae378acd62e11 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Mon, 27 Nov 2017 12:42:13 +0100 Subject: [PATCH 03/14] Add AMP status option on a per post basis --- assets/css/amp-post-meta-box.css | 24 ++++++ assets/images/amp-icon.svg | 2 +- assets/js/amp-post-meta-box.js | 51 +++++++++++- includes/admin/class-amp-post-meta-box.php | 94 +++++++++++++++++++++- includes/amp-helper-functions.php | 5 ++ templates/admin/amp-status.php | 34 ++++++++ tests/test-class-amp-meta-box.php | 66 +++++++++++++++ 7 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 templates/admin/amp-status.php diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index c5957275e25..2fc9eb8e2b1 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -20,3 +20,27 @@ background: #f7f7f7 url( '../images/amp-icon.svg' ) no-repeat center; background-size: 14px; } + +/* AMP status */ +.misc-amp-status > i { + float: left; + background: transparent url( '../images/amp-icon.svg' ) no-repeat left; + background-size: 17px; + width: 17px; + height: 17px; + margin: 0 8px 0 1px; +} + +#amp-status-select { + margin-top: 4px; +} + +.amp-status-actions { + margin-top: 10px; +} + +@media screen and ( max-width: 782px ) { + #amp-status-select { + line-height: 280%; + } +} diff --git a/assets/images/amp-icon.svg b/assets/images/amp-icon.svg index 9e59350b584..a30ea6d2f0d 100644 --- a/assets/images/amp-icon.svg +++ b/assets/images/amp-icon.svg @@ -1,7 +1,7 @@ AMP-Icon - + diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index 1effe40ff14..950d392d9ec 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -17,6 +17,13 @@ var AmpPostMetaBox = ( function( $ ) { */ data: {}, + /** + * Toggle animation speed. + * + * @since 0.6 + */ + toggleSpeed: 200, + /** * Boot plugin. * @@ -26,9 +33,22 @@ var AmpPostMetaBox = ( function( $ ) { */ boot: function( data ) { this.data = data; - $( document ).ready( function() { this.addPreviewButton(); + this.listen(); + }.bind( this ) ); + }, + + /** + * Events listener. + * + * @since 0.6 + * @return {void} + */ + listen: function() { + $( '.edit-amp-status, [href="#amp_status"]' ).click( function( e ) { + e.preventDefault(); + this.toggleAmpStatus( $( e.target ) ); }.bind( this ) ); }, @@ -52,6 +72,35 @@ var AmpPostMetaBox = ( function( $ ) { } ) .parent() .addClass( 'has-next-sibling' ); + }, + + /** + * Add AMP Preview button. + * + * @since 0.6 + * @param {Object} $target Event target. + * @return {void} + */ + toggleAmpStatus: function( $target ) { + var $container = $( '#amp-status-select' ), + status = $container.data( 'amp-status' ), + $checked; + + // Don't modify status on cancel button click. + if ( ! $target.hasClass( 'button-cancel' ) ) { + status = $( '[name="amp_status"]:checked' ).val(); + } + + $checked = $( '#amp-satus-' + status ); + + // Toggle elements. + $( '.edit-amp-status' ).fadeToggle( this.toggleSpeed ); + $container.slideToggle( this.toggleSpeed ); + + // Update status. + $container.data( 'amp-status', status ); + $checked.prop( 'checked', 'checked' ); + $( '.amp-status-text' ).text( $checked.next().text() ); } }; })( window.jQuery ); diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index bf7a2c4de76..efe8678f7b5 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -16,10 +16,35 @@ class AMP_Post_Meta_Box { /** * Assets handle. * + * @since 0.6 * @const string */ const ASSETS_HANDLE = 'amp-post-meta-box'; + /** + * The post meta key. + * + * @since 0.6 + * @const string + */ + const POST_META_KEY = 'amp_status'; + + /** + * The nonce name. + * + * @since 0.6 + * @const string + */ + const NONCE_NAME = 'amp-status'; + + /** + * The nonce action. + * + * @since 0.6 + * @const string + */ + const NONCE_ACTION = 'amp-update-status'; + /** * Initialize. * @@ -27,6 +52,8 @@ class AMP_Post_Meta_Box { */ public function init() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) ); + add_action( 'post_submitbox_misc_actions', array( $this, 'render_status' ) ); + add_action( 'save_post', array( $this, 'save_amp_status' ) ); } /** @@ -38,7 +65,7 @@ public function enqueue_admin_assets() { $post = get_post(); // Stop if the post doesn't have AMP support. - if ( ! isset( $post->post_type ) || true !== post_supports_amp( $post ) ) { + if ( ! isset( $post->post_type ) || true !== post_type_supports( $post->post_type, AMP_QUERY_VAR ) ) { return; } @@ -64,4 +91,69 @@ public function enqueue_admin_assets() { ) ); } + /** + * Render AMP status. + * + * @since 0.6 + * @param object $post \WP_POST object. + */ + public function render_status( $post ) { + $verify = ( + isset( $post->ID ) + && + isset( $post->post_type ) + && + post_type_supports( $post->post_type, AMP_QUERY_VAR ) + && + current_user_can( 'edit_post', $post->ID ) + ); + + if ( true !== $verify ) { + return; + } + + $status = get_post_meta( $post->ID, self::POST_META_KEY, true ); + $labels = array( + 'enabled' => __( 'Enabled', 'amp' ), + 'disabled' => __( 'Disabled', 'amp' ), + ); + + // Set default. + if ( empty( $status ) ) { + $status = 'enabled'; + } + + include_once AMP__DIR__ . '/templates/admin/amp-status.php'; + } + + /** + * Save AMP Status. + * + * @since 0.6 + * @param int $post_id The Post ID. + */ + public function save_amp_status( $post_id ) { + $verify = ( + isset( $_POST[ self::NONCE_NAME ] ) + && + isset( $_POST[ self::POST_META_KEY ] ) + && + wp_verify_nonce( sanitize_key( wp_unslash( $_POST[ self::NONCE_NAME ] ) ), self::NONCE_ACTION ) + && + current_user_can( 'edit_post', $post_id ) + && + ! wp_is_post_revision( $post_id ) + && + ! wp_is_post_autosave( $post_id ) + ); + + if ( true === $verify ) { + update_post_meta( + $post_id, + self::POST_META_KEY, + sanitize_key( wp_unslash( $_POST[ self::POST_META_KEY ] ) ) + ); + } + } + } diff --git a/includes/amp-helper-functions.php b/includes/amp-helper-functions.php index d9c5d86ea93..159a446186f 100644 --- a/includes/amp-helper-functions.php +++ b/includes/amp-helper-functions.php @@ -23,6 +23,11 @@ function post_supports_amp( $post ) { return false; } + // Listen to post meta. + if ( ! isset( $post->ID ) || 'disabled' === get_post_meta( $post->ID, AMP_Post_Meta_Box::POST_META_KEY, true ) ) { + return false; + } + if ( post_password_required( $post ) ) { return false; } diff --git a/templates/admin/amp-status.php b/templates/admin/amp-status.php new file mode 100644 index 00000000000..ac98628208a --- /dev/null +++ b/templates/admin/amp-status.php @@ -0,0 +1,34 @@ + +
+ + + + + + + +
+ > + +
+ > + +
+ +
+ + +
+
+
diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index 4c361399e8f..ca85b19b6f0 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -35,6 +35,8 @@ public function setUp() { public function test_init() { $this->instance->init(); $this->assertEquals( 10, has_action( 'admin_enqueue_scripts', array( $this->instance, 'enqueue_admin_assets' ) ) ); + $this->assertEquals( 10, has_action( 'post_submitbox_misc_actions', array( $this->instance, 'render_status' ) ) ); + $this->assertEquals( 10, has_action( 'save_post', array( $this->instance, 'save_amp_status' ) ) ); } /** @@ -64,4 +66,68 @@ public function test_enqueue_admin_assets() { unset( $GLOBALS['post'] ); } + /** + * Test render_status. + * + * @see AMP_Settings::render_status() + */ + public function test_render_status() { + $post = $this->factory->post->create_and_get(); + wp_set_current_user( $this->factory->user->create( array( + 'role' => 'administrator', + ) ) ); + + ob_start(); + $this->instance->render_status( $post ); + $this->assertContains( '
instance->render_status( $post ); + $this->assertEmpty( ob_get_clean() ); + + add_post_type_support( 'post', AMP_QUERY_VAR ); + wp_set_current_user( $this->factory->user->create( array( + 'role' => 'subscriber', + ) ) ); + + ob_start(); + $this->instance->render_status( $post ); + $this->assertEmpty( ob_get_clean() ); + } + + /** + * Test save_amp_status. + * + * @see AMP_Settings::save_amp_status() + */ + public function test_save_amp_status() { + // Test failure. + $post_id = $this->factory->post->create(); + $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + + // Setup for success. + wp_set_current_user( $this->factory->user->create( array( + 'role' => 'administrator', + ) ) ); + $_POST[ AMP_Post_Meta_Box::NONCE_NAME ] = wp_create_nonce( AMP_Post_Meta_Box::NONCE_ACTION ); + $_POST[ AMP_Post_Meta_Box::POST_META_KEY ] = 'foo'; + + // Test revision bail. + $post_id = $this->factory->post->create(); + delete_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY ); + wp_save_post_revision( $post_id ); + $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + + // Test post update success. + $post_id = $this->factory->post->create(); + delete_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY ); + wp_update_post( array( + 'ID' => $post_id, + 'post_title' => 'updated', + ) ); + $this->assertEquals( 'foo', get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + } + } From 0f8201478da454b0407f817bc4f8c05ffe24fc79 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Tue, 28 Nov 2017 17:54:47 +0100 Subject: [PATCH 04/14] AMP preview code improvement --- assets/css/amp-post-meta-box.css | 17 ++++-- assets/js/amp-post-meta-box.js | 63 ++++++++++++++++++---- includes/admin/class-amp-post-meta-box.php | 18 ++++--- tests/test-class-amp-meta-box.php | 6 ++- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index c5957275e25..17276d14300 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -5,18 +5,25 @@ */ /* Core preview button */ -#preview-action.has-next-sibling .preview:first-of-type { - border-top-right-radius: 0; +#post-preview { + border-top-right-radius: 0; border-bottom-right-radius: 0; float: none; } /* AMP preview button */ -#preview-action.has-next-sibling .preview.amp-preview { - border-top-left-radius: 0; +#amp-post-preview { + border-top-left-radius: 0; border-bottom-left-radius: 0; text-indent: -9999px; width: 30px; - background: #f7f7f7 url( '../images/amp-icon.svg' ) no-repeat center; + background-image: url( '../images/amp-icon.svg' ); + background-position: center; + background-repeat: no-repeat; background-size: 14px; } + +#amp-post-preview.amp-disabled { + box-shadow: none; + opacity: 0.7; +} diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index 1effe40ff14..78ceb96fa3d 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -1,11 +1,11 @@ -/* exported AmpPostMetaBox */ +/* exported ampPostMetaBox */ /** * AMP Post Meta Box. * * @since 0.6 */ -var AmpPostMetaBox = ( function( $ ) { +var ampPostMetaBox = ( function( $ ) { 'use strict'; // Exports. @@ -17,6 +17,20 @@ var AmpPostMetaBox = ( function( $ ) { */ data: {}, + /** + * Core preview button selector. + * + * @since 0.6 + */ + previewBtn: '#post-preview', + + /** + * AMP preview button selector. + * + * @since 0.6 + */ + ampPreviewBtn: '#amp-post-preview', + /** * Boot plugin. * @@ -29,6 +43,24 @@ var AmpPostMetaBox = ( function( $ ) { $( document ).ready( function() { this.addPreviewButton(); + this.listen(); + }.bind( this ) ); + }, + + /** + * Events listener. + * + * @since 0.6 + * @return {void} + */ + listen: function() { + $( this.ampPreviewBtn ).on( 'click.amp-post-preview', function( e ) { + e.preventDefault(); + this.onAmpPreviewButtonClick(); + }.bind( this ) ); + + $( '#submitpost input[type="submit"]' ).on( 'click', function() { + $( this.ampPreviewBtn ).addClass( 'amp-disabled' ); }.bind( this ) ); }, @@ -39,19 +71,32 @@ var AmpPostMetaBox = ( function( $ ) { * @return {void} */ addPreviewButton: function() { - var $previewBtn = $( '#preview-action a.preview' ); - - $previewBtn + $( this.previewBtn ) .clone() - .insertAfter( $previewBtn ) - .addClass( 'amp-preview' ) + .insertAfter( this.previewBtn ) .prop( { 'href': this.data.previewLink, - 'id': 'amp-' + $previewBtn.prop( 'id' ), - 'target': 'amp-' + $previewBtn.prop( 'target' ) + 'id': this.ampPreviewBtn.replace( '#', '' ) } ) .parent() .addClass( 'has-next-sibling' ); + }, + + /** + * AMP Preview button click handler. + * + * We trigger the Core preview link for events propagation purposes. + * + * @since 0.6 + * @return {void} + */ + onAmpPreviewButtonClick: function() { + var currentHref = $( this.ampPreviewBtn ).prop( 'href' ); + + $( this.previewBtn ) + .prop( 'href', $( this.ampPreviewBtn ).prop( 'href' ) ) + .trigger( 'click' ) + .prop( 'href', currentHref ); } }; })( window.jQuery ); diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index bf7a2c4de76..491684aa062 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -16,7 +16,7 @@ class AMP_Post_Meta_Box { /** * Assets handle. * - * @const string + * @var string */ const ASSETS_HANDLE = 'amp-post-meta-box'; @@ -33,12 +33,18 @@ public function init() { * Enqueue admin assets. * * @since 0.6 + * @param string $hook_suffix The current admin page. + * @return Void Void on failure. */ - public function enqueue_admin_assets() { - $post = get_post(); + public function enqueue_admin_assets( $hook_suffix ) { + $post = get_post(); + $validate = ( + true === (bool) preg_match( '#(post|post-new).php#', $hook_suffix ) + && + true === post_supports_amp( $post ) + ); - // Stop if the post doesn't have AMP support. - if ( ! isset( $post->post_type ) || true !== post_supports_amp( $post ) ) { + if ( true !== $validate ) { return; } @@ -57,7 +63,7 @@ public function enqueue_admin_assets() { array( 'jquery' ), AMP__VERSION ); - wp_add_inline_script( self::ASSETS_HANDLE, sprintf( 'AmpPostMetaBox.boot( %s );', + wp_add_inline_script( self::ASSETS_HANDLE, sprintf( 'ampPostMetaBox.boot( %s );', wp_json_encode( array( 'previewLink' => esc_url_raw( add_query_arg( AMP_QUERY_VAR, true, get_preview_post_link( $post ) ) ), ) ) diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index 4c361399e8f..2755b27d248 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -46,11 +46,13 @@ public function test_enqueue_admin_assets() { // Test enqueue outside of a post with AMP support. $this->assertFalse( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); $this->assertFalse( wp_script_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); + $this->instance->enqueue_admin_assets( 'foo-bar.php' ); + $this->assertFalse( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); // Test enqueue on a post with AMP support. $post = self::factory()->post->create_and_get(); $GLOBALS['post'] = $post; - $this->instance->enqueue_admin_assets(); + $this->instance->enqueue_admin_assets( 'post.php' ); $this->assertTrue( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); $this->assertTrue( wp_script_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); $script_data = wp_scripts()->get_data( AMP_Post_Meta_Box::ASSETS_HANDLE, 'after' ); @@ -60,7 +62,7 @@ public function test_enqueue_admin_assets() { } // Test inline script boot. - $this->assertTrue( false !== stripos( wp_json_encode( $script_data ), 'AmpPostMetaBox.boot(' ) ); + $this->assertTrue( false !== stripos( wp_json_encode( $script_data ), 'ampPostMetaBox.boot(' ) ); unset( $GLOBALS['post'] ); } From 779f76317301c3ae1843936d697b58b92cc2bd16 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Fri, 1 Dec 2017 01:09:05 -0600 Subject: [PATCH 05/14] Fix AMP preview button --- assets/js/amp-post-meta-box.js | 18 ++++++++++++----- includes/admin/class-amp-post-meta-box.php | 23 ++++++++++++++++++++++ tests/test-class-amp-meta-box.php | 12 +++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index 78ceb96fa3d..5165a54143d 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -91,12 +91,20 @@ var ampPostMetaBox = ( function( $ ) { * @return {void} */ onAmpPreviewButtonClick: function() { - var currentHref = $( this.ampPreviewBtn ).prop( 'href' ); + var $input; - $( this.previewBtn ) - .prop( 'href', $( this.ampPreviewBtn ).prop( 'href' ) ) - .trigger( 'click' ) - .prop( 'href', currentHref ); + // Flag the AMP preview referer. + $input = $( '' ) + .prop( { + 'type': 'hidden', + 'name': 'amp-preview', + 'value': 'do-preview' + } ) + .insertAfter( this.ampPreviewBtn ); + + // Trigger Core preview button and remove AMP flag. + $( this.previewBtn ).click(); + $input.remove(); } }; })( window.jQuery ); diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index 491684aa062..dbb48a725bf 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -27,6 +27,7 @@ class AMP_Post_Meta_Box { */ public function init() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) ); + add_filter( 'preview_post_link', array( $this, 'preview_post_link' ) ); } /** @@ -70,4 +71,26 @@ public function enqueue_admin_assets( $hook_suffix ) { ) ); } + /** + * Modify post preview link. + * + * Add the AMP query var is the amp-preview flag is set. + * + * @param string $link The post preview link. + * @since 0.6 + */ + public function preview_post_link( $link ) { + $is_amp = ( + isset( $_POST['amp-preview'] ) // WPCS: CSRF ok. + && + 'do-preview' === sanitize_key( wp_unslash( $_POST['amp-preview'] ) ) // WPCS: CSRF ok. + ); + + if ( $is_amp ) { + $link = add_query_arg( AMP_QUERY_VAR, true, $link ); + } + + return $link; + } + } diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index 2755b27d248..e35d4b5e516 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -66,4 +66,16 @@ public function test_enqueue_admin_assets() { unset( $GLOBALS['post'] ); } + /** + * Test preview_post_link. + * + * @see AMP_Settings::preview_post_link() + */ + public function test_preview_post_link() { + $link = 'https://foo.bar'; + $this->assertEquals( 'https://foo.bar', $this->instance->preview_post_link( $link ) ); + $_POST['amp-preview'] = 'do-preview'; + $this->assertEquals( 'https://foo.bar?' . AMP_QUERY_VAR . '=1', $this->instance->preview_post_link( $link ) ); + } + } From ce391a01747c248e561eddb6d6d1a55a32263689 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Fri, 1 Dec 2017 01:28:30 -0600 Subject: [PATCH 06/14] AMP preview code improvement --- includes/admin/class-amp-post-meta-box.php | 8 +++++--- tests/test-class-amp-meta-box.php | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index dbb48a725bf..5e36e6a3ed4 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -34,13 +34,15 @@ public function init() { * Enqueue admin assets. * * @since 0.6 - * @param string $hook_suffix The current admin page. * @return Void Void on failure. */ - public function enqueue_admin_assets( $hook_suffix ) { + public function enqueue_admin_assets() { $post = get_post(); + $screen = get_current_screen(); $validate = ( - true === (bool) preg_match( '#(post|post-new).php#', $hook_suffix ) + isset( $screen->base ) + && + 'post' === $screen->base && true === post_supports_amp( $post ) ); diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index e35d4b5e516..fb5cf71335c 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -52,7 +52,8 @@ public function test_enqueue_admin_assets() { // Test enqueue on a post with AMP support. $post = self::factory()->post->create_and_get(); $GLOBALS['post'] = $post; - $this->instance->enqueue_admin_assets( 'post.php' ); + set_current_screen( 'post.php' ); + $this->instance->enqueue_admin_assets(); $this->assertTrue( wp_style_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); $this->assertTrue( wp_script_is( AMP_Post_Meta_Box::ASSETS_HANDLE ) ); $script_data = wp_scripts()->get_data( AMP_Post_Meta_Box::ASSETS_HANDLE, 'after' ); From e4f6c8733ebadf0766242a7c6e39e04393ca15e2 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Sun, 3 Dec 2017 13:42:10 -0600 Subject: [PATCH 07/14] AMP status code improvements --- assets/css/amp-post-meta-box.css | 2 +- includes/admin/class-amp-post-meta-box.php | 2 +- templates/admin/amp-status.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index 3537c55152e..d49ccae2929 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -29,7 +29,7 @@ } /* AMP status */ -.misc-amp-status > i { +.misc-amp-status .amp-icon { float: left; background: transparent url( '../images/amp-icon.svg' ) no-repeat left; background-size: 17px; diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index 0662ca55514..9aa8634c8b3 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -104,7 +104,7 @@ public function enqueue_admin_assets() { * Render AMP status. * * @since 0.6 - * @param object $post \WP_POST object. + * @param object $post WP_POST object. */ public function render_status( $post ) { $verify = ( diff --git a/templates/admin/amp-status.php b/templates/admin/amp-status.php index ac98628208a..7a6d03d7f48 100644 --- a/templates/admin/amp-status.php +++ b/templates/admin/amp-status.php @@ -11,7 +11,7 @@ } ?>
- + From 4f589491e89627fe1a3b2bf0063a08641bd0a9ab Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 13:36:28 -0800 Subject: [PATCH 08/14] Load JS for AMP post meta box if post type supports not if post is not skipped. * Restore focus on edit link for AMP status edit for accessibility. * Do not add AMP preview button if AMP has been disabled. * Change postmeta to be flag indicating whether AMP is disabled. * Fix spelling and clean up phpdoc. --- assets/css/amp-post-meta-box.css | 2 +- assets/js/amp-post-meta-box.js | 33 +++++++++----- includes/admin/class-amp-post-meta-box.php | 52 ++++++++++++---------- includes/amp-helper-functions.php | 24 ++++++++-- templates/admin/amp-status.php | 8 ++-- tests/test-class-amp-meta-box.php | 25 +++++++---- 6 files changed, 95 insertions(+), 49 deletions(-) diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index d49ccae2929..d11cc755ba1 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -5,7 +5,7 @@ */ /* Core preview button */ -#post-preview { +#post-preview.without-amp { border-top-right-radius: 0; border-bottom-right-radius: 0; float: none; diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index 1305d2396cb..67e41255e24 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -15,7 +15,11 @@ var ampPostMetaBox = ( function( $ ) { * * @since 0.6 */ - data: {}, + data: { + previewLink: '', + disabled: false, + statusInputName: '' + }, /** * Toggle animation speed. @@ -48,7 +52,9 @@ var ampPostMetaBox = ( function( $ ) { boot: function( data ) { this.data = data; $( document ).ready( function() { - this.addPreviewButton(); + if ( ! this.data.disabled ) { + this.addPreviewButton(); + } this.listen(); }.bind( this ) ); }, @@ -82,9 +88,11 @@ var ampPostMetaBox = ( function( $ ) { * @return {void} */ addPreviewButton: function() { - $( this.previewBtn ) + var previewBtn = $( this.previewBtn ); + previewBtn.addClass( 'without-amp' ); + previewBtn .clone() - .insertAfter( this.previewBtn ) + .insertAfter( previewBtn ) .prop( { 'href': this.data.previewLink, 'id': this.ampPreviewBtn.replace( '#', '' ) @@ -119,7 +127,7 @@ var ampPostMetaBox = ( function( $ ) { }, /** - * Add AMP Preview button. + * Add AMP status toggle. * * @since 0.6 * @param {Object} $target Event target. @@ -128,22 +136,27 @@ var ampPostMetaBox = ( function( $ ) { toggleAmpStatus: function( $target ) { var $container = $( '#amp-status-select' ), status = $container.data( 'amp-status' ), - $checked; + $checked, + editAmpStatus = $( '.edit-amp-status' ); // Don't modify status on cancel button click. if ( ! $target.hasClass( 'button-cancel' ) ) { - status = $( '[name="amp_status"]:checked' ).val(); + status = $( '[name="' + this.data.statusInputName + '"]:checked' ).val(); } - $checked = $( '#amp-satus-' + status ); + $checked = $( '#amp-status-' + status ); // Toggle elements. - $( '.edit-amp-status' ).fadeToggle( this.toggleSpeed ); + editAmpStatus.fadeToggle( this.toggleSpeed, function() { + if ( editAmpStatus.is( ':visible' ) ) { + editAmpStatus.focus(); + } + } ); $container.slideToggle( this.toggleSpeed ); // Update status. $container.data( 'amp-status', status ); - $checked.prop( 'checked', 'checked' ); + $checked.prop( 'checked', true ); $( '.amp-status-text' ).text( $checked.next().text() ); } }; diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index 9aa8634c8b3..4101df023b3 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -22,12 +22,20 @@ class AMP_Post_Meta_Box { const ASSETS_HANDLE = 'amp-post-meta-box'; /** - * The post meta key. + * The post meta key for whether the post is skipped. * * @since 0.6 * @var string */ - const POST_META_KEY = 'amp_status'; + const DISABLED_POST_META_KEY = 'amp_disabled'; + + /** + * The field name for the enabled/disabled radio buttons. + * + * @since 0.6 + * @var string + */ + const STATUS_INPUT_NAME = 'amp_status'; /** * The nonce name. @@ -35,7 +43,7 @@ class AMP_Post_Meta_Box { * @since 0.6 * @var string */ - const NONCE_NAME = 'amp-status'; + const NONCE_NAME = 'amp-status-nonce'; /** * The nonce action. @@ -61,7 +69,6 @@ public function init() { * Enqueue admin assets. * * @since 0.6 - * @return Void Void on failure. */ public function enqueue_admin_assets() { $post = get_post(); @@ -71,10 +78,9 @@ public function enqueue_admin_assets() { && 'post' === $screen->base && - true === post_supports_amp( $post ) + post_type_supports( $post->post_type, AMP_QUERY_VAR ) ); - - if ( true !== $validate ) { + if ( ! $validate ) { return; } @@ -95,7 +101,9 @@ public function enqueue_admin_assets() { ); wp_add_inline_script( self::ASSETS_HANDLE, sprintf( 'ampPostMetaBox.boot( %s );', wp_json_encode( array( - 'previewLink' => esc_url_raw( add_query_arg( AMP_QUERY_VAR, true, get_preview_post_link( $post ) ) ), + 'previewLink' => esc_url_raw( add_query_arg( AMP_QUERY_VAR, '', get_preview_post_link( $post ) ) ), + 'disabled' => (bool) get_post_meta( $post->ID, self::DISABLED_POST_META_KEY, true ), + 'statusInputName' => self::STATUS_INPUT_NAME, ) ) ) ); } @@ -104,7 +112,7 @@ public function enqueue_admin_assets() { * Render AMP status. * * @since 0.6 - * @param object $post WP_POST object. + * @param WP_Post $post Post. */ public function render_status( $post ) { $verify = ( @@ -121,17 +129,13 @@ public function render_status( $post ) { return; } - $status = get_post_meta( $post->ID, self::POST_META_KEY, true ); - $labels = array( + $disabled = (bool) get_post_meta( $post->ID, self::DISABLED_POST_META_KEY, true ); + $status = $disabled ? 'disabled' : 'enabled'; + $labels = array( 'enabled' => __( 'Enabled', 'amp' ), 'disabled' => __( 'Disabled', 'amp' ), ); - // Set default. - if ( empty( $status ) ) { - $status = 'enabled'; - } - include_once AMP__DIR__ . '/templates/admin/amp-status.php'; } @@ -145,7 +149,7 @@ public function save_amp_status( $post_id ) { $verify = ( isset( $_POST[ self::NONCE_NAME ] ) && - isset( $_POST[ self::POST_META_KEY ] ) + isset( $_POST[ self::STATUS_INPUT_NAME ] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST[ self::NONCE_NAME ] ) ), self::NONCE_ACTION ) && @@ -157,11 +161,11 @@ public function save_amp_status( $post_id ) { ); if ( true === $verify ) { - update_post_meta( - $post_id, - self::POST_META_KEY, - sanitize_key( wp_unslash( $_POST[ self::POST_META_KEY ] ) ) - ); + if ( 'disabled' === $_POST[ self::STATUS_INPUT_NAME ] ) { + update_post_meta( $post_id, self::DISABLED_POST_META_KEY, true ); + } else { + delete_post_meta( $post_id, self::DISABLED_POST_META_KEY ); + } } } @@ -170,8 +174,10 @@ public function save_amp_status( $post_id ) { * * Add the AMP query var is the amp-preview flag is set. * - * @param string $link The post preview link. * @since 0.6 + * + * @param string $link The post preview link. + * @return string Preview URL. */ public function preview_post_link( $link ) { $is_amp = ( diff --git a/includes/amp-helper-functions.php b/includes/amp-helper-functions.php index 159a446186f..040418d440f 100644 --- a/includes/amp-helper-functions.php +++ b/includes/amp-helper-functions.php @@ -17,14 +17,23 @@ function amp_get_permalink( $post_id ) { return apply_filters( 'amp_get_permalink', $amp_url, $post_id ); } +/** + * Determine whether a given post supports AMP. + * + * @since 0.1 + * + * @param WP_Post $post Post. + * @return bool Whether the post supports AMP. + */ function post_supports_amp( $post ) { - // Because `add_rewrite_endpoint` doesn't let us target specific post_types :( + + // Because `add_rewrite_endpoint` doesn't let us target specific post_types. if ( ! post_type_supports( $post->post_type, AMP_QUERY_VAR ) ) { return false; } - // Listen to post meta. - if ( ! isset( $post->ID ) || 'disabled' === get_post_meta( $post->ID, AMP_Post_Meta_Box::POST_META_KEY, true ) ) { + // Skip based on postmeta. + if ( ! isset( $post->ID ) || (bool) get_post_meta( $post->ID, AMP_Post_Meta_Box::DISABLED_POST_META_KEY, true ) ) { return false; } @@ -32,6 +41,15 @@ function post_supports_amp( $post ) { return false; } + /** + * Filters whether to skip the post from AMP. + * + * @since 0.3 + * + * @param bool $skipped Skipped. + * @param int $post_id Post ID. + * @param WP_Post $post Post. + */ if ( true === apply_filters( 'amp_skip_post', false, $post->ID, $post ) ) { return false; } diff --git a/templates/admin/amp-status.php b/templates/admin/amp-status.php index 7a6d03d7f48..170b4f13c7b 100644 --- a/templates/admin/amp-status.php +++ b/templates/admin/amp-status.php @@ -19,11 +19,11 @@
- > - + > +
- > - + > +
diff --git a/tests/test-class-amp-meta-box.php b/tests/test-class-amp-meta-box.php index bddbb510808..e9b7d7eaa71 100644 --- a/tests/test-class-amp-meta-box.php +++ b/tests/test-class-amp-meta-box.php @@ -108,29 +108,38 @@ public function test_render_status() { public function test_save_amp_status() { // Test failure. $post_id = $this->factory->post->create(); - $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY, true ) ); // Setup for success. wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator', ) ) ); - $_POST[ AMP_Post_Meta_Box::NONCE_NAME ] = wp_create_nonce( AMP_Post_Meta_Box::NONCE_ACTION ); - $_POST[ AMP_Post_Meta_Box::POST_META_KEY ] = 'foo'; + $_POST[ AMP_Post_Meta_Box::NONCE_NAME ] = wp_create_nonce( AMP_Post_Meta_Box::NONCE_ACTION ); + $_POST[ AMP_Post_Meta_Box::STATUS_INPUT_NAME ] = 'disabled'; // Test revision bail. $post_id = $this->factory->post->create(); - delete_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY ); + delete_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY ); wp_save_post_revision( $post_id ); - $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + $this->assertEmpty( get_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY, true ) ); - // Test post update success. + // Test post update success to disable. $post_id = $this->factory->post->create(); - delete_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY ); + delete_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY ); wp_update_post( array( 'ID' => $post_id, 'post_title' => 'updated', ) ); - $this->assertEquals( 'foo', get_post_meta( $post_id, AMP_Post_Meta_Box::POST_META_KEY, true ) ); + $this->assertTrue( (bool) get_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY, true ) ); + + // Test post update success to enable. + $_POST[ AMP_Post_Meta_Box::STATUS_INPUT_NAME ] = 'enabled'; + delete_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY ); + wp_update_post( array( + 'ID' => $post_id, + 'post_title' => 'updated', + ) ); + $this->assertFalse( (bool) get_post_meta( $post_id, AMP_Post_Meta_Box::DISABLED_POST_META_KEY, true ) ); } /** From 18ab955daee5be27dd2415b23adb9ddea3df805c Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 16:13:11 -0800 Subject: [PATCH 09/14] Use queried object in amp_render() and allow passing post object to AMP_Post_Template for sake of preview --- amp.php | 30 ++++- includes/class-amp-post-template.php | 191 ++++++++++++++++++++------- 2 files changed, 163 insertions(+), 58 deletions(-) diff --git a/amp.php b/amp.php index e5f512b8544..efdea37fe33 100644 --- a/amp.php +++ b/amp.php @@ -148,24 +148,40 @@ function amp_prepare_render() { add_action( 'template_redirect', 'amp_render' ); } +/** + * Render AMP for queried post. + * + * @since 0.1 + */ function amp_render() { - $post_id = get_queried_object_id(); - amp_render_post( $post_id ); + + // Note that queried object is used instead of the ID so that the_preview for the queried post can apply. + amp_render_post( get_queried_object() ); exit; } -function amp_render_post( $post_id ) { - $post = get_post( $post_id ); - if ( ! $post ) { - return; +/** + * Render AMP post template. + * + * @since 0.5 + * @param WP_Post|int $post Post. + */ +function amp_render_post( $post ) { + + if ( ! ( $post instanceof WP_Post ) ) { + $post = get_post( $post ); + if ( ! $post ) { + return; + } } + $post_id = $post->ID; amp_load_classes(); do_action( 'pre_amp_render_post', $post_id ); amp_add_post_template_actions(); - $template = new AMP_Post_Template( $post_id ); + $template = new AMP_Post_Template( $post ); $template->load(); } diff --git a/includes/class-amp-post-template.php b/includes/class-amp-post-template.php index 8c1adc7cdc6..020b2007781 100644 --- a/includes/class-amp-post-template.php +++ b/includes/class-amp-post-template.php @@ -1,48 +1,129 @@ template_dir = apply_filters( 'amp_post_template_dir', AMP__DIR__ . '/templates' ); - $this->ID = $post_id; - $this->post = get_post( $post_id ); + if ( $post instanceof WP_Post ) { + $this->ID = $post->ID; + $this->post = $post; + } else { + $this->post = get_post( $post ); + $this->ID = $this->post->ID; + } + $post_id = $this->ID; $content_max_width = self::CONTENT_MAX_WIDTH; if ( isset( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 0 ) { @@ -51,34 +132,34 @@ public function __construct( $post_id ) { $content_max_width = apply_filters( 'amp_content_max_width', $content_max_width ); $this->data = array( - 'content_max_width' => $content_max_width, + 'content_max_width' => $content_max_width, - 'document_title' => function_exists( 'wp_get_document_title' ) ? wp_get_document_title() : wp_title( '', false ), // back-compat with 4.3 - 'canonical_url' => get_permalink( $post_id ), - 'home_url' => home_url(), - 'blog_name' => get_bloginfo( 'name' ), + 'document_title' => function_exists( 'wp_get_document_title' ) ? wp_get_document_title() : wp_title( '', false ), // Back-compat with 4.3. + 'canonical_url' => get_permalink( $post_id ), + 'home_url' => home_url(), + 'blog_name' => get_bloginfo( 'name' ), 'generator_metadata' => 'AMP Plugin v' . AMP__VERSION, - 'html_tag_attributes' => array(), - 'body_class' => '', + 'html_tag_attributes' => array(), + 'body_class' => '', - 'site_icon_url' => apply_filters( 'amp_site_icon_url', function_exists( 'get_site_icon_url' ) ? get_site_icon_url( self::SITE_ICON_SIZE ) : '' ), + 'site_icon_url' => apply_filters( 'amp_site_icon_url', function_exists( 'get_site_icon_url' ) ? get_site_icon_url( self::SITE_ICON_SIZE ) : '' ), 'placeholder_image_url' => amp_get_asset_url( 'images/placeholder-icon.png' ), - 'featured_image' => false, - 'comments_link_url' => false, - 'comments_link_text' => false, + 'featured_image' => false, + 'comments_link_url' => false, + 'comments_link_text' => false, - 'amp_runtime_script' => 'https://cdn.ampproject.org/v0.js', + 'amp_runtime_script' => 'https://cdn.ampproject.org/v0.js', 'amp_component_scripts' => array(), - 'customizer_settings' => array(), + 'customizer_settings' => array(), - 'font_urls' => array( + 'font_urls' => array( 'merriweather' => 'https://fonts.googleapis.com/css?family=Merriweather:400,400italic,700,700italic', ), - 'post_amp_styles' => array(), + 'post_amp_styles' => array(), /** * Add amp-analytics tags. @@ -86,18 +167,26 @@ public function __construct( $post_id ) { * This filter allows you to easily insert any amp-analytics tags without needing much heavy lifting. * * @since 0.4 - *. - * @param array $analytics An associative array of the analytics entries we want to output. Each array entry must have a unique key, and the value should be an array with the following keys: `type`, `attributes`, `script_data`. See readme for more details. - * @param object $post The current post. + * + * @param array $analytics An associative array of the analytics entries we want to output. Each array entry must have a unique key, and the value should be an array with the following keys: `type`, `attributes`, `script_data`. See readme for more details. + * @param WP_Post $post The current post. */ 'amp_analytics' => apply_filters( 'amp_post_template_analytics', array(), $this->post ), - ); + ); $this->build_post_content(); $this->build_post_data(); $this->build_customizer_settings(); $this->build_html_tag_attributes(); + /** + * Filters AMP template data. + * + * @since 0.2 + * + * @param array $data Template data. + * @param WP_Post $post Post. + */ $this->data = apply_filters( 'amp_post_template_data', $this->data, $this->post ); } From ced9461d1bdfe68d2d47f6a776a529452f2cf782 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 17:18:01 -0800 Subject: [PATCH 10/14] Eliminate need to bind this context in JS; add AMP preview button screen reader text --- assets/js/amp-post-meta-box.js | 238 +++++++++++---------- includes/admin/class-amp-post-meta-box.php | 4 + 2 files changed, 127 insertions(+), 115 deletions(-) diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index 67e41255e24..b71c9cfba6e 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -3,13 +3,15 @@ /** * AMP Post Meta Box. * + * @todo Rename this to be just the ampEditPostScreen? + * * @since 0.6 */ var ampPostMetaBox = ( function( $ ) { 'use strict'; - // Exports. - return { + var component = { + /** * Holds data. * @@ -18,7 +20,10 @@ var ampPostMetaBox = ( function( $ ) { data: { previewLink: '', disabled: false, - statusInputName: '' + statusInputName: '', + l10n: { + ampPreviewBtnLabel: '' + } }, /** @@ -33,131 +38,134 @@ var ampPostMetaBox = ( function( $ ) { * * @since 0.6 */ - previewBtn: '#post-preview', + previewBtnSelector: '#post-preview', /** * AMP preview button selector. * * @since 0.6 */ - ampPreviewBtn: '#amp-post-preview', + ampPreviewBtnSelector: '#amp-post-preview' + }; - /** - * Boot plugin. - * - * @since 0.6 - * @param {Object} data Object data. - * @return {void} - */ - boot: function( data ) { - this.data = data; - $( document ).ready( function() { - if ( ! this.data.disabled ) { - this.addPreviewButton(); - } - this.listen(); - }.bind( this ) ); - }, + /** + * Boot plugin. + * + * @since 0.6 + * @param {Object} data Object data. + * @return {void} + */ + component.boot = function boot( data ) { + component.data = data; + $( document ).ready( function() { + if ( ! component.data.disabled ) { + component.addPreviewButton(); + } + component.listen(); + } ); + }; - /** - * Events listener. - * - * @since 0.6 - * @return {void} - */ - listen: function() { - $( this.ampPreviewBtn ).on( 'click.amp-post-preview', function( e ) { - e.preventDefault(); - this.onAmpPreviewButtonClick(); - }.bind( this ) ); - - $( '.edit-amp-status, [href="#amp_status"]' ).click( function( e ) { - e.preventDefault(); - this.toggleAmpStatus( $( e.target ) ); - }.bind( this ) ); - - $( '#submitpost input[type="submit"]' ).on( 'click', function() { - $( this.ampPreviewBtn ).addClass( 'amp-disabled' ); - }.bind( this ) ); - }, + /** + * Events listener. + * + * @since 0.6 + * @return {void} + */ + component.listen = function listen() { + $( component.ampPreviewBtnSelector ).on( 'click.amp-post-preview', function( e ) { + e.preventDefault(); + component.onAmpPreviewButtonClick(); + } ); + + $( '.edit-amp-status, [href="#amp_status"]' ).click( function( e ) { + e.preventDefault(); + component.toggleAmpStatus( $( e.target ) ); + } ); + + $( '#submitpost input[type="submit"]' ).on( 'click', function() { + $( component.ampPreviewBtnSelector ).addClass( 'amp-disabled' ); + } ); + }; - /** - * Add AMP Preview button. - * - * @since 0.6 - * @return {void} - */ - addPreviewButton: function() { - var previewBtn = $( this.previewBtn ); - previewBtn.addClass( 'without-amp' ); - previewBtn - .clone() - .insertAfter( previewBtn ) - .prop( { - 'href': this.data.previewLink, - 'id': this.ampPreviewBtn.replace( '#', '' ) - } ) - .parent() - .addClass( 'has-next-sibling' ); - }, + /** + * Add AMP Preview button. + * + * @since 0.6 + * @return {void} + */ + component.addPreviewButton = function addPreviewButton() { + var previewBtn = $( component.previewBtnSelector ); + previewBtn + .clone() + .insertAfter( previewBtn ) + .prop( { + 'href': component.data.previewLink, + 'id': component.ampPreviewBtnSelector.replace( '#', '' ) + } ) + .text( component.data.l10n.ampPreviewBtnLabel ) + .parent() + .addClass( 'has-next-sibling' ); + previewBtn.addClass( 'without-amp' ); + }; - /** - * AMP Preview button click handler. - * - * We trigger the Core preview link for events propagation purposes. - * - * @since 0.6 - * @return {void} - */ - onAmpPreviewButtonClick: function() { - var $input; - - // Flag the AMP preview referer. - $input = $( '' ) - .prop( { - 'type': 'hidden', - 'name': 'amp-preview', - 'value': 'do-preview' - } ) - .insertAfter( this.ampPreviewBtn ); - - // Trigger Core preview button and remove AMP flag. - $( this.previewBtn ).click(); - $input.remove(); - }, + /** + * AMP Preview button click handler. + * + * We trigger the Core preview link for events propagation purposes. + * + * @since 0.6 + * @return {void} + */ + component.onAmpPreviewButtonClick = function onAmpPreviewButtonClick() { + var $input; + + // Flag the AMP preview referer. + $input = $( '' ) + .prop( { + 'type': 'hidden', + 'name': 'amp-preview', + 'value': 'do-preview' + } ) + .insertAfter( component.ampPreviewBtnSelector ); + + // Trigger Core preview button and remove AMP flag. + $( component.previewBtnSelector ).click(); + $input.remove(); + }; - /** - * Add AMP status toggle. - * - * @since 0.6 - * @param {Object} $target Event target. - * @return {void} - */ - toggleAmpStatus: function( $target ) { - var $container = $( '#amp-status-select' ), - status = $container.data( 'amp-status' ), - $checked, - editAmpStatus = $( '.edit-amp-status' ); - - // Don't modify status on cancel button click. - if ( ! $target.hasClass( 'button-cancel' ) ) { - status = $( '[name="' + this.data.statusInputName + '"]:checked' ).val(); - } + /** + * Add AMP status toggle. + * + * @since 0.6 + * @param {Object} $target Event target. + * @return {void} + */ + component.toggleAmpStatus = function toggleAmpStatus( $target ) { + var $container = $( '#amp-status-select' ), + status = $container.data( 'amp-status' ), + $checked, + editAmpStatus = $( '.edit-amp-status' ); + + // Don't modify status on cancel button click. + if ( ! $target.hasClass( 'button-cancel' ) ) { + status = $( '[name="' + component.data.statusInputName + '"]:checked' ).val(); + } - $checked = $( '#amp-status-' + status ); + $checked = $( '#amp-status-' + status ); - // Toggle elements. - editAmpStatus.fadeToggle( this.toggleSpeed, function() { - if ( editAmpStatus.is( ':visible' ) ) { - editAmpStatus.focus(); - } - } ); - $container.slideToggle( this.toggleSpeed ); + // Toggle elements. + editAmpStatus.fadeToggle( component.toggleSpeed, function() { + if ( editAmpStatus.is( ':visible' ) ) { + editAmpStatus.focus(); + } + } ); + $container.slideToggle( component.toggleSpeed ); - // Update status. - $container.data( 'amp-status', status ); - $checked.prop( 'checked', true ); - $( '.amp-status-text' ).text( $checked.next().text() ); - } + // Update status. + $container.data( 'amp-status', status ); + $checked.prop( 'checked', true ); + $( '.amp-status-text' ).text( $checked.next().text() ); }; + + return component; })( window.jQuery ); diff --git a/includes/admin/class-amp-post-meta-box.php b/includes/admin/class-amp-post-meta-box.php index 4101df023b3..e3b23270357 100644 --- a/includes/admin/class-amp-post-meta-box.php +++ b/includes/admin/class-amp-post-meta-box.php @@ -104,6 +104,9 @@ public function enqueue_admin_assets() { 'previewLink' => esc_url_raw( add_query_arg( AMP_QUERY_VAR, '', get_preview_post_link( $post ) ) ), 'disabled' => (bool) get_post_meta( $post->ID, self::DISABLED_POST_META_KEY, true ), 'statusInputName' => self::STATUS_INPUT_NAME, + 'l10n' => array( + 'ampPreviewBtnLabel' => __( 'Preview changes in AMP (opens in new window)', 'amp' ), + ), ) ) ) ); } @@ -129,6 +132,7 @@ public function render_status( $post ) { return; } + // The following variables are used inside amp-status.php template. $disabled = (bool) get_post_meta( $post->ID, self::DISABLED_POST_META_KEY, true ); $status = $disabled ? 'disabled' : 'enabled'; $labels = array( From 1134bb1982bc90405b8c71fbf9a11ad6b2dff1ea Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 20:29:52 -0800 Subject: [PATCH 11/14] Add amp prefix for define_query_var function; make sure constant defined before use --- amp.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/amp.php b/amp.php index efdea37fe33..56344025e68 100644 --- a/amp.php +++ b/amp.php @@ -62,6 +62,7 @@ function amp_init() { load_plugin_textdomain( 'amp', false, plugin_basename( AMP__DIR__ ) . '/languages' ); + amp_define_query_var(); add_rewrite_endpoint( AMP_QUERY_VAR, EP_PERMALINK ); add_filter( 'request', 'amp_force_query_var_value' ); @@ -83,7 +84,11 @@ function amp_init() { * * @since 0.6 */ -function define_query_var() { +function amp_define_query_var() { + if ( defined( 'AMP_QUERY_VAR' ) ) { + return; + } + /** * Filter the AMP query variable. * @@ -92,7 +97,7 @@ function define_query_var() { */ define( 'AMP_QUERY_VAR', apply_filters( 'amp_query_var', 'amp' ) ); } -add_action( 'after_setup_theme', 'define_query_var', 3 ); +add_action( 'after_setup_theme', 'amp_define_query_var', 3 ); // Make sure the `amp` query var has an explicit value. // Avoids issues when filtering the deprecated `query_string` hook. From 5c5074e343bbca852296c82f79ae1778d0496268 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 6 Dec 2017 20:34:42 -0800 Subject: [PATCH 12/14] Improve styling and behavior of AMP preview button --- assets/css/amp-post-meta-box.css | 14 +++++--------- assets/js/amp-post-meta-box.js | 5 ++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index d11cc755ba1..87acf58f224 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -5,26 +5,22 @@ */ /* Core preview button */ -#post-preview.without-amp { +.wp-core-ui #preview-action.has-amp-preview #post-preview { border-top-right-radius: 0; border-bottom-right-radius: 0; float: none; } /* AMP preview button */ -#amp-post-preview { +.wp-core-ui #amp-post-preview.preview { border-top-left-radius: 0; border-bottom-left-radius: 0; text-indent: -9999px; width: 30px; - background-image: url( '../images/amp-icon.svg' ); - background-position: center; - background-repeat: no-repeat; - background-size: 14px; + background: no-repeat center url( '../images/amp-icon.svg' ) !important; /* Important needed due to .disabled rule in buttons.css */ + background-size: 14px !important; } - -#amp-post-preview.amp-disabled { - box-shadow: none; +.wp-core-ui #amp-post-preview.preview.disabled { opacity: 0.7; } diff --git a/assets/js/amp-post-meta-box.js b/assets/js/amp-post-meta-box.js index b71c9cfba6e..6d5d7253fda 100644 --- a/assets/js/amp-post-meta-box.js +++ b/assets/js/amp-post-meta-box.js @@ -83,7 +83,7 @@ var ampPostMetaBox = ( function( $ ) { } ); $( '#submitpost input[type="submit"]' ).on( 'click', function() { - $( component.ampPreviewBtnSelector ).addClass( 'amp-disabled' ); + $( component.ampPreviewBtnSelector ).addClass( 'disabled' ); } ); }; @@ -104,8 +104,7 @@ var ampPostMetaBox = ( function( $ ) { } ) .text( component.data.l10n.ampPreviewBtnLabel ) .parent() - .addClass( 'has-next-sibling' ); - previewBtn.addClass( 'without-amp' ); + .addClass( 'has-amp-preview' ); }; /** From 802bcfb5f2b31671c41b61cb24ff3b28bf4f2d51 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Thu, 7 Dec 2017 11:07:46 +0100 Subject: [PATCH 13/14] Improve AMP Preview button styling --- assets/css/amp-post-meta-box.css | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/assets/css/amp-post-meta-box.css b/assets/css/amp-post-meta-box.css index 87acf58f224..154667b649f 100644 --- a/assets/css/amp-post-meta-box.css +++ b/assets/css/amp-post-meta-box.css @@ -16,12 +16,20 @@ border-top-left-radius: 0; border-bottom-left-radius: 0; text-indent: -9999px; - width: 30px; - background: no-repeat center url( '../images/amp-icon.svg' ) !important; /* Important needed due to .disabled rule in buttons.css */ + padding-right: 7px; + padding-left: 7px; +} + +.wp-core-ui #amp-post-preview.preview::after { + content: "icon"; + width: 14px; + float: left; + background: no-repeat center url( '../images/amp-icon.svg' ); background-size: 14px !important; } -.wp-core-ui #amp-post-preview.preview.disabled { - opacity: 0.7; + +.wp-core-ui #amp-post-preview.preview.disabled::after { + opacity: 0.6; } /* AMP status */ From 1b6cc5465114be26502b22319f2fdeab3a3ae651 Mon Sep 17 00:00:00 2001 From: ThierryA Date: Thu, 7 Dec 2017 11:12:28 +0100 Subject: [PATCH 14/14] Slight code improvement --- includes/class-amp-post-template.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/includes/class-amp-post-template.php b/includes/class-amp-post-template.php index 020b2007781..49177f8ede4 100644 --- a/includes/class-amp-post-template.php +++ b/includes/class-amp-post-template.php @@ -117,13 +117,11 @@ public function __construct( $post ) { $this->template_dir = apply_filters( 'amp_post_template_dir', AMP__DIR__ . '/templates' ); if ( $post instanceof WP_Post ) { - $this->ID = $post->ID; $this->post = $post; } else { $this->post = get_post( $post ); - $this->ID = $this->post->ID; } - $post_id = $this->ID; + $this->ID = $this->post->ID; $content_max_width = self::CONTENT_MAX_WIDTH; if ( isset( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 0 ) { @@ -135,7 +133,7 @@ public function __construct( $post ) { 'content_max_width' => $content_max_width, 'document_title' => function_exists( 'wp_get_document_title' ) ? wp_get_document_title() : wp_title( '', false ), // Back-compat with 4.3. - 'canonical_url' => get_permalink( $post_id ), + 'canonical_url' => get_permalink( $this->ID ), 'home_url' => home_url(), 'blog_name' => get_bloginfo( 'name' ), 'generator_metadata' => 'AMP Plugin v' . AMP__VERSION,