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

Improve handling of WordPress post embeds #6665

Merged
merged 41 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d4a6fd2
Excluded WP Embeds from being handled by iframe sanitizer
bartoszgadomski Oct 27, 2021
5b434eb
Changes in iframe-sanitizer removed; WordPress embed handler added fo…
bartoszgadomski Oct 29, 2021
c860f51
Tests created for AMP_WordPress_Embed_Handler class
bartoszgadomski Nov 9, 2021
42dda75
AMP_WordPress_Embed_Handler improved
bartoszgadomski Nov 10, 2021
d6efba4
Merge branch 'develop' of github.com:ampproject/amp-wp into fix/809-h…
westonruter Nov 13, 2021
fdb57df
Improve tests and implement HTTP mocking
westonruter Nov 13, 2021
8ea5b97
AMP_WordPress_Embed_Handler changed to use sanitize_raw_embeds method…
bartoszgadomski Nov 15, 2021
00f0dfb
Paragraph unwrap moved to happen one step earlier
bartoszgadomski Nov 16, 2021
5de53b7
Removal of wp_oembed_add_host_js action moved from AMP_Theme_Support …
bartoszgadomski Nov 16, 2021
caad135
Code cleanup and improvements
bartoszgadomski Nov 16, 2021
23ebbec
AMP_WordPress_Embed_Handler tests updated
bartoszgadomski Nov 16, 2021
1411c6e
Merge branch 'develop' of https://github.com/ampproject/amp-wp into f…
bartoszgadomski Nov 16, 2021
5074b87
The 'test_get_scripts' updated to work with sanitize_raw_embeds
bartoszgadomski Nov 16, 2021
6338bd4
Test case for Test_AMP_Theme_Support updated
bartoszgadomski Nov 16, 2021
46805a4
AMP_WordPress_Embed_Handler test cases extended with two WP Embed blo…
bartoszgadomski Nov 16, 2021
6650a84
Blockquote and iframe pairs selection improved; tests cases extended …
bartoszgadomski Nov 16, 2021
d613f71
Utilize preceding-sibling XPath axis to simplify querying for iframe …
westonruter Nov 18, 2021
fb1eb6f
Unwrap iframes if preceding blockquote found and even when paragrpah …
westonruter Nov 18, 2021
b072215
Obtain attributes from iframe node rather than serializing and using …
westonruter Nov 18, 2021
d563a24
Remove data-secret from blockquote and reuse default overflow text
westonruter Nov 18, 2021
f1fb431
Update covers tags and combine register/unregister testing
westonruter Nov 18, 2021
976b832
De-duplicate test data with sprintf()
westonruter Nov 18, 2021
42b1461
Add test for HTML Embed code that users can use in non-WP context
westonruter Nov 18, 2021
76a3684
Add tests for output of get_post_embed_html() and ensure embed script…
westonruter Nov 18, 2021
d32ea7f
Merge branch 'develop' of github.com:ampproject/amp-wp into fix/809-h…
westonruter Mar 1, 2022
eed4a04
Update since tag to 2.2.2
westonruter Mar 1, 2022
b1f44b6
Add tests for internal post embeds
westonruter Mar 2, 2022
c0184cc
Merge branch 'develop' of github.com:ampproject/amp-wp into fix/809-h…
westonruter Mar 2, 2022
fa016ee
Add missing HTTP response mock
westonruter Mar 2, 2022
02ea5e2
Fix test_add_block_source_comments for Gutenberg 12.7
westonruter Mar 2, 2022
bc48ac2
Add debugging code
westonruter Mar 2, 2022
11cd07f
Use oembed_request_post_id for test
westonruter Mar 2, 2022
49fc7bf
Ensure video shortcode is registered to test_process_text_widgets
westonruter Mar 2, 2022
27de98b
Add assertions
westonruter Mar 2, 2022
0b311fc
Add more assertions
westonruter Mar 3, 2022
04c91f8
Add oembed_request_post_id filter sooner
westonruter Mar 3, 2022
505dbcc
Add yet more assertions to debug oEmbed problem on GHA
westonruter Mar 3, 2022
c72a71b
Add assertion for post data being created before test
westonruter Mar 3, 2022
f21d14f
Defer creation of post fixture until test
westonruter Mar 3, 2022
e884dbc
Remove obsolete debug code
westonruter Mar 3, 2022
73b4305
Update namespace for Attribute and Tag interfaces
westonruter Mar 3, 2022
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 includes/amp-helper-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,7 @@ function amp_get_content_embed_handlers( $post = null ) {
AMP_Gfycat_Embed_Handler::class => [],
AMP_Imgur_Embed_Handler::class => [],
AMP_Scribd_Embed_Handler::class => [],
AMP_WordPress_Embed_Handler::class => [],
AMP_WordPress_TV_Embed_Handler::class => [],
],
$post
Expand Down
3 changes: 0 additions & 3 deletions includes/class-amp-theme-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -845,9 +845,6 @@ public static function get_supportable_templates( $options = [] ) {
*/
public static function add_hooks() {

// This is not needed when post embeds are embedded via <amp-wordpress-embed>. See <https://github.com/ampproject/amp-wp/issues/809>.
remove_action( 'wp_head', 'wp_oembed_add_host_js' );

// Prevent emoji detection and emoji loading since platforms/browsers now support emoji natively (and Twemoji is not AMP-compatible).
add_filter( 'wp_resource_hints', [ __CLASS__, 'filter_resource_hints_to_remove_emoji_dns_prefetch' ], 10, 2 );
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
Expand Down
144 changes: 144 additions & 0 deletions includes/embeds/class-amp-wordpress-embed-handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php
/**
* Class AMP_WordPress_Embed_Handler
*
* @package AMP
*/

use AmpProject\Extension;
use AmpProject\Dom\Document;
use AmpProject\Dom\Element;
use AmpProject\Html\Attribute;
use AmpProject\Html\Tag;
use AmpProject\Layout;

/**
* Class AMP_WordPress_Embed_Handler
*
* @since 2.2.2
*/
class AMP_WordPress_Embed_Handler extends AMP_Base_Embed_Handler {

/**
* Default height.
*
* Note that 200px is the minimum that WordPress allows for a post embed. This minimum height is enforced by
* WordPress in the wp.receiveEmbedMessage() function, and the <amp-wordpress-embed> also enforces that same
* minimum height. It is important for the minimum height to be initially used because if the actual post embed
* window is _less_ than the initial, then no overflow button will be presented to resize the iframe to be
* _smaller_. So this ensures that the iframe will only ever overflow to grow in height.
*
* @var int
*/
protected $DEFAULT_HEIGHT = 200;

/**
* Tag.
*
* @var string AMP amp-wordpress-embed tag
*/
private $amp_tag = Extension::WORDPRESS_EMBED;

/**
* Register embed.
*/
public function register_embed() {
remove_action( 'wp_head', 'wp_oembed_add_host_js' );
}

/**
* Unregister embed.
*/
public function unregister_embed() {
add_action( 'wp_head', 'wp_oembed_add_host_js' );
}

/**
* Sanitize WordPress embed raw embeds.
*
* @param Document $dom Document.
*
* @return void
*/
public function sanitize_raw_embeds( Document $dom ) {

$embed_iframes = $dom->xpath->query( '//iframe[ @src and contains( concat( " ", normalize-space( @class ), " " ), " wp-embedded-content " ) ]', $dom->body );
foreach ( $embed_iframes as $embed_iframe ) {
/** @var Element $embed_iframe */

// Remove embed script included when user copies HTML Embed code, per get_post_embed_html().
$embed_script = $dom->xpath->query( './following-sibling::script[ contains( text(), "wp.receiveEmbedMessage" ) ]', $embed_iframe )->item( 0 );
if ( $embed_script instanceof Element ) {
$embed_script->parentNode->removeChild( $embed_script );
}

// If the post embed iframe got wrapped in a paragraph by `wpautop()`, unwrap it. This happens not with
// the Embed block but it does with the [embed] shortcode.
$is_wrapped_in_paragraph = (
$embed_iframe->parentNode instanceof Element
&&
Tag::P === $embed_iframe->parentNode->tagName
);

// If the iframe is wrapped in a paragraph, but it's not the only node, then abort.
if ( $is_wrapped_in_paragraph && 1 !== $embed_iframe->parentNode->childNodes->length ) {
continue;
}

$embed_blockquote = $dom->xpath->query(
'./preceding-sibling::blockquote[ contains( concat( " ", normalize-space( @class ), " " ), " wp-embedded-content " ) ]',
$is_wrapped_in_paragraph ? $embed_iframe->parentNode : $embed_iframe
)->item( 0 );
if ( $embed_blockquote instanceof Element ) {

// Note that unwrap_p_element() is not being used here because it will do nothing if the paragraph
// happens to have an attribute on it, which is possible with the_content filters.
if ( $is_wrapped_in_paragraph && $embed_iframe->parentNode->parentNode instanceof Element ) {
$embed_iframe->parentNode->parentNode->replaceChild( $embed_iframe, $embed_iframe->parentNode );
}

$this->create_amp_wordpress_embed_and_replace_node( $dom, $embed_blockquote, $embed_iframe );
}
}
}

/**
* Make final modifications to DOMNode
*
* @param Document $dom The HTML Document.
* @param Element $blockquote The blockquote to be moved inside <amp-wordpress-embed>.
* @param Element $iframe The iframe to be replaced with <amp-wordpress-embed>.
*/
private function create_amp_wordpress_embed_and_replace_node( Document $dom, Element $blockquote, Element $iframe ) {

$attributes = [
Attribute::HEIGHT => $this->args['height'],
Attribute::LAYOUT => Layout::FIXED_HEIGHT,
];
if ( $iframe->hasAttribute( Attribute::TITLE ) ) {
$attributes[ Attribute::TITLE ] = $iframe->getAttribute( Attribute::TITLE );
}

$src = $iframe->getAttribute( Attribute::SRC );

// Remove the secret which will be handled by amp-wordpress-embed.
$src = preg_replace( '/#\?secret=.+/', '', $src );
$blockquote->removeAttribute( 'data-secret' );

$attributes[ Attribute::DATA_URL ] = $src;

$amp_wordpress_embed_node = AMP_DOM_Utils::create_node(
$dom,
$this->amp_tag,
$attributes
);

$blockquote->setAttributeNode( $dom->createAttribute( Attribute::PLACEHOLDER ) );
$amp_wordpress_embed_node->appendChild( $blockquote );
$amp_wordpress_embed_node->appendChild( $this->create_overflow_button_element( $dom ) );

$iframe->parentNode->replaceChild( $amp_wordpress_embed_node, $iframe );

$this->did_convert_elements = true;
}
}
Loading