Skip to content

Commit 8fa8c2c

Browse files
pierlonwestonruter
andcommitted
Reregister Facebook embed handler (#5548)
Co-authored-by: Weston Ruter <[email protected]>
1 parent 166f23d commit 8fa8c2c

File tree

4 files changed

+129
-89
lines changed

4 files changed

+129
-89
lines changed

.github/workflows/build-test-measure.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ jobs:
2525
- name: Check out source files
2626
uses: actions/checkout@v2
2727

28+
- name: Setup PHP
29+
uses: shivammathur/setup-php@v2
30+
with:
31+
php-version: '7.4'
32+
coverage: none
33+
tools: composer:v1
34+
2835
- name: Get Composer Cache Directory
2936
id: composer-cache
3037
run: |
@@ -97,6 +104,13 @@ jobs:
97104
- name: Check out source files
98105
uses: actions/checkout@v2
99106

107+
- name: Setup PHP
108+
uses: shivammathur/setup-php@v2
109+
with:
110+
php-version: '7.4'
111+
coverage: none
112+
tools: composer:v1
113+
100114
- name: Get Composer Cache Directory
101115
id: composer-cache
102116
run: |

includes/embeds/class-amp-base-embed-handler.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ protected function match_element_attributes( $html, $tag_name, $attribute_names
9797
implode(
9898
'',
9999
array_map(
100-
function ( $attr_name ) {
100+
static function ( $attr_name ) {
101101
return sprintf( '(?=[^>]*?%1$s="(?P<%1$s>[^"]+)")?', preg_quote( $attr_name, '/' ) );
102102
},
103103
$attribute_names
@@ -109,4 +109,46 @@ function ( $attr_name ) {
109109
}
110110
return wp_array_slice_assoc( $matches, $attribute_names );
111111
}
112+
113+
/**
114+
* Get all child elements of the specified element.
115+
*
116+
* @since 2.0.6
117+
*
118+
* @param DOMElement $node Element.
119+
* @return DOMElement[] Array of child elements for specified element.
120+
*/
121+
protected function get_child_elements( DOMElement $node ) {
122+
return array_filter(
123+
iterator_to_array( $node->childNodes ),
124+
static function ( DOMNode $child ) {
125+
return $child instanceof DOMElement;
126+
}
127+
);
128+
}
129+
130+
/**
131+
* Replace an element's parent with itself if the parent is a <p> tag which has no attributes and has no other children.
132+
*
133+
* This usually happens while `wpautop()` processes the element.
134+
*
135+
* @since 2.0.6
136+
* @see AMP_Tag_And_Attribute_Sanitizer::remove_node()
137+
*
138+
* @param DOMElement $node Node.
139+
*/
140+
protected function unwrap_p_element( DOMElement $node ) {
141+
$parent_node = $node->parentNode;
142+
if (
143+
$parent_node instanceof DOMElement
144+
&&
145+
'p' === $parent_node->tagName
146+
&&
147+
false === $parent_node->hasAttributes()
148+
&&
149+
1 === count( $this->get_child_elements( $parent_node ) )
150+
) {
151+
$parent_node->parentNode->replaceChild( $node, $parent_node );
152+
}
153+
}
112154
}

includes/embeds/class-amp-facebook-embed-handler.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
* @internal
1414
*/
1515
class AMP_Facebook_Embed_Handler extends AMP_Base_Embed_Handler {
16+
17+
/**
18+
* URL pattern.
19+
*
20+
* @var string
21+
*/
22+
const URL_PATTERN = '#https?://(www\.)?facebook\.com/.*#i';
23+
24+
/**
25+
* Default width.
26+
*
27+
* @var int
28+
*/
29+
protected $DEFAULT_WIDTH = 600;
30+
1631
/**
1732
* Default height.
1833
*
@@ -38,14 +53,57 @@ class AMP_Facebook_Embed_Handler extends AMP_Base_Embed_Handler {
3853
* Registers embed.
3954
*/
4055
public function register_embed() {
41-
// Not implemented.
56+
wp_embed_register_handler( $this->amp_tag, self::URL_PATTERN, [ $this, 'oembed' ], -1 );
4257
}
4358

4459
/**
4560
* Unregisters embed.
4661
*/
4762
public function unregister_embed() {
48-
// Not implemented.
63+
wp_embed_unregister_handler( $this->amp_tag, -1 );
64+
}
65+
66+
/**
67+
* WordPress oEmbed rendering callback.
68+
*
69+
* @param array $matches URL pattern matches.
70+
* @param array $attr Matched attributes.
71+
* @param string $url Matched URL.
72+
* @return string HTML markup for rendered embed.
73+
*/
74+
public function oembed( $matches, $attr, $url ) {
75+
return $this->render( [ 'url' => $url ] );
76+
}
77+
78+
/**
79+
* Gets the rendered embed markup.
80+
*
81+
* @param array $args Embed rendering arguments.
82+
* @return string HTML markup for rendered embed.
83+
*/
84+
public function render( $args ) {
85+
$args = wp_parse_args(
86+
$args,
87+
[
88+
'url' => false,
89+
]
90+
);
91+
92+
if ( empty( $args['url'] ) ) {
93+
return '';
94+
}
95+
96+
$this->did_convert_elements = true;
97+
98+
return AMP_HTML_Utils::build_tag(
99+
$this->amp_tag,
100+
[
101+
'data-href' => $args['url'],
102+
'layout' => 'responsive',
103+
'width' => $this->args['width'],
104+
'height' => $this->args['height'],
105+
]
106+
);
49107
}
50108

51109
/**
@@ -54,6 +112,14 @@ public function unregister_embed() {
54112
* @param Document $dom DOM.
55113
*/
56114
public function sanitize_raw_embeds( Document $dom ) {
115+
// If there were any previous embeds in the DOM that were wrapped by `wpautop()`, unwrap them.
116+
$embed_nodes = $dom->xpath->query( "//p/{$this->amp_tag}" );
117+
if ( $embed_nodes->length ) {
118+
foreach ( $embed_nodes as $embed_node ) {
119+
$this->unwrap_p_element( $embed_node );
120+
}
121+
}
122+
57123
$nodes = $dom->getElementsByTagName( $this->sanitize_tag );
58124
$num_nodes = $nodes->length;
59125

tests/php/test-amp-facebook-embed-handler.php

Lines changed: 4 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -20,55 +20,6 @@ class AMP_Facebook_Embed_Handler_Test extends WP_UnitTestCase {
2020
setUp as public prevent_block_pre_render;
2121
}
2222

23-
/**
24-
* Set up.
25-
*/
26-
public function setUp() {
27-
$this->prevent_block_pre_render();
28-
29-
// Mock the HTTP request.
30-
add_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );
31-
}
32-
33-
/**
34-
* Mock HTTP request.
35-
*
36-
* @param mixed $preempt Whether to preempt an HTTP request's return value. Default false.
37-
* @param mixed $r HTTP request arguments.
38-
* @param string $url The request URL.
39-
* @return array Response data.
40-
*/
41-
public function mock_http_request( $preempt, $r, $url ) {
42-
if ( self::is_external_http_test_suite() ) {
43-
return $preempt;
44-
}
45-
46-
if ( false !== strpos( $url, '10102593740125791' ) ) {
47-
$body = '{"author_name":"Mark","author_url":"https://www.facebook.com/zuck","provider_url":"https://www.facebook.com","provider_name":"Facebook","success":true,"height":null,"html":"\u003Cdiv id=\"fb-root\">\u003C/div>\n\u003Cscript async=\"1\" defer=\"1\" crossorigin=\"anonymous\" src=\"https://connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v6.0\">\u003C/script>\u003Cdiv class=\"fb-post\" data-href=\"https://www.facebook.com/zuck/posts/10102593740125791\" data-width=\"500\">\u003Cblockquote cite=\"https://www.facebook.com/zuck/posts/10102593740125791\" class=\"fb-xfbml-parse-ignore\">\u003Cp>February 4 is Facebook\u2019s 12th birthday!\n\nOur anniversary has a lot of meaning to me as an opportunity to reflect on how...\u003C/p>Posted by \u003Ca href=\"https://www.facebook.com/zuck\">Mark Zuckerberg\u003C/a> on&nbsp;\u003Ca href=\"https://www.facebook.com/zuck/posts/10102593740125791\">Tuesday, January 12, 2016\u003C/a>\u003C/blockquote>\u003C/div>","type":"rich","version":"1.0","url":"https://www.facebook.com/zuck/posts/10102593740125791","width":500}';
48-
} elseif ( false !== strpos( $url, '10151176218703920' ) ) {
49-
$body = '{"author_name":"Facebook Engineering","author_url":"https://www.facebook.com/Engineering/","provider_url":"https://www.facebook.com","provider_name":"Facebook","success":true,"height":null,"html":"\u003Cdiv id=\"fb-root\">\u003C/div>\n\u003Cscript async=\"1\" defer=\"1\" crossorigin=\"anonymous\" src=\"https://connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v6.0\">\u003C/script>\u003Cdiv class=\"fb-post\" data-href=\"https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/\" data-width=\"500\">\u003Cblockquote cite=\"https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/\" class=\"fb-xfbml-parse-ignore\">Posted by \u003Ca href=\"https://www.facebook.com/Engineering/\">Facebook Engineering\u003C/a> on&nbsp;\u003Ca href=\"https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/\">Saturday, December 8, 2012\u003C/a>\u003C/blockquote>\u003C/div>","type":"rich","version":"1.0","url":"https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/","width":500}';
50-
} elseif ( false !== strpos( $url, '10102533316889441' ) ) {
51-
$body = '{"author_name":"Mark","author_url":"https://www.facebook.com/zuck","provider_url":"https://www.facebook.com","provider_name":"Facebook","success":true,"height":null,"html":"\u003Cdiv id=\"fb-root\">\u003C/div>\n\u003Cscript async=\"1\" defer=\"1\" crossorigin=\"anonymous\" src=\"https://connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v6.0\">\u003C/script>\u003Cdiv class=\"fb-post\" data-href=\"https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231.2034669.4&amp;type=3&amp;theater\" data-width=\"500\">\u003Cblockquote cite=\"https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231&amp;type=3\" class=\"fb-xfbml-parse-ignore\">\u003Cp>Meanwhile, Beast turned to the dark side.\u003C/p>Posted by \u003Ca href=\"https://www.facebook.com/zuck\">Mark Zuckerberg\u003C/a> on&nbsp;\u003Ca href=\"https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231&amp;type=3\">Friday, December 18, 2015\u003C/a>\u003C/blockquote>\u003C/div>","type":"rich","version":"1.0","url":"https://www.facebook.com/photo.php?fbid=10102533316889441&set=a.529237706231.2034669.4&type=3&theater","width":500}';
52-
} elseif ( false !== strpos( $url, '10102509264909801' ) ) {
53-
$body = '{"author_name":"Mark","author_url":"https://www.facebook.com/zuck","provider_url":"https://www.facebook.com","provider_name":"Facebook","success":true,"height":280,"html":"\u003Cdiv id=\"fb-root\">\u003C/div>\n\u003Cscript async=\"1\" defer=\"1\" crossorigin=\"anonymous\" src=\"https://connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v6.0\">\u003C/script>\u003Cdiv class=\"fb-video\" data-href=\"https://www.facebook.com/zuck/videos/10102509264909801/\" data-width=\"500\">\u003Cblockquote cite=\"https://www.facebook.com/zuck/videos/10102509264909801/\" class=\"fb-xfbml-parse-ignore\">\u003Ca href=\"https://www.facebook.com/zuck/videos/10102509264909801/\">\u003C/a>\u003Cp>I want to share a few more thoughts on the Chan Zuckerberg Initiative before I just start posting photos of me and Max for a while :)\n\nI hope one idea comes through: that we as a society should make investments now to ensure this world is much better for the next generation.\n\nI don&#039;t think we do enough of this right now. \n\nSure, there are many areas where investment now will solve problems for today and also improve the world for the future. We do muster the will to solve some of those.\n\nBut for the problems that will truly take decades of investment before we see any major return, we are dramatically underinvested.\n\nOne example is basic science research to cure disease. Another is developing clean energy to protect the world for the future. Another is the slow and steady improvement to modernize schools. Others are systematic issues around poverty and justice. There is a long list of these opportunities.\n\nThe role of philanthropy is to invest in important areas that companies and governments aren&#039;t funding -- either because they may not be profitable for companies or because they are too long term for people to want to invest now.\n\nIn the case of disease, basic research often needs to be funded before biotech or pharma companies can create drugs to help people. If we invest more in science, we can make faster progress towards curing disease.\n\nOur investment in the Chan Zuckerberg Initiative is small compared to what the world can invest in solving these great challenges. My hope is that our work inspires more people to invest in these longer term issues. If we can do that, then we can all really make a difference together.\u003C/p>Posted by \u003Ca href=\"https://www.facebook.com/zuck\">Mark Zuckerberg\u003C/a> on Friday, December 4, 2015\u003C/blockquote>\u003C/div>","type":"video","version":"1.0","url":"https://www.facebook.com/zuck/videos/10102509264909801/","width":500}';
54-
} elseif ( false !== strpos( $url, '10154009990506729' ) ) {
55-
$body = '{"author_name":"Facebook App","author_url":"https://www.facebook.com/facebookapp/","provider_url":"https://www.facebook.com","provider_name":"Facebook","success":true,"height":null,"html":"\u003Cdiv id=\"fb-root\">\u003C/div>\n\u003Cscript async=\"1\" defer=\"1\" crossorigin=\"anonymous\" src=\"https://connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v6.0\">\u003C/script>\u003Cdiv class=\"fb-post\" data-href=\"https://www.facebook.com/20531316728/posts/10154009990506729/\" data-width=\"552\">\u003Cblockquote cite=\"https://www.facebook.com/20531316728/posts/10154009990506729/\" class=\"fb-xfbml-parse-ignore\">Posted by \u003Ca href=\"https://www.facebook.com/facebookapp/\">Facebook App\u003C/a> on&nbsp;\u003Ca href=\"https://www.facebook.com/20531316728/posts/10154009990506729/\">Thursday, August 27, 2015\u003C/a>\u003C/blockquote>\u003C/div>","type":"rich","version":"1.0","url":"https://www.facebook.com/20531316728/posts/10154009990506729/","width":552}';
56-
} else {
57-
return $preempt;
58-
}
59-
60-
return [
61-
'body' => $body,
62-
'headers' => [],
63-
'response' => [
64-
'code' => 200,
65-
'message' => 'ok',
66-
],
67-
'cookies' => [],
68-
'http_response' => null,
69-
];
70-
}
71-
7223
/**
7324
* Get scripts data.
7425
*
@@ -95,10 +46,6 @@ public function get_scripts_data() {
9546
* @param array $expected Expected scripts.
9647
*/
9748
public function test__get_scripts( $source, $expected ) {
98-
if ( self::is_external_http_test_suite() ) {
99-
$this->markTestSkipped( 'Endpoint is gone.' );
100-
}
101-
10249
$embed = new AMP_Facebook_Embed_Handler();
10350
$embed->register_embed();
10451

@@ -137,38 +84,22 @@ public function get_raw_embed_dataset() {
13784

13885
'simple_url_https' => [
13986
'https://www.facebook.com/zuck/posts/10102593740125791' . PHP_EOL,
140-
'
141-
<amp-facebook width="500" height="400" data-href="https://www.facebook.com/zuck/posts/10102593740125791" data-embed-as="post" layout="responsive">
142-
<blockquote cite="https://www.facebook.com/zuck/posts/10102593740125791" class="fb-xfbml-parse-ignore" fallback=""><!--blockquote_contents--></blockquote>
143-
</amp-facebook>
144-
' . PHP_EOL,
87+
'<amp-facebook data-href="https://www.facebook.com/zuck/posts/10102593740125791" layout="responsive" width="600" height="400"></amp-facebook>' . PHP_EOL,
14588
],
14689

14790
'notes_url' => [
14891
'https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/' . PHP_EOL,
149-
'
150-
<amp-facebook width="500" height="400" data-href="https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/" data-embed-as="post" layout="responsive">
151-
<blockquote cite="https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/" class="fb-xfbml-parse-ignore" fallback=""><!--blockquote_contents--></blockquote>
152-
</amp-facebook>
153-
' . PHP_EOL,
92+
'<amp-facebook data-href="https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/" layout="responsive" width="600" height="400"></amp-facebook>' . PHP_EOL,
15493
],
15594

15695
'photo_url' => [
15796
'https://www.facebook.com/photo.php?fbid=10102533316889441&set=a.529237706231.2034669.4&type=3&theater' . PHP_EOL,
158-
'
159-
<amp-facebook width="500" height="400" data-href="https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231.2034669.4&amp;type=3&amp;theater" data-embed-as="post" layout="responsive">
160-
<blockquote cite="https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231&amp;type=3" class="fb-xfbml-parse-ignore" fallback=""><!--blockquote_contents--></blockquote>
161-
</amp-facebook>
162-
' . PHP_EOL,
97+
'<amp-facebook data-href="https://www.facebook.com/photo.php?fbid=10102533316889441&amp;set=a.529237706231.2034669.4&amp;type=3&amp;theater" layout="responsive" width="600" height="400"></amp-facebook>' . PHP_EOL,
16398
],
16499

165100
'video_url' => [
166101
'https://www.facebook.com/zuck/videos/10102509264909801/' . PHP_EOL,
167-
'
168-
<amp-facebook width="500" height="400" data-href="https://www.facebook.com/zuck/videos/10102509264909801/" data-embed-as="video" layout="responsive">
169-
<blockquote cite="https://www.facebook.com/zuck/videos/10102509264909801/" class="fb-xfbml-parse-ignore" fallback=""><!--blockquote_contents--></blockquote>
170-
</amp-facebook>
171-
' . PHP_EOL,
102+
'<amp-facebook data-href="https://www.facebook.com/zuck/videos/10102509264909801/" layout="responsive" width="600" height="400"></amp-facebook>' . PHP_EOL,
172103
],
173104

174105
'post_embed' => [
@@ -280,10 +211,6 @@ public function get_raw_embed_dataset() {
280211
* @covers AMP_Facebook_Embed_Handler::sanitize_raw_embeds()
281212
*/
282213
public function test__raw_embed_sanitizer( $source, $expected ) {
283-
if ( self::is_external_http_test_suite() ) {
284-
$this->markTestSkipped( 'Endpoint is gone.' );
285-
}
286-
287214
$embed = new AMP_Facebook_Embed_Handler();
288215
$embed->register_embed();
289216

@@ -302,13 +229,4 @@ public function test__raw_embed_sanitizer( $source, $expected ) {
302229

303230
$this->assertEqualMarkup( $expected, $content );
304231
}
305-
306-
/**
307-
* Whether external-http test suite is running.
308-
*
309-
* @return bool Running external-http test suite.
310-
*/
311-
private static function is_external_http_test_suite() {
312-
return in_array( 'external-http', $_SERVER['argv'], true );
313-
}
314232
}

0 commit comments

Comments
 (0)