Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #864: Fix 'Video' widget for YouTube and Vimeo, simplify 'Gallery' solution #921

Merged
merged 11 commits into from
Feb 3, 2018
Merged
2 changes: 1 addition & 1 deletion includes/amp-helper-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,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(),
Expand All @@ -231,6 +230,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
Expand Down
3 changes: 2 additions & 1 deletion includes/class-amp-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
20 changes: 16 additions & 4 deletions includes/embeds/class-amp-gallery-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Copy link
Contributor Author

@kienstra kienstra Jan 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extends an abstract class, so this method has to be implemented. This isn't ideal, but editing this embed handler enables deleting the entire 'Gallery' widget subclass.


/**
* Shortcode handler.
Expand Down Expand Up @@ -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 <amp-carousel>.
*
* @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.
*
Expand Down
24 changes: 24 additions & 0 deletions includes/embeds/class-amp-vimeo-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}

}
26 changes: 25 additions & 1 deletion includes/embeds/class-amp-youtube-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ 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 );
}
}

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() {
Expand Down Expand Up @@ -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;
}

}
3 changes: 2 additions & 1 deletion includes/sanitizers/class-amp-video-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down
67 changes: 0 additions & 67 deletions includes/widgets/class-amp-widget-media-gallery.php

This file was deleted.

33 changes: 33 additions & 0 deletions includes/widgets/class-amp-widget-media-video.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Class AMP_Widget_Media_Video
*
* @since 0.7.0
* @package AMP
*/

if ( class_exists( 'WP_Widget_Media_Video' ) ) {
/**
* Class AMP_Widget_Media_Video
*
* @since 0.7.0
* @package AMP
*/
class AMP_Widget_Media_Video extends WP_Widget_Media_Video {

/**
* Overrides the parent callback that strips width and height values.
*
* @param string $html Video shortcode HTML output.
* @return string HTML Output.
*/
public function inject_video_max_width_style( $html ) {
if ( is_amp_endpoint() ) {
return $html;
}
return parent::inject_video_max_width_style( $html );
}

}

}
33 changes: 33 additions & 0 deletions includes/widgets/class-amp-widget-text.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Class AMP_Widget_Text
*
* @since 0.7.0
* @package AMP
*/

if ( class_exists( 'WP_Widget_Text' ) ) {
/**
* Class AMP_Widget_Text
*
* @since 0.7.0
* @package AMP
*/
class AMP_Widget_Text extends WP_Widget_Text {

/**
* Overrides the parent callback that strips width and height attributes.
*
* @param array $matches The matches returned from preg_replace_callback().
* @return string $html The markup, unaltered.
*/
public function inject_video_max_width_style( $matches ) {
if ( is_amp_endpoint() ) {
return $matches[0];
}
return parent::inject_video_max_width_style( $matches );
}

}

}
24 changes: 12 additions & 12 deletions tests/test-amp-video-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,70 +10,70 @@ public function get_data() {

'simple_video' => array(
'<video width="300" height="300" src="https://example.com/video.mp4"></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_without_dimensions' => array(
'<video src="https://example.com/file.mp4"></video>',
'<amp-video src="https://example.com/file.mp4" height="400" layout="fixed-height"></amp-video>',
'<amp-video style="max-width:100%" src="https://example.com/file.mp4" height="400" layout="fixed-height"></amp-video>',
),

'autoplay_attribute' => array(
'<video width="300" height="300" src="https://example.com/video.mp4" autoplay></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" autoplay="" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" autoplay="" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'autoplay_attribute__false' => array(
'<video width="300" height="300" src="https://example.com/video.mp4" autoplay="false"></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_with_whitelisted_attributes__enabled' => array(
'<video width="300" height="300" src="https://example.com/video.mp4" controls loop="true" muted="muted"></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" controls="" loop="" muted="" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" controls="" loop="" muted="" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_with_whitelisted_attributes__disabled' => array(
'<video width="300" height="300" src="https://example.com/video.mp4" controls="false" loop="false" muted="false"></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_with_blacklisted_attribute' => array(
'<video width="300" height="300" src="https://example.com/video.mp4" style="border-color: red;"></video>',
'<amp-video width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="https://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_with_sizes_attribute_is_overridden' => array(
'<video width="300" height="200" src="https://example.com/file.mp4" sizes="(min-width: 100px) 200px, 90vw"></video>',
'<amp-video width="300" height="200" src="https://example.com/file.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="200" src="https://example.com/file.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'video_with_children' => array(
'<video width="480" height="300" poster="https://example.com/video-image.gif">
<source src="https://example.com/video.mp4" type="video/mp4">
<source src="https://example.com/video.ogv" type="video/ogg">
</video>',
'<amp-video width="480" height="300" poster="https://example.com/video-image.gif" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"><source src="https://example.com/video.mp4" type="video/mp4"><source src="https://example.com/video.ogv" type="video/ogg"></amp-video>',
'<amp-video style="max-width:100%" width="480" height="300" poster="https://example.com/video-image.gif" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"><source src="https://example.com/video.mp4" type="video/mp4"><source src="https://example.com/video.ogv" type="video/ogg"></amp-video>',
),

'multiple_same_video' => array(
'<video src="https://example.com/video.mp4" width="480" height="300"></video>
<video src="https://example.com/video.mp4" width="480" height="300"></video>
<video src="https://example.com/video.mp4" width="480" height="300"></video>
<video src="https://example.com/video.mp4" width="480" height="300"></video>',
'<amp-video src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video style="max-width:100%" src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video style="max-width:100%" src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video style="max-width:100%" src="https://example.com/video.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'multiple_different_videos' => array(
'<video src="https://example.com/video1.mp4" width="480" height="300"></video>
<video src="https://example.com/video2.ogv" width="300" height="480"></video>
<video src="https://example.com/video3.webm" height="100" width="200"></video>',
'<amp-video src="https://example.com/video1.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video src="https://example.com/video2.ogv" width="300" height="480" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video src="https://example.com/video3.webm" height="100" width="200" sizes="(min-width: 200px) 200px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" src="https://example.com/video1.mp4" width="480" height="300" sizes="(min-width: 480px) 480px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video style="max-width:100%" src="https://example.com/video2.ogv" width="300" height="480" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video><amp-video style="max-width:100%" src="https://example.com/video3.webm" height="100" width="200" sizes="(min-width: 200px) 200px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),

'https_not_required' => array(
'<video width="300" height="300" src="http://example.com/video.mp4"></video>',
'<amp-video width="300" height="300" src="http://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
'<amp-video style="max-width:100%" width="300" height="300" src="http://example.com/video.mp4" sizes="(min-width: 300px) 300px, 100vw" class="amp-wp-enforced-sizes"></amp-video>',
),
);
}
Expand Down
Loading