Skip to content

Commit 6035d35

Browse files
authored
Merge pull request #6665 from ampproject/fix/809-handle-wp-post-embeds
Improve handling of WordPress post embeds
2 parents 398c5a6 + 73b4305 commit 6035d35

7 files changed

+595
-12
lines changed

includes/amp-helper-functions.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,7 @@ function amp_get_content_embed_handlers( $post = null ) {
14071407
AMP_Gfycat_Embed_Handler::class => [],
14081408
AMP_Imgur_Embed_Handler::class => [],
14091409
AMP_Scribd_Embed_Handler::class => [],
1410+
AMP_WordPress_Embed_Handler::class => [],
14101411
AMP_WordPress_TV_Embed_Handler::class => [],
14111412
],
14121413
$post

includes/class-amp-theme-support.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,9 +845,6 @@ public static function get_supportable_templates( $options = [] ) {
845845
*/
846846
public static function add_hooks() {
847847

848-
// This is not needed when post embeds are embedded via <amp-wordpress-embed>. See <https://github.com/ampproject/amp-wp/issues/809>.
849-
remove_action( 'wp_head', 'wp_oembed_add_host_js' );
850-
851848
// Prevent emoji detection and emoji loading since platforms/browsers now support emoji natively (and Twemoji is not AMP-compatible).
852849
add_filter( 'wp_resource_hints', [ __CLASS__, 'filter_resource_hints_to_remove_emoji_dns_prefetch' ], 10, 2 );
853850
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
/**
3+
* Class AMP_WordPress_Embed_Handler
4+
*
5+
* @package AMP
6+
*/
7+
8+
use AmpProject\Extension;
9+
use AmpProject\Dom\Document;
10+
use AmpProject\Dom\Element;
11+
use AmpProject\Html\Attribute;
12+
use AmpProject\Html\Tag;
13+
use AmpProject\Layout;
14+
15+
/**
16+
* Class AMP_WordPress_Embed_Handler
17+
*
18+
* @since 2.2.2
19+
*/
20+
class AMP_WordPress_Embed_Handler extends AMP_Base_Embed_Handler {
21+
22+
/**
23+
* Default height.
24+
*
25+
* Note that 200px is the minimum that WordPress allows for a post embed. This minimum height is enforced by
26+
* WordPress in the wp.receiveEmbedMessage() function, and the <amp-wordpress-embed> also enforces that same
27+
* minimum height. It is important for the minimum height to be initially used because if the actual post embed
28+
* window is _less_ than the initial, then no overflow button will be presented to resize the iframe to be
29+
* _smaller_. So this ensures that the iframe will only ever overflow to grow in height.
30+
*
31+
* @var int
32+
*/
33+
protected $DEFAULT_HEIGHT = 200;
34+
35+
/**
36+
* Tag.
37+
*
38+
* @var string AMP amp-wordpress-embed tag
39+
*/
40+
private $amp_tag = Extension::WORDPRESS_EMBED;
41+
42+
/**
43+
* Register embed.
44+
*/
45+
public function register_embed() {
46+
remove_action( 'wp_head', 'wp_oembed_add_host_js' );
47+
}
48+
49+
/**
50+
* Unregister embed.
51+
*/
52+
public function unregister_embed() {
53+
add_action( 'wp_head', 'wp_oembed_add_host_js' );
54+
}
55+
56+
/**
57+
* Sanitize WordPress embed raw embeds.
58+
*
59+
* @param Document $dom Document.
60+
*
61+
* @return void
62+
*/
63+
public function sanitize_raw_embeds( Document $dom ) {
64+
65+
$embed_iframes = $dom->xpath->query( '//iframe[ @src and contains( concat( " ", normalize-space( @class ), " " ), " wp-embedded-content " ) ]', $dom->body );
66+
foreach ( $embed_iframes as $embed_iframe ) {
67+
/** @var Element $embed_iframe */
68+
69+
// Remove embed script included when user copies HTML Embed code, per get_post_embed_html().
70+
$embed_script = $dom->xpath->query( './following-sibling::script[ contains( text(), "wp.receiveEmbedMessage" ) ]', $embed_iframe )->item( 0 );
71+
if ( $embed_script instanceof Element ) {
72+
$embed_script->parentNode->removeChild( $embed_script );
73+
}
74+
75+
// If the post embed iframe got wrapped in a paragraph by `wpautop()`, unwrap it. This happens not with
76+
// the Embed block but it does with the [embed] shortcode.
77+
$is_wrapped_in_paragraph = (
78+
$embed_iframe->parentNode instanceof Element
79+
&&
80+
Tag::P === $embed_iframe->parentNode->tagName
81+
);
82+
83+
// If the iframe is wrapped in a paragraph, but it's not the only node, then abort.
84+
if ( $is_wrapped_in_paragraph && 1 !== $embed_iframe->parentNode->childNodes->length ) {
85+
continue;
86+
}
87+
88+
$embed_blockquote = $dom->xpath->query(
89+
'./preceding-sibling::blockquote[ contains( concat( " ", normalize-space( @class ), " " ), " wp-embedded-content " ) ]',
90+
$is_wrapped_in_paragraph ? $embed_iframe->parentNode : $embed_iframe
91+
)->item( 0 );
92+
if ( $embed_blockquote instanceof Element ) {
93+
94+
// Note that unwrap_p_element() is not being used here because it will do nothing if the paragraph
95+
// happens to have an attribute on it, which is possible with the_content filters.
96+
if ( $is_wrapped_in_paragraph && $embed_iframe->parentNode->parentNode instanceof Element ) {
97+
$embed_iframe->parentNode->parentNode->replaceChild( $embed_iframe, $embed_iframe->parentNode );
98+
}
99+
100+
$this->create_amp_wordpress_embed_and_replace_node( $dom, $embed_blockquote, $embed_iframe );
101+
}
102+
}
103+
}
104+
105+
/**
106+
* Make final modifications to DOMNode
107+
*
108+
* @param Document $dom The HTML Document.
109+
* @param Element $blockquote The blockquote to be moved inside <amp-wordpress-embed>.
110+
* @param Element $iframe The iframe to be replaced with <amp-wordpress-embed>.
111+
*/
112+
private function create_amp_wordpress_embed_and_replace_node( Document $dom, Element $blockquote, Element $iframe ) {
113+
114+
$attributes = [
115+
Attribute::HEIGHT => $this->args['height'],
116+
Attribute::LAYOUT => Layout::FIXED_HEIGHT,
117+
];
118+
if ( $iframe->hasAttribute( Attribute::TITLE ) ) {
119+
$attributes[ Attribute::TITLE ] = $iframe->getAttribute( Attribute::TITLE );
120+
}
121+
122+
$src = $iframe->getAttribute( Attribute::SRC );
123+
124+
// Remove the secret which will be handled by amp-wordpress-embed.
125+
$src = preg_replace( '/#\?secret=.+/', '', $src );
126+
$blockquote->removeAttribute( 'data-secret' );
127+
128+
$attributes[ Attribute::DATA_URL ] = $src;
129+
130+
$amp_wordpress_embed_node = AMP_DOM_Utils::create_node(
131+
$dom,
132+
$this->amp_tag,
133+
$attributes
134+
);
135+
136+
$blockquote->setAttributeNode( $dom->createAttribute( Attribute::PLACEHOLDER ) );
137+
$amp_wordpress_embed_node->appendChild( $blockquote );
138+
$amp_wordpress_embed_node->appendChild( $this->create_overflow_button_element( $dom ) );
139+
140+
$iframe->parentNode->replaceChild( $amp_wordpress_embed_node, $iframe );
141+
142+
$this->did_convert_elements = true;
143+
}
144+
}

0 commit comments

Comments
 (0)