-
Notifications
You must be signed in to change notification settings - Fork 383
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 #841: Native AMP audio and video playlists. #954
Conversation
Create a custom shortcode handler for video playlists. Use <amp-video> and <amp-state>, on Weston't suggestion. This still doesn't support audio playlists.
Before, test_shortcode() used test files from Core. But these did not exist in 4.7, and caused a failure. So create new mock files to test.
Use an <amp-carousel>, As <amp-bind> doesn't work with <amp-audio>. Abstract common logic into helper methods. This mainly allows using styling from wp-mediaelement.css. But there are 4 rules needed to correct the styling.
Audio Playlist Support, Screencast This commit adds support for 'audio' playlists. Here's a screencast. This uses an This looks similar to the Core playlist, after pasting wp-mediaelement.css into the dev tools' 'inspector-stylesheet.' But these rules are also needed:
Those rules aren't included in this PR, nor is wp-mediaelement.css. |
@kienstra for the styles I suggest putting it into a CSS file and then enqueueing it. The preprocessor/sanitizer will automatically concatenate it into |
The video and audio playlist need 'wp-mediaelement.' And the audio playlist needs a simple custom stylesheet. Use the action 'wp_enqueue_scripts,' instead of 'wp_playlist_script.' That enqueues too late. Also, update the tests.
Thanks, Enqueued Stylesheets Hi @westonruter, It looks like with the theme
|
@@ -57,7 +64,8 @@ class AMP_Playlist_Embed_Handler extends AMP_Base_Embed_Handler { | |||
* Registers the playlist shortcode. | |||
*/ | |||
public function register_embed() { | |||
add_shortcode( 'playlist', array( $this, 'shortcode' ) ); | |||
add_shortcode( self::SHORTCODE, array( $this, 'shortcode' ) ); | |||
add_action( 'wp_enqueue_scripts', array( $this, 'styling' ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This uses wp_enqueue_scripts
, instead of wp_playlist_script
. That enqueues too late.
foreach ( $this->data['tracks'] as $index => $track ) { | ||
$title = $this->get_title( $track ); | ||
if ( 'audio' === $type ) { | ||
$on = 'tap:AMP.setState({' . $container_id . ': {selectedSlide: ' . $i . '}})'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use wp_json_encode()
here:
- $on = 'tap:AMP.setState({' . $container_id . ': {selectedSlide: ' . $i . '}})';
+ $on = 'tap:AMP.setState(' . wp_json_encode( array( $container_id => array( 'selectedSlide' => $i ) ) ) . ')';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit uses wp_json_encode()
.
} | ||
|
||
?> | ||
<div class="wp-playlist-item" [class]="<?php echo isset( $item_class ) ? esc_attr( $item_class ) : ''; ?>"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to do echo esc_attr( isset( $item_class ) ? $item_class : '' );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other such cases in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit moves the ternary conditionals inside the escaping functions.
<div class="wp-playlist-current-item"> | ||
<amp-img src="<?php echo esc_url( $image_url ); ?>" height="<?php echo esc_attr( $image_height ); ?>" width="<?php echo esc_attr( $image_width ); ?>"></amp-img> | ||
<div class="wp-playlist-caption"> | ||
<span class="wp-playlist-item-meta wp-playlist-item-title"><?php echo isset( $title ) ? esc_html( $title ) : ''; ?></span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The $title
is always going to be set since get_title
returns a string. No need for the isset
check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit from above also removes the isset()
check for $title
.
*/ | ||
public function audio_playlist() { | ||
if ( ! isset( $this->data['tracks'] ) ) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method is declared as returning a string
, so this should return an empty string not void.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commit returns an empty string inside that conditional.
* This uses similar markup to the native playlist shortcode output. | ||
* So the styles from wp-mediaelement.min.css will apply to it. | ||
* | ||
* @global content_width. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be:
- @global content_width.
+ @global int $content_width
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit corrects the DocBlock.
*/ | ||
public function styling() { | ||
global $post; | ||
if ( ! isset( $post->post_content ) || ! has_shortcode( $post->post_content, self::SHORTCODE ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conditional can be removed if styling
is called from inside the playlist method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @westonruter,
It'd be good to remove this conditional. I'll do this if I can figure out the issue that we're discussing above.
$image_url = isset( $track['thumb']['src'] ) ? esc_url( $track['thumb']['src'] ) : ''; | ||
$thumb_dimensions = $this->get_thumb_dimensions( $track ); | ||
$image_height = isset( $thumb_dimensions['height'] ) ? $thumb_dimensions['height'] : ''; | ||
$image_width = isset( $thumb_dimensions['width'] ) ? $thumb_dimensions['width'] : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The width
and height
must be defined in AMP, so if it is not available then we need to supply a fallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit sets a default width and height for the thumbnails. These are based on the defaults in wp_playlist_shortcode().
* | ||
* @var string. | ||
*/ | ||
const PLAYLIST_REGEX = '/(?s)\<script [^>]* class="wp-playlist-script"\>[^<]*?(.*).*?\<\/script\>/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this regex is quite right. This should be more robust:
const PLAYLIST_REGEX = ':<script type="application/json" class="wp-playlist-script">(.+?)</script>:s';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit applies your regex.
* @return void. | ||
*/ | ||
public function unregister_embed() { | ||
remove_shortcode( self::SHORTCODE ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the other examples of embeds in the plugin aren't quite right in how they call remove_shortcode()
. This should actually be restoring the previous shortcode that was added. So in the register_embed
method instead of:
add_shortcode( self::SHORTCODE, array( $this, 'shortcode' ) );
It should do:
global $shortcode_tags;
if ( shortcode_exists( self::SHORTCODE ) ) {
$this->removed_shortcode = $shortcode_tags[ self::SHORTCODE ];
}
add_shortcode( self::SHORTCODE, array( $this, 'shortcode' ) );
And then in unregister_embed
it should do:
add_shortcode( self::SHORTCODE, $this->removed_shortcode );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit applies your suggestion of restoring the shortcode before register_embed()
changed it.
/** | ||
* Unregisters the playlist shortcode. | ||
* | ||
* @return void. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The period shouldn't be used here. A period should only appear after a description when it is provided, for example:
@return int The count.
See examples https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/php/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this commit removes that extra period.
At Weston's suggestion. This is easier to understand.
Before, the output was only escaped if the value was set. Also, remove the isset() check for $title. As Weston mentioned, this is always a string.
Inside a conditional, return an empty string. As Weston mentioned, the PHP DocBlock indicates a string return value. Also, add an assertion for this. And correct the documentation of 'content_width.'
Props @westonruter for the new regex. Also, remove periods from '@return void.'
On Weston's suggestion. This function should return the shortcode to the state before this embed handler changed it. So it stores the previous callback in $removed_shortcode. And it adds that callback in remove_embed().
As Weston mentioned, the DocBlock indicates an array(). So return an empty array instead of void.
This should always be present. @see wp_playlist_shortcode().
Audio playlists have thumbnail images. If the height and width aren't defined in $data, Set fallbacks. These are based on the fallback heights in: wp_playlist_shortcode().
Applied Or Responded To Suggestions Hi @westonruter, |
The playlist is actually a carousel, as it's not possible to use <amp-bind>. But that doesn't match native WP UI. So remove the buttons that go other carousel items. One can click the tracks to go to another track.
* Restore wp_print_head_scripts and wp_print_footer_scripts. * Return associative array instead of positional array in get_thumb_dimensions. * Further clean phpdoc.
…ut anyway * Remove script output by wp_comment_form_unfiltered_html_nonce(). * Remove wp-embed script enqueued by wp_oembed_add_host_js().
?> | ||
<div class="wp-playlist wp-video-playlist wp-playlist-light"> | ||
<amp-state id="<?php echo esc_attr( $playlist ); ?>"> | ||
<script type="application/json"><?php echo wp_unslash( wp_json_encode( $amp_state ) ); // WPCS: XSS ok. ?></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that wp_unslash()
isn't right here. If you want to not have slashes in the output, you should use JSON_UNESCAPED_SLASHES
. Otherwise, the slashes are important for security since it ensures that if a string contains </script>
it will get output as <\/script>
and prevented from breaking out of the scriptl
I'm amending the PR.
I'm seeing warnings in the console, including:
|
This WIP pull request adds a custom shortcode handler for video playlists. It uses
<amp-video>
and<amp-state>
, on Weston's suggestion.Here's a screencast. It uses much of the same markup as the native shortcode, so it appears styled when adding wp-mediaelement.min.css.
Fixes #841.