Skip to content

Commit

Permalink
Merge pull request #1956 from ampproject/fix/facebook-embed-handling
Browse files Browse the repository at this point in the history
Fix conversion of Facebook embeds
  • Loading branch information
westonruter authored Mar 16, 2019
2 parents c82a6b9 + 12b406c commit c5280ae
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 22 deletions.
92 changes: 77 additions & 15 deletions includes/embeds/class-amp-facebook-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ public function sanitize_raw_embeds( $dom ) {
$this->create_amp_facebook_and_replace_node( $dom, $node, $embed_type );
}
}

/*
* Remove the fb-root div and the Facebook Connect JS script since irrelevant.
* <div id="fb-root"></div>
* <script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.2"></script>
*/
$fb_root = $dom->getElementById( 'fb-root' );
if ( $fb_root ) {
$xpath = new DOMXPath( $dom );
$scripts = array();
foreach ( $xpath->query( '//script[ starts-with( @src, "https://connect.facebook.net" ) and contains( @src, "sdk.js" ) ]' ) as $script ) {
$scripts[] = $script;
}
foreach ( $scripts as $script ) {
$script->parentNode->removeChild( $script );
}
$fb_root->parentNode->removeChild( $fb_root );
}
}

/**
Expand All @@ -137,13 +155,22 @@ public function sanitize_raw_embeds( $dom ) {
*/
private function get_embed_type( $node ) {
$class_attr = $node->getAttribute( 'class' );
if ( null !== $class_attr && $node->hasAttribute( 'data-href' ) ) {
if ( false !== strpos( $class_attr, 'fb-post' ) ) {
return 'post';
} elseif ( false !== strpos( $class_attr, 'fb-video' ) ) {
return 'video';
}
return false !== strpos( $class_attr, 'fb-video' ) ? 'video' : 'post';
if ( null === $class_attr || ! $node->hasAttribute( 'data-href' ) ) {
return null;
}

if ( false !== strpos( $class_attr, 'fb-post' ) ) {
return 'post';
} elseif ( false !== strpos( $class_attr, 'fb-video' ) ) {
return 'video';
} elseif ( false !== strpos( $class_attr, 'fb-page' ) ) {
return 'page';
} elseif ( false !== strpos( $class_attr, 'fb-like' ) ) {
return 'like';
} elseif ( false !== strpos( $class_attr, 'fb-comments' ) ) {
return 'comments';
} elseif ( false !== strpos( $class_attr, 'fb-comment-embed' ) ) {
return 'comment';
}

return null;
Expand All @@ -157,19 +184,54 @@ private function get_embed_type( $node ) {
* @param string $embed_type Embed type.
*/
private function create_amp_facebook_and_replace_node( $dom, $node, $embed_type ) {

$attributes = array(
'layout' => 'responsive',
'width' => $node->hasAttribute( 'data-width' ) ? $node->getAttribute( 'data-width' ) : $this->DEFAULT_WIDTH,
'height' => $node->hasAttribute( 'data-height' ) ? $node->getAttribute( 'data-height' ) : $this->DEFAULT_HEIGHT,
);

$node->removeAttribute( 'data-width' );
$node->removeAttribute( 'data-height' );

foreach ( $node->attributes as $attribute ) {
if ( 'data-' === substr( $attribute->nodeName, 0, 5 ) ) {
$attributes[ $attribute->nodeName ] = $attribute->nodeValue;
}
}

if ( 'page' === $embed_type ) {
$amp_tag = 'amp-facebook-page';
} elseif ( 'like' === $embed_type ) {
$amp_tag = 'amp-facebook-like';
} elseif ( 'comments' === $embed_type ) {
$amp_tag = 'amp-facebook-comments';
} else {
$amp_tag = $this->amp_tag;

$attributes['data-embed-as'] = $embed_type;
}

$amp_facebook_node = AMP_DOM_Utils::create_node(
$dom,
$this->amp_tag,
array(
'data-href' => $node->getAttribute( 'data-href' ),
'data-embed-as' => $embed_type,
'layout' => 'responsive',
'width' => $this->DEFAULT_WIDTH,
'height' => $this->DEFAULT_HEIGHT,
)
$amp_tag,
$attributes
);

$fallback = null;
foreach ( $node->childNodes as $child_node ) {
if ( $child_node instanceof DOMElement && false !== strpos( $child_node->getAttribute( 'class' ), 'fb-xfbml-parse-ignore' ) ) {
$fallback = $child_node;
$child_node->parentNode->removeChild( $child_node );
$fallback->setAttribute( 'fallback', '' );
break;
}
}

$node->parentNode->replaceChild( $amp_facebook_node, $node );
if ( $fallback ) {
$amp_facebook_node->appendChild( $fallback );
}

$this->did_convert_elements = true;
}
Expand Down
124 changes: 117 additions & 7 deletions tests/test-amp-facebook-embed.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
<?php

/**
* Class AMP_Facebook_Embed_Test
*
* @package AMP
*/

/**
* Test AMP_Facebook_Embed_Test
*
* @covers AMP_Facebook_Embed_Handler
*/
class AMP_Facebook_Embed_Test extends WP_UnitTestCase {

/**
* Data provider for test__conversion.
*
* @return array Data.
*/
public function get_conversion_data() {
return array(
'no_embed' => array(
Expand All @@ -27,7 +43,7 @@ public function get_conversion_data() {
'https://www.facebook.com/photo.php?fbid=10102533316889441&set=a.529237706231.2034669.4&type=3&theater' . PHP_EOL,
'<p><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></p>' . PHP_EOL,
),
'notes_url' => array(
'notes_url2' => array(
'https://www.facebook.com/zuck/videos/10102509264909801/' . PHP_EOL,
'<p><amp-facebook data-href="https://www.facebook.com/zuck/videos/10102509264909801/" layout="responsive" width="600" height="400"></amp-facebook></p>' . PHP_EOL,
),
Expand All @@ -36,16 +52,25 @@ public function get_conversion_data() {
}

/**
* Test conversion.
*
* @dataProvider get_conversion_data
* @param string $source Source.
* @param string $expected Expected.
*/
public function test__conversion( $source, $expected ) {
$embed = new AMP_Facebook_Embed_Handler();
$embed->register_embed();
$filtered_content = apply_filters( 'the_content', $source );

$this->assertEquals( $expected, $filtered_content );
$this->assertEqualMarkup( $expected, $filtered_content );
}

/**
* Get scripts data.
*
* @return array Scripts.
*/
public function get_scripts_data() {
return array(
'not_converted' => array(
Expand All @@ -60,7 +85,11 @@ public function get_scripts_data() {
}

/**
* Test get_scripts().
*
* @dataProvider get_scripts_data
* @param string $source Source.
* @param array $expected Expected scripts.
*/
public function test__get_scripts( $source, $expected ) {
$embed = new AMP_Facebook_Embed_Handler();
Expand Down Expand Up @@ -96,16 +125,79 @@ public function get_raw_embed_dataset() {

'post_embed' => array(
'<div class="fb-post" data-href="https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-javascript-sdk-truly-asynchronous-loading/10151176218703920/"></div>',
'<amp-facebook 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" width="600" height="400"></amp-facebook>',
'<amp-facebook layout="responsive" width="600" 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"></amp-facebook>',
),

'post_with_fallbacks' => array(
'
<div class="fb-post" data-href="https://www.facebook.com/20531316728/posts/10154009990506729/" data-width="500" data-show-text="true">
<blockquote cite="https://developers.facebook.com/20531316728/posts/10154009990506729/" class="fb-xfbml-parse-ignore">
Posted by <a href="https://www.facebook.com/facebook/">Facebook</a> on <a href="https://developers.facebook.com/20531316728/posts/10154009990506729/">Thursday, August 27, 2015</a>
</blockquote>
</div>
',
'
<amp-facebook layout="responsive" width="500" height="400" data-href="https://www.facebook.com/20531316728/posts/10154009990506729/" data-show-text="true" data-embed-as="post">
<blockquote cite="https://developers.facebook.com/20531316728/posts/10154009990506729/" class="fb-xfbml-parse-ignore" fallback="">
Posted by <a href="https://www.facebook.com/facebook/">Facebook</a> on <a href="https://developers.facebook.com/20531316728/posts/10154009990506729/">Thursday, August 27, 2015</a>
</blockquote>
</amp-facebook>
',
),

'video_embed' => array(
'<div class="fb-video" data-href="https://www.facebook.com/amanda.orr.56/videos/10212156330049017/" data-show-text="false"></div>',
'<amp-facebook data-href="https://www.facebook.com/amanda.orr.56/videos/10212156330049017/" data-embed-as="video" layout="responsive" width="600" height="400"></amp-facebook>',
'<amp-facebook layout="responsive" width="600" height="400" data-href="https://www.facebook.com/amanda.orr.56/videos/10212156330049017/" data-show-text="false" data-embed-as="video"></amp-facebook>',
),

'page_embed' => array(
'
<div class="fb-page" data-href="https://www.facebook.com/xwp.co/" data-width="340" data-height="432" data-hide-cover="true" data-show-facepile="true" data-show-posts="false">
<div class="fb-xfbml-parse-ignore">
<blockquote cite="https://www.facebook.com/xwp.co/"><a href="https://www.facebook.com/xwp.co/">Like Us</a></blockquote>
</div>
</div>
',
'
<amp-facebook-page layout="responsive" width="340" height="432" data-href="https://www.facebook.com/xwp.co/" data-hide-cover="true" data-show-facepile="true" data-show-posts="false">
<div class="fb-xfbml-parse-ignore" fallback="">
<blockquote cite="https://www.facebook.com/xwp.co/"><a href="https://www.facebook.com/xwp.co/">Like Us</a></blockquote>
</div>
</amp-facebook-page>
',
),

'like' => array(
'
<div class="fb-like" data-href="https://developers.facebook.com/docs/plugins/" data-width="400" data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="true"></div>
',
'
<amp-facebook-like layout="responsive" width="400" height="400" data-href="https://developers.facebook.com/docs/plugins/" data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="true">
</amp-facebook-like>
',
),

'comments' => array(
'
<div class="fb-comments" data-href="https://developers.facebook.com/docs/plugins/comments#configurator" data-numposts="5"></div>
',
'<amp-facebook-comments layout="responsive" width="600" height="400" data-href="https://developers.facebook.com/docs/plugins/comments#configurator" data-numposts="5"></amp-facebook-comments>',
),

'comment_embed' => array(
'
<div class="fb-comment-embed" data-href="https://www.facebook.com/zuck/posts/10102735452532991?comment_id=1070233703036185" data-width="500"></div>
',
'<amp-facebook layout="responsive" width="500" height="400" data-href="https://www.facebook.com/zuck/posts/10102735452532991?comment_id=1070233703036185" data-embed-as="comment"></amp-facebook>',
),

'remove_fb_root' => array(
'<div id="fb-root"></div><script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.2"></script>', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
'',
),
);
}


/**
* Test raw_embed_sanitizer.
*
Expand All @@ -122,6 +214,24 @@ public function test__raw_embed_sanitizer( $source, $expected ) {

$content = AMP_DOM_Utils::get_content_from_dom( $dom );

$this->assertEquals( $expected, $content );
$this->assertEqualMarkup( $expected, $content );
}

/**
* Assert markup is equal.
*
* @param string $expected Expected markup.
* @param string $actual Actual markup.
*/
public function assertEqualMarkup( $expected, $actual ) {
$actual = preg_replace( '/\s+/', ' ', $actual );
$expected = preg_replace( '/\s+/', ' ', $expected );
$actual = preg_replace( '/(?<=>)\s+(?=<)/', '', trim( $actual ) );
$expected = preg_replace( '/(?<=>)\s+(?=<)/', '', trim( $expected ) );

$this->assertEquals(
array_filter( preg_split( '#(<[^>]+>|[^<>]+)#', $expected, -1, PREG_SPLIT_DELIM_CAPTURE ) ),
array_filter( preg_split( '#(<[^>]+>|[^<>]+)#', $actual, -1, PREG_SPLIT_DELIM_CAPTURE ) )
);
}
}

0 comments on commit c5280ae

Please sign in to comment.