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

[WIP] Add post embed support #914

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions amp.php
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ function amp_load_classes() {
*/
function amp_add_frontend_actions() {
add_action( 'wp_head', 'amp_add_amphtml_link' );
add_action( 'embed_footer', 'amp_add_post_embed_js' );
}

/**
Expand Down
23 changes: 23 additions & 0 deletions includes/amp-helper-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ function amp_get_content_embed_handlers( $post = null ) {
'AMP_Instagram_Embed_Handler' => array(),
'AMP_Issuu_Embed_Handler' => array(),
'AMP_Meetup_Embed_Handler' => array(),
'AMP_Post_Embed_Handler' => array(),
'AMP_Vine_Embed_Handler' => array(),
'AMP_Facebook_Embed_Handler' => array(),
'AMP_Pinterest_Embed_Handler' => array(),
Expand Down Expand Up @@ -888,3 +889,25 @@ function amp_wp_kses_mustache( $markup ) {
$amp_mustache_allowed_html_tags = array( 'strong', 'b', 'em', 'i', 'u', 's', 'small', 'mark', 'del', 'ins', 'sup', 'sub' );
return wp_kses( $markup, array_fill_keys( $amp_mustache_allowed_html_tags, array() ) );
}

/**
* Add JS required for iframe to resize itself in AMP.
*
* @todo This should be incorporated into core.
* @since ?.?
*/
function amp_add_post_embed_js() {
?>
<script>
window.addEventListener( 'load', function() {
if ( /amp=1/.test( location.hash ) ) {
window.parent.postMessage({
sentinel: 'amp',
type: 'embed-size',
height: document.body.scrollHeight
}, '*');
}
} );
</script>
<?php
}
1 change: 1 addition & 0 deletions includes/class-amp-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class AMP_Autoloader {
'AMP_Issuu_Embed_Handler' => 'includes/embeds/class-amp-issuu-embed-handler',
'AMP_Meetup_Embed_Handler' => 'includes/embeds/class-amp-meetup-embed-handler',
'AMP_Pinterest_Embed_Handler' => 'includes/embeds/class-amp-pinterest-embed',
'AMP_Post_Embed_Handler' => 'includes/embeds/class-amp-post-embed-handler',
'AMP_Playlist_Embed_Handler' => 'includes/embeds/class-amp-playlist-embed-handler',
'AMP_Reddit_Embed_Handler' => 'includes/embeds/class-amp-reddit-embed-handler',
'AMP_SoundCloud_Embed_Handler' => 'includes/embeds/class-amp-soundcloud-embed',
Expand Down
97 changes: 97 additions & 0 deletions includes/embeds/class-amp-post-embed-handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php
/**
* Class AMP_Post_Embed_Handler
*
* @package AMP
* @since ?.?
*/

/**
* Class AMP_Post_Embed_Handler
*
* @todo Patch core to send embed-size message to parent when URL contains `#amp=1`. See <https://www.ampproject.org/docs/reference/components/amp-iframe#iframe-resizing>.
*/
class AMP_Post_Embed_Handler extends AMP_Base_Embed_Handler {

/**
* Register embed.
*/
public function register_embed() {

// Note that oembed_dataparse filter should not be used as the response will get cached in the DB.
add_filter( 'embed_oembed_html', array( $this, 'filter_embed_oembed_html' ), 10, 3 );
}

/**
* Unregister embed.
*/
public function unregister_embed() {
remove_filter( 'embed_oembed_html', array( $this, 'filter_embed_oembed_html' ), 10 );
}

/**
* Filter oEmbed HTML for WordPress post embeds to prepare it for AMP.
*
* @see \get_post_embed_html()
* @param string $cache Cache for oEmbed.
* @param string $url Embed URL.
* @param array $attr Embed attributes, including width and height.
* @return string Embed.
*/
public function filter_embed_oembed_html( $cache, $url, $attr ) {
unset( $url );

// See regex in wp_filter_oembed_result() where blockquote and iframe are presumed to exist.
if ( ! preg_match( '#<iframe\s[^>]*class="wp-embedded-content"[^>]*?></iframe>#s', $cache ) ) {
return $cache;
}

$dom = AMP_DOM_Utils::get_dom_from_content( $cache );
$iframe = $dom->getElementsByTagName( 'iframe' )->item( 0 );
if ( ! $iframe ) {
return $cache;
}

$iframe->removeAttribute( 'style' );

// @todo Top-navigation doesn't work because linkClickHandler() prevents it. See <https://github.com/WordPress/wordpress-develop/blob/4.9.2/src/wp-includes/js/wp-embed-template.js#L149-L170>.
$iframe->setAttribute( 'sandbox', strval( $iframe->getAttribute( 'sandbox' ) ) . ' allow-scripts allow-same-origin allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation' );

// Note we have to exclude the blockquote because wpautop() does not like it.
$link = $dom->getElementsByTagName( 'a' )->item( 0 );
$link->setAttribute( 'placeholder', '' );

$attributes = $attr; // Initially width and height.
foreach ( $iframe->attributes as $attribute ) {
$attributes[ $attribute->nodeName ] = $attribute->nodeValue;
}
unset( $attributes['data-secret'] );

// @todo Try srcdoc
$amp_iframe = AMP_DOM_Utils::create_node(
$dom,
'amp-iframe',
array_merge(
$attributes,
array(
'src' => strtok( $attributes['src'], '#' ), // So that `#amp=1` can be added.
'layout' => 'responsive',
'resizable' => '',
)
)
);

$link->setAttribute( 'fallback', '' );
$amp_iframe->appendChild( $link->parentNode->removeChild( $link ) );

$overflow = $dom->createElement( 'span' );
$overflow->setAttribute( 'role', 'button' );
$overflow->setAttribute( 'tabindex', '0' );
$overflow->appendChild( $dom->createTextNode( 'More' ) );
$overflow->setAttribute( 'overflow', '' );
$amp_iframe->appendChild( $overflow );

return $dom->saveHTML( $amp_iframe );
}
}