Skip to content

Commit

Permalink
Add AMP support for the Twitter Timeline widget (#15328)
Browse files Browse the repository at this point in the history
  • Loading branch information
kienstra authored Apr 24, 2020
1 parent 9d8ef36 commit bdf1846
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 42 deletions.
96 changes: 54 additions & 42 deletions modules/widgets/twitter-timeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ public function __construct() {
* Enqueue scripts.
*/
public function enqueue_scripts() {
wp_enqueue_script( 'jetpack-twitter-timeline' );
if ( ! class_exists( 'Jetpack_AMP_Support' ) || ! Jetpack_AMP_Support::is_amp_request() ) {
wp_enqueue_script( 'jetpack-twitter-timeline' );
}
}

/**
Expand Down Expand Up @@ -85,59 +87,54 @@ public function admin_scripts( $hook ) {
* @param array $instance Saved values from database.
*/
public function widget( $args, $instance ) {
$output = '';

// Twitter deprecated `data-widget-id` on 2018-05-25,
// with cease support deadline on 2018-07-27.
if ( isset( $instance['type'] ) && 'widget-id' === $instance['type'] ) {
if ( current_user_can( 'edit_theme_options' ) ) {
echo $args['before_widget'];
echo $args['before_title'] . esc_html__( 'Twitter Timeline', 'jetpack' ) . $args['after_title'];
echo '<p>' . esc_html__( "The Twitter Timeline widget can't display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username. Otherwise, delete this widget.", 'jetpack' ) . '</p>';
echo '<p>' . esc_html__( '(Only administrators will see this message.)', 'jetpack' ) . '</p>';
echo $args['after_widget'];
$output .= $args['before_widget']
. $args['before_title'] . esc_html__( 'Twitter Timeline', 'jetpack' ) . $args['after_title']
. '<p>' . esc_html__( "The Twitter Timeline widget can't display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username. Otherwise, delete this widget.", 'jetpack' ) . '</p>'
. '<p>' . esc_html__( '(Only administrators will see this message.)', 'jetpack' ) . '</p>'
. $args['after_widget'];
}

echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}

$instance['lang'] = substr( strtoupper( get_locale() ), 0, 2 );

echo $args['before_widget'];
$output .= $args['before_widget'];

$title = isset( $instance['title'] ) ? $instance['title'] : '';

/** This filter is documented in core/src/wp-includes/default-widgets.php */
$title = apply_filters( 'widget_title', $title );
if ( ! empty( $title ) ) {
echo $args['before_title'] . $title . $args['after_title'];
}

if ( isset( $instance['type'] ) && 'widget-id' === $instance['type'] && current_user_can( 'edit_theme_options' ) ) {
echo '<p>' . esc_html__( 'As of July 27, 2018, the Twitter Timeline widget will no longer display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username.', 'jetpack' ) . '</p>';
echo '<p>' . esc_html__( '(Only administrators will see this message.)', 'jetpack' ) . '</p>';
$output .= $args['before_title'] . $title . $args['after_title'];
}

// Start tag output
// This tag is transformed into the widget markup by Twitter's
// widgets.js code
echo '<a class="twitter-timeline"';

$data_attribs = array(
$possible_data_attribs = array(
'width',
'height',
'theme',
'border-color',
'tweet-limit',
'lang',
);
foreach ( $data_attribs as $att ) {
$data_attrs = '';
foreach ( $possible_data_attribs as $att ) {
if ( ! empty( $instance[ $att ] ) && ! is_array( $instance[ $att ] ) ) {
echo ' data-' . esc_attr( $att ) . '="' . esc_attr( $instance[ $att ] ) . '"';
$data_attrs .= ' data-' . esc_attr( $att ) . '="' . esc_attr( $instance[ $att ] ) . '"';
}
}

/** This filter is documented in modules/shortcodes/tweet.php */
$partner = apply_filters( 'jetpack_twitter_partner_id', 'jetpack' );
if ( ! empty( $partner ) ) {
echo ' data-partner="' . esc_attr( $partner ) . '"';
$data_attrs .= ' data-partner="' . esc_attr( $partner ) . '"';
}

/**
Expand All @@ -153,29 +150,13 @@ public function widget( $args, $instance ) {
*/
$dnt = apply_filters( 'jetpack_twitter_timeline_default_dnt', false );
if ( true === $dnt ) {
echo ' data-dnt="true"';
$data_attrs .= ' data-dnt="true"';
}

if ( ! empty( $instance['chrome'] ) && is_array( $instance['chrome'] ) ) {
echo ' data-chrome="' . esc_attr( join( ' ', $instance['chrome'] ) ) . '"';
$data_attrs .= ' data-chrome="' . esc_attr( join( ' ', $instance['chrome'] ) ) . '"';
}

$type = ( isset( $instance['type'] ) ? $instance['type'] : '' );
$widget_id = ( isset( $instance['widget-id'] ) ? $instance['widget-id'] : '' );
switch ( $type ) {
case 'profile':
echo ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';
break;
case 'widget-id':
default:
echo ' data-widget-id="' . esc_attr( $widget_id ) . '"';
break;
}
echo ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';

// End tag output
echo '>';

$timeline_placeholder = __( 'My Tweets', 'jetpack' );

/**
Expand All @@ -189,11 +170,42 @@ public function widget( $args, $instance ) {
*/
$timeline_placeholder = apply_filters( 'jetpack_twitter_timeline_placeholder', $timeline_placeholder );

echo esc_html( $timeline_placeholder ) . '</a>';
$type = ( isset( $instance['type'] ) ? $instance['type'] : '' );
$widget_id = ( isset( $instance['widget-id'] ) ? $instance['widget-id'] : '' );

if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
$width = ! empty( $instance['width'] ) ? $instance['width'] : 600;
$height = ! empty( $instance['height'] ) ? $instance['height'] : 480;
$output .= '<amp-twitter' . $data_attrs . ' layout="responsive" data-timeline-source-type="profile" data-timeline-screen-name="' . esc_attr( $widget_id ) . '" width="' . absint( $width ) . '" height="' . absint( $height ) . '">'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$output .= esc_html( $timeline_placeholder ) . '</amp-twitter>';

echo $output . $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}

// Start tag output
// This tag is transformed into the widget markup by Twitter's
// widgets.js code.
$output .= '<a class="twitter-timeline"' . $data_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
switch ( $type ) {
case 'profile':
$output .= ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';
break;
case 'widget-id':
default:
$output .= ' data-widget-id="' . esc_attr( $widget_id ) . '"';
break;
}
$output .= ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';

// End tag output.
$output .= '>';

$output .= esc_html( $timeline_placeholder ) . '</a>';

// End tag output

echo $args['after_widget'];
echo $output . $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

/** This action is documented in modules/widgets/gravatar-profile.php */
do_action( 'jetpack_stats_extra', 'widget_view', 'twitter_timeline' );
Expand Down
135 changes: 135 additions & 0 deletions tests/php/modules/widgets/test_twitter-timeline-widget.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php // phpcs:ignore Wordpress.Files.FileName.NotHyphenatedLowercase
/**
* Test Jetpack_Twitter_Timeline_Widget.
*
* @package Jetpack
*/

require dirname( __FILE__ ) . '/../../../../modules/widgets/twitter-timeline.php';

/**
* Test Jetpack_Twitter_Timeline_Widget.
*/
class WP_Test_Twitter_Timeline_Widget extends WP_UnitTestCase {

/**
* The tested instance.
*
* @var Jetpack_Twitter_Timeline_Widget
*/
public $instance;

/**
* Sets up each test.
*
* @inheritDoc
*/
public function setUp() {
parent::setUp();
$this->instance = new Jetpack_Twitter_Timeline_Widget();
}

/**
* Gets the test data for test_widget().
*
* @return array The test data.
*/
public function get_widget_data() {
return array(
'no_id' => array(
array(),
false,
'<div><a class="twitter-timeline" data-lang="EN" data-partner="jetpack" data-widget-id="" href="https://twitter.com/">My Tweets</a></div>',
),
'type_is_widget_id' => array(
array( 'type' => 'widget-id' ),
false,
'<div><h1>Twitter Timeline</h1><p>The Twitter Timeline widget can&#039;t display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username. Otherwise, delete this widget.</p><p>(Only administrators will see this message.)</p></div>',
),
'only_widget_id_present' => array(
array( 'widget-id' => 'wordpress' ),
false,
'<div><a class="twitter-timeline" data-lang="EN" data-partner="jetpack" data-widget-id="wordpress" href="https://twitter.com/wordpress">My Tweets</a></div>',
),
'type_is_profile' => array(
array(
'widget-id' => 'wordpress',
'type' => 'profile',
),
false,
'<div><a class="twitter-timeline" data-lang="EN" data-partner="jetpack" href="https://twitter.com/wordpress" href="https://twitter.com/wordpress">My Tweets</a></div>',
),
'with_data_attributes' => array(
array(
'width' => '200',
'height' => '400',
'theme' => 'dark',
'border-color' => '#ffffff',
'tweet-limit' => '9',
'lang' => 'es',
),
false,
'<div><a class="twitter-timeline" data-width="200" data-height="400" data-theme="dark" data-border-color="#ffffff" data-tweet-limit="9" data-lang="EN" data-partner="jetpack" data-widget-id="" href="https://twitter.com/">My Tweets</a></div>',
),
'data_chrome' => array(
array(
'widget-id' => 'wordpress',
'chrome' => array( 'noborders', 'nofooter' ),
),
false,
'<div><a class="twitter-timeline" data-lang="EN" data-partner="jetpack" data-chrome="noborders nofooter" data-widget-id="wordpress" href="https://twitter.com/wordpress">My Tweets</a></div>',
),
'amp_no_widget_id_present' => array(
array(),
true,
'<div><amp-twitter data-lang="EN" data-partner="jetpack" layout="responsive" data-timeline-source-type="profile" data-timeline-screen-name="" width="600" height="480">My Tweets</amp-twitter></div>',
),
'amp_widget_id_present' => array(
array( 'widget-id' => 'wordpress' ),
true,
'<div><amp-twitter data-lang="EN" data-partner="jetpack" layout="responsive" data-timeline-source-type="profile" data-timeline-screen-name="wordpress" width="600" height="480">My Tweets</amp-twitter></div>',
),
'amp_with_data_attributes' => array(
array(
'width' => '200',
'height' => '800',
'theme' => 'light',
'border-color' => '#ff0000',
'tweet-limit' => '4',
'lang' => 'cnr',
),
true,
'<div><amp-twitter data-width="200" data-height="800" data-theme="light" data-border-color="#ff0000" data-tweet-limit="4" data-lang="EN" data-partner="jetpack" layout="responsive" data-timeline-source-type="profile" data-timeline-screen-name="" width="200" height="800">My Tweets</amp-twitter></div>',
),
);
}

/**
* Test the widget method that outputs the markup.
*
* @dataProvider get_widget_data
* @covers Jetpack_Twitter_Timeline_Widget::widget()
*
* @param array $instance The widget instance.
* @param bool $is_amp Whether this is on an AMP endpoint.
* @param string $expected The expected output of the tested method.
*/
public function test_widget( $instance, $is_amp, $expected ) {
wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
if ( $is_amp ) {
add_filter( 'jetpack_is_amp_request', '__return_true' );
}

$args = array(
'before_widget' => '<div>',
'after_widget' => '</div>',
'before_title' => '<h1>',
'after_title' => '</h1>',
);

ob_start();
$this->instance->widget( $args, $instance );

$this->assertEquals( $expected, ob_get_clean() );
}
}

0 comments on commit bdf1846

Please sign in to comment.