diff --git a/includes/amp-helper-functions.php b/includes/amp-helper-functions.php index f3a4d9896a9..4939f0417f8 100644 --- a/includes/amp-helper-functions.php +++ b/includes/amp-helper-functions.php @@ -293,7 +293,6 @@ function amp_get_content_sanitizers( $post = null ) { */ return apply_filters( 'amp_content_sanitizers', array( - 'AMP_Style_Sanitizer' => array(), 'AMP_Img_Sanitizer' => array(), 'AMP_Form_Sanitizer' => array(), 'AMP_Comments_Sanitizer' => array(), @@ -303,6 +302,7 @@ function amp_get_content_sanitizers( $post = null ) { 'AMP_Iframe_Sanitizer' => array( 'add_placeholder' => true, ), + 'AMP_Style_Sanitizer' => array(), 'AMP_Tag_And_Attribute_Sanitizer' => array(), // Note: This whitelist sanitizer must come at the end to clean up any remaining issues the other sanitizers didn't catch. ), $post diff --git a/includes/class-amp-autoloader.php b/includes/class-amp-autoloader.php index 5c51b42af09..f9dfb3dc175 100644 --- a/includes/class-amp-autoloader.php +++ b/includes/class-amp-autoloader.php @@ -88,8 +88,9 @@ class AMP_Autoloader { 'AMP_WP_Utils' => 'includes/utils/class-amp-wp-utils', 'AMP_Widget_Archives' => 'includes/widgets/class-amp-widget-archives', 'AMP_Widget_Categories' => 'includes/widgets/class-amp-widget-categories', - 'AMP_Widget_Media_Gallery' => 'includes/widgets/class-amp-widget-media-gallery', + 'AMP_Widget_Media_Video' => 'includes/widgets/class-amp-widget-media-video', 'AMP_Widget_Recent_Comments' => 'includes/widgets/class-amp-widget-recent-comments', + 'AMP_Widget_Text' => 'includes/widgets/class-amp-widget-text', 'WPCOM_AMP_Polldaddy_Embed' => 'wpcom/class-amp-polldaddy-embed', 'AMP_Test_Stub_Sanitizer' => 'tests/stubs', 'AMP_Test_World_Sanitizer' => 'tests/stubs', diff --git a/includes/embeds/class-amp-gallery-embed.php b/includes/embeds/class-amp-gallery-embed.php index 1261d38747b..46d44fd6951 100644 --- a/includes/embeds/class-amp-gallery-embed.php +++ b/includes/embeds/class-amp-gallery-embed.php @@ -16,15 +16,13 @@ class AMP_Gallery_Embed_Handler extends AMP_Base_Embed_Handler { * Register embed. */ public function register_embed() { - add_shortcode( 'gallery', array( $this, 'shortcode' ) ); + add_filter( 'post_gallery', array( $this, 'override_gallery' ), 10, 2 ); } /** * Unregister embed. */ - public function unregister_embed() { - remove_shortcode( 'gallery' ); - } + public function unregister_embed() {} /** * Shortcode handler. @@ -120,6 +118,20 @@ public function shortcode( $attr ) { ) ); } + /** + * Override the output of gallery_shortcode(). + * + * The 'Gallery' widget also uses this function. + * This ensures that it outputs an . + * + * @param string $html Markup to filter, possibly ''. + * @param array $attributes Shortcode attributes. + * @return string $html Markup for the gallery. + */ + public function override_gallery( $html, $attributes ) { + return $this->shortcode( $attributes ); + } + /** * Render. * diff --git a/includes/embeds/class-amp-vimeo-embed.php b/includes/embeds/class-amp-vimeo-embed.php index 6e0754b227e..6b334ce6441 100644 --- a/includes/embeds/class-amp-vimeo-embed.php +++ b/includes/embeds/class-amp-vimeo-embed.php @@ -32,6 +32,7 @@ function __construct( $args = array() ) { function register_embed() { wp_embed_register_handler( 'amp-vimeo', self::URL_PATTERN, array( $this, 'oembed' ), -1 ); add_shortcode( 'vimeo', array( $this, 'shortcode' ) ); + add_filter( 'wp_video_shortcode_override', array( $this, 'video_override' ), 10, 2 ); } public function unregister_embed() { @@ -107,4 +108,27 @@ private function get_video_id_from_url( $url ) { return $video_id; } + + /** + * Override the output of Vimeo videos. + * + * This overrides the value in wp_video_shortcode(). + * The pattern matching is copied from WP_Widget_Media_Video::render(). + * + * @param string $html Empty variable to be replaced with shortcode markup. + * @param array $attr The shortcode attributes. + * @return string|null $markup The markup to output. + */ + public function video_override( $html, $attr ) { + if ( ! isset( $attr['src'] ) ) { + return $html; + } + $src = $attr['src']; + $vimeo_pattern = '#^https?://(.+\.)?vimeo\.com/.*#'; + if ( 1 === preg_match( $vimeo_pattern, $src ) ) { + return $this->shortcode( array( $src ) ); + } + return $html; + } + } diff --git a/includes/embeds/class-amp-youtube-embed.php b/includes/embeds/class-amp-youtube-embed.php index be1b3217a5a..a019a6a6334 100644 --- a/includes/embeds/class-amp-youtube-embed.php +++ b/includes/embeds/class-amp-youtube-embed.php @@ -24,7 +24,7 @@ function __construct( $args = array() ) { if ( isset( $this->args['content_max_width'] ) ) { $max_width = $this->args['content_max_width']; - $this->args['width'] = $max_width; + $this->args['width'] = $max_width; $this->args['height'] = round( $max_width * self::RATIO ); } } @@ -32,6 +32,7 @@ function __construct( $args = array() ) { function register_embed() { wp_embed_register_handler( 'amp-youtube', self::URL_PATTERN, array( $this, 'oembed' ), -1 ); add_shortcode( 'youtube', array( $this, 'shortcode' ) ); + add_filter( 'wp_video_shortcode_override', array( $this, 'video_override' ), 10, 2 ); } public function unregister_embed() { @@ -125,4 +126,27 @@ private function sanitize_v_arg( $value ) { return $value; } + + /** + * Override the output of YouTube videos. + * + * This overrides the value in wp_video_shortcode(). + * The pattern matching is copied from WP_Widget_Media_Video::render(). + * + * @param string $html Empty variable to be replaced with shortcode markup. + * @param array $attr The shortcode attributes. + * @return string|null $markup The markup to output. + */ + public function video_override( $html, $attr ) { + if ( ! isset( $attr['src'] ) ) { + return $html; + } + $src = $attr['src']; + $youtube_pattern = '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#'; + if ( 1 === preg_match( $youtube_pattern, $src ) ) { + return $this->shortcode( array( $src ) ); + } + return $html; + } + } diff --git a/includes/sanitizers/class-amp-video-sanitizer.php b/includes/sanitizers/class-amp-video-sanitizer.php index 804a2a6ceb8..87bf0df6924 100644 --- a/includes/sanitizers/class-amp-video-sanitizer.php +++ b/includes/sanitizers/class-amp-video-sanitizer.php @@ -124,7 +124,8 @@ public function sanitize() { * @return array Returns HTML attributes; removes any not specifically declared above from input. */ private function filter_attributes( $attributes ) { - $out = array(); + $out = array(); + $out['style'] = 'max-width:100%'; // Note that this will get moved to amp-custom style by AMP_Style_Sanitizer. foreach ( $attributes as $name => $value ) { switch ( $name ) { diff --git a/includes/widgets/class-amp-widget-media-gallery.php b/includes/widgets/class-amp-widget-media-gallery.php deleted file mode 100644 index e836025a986..00000000000 --- a/includes/widgets/class-amp-widget-media-gallery.php +++ /dev/null @@ -1,67 +0,0 @@ -get_instance_schema(), 'default' ), $instance ); - $shortcode_atts = array_merge( - $instance, - array( - 'link' => $instance['link_type'], - ) - ); - - if ( isset( $instance['orderby_random'] ) && ( true === $instance['orderby_random'] ) ) { - $shortcode_atts['orderby'] = 'rand'; - } - - /* - * The following calls do_shortcode() in case another plugin overrides the gallery shortcode. - * The AMP_Gallery_Embed_Handler in the plugin is doing this itself, but other plugins may - * do it as well, so this ensures that a plugin has the option to override the gallery behavior - * via registering a different gallery shortcode handler. The shortcode serialization can be - * eliminated once WP Trac #25435 is merged and the Gallery widget uses the proposed do_single_shortcode(). - */ - $shortcode_atts_str = ''; - if ( is_array( $shortcode_atts['ids'] ) ) { - $shortcode_atts['ids'] = join( ',', $shortcode_atts['ids'] ); - } - foreach ( $shortcode_atts as $key => $value ) { - $shortcode_atts_str .= sprintf( ' %s="%s"', $key, esc_attr( $value ) ); - } - echo do_shortcode( "[gallery $shortcode_atts_str]" ); // WPCS: XSS ok. - } - - } -} diff --git a/includes/widgets/class-amp-widget-media-video.php b/includes/widgets/class-amp-widget-media-video.php new file mode 100644 index 00000000000..1bcdfad5fc3 --- /dev/null +++ b/includes/widgets/class-amp-widget-media-video.php @@ -0,0 +1,33 @@ + array( '', - '', + '', ), 'video_without_dimensions' => array( '', - '', + '', ), 'autoplay_attribute' => array( '', - '', + '', ), 'autoplay_attribute__false' => array( '', - '', + '', ), 'video_with_whitelisted_attributes__enabled' => array( '', - '', + '', ), 'video_with_whitelisted_attributes__disabled' => array( '', - '', + '', ), 'video_with_blacklisted_attribute' => array( '', - '', + '', ), 'video_with_sizes_attribute_is_overridden' => array( '', - '', + '', ), 'video_with_children' => array( @@ -53,7 +53,7 @@ public function get_data() { ', - '', + '', ), 'multiple_same_video' => array( @@ -61,19 +61,19 @@ public function get_data() { ', - '', + '', ), 'multiple_different_videos' => array( ' ', - '', + '', ), 'https_not_required' => array( '', - '', + '', ), ); } diff --git a/tests/test-class-amp-vimeo-embed-handler.php b/tests/test-class-amp-vimeo-embed-handler.php new file mode 100644 index 00000000000..15e14b1f37f --- /dev/null +++ b/tests/test-class-amp-vimeo-embed-handler.php @@ -0,0 +1,69 @@ +handler = new AMP_Vimeo_Embed_Handler(); + } + + /** + * Test video_override(). + * + * @covers AMP_Vimeo_Embed_Handler::video_override() + */ + public function test_video_override() { + remove_all_filters( 'wp_video_shortcode_override' ); + $this->handler->register_embed(); + $youtube_id = 'XOY3ZUO6P0k'; + $youtube_src = 'https://youtu.be/' . $youtube_id; + $attr_youtube = array( + 'src' => $youtube_src, + ); + + $youtube_shortcode = $this->handler->video_override( '', $attr_youtube ); + $this->assertEquals( '', $youtube_shortcode ); + + $vimeo_id = '64086087'; + $vimeo_src = 'https://vimeo.com/' . $vimeo_id; + $attr_vimeo = array( + 'src' => $vimeo_src, + ); + $yimeo_shortcode = $this->handler->video_override( '', $attr_vimeo ); + $this->assertContains( 'assertContains( $vimeo_id, $yimeo_shortcode ); + + $daily_motion_id = 'x6bacgf'; + $daily_motion_src = 'http://www.dailymotion.com/video/' . $daily_motion_id; + $attr_daily_motion = array( + 'src' => $daily_motion_src, + ); + $daily_motion_shortcode = $this->handler->video_override( '', $attr_daily_motion ); + $this->assertEquals( '', $daily_motion_shortcode ); + $no_attributes = $this->handler->video_override( '', array() ); + $this->assertEquals( '', $no_attributes ); + remove_all_filters( 'wp_video_shortcode_override' ); + } + +} diff --git a/tests/test-class-amp-widget-media-gallery.php b/tests/test-class-amp-widget-media-gallery.php deleted file mode 100644 index 281dd205adb..00000000000 --- a/tests/test-class-amp-widget-media-gallery.php +++ /dev/null @@ -1,77 +0,0 @@ -markTestSkipped( 'This WordPress version does not have a Gallery widget.' ); - } - parent::setUp(); - AMP_Theme_Support::register_widgets(); - $this->instance = new AMP_Widget_Media_Gallery(); - } - - /** - * Test render_media(). - * - * @see AMP_Widget_Media_Gallery::widget(). - */ - public function test_render_media() { - $first_test_image = '/tmp/test-image.jpg'; - copy( DIR_TESTDATA . '/images/test-image.jpg', $first_test_image ); - $first_attachment_id = self::factory()->attachment->create_object( array( - 'file' => $first_test_image, - 'post_parent' => 0, - 'post_mime_type' => 'image/jpeg', - 'post_title' => 'Test Image', - ) ); - wp_update_attachment_metadata( $first_attachment_id, wp_generate_attachment_metadata( $first_attachment_id, $first_test_image ) ); - $ids[] = $first_attachment_id; - - $second_test_image = '/tmp/test-image.jpg'; - copy( DIR_TESTDATA . '/images/test-image.jpg', $second_test_image ); - $second_attachment_id = self::factory()->attachment->create_object( array( - 'file' => $second_test_image, - 'post_parent' => 0, - 'post_mime_type' => 'image/jpeg', - 'post_title' => 'Test Image', - ) ); - wp_update_attachment_metadata( $second_attachment_id, wp_generate_attachment_metadata( $second_attachment_id, $second_test_image ) ); - $ids[] = $second_attachment_id; - $instance = array( - 'title' => 'Test Gallery Widget', - 'ids' => $ids, - ); - - ob_start(); - $this->instance->render_media( $instance ); - $output = ob_get_clean(); - - $this->assertContains( 'amp-carousel', $output ); - $this->assertContains( $first_test_image, $output ); - $this->assertContains( $second_test_image, $output ); - } - -} diff --git a/tests/test-class-amp-widget-media-video.php b/tests/test-class-amp-widget-media-video.php new file mode 100644 index 00000000000..d93556d85ab --- /dev/null +++ b/tests/test-class-amp-widget-media-video.php @@ -0,0 +1,52 @@ +markTestSkipped( 'This version of WordPress does not have the Video widget, so this test does not apply.' ); + } + parent::setUp(); + wp_maybe_load_widgets(); + $this->widget = new $class(); + } + + /** + * Test inject_video_max_width_style(). + * + * @covers AMP_Widget_Media_Video::inject_video_max_width_style() + */ + public function test_inject_video_max_width_style() { + $video = ''; + $video_no_height = ''; + $this->assertEquals( $video, $this->widget->inject_video_max_width_style( $video ) ); + $this->assertEquals( $video_no_height, $this->widget->inject_video_max_width_style( $video_no_height ) ); + $this->assertEquals( '', $this->widget->inject_video_max_width_style( '' ) ); + } + +} diff --git a/tests/test-class-amp-widget-text.php b/tests/test-class-amp-widget-text.php new file mode 100644 index 00000000000..26d371d666f --- /dev/null +++ b/tests/test-class-amp-widget-text.php @@ -0,0 +1,53 @@ +markTestSkipped( 'This version of WordPress does not have the Video widget, so this test does not apply.' ); + } + parent::setUp(); + wp_maybe_load_widgets(); + $this->widget = new $class(); + } + + /** + * Test inject_video_max_width_style(). + * + * @covers AMP_Widget_Text::inject_video_max_width_style() + */ + public function test_inject_video_max_width_style() { + add_theme_support( 'amp' ); + $video = ''; + $video_only_width = '