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

Add embed support for Twitter timelines via new amp-twitter attributes #1396

Merged
Merged
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
90 changes: 76 additions & 14 deletions includes/embeds/class-amp-twitter-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,22 @@
* Much of this class is borrowed from Jetpack embeds
*/
class AMP_Twitter_Embed_Handler extends AMP_Base_Embed_Handler {
const URL_PATTERN = '#http(s|):\/\/twitter\.com(\/\#\!\/|\/)([a-zA-Z0-9_]{1,20})\/status(es)*\/(\d+)#i';

/**
* URL pattern for a Tweet URL.
*
* @since 0.2
* @var string
*/
const URL_PATTERN = '#https?:\/\/twitter\.com(?:\/\#\!\/|\/)(?P<username>[a-zA-Z0-9_]{1,20})\/status(?:es)?\/(?P<tweet>\d+)#i';

/**
* URL pattern for a Twitter timeline.
*
* @since 1.0
* @var string
*/
const URL_PATTERN_TIMELINE = '#https?:\/\/twitter\.com(?:\/\#\!\/|\/)(?P<username>[a-zA-Z0-9_]{1,20})(?:$|\/(?P<type>likes|lists)(\/(?P<id>[a-zA-Z0-9_-]+))?)#i';

/**
* Tag.
Expand All @@ -31,21 +46,25 @@ class AMP_Twitter_Embed_Handler extends AMP_Base_Embed_Handler {
* Register embed.
*/
public function register_embed() {
add_shortcode( 'tweet', array( $this, 'shortcode' ) );
add_shortcode( 'tweet', array( $this, 'shortcode' ) ); // Note: This is a Jetpack shortcode.
wp_embed_register_handler( 'amp-twitter', self::URL_PATTERN, array( $this, 'oembed' ), -1 );
wp_embed_register_handler( 'amp-twitter-timeline', self::URL_PATTERN_TIMELINE, array( $this, 'oembed_timeline' ), -1 );
}

/**
* Unregister embed.
*/
public function unregister_embed() {
remove_shortcode( 'tweet' );
remove_shortcode( 'tweet' ); // Note: This is a Jetpack shortcode.
wp_embed_unregister_handler( 'amp-twitter', -1 );
wp_embed_unregister_handler( 'amp-twitter-timeline', -1 );
}

/**
* Gets AMP-compliant markup for the Twitter shortcode.
*
* Note that this shortcode is is defined in Jetpack.
*
* @param array $attr The Twitter attributes.
* @return string Twitter shortcode markup.
*/
Expand All @@ -63,8 +82,8 @@ public function shortcode( $attr ) {
$id = $attr['tweet'];
} else {
preg_match( self::URL_PATTERN, $attr['tweet'], $matches );
if ( isset( $matches[5] ) && is_numeric( $matches[5] ) ) {
$id = $matches[5];
if ( isset( $matches['tweet'] ) && is_numeric( $matches['tweet'] ) ) {
$id = $matches['tweet'];
}

if ( empty( $id ) ) {
Expand All @@ -90,17 +109,14 @@ public function shortcode( $attr ) {
*
* @see \WP_Embed::shortcode()
*
* @param array $matches URL pattern matches.
* @param array $attr Shortcode attributes.
* @param string $url URL.
* @param string $rawattr Unmodified shortcode attributes.
* @param array $matches URL pattern matches.
* @return string Rendered oEmbed.
*/
public function oembed( $matches, $attr, $url, $rawattr ) {
public function oembed( $matches ) {
$id = false;

if ( isset( $matches[5] ) && is_numeric( $matches[5] ) ) {
$id = $matches[5];
if ( isset( $matches['tweet'] ) && is_numeric( $matches['tweet'] ) ) {
$id = $matches['tweet'];
}

if ( ! $id ) {
Expand All @@ -110,6 +126,52 @@ public function oembed( $matches, $attr, $url, $rawattr ) {
return $this->shortcode( array( 'tweet' => $id ) );
}

/**
* Render oEmbed for a timeline.
*
* @since 1.0
*
* @param array $matches URL pattern matches.
* @return string Rendered oEmbed.
*/
public function oembed_timeline( $matches ) {
if ( ! isset( $matches['username'] ) ) {
return '';
}

$attributes = array(
'data-timeline-source-type' => 'profile',
'data-timeline-screen-name' => $matches['username'],
);

if ( isset( $matches['type'] ) ) {
switch ( $matches['type'] ) {
case 'likes':
$attributes['data-timeline-source-type'] = 'likes';
break;
case 'lists':
if ( ! isset( $matches['id'] ) ) {
return '';
}
$attributes['data-timeline-source-type'] = 'list';
$attributes['data-timeline-slug'] = $matches['id'];
$attributes['data-timeline-owner-screen-name'] = $attributes['data-timeline-screen-name'];
unset( $attributes['data-timeline-screen-name'] );
break;
default:
return '';
}
}

$attributes['layout'] = 'responsive';
$attributes['width'] = $this->args['width'];
$attributes['height'] = $this->args['height'];

$this->did_convert_elements = true;

return AMP_HTML_Utils::build_tag( $this->amp_tag, $attributes );
}

/**
* Sanitized <blockquote class="twitter-tweet"> tags to <amp-twitter>.
*
Expand Down Expand Up @@ -188,7 +250,7 @@ private function get_tweet_id( $node ) {
/**
* DOMNode
*
* @var DOMNode $anchors
* @var DOMNodeList $anchors
*/
$anchors = $node->getElementsByTagName( 'a' );

Expand All @@ -200,7 +262,7 @@ private function get_tweet_id( $node ) {
foreach ( $anchors as $anchor ) {
$found = preg_match( self::URL_PATTERN, $anchor->getAttribute( 'href' ), $matches );
if ( $found ) {
return $matches[5];
return $matches['tweet'];
}
}

Expand Down
35 changes: 26 additions & 9 deletions tests/test-amp-twitter-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,61 @@
class AMP_Twitter_Embed_Test extends WP_UnitTestCase {
public function get_conversion_data() {
return array(
'no_embed' => array(
'no_embed' => array(
'<p>Hello world.</p>',
'<p>Hello world.</p>' . PHP_EOL,
),
'url_simple' => array(
'url_simple' => array(
'https://twitter.com/wordpress/status/987437752164737025' . PHP_EOL,
'<p><amp-twitter data-tweetid="987437752164737025" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),
'url_with_big_tweet_id' => array(
'url_with_big_tweet_id' => array(
'https://twitter.com/wordpress/status/705219971425574912' . PHP_EOL,
'<p><amp-twitter data-tweetid="705219971425574912" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),

'shortcode_without_id' => array(
'timeline_url_with_profile' => array(
'https://twitter.com/wordpress' . PHP_EOL,
'<p><amp-twitter data-timeline-source-type="profile" data-timeline-screen-name="wordpress" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),
'timeline_url_with_likes' => array(
'https://twitter.com/wordpress/likes' . PHP_EOL,
'<p><amp-twitter data-timeline-source-type="likes" data-timeline-screen-name="wordpress" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),
'timeline_url_with_list' => array(
'https://twitter.com/wordpress/lists/random_list' . PHP_EOL,
'<p><amp-twitter data-timeline-source-type="list" data-timeline-slug="random_list" data-timeline-owner-screen-name="wordpress" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),
'timeline_url_with_list2' => array(
'https://twitter.com/robertnyman/lists/web-gdes' . PHP_EOL,
'<p><amp-twitter data-timeline-source-type="list" data-timeline-slug="web-gdes" data-timeline-owner-screen-name="robertnyman" layout="responsive" width="600" height="480"></amp-twitter></p>' . PHP_EOL,
),

'shortcode_without_id' => array(
'[tweet]' . PHP_EOL,
'' . PHP_EOL,
),
'shortcode_simple' => array(
'shortcode_simple' => array(
'[tweet 987437752164737025]' . PHP_EOL,
'<amp-twitter data-tweetid="987437752164737025" layout="responsive" width="600" height="480"></amp-twitter>' . PHP_EOL,
),
'shortcode_with_tweet_attribute' => array(
'shortcode_with_tweet_attribute' => array(
'[tweet tweet=987437752164737025]' . PHP_EOL,
'<amp-twitter data-tweetid="987437752164737025" layout="responsive" width="600" height="480"></amp-twitter>' . PHP_EOL,
),
'shortcode_with_big_tweet_id' => array(
'shortcode_with_big_tweet_id' => array(
'[tweet 705219971425574912]' . PHP_EOL,
'<amp-twitter data-tweetid="705219971425574912" layout="responsive" width="600" height="480"></amp-twitter>' . PHP_EOL,
),
'shortcode_with_url' => array(
'shortcode_with_url' => array(
'[tweet https://twitter.com/wordpress/status/987437752164737025]' . PHP_EOL,
'<amp-twitter data-tweetid="987437752164737025" layout="responsive" width="600" height="480"></amp-twitter>' . PHP_EOL,
),
'shortcode_with_url_with_big_tweet_id' => array(
'[tweet https://twitter.com/wordpress/status/705219971425574912]' . PHP_EOL,
'<amp-twitter data-tweetid="705219971425574912" layout="responsive" width="600" height="480"></amp-twitter>' . PHP_EOL,
),
'shortcode_with_non_numeric_tweet_id' => array(
'shortcode_with_non_numeric_tweet_id' => array(
'[tweet abcd]' . PHP_EOL,
'' . PHP_EOL,
),
Expand Down