Enterprise Integration Zone is brought to you in partnership with:

Paulund is a website dedicated to writing tutorials and code snippets about Web Development, the main subjects are PHP, Wordpress, jQuery, CSS3 and HTML5. Paul is a DZone MVB and is not an employee of DZone and has posted 124 posts at DZone. You can read more from them at their website. View Full User Profile

Using The New Twitter API V1.1

02.11.2013
| 11206 views |
  • submit to reddit
From March 5th 2013 Twitter are removing there current API and it will be fully replaced with the new API V1.1. This means that any application that is currently using the old API will stop working on March 5th. The main feature of the API is that requests need to be authenticated before they will work correctly. This is so Twitter can prevent abusive behaviour of their API.

A while ago I wrote a WordPress widget that will display your latest Twitter posts, this widget will now need to be updated and replaced with the new API.

In this tutorial we are going to investigate the changes we need to make to update a Twitter application from version 1 to version 1.1, in the previous tutorial we used WordPress to cache and display the Tweets and will continue to use WordPress with the new API.

Create An Application On Twitter

To start using the new API you need to be authenticated, which means Twitter needs to have certain information about your application and how it is going to be used so that it will provide you with access keys to use the API.

To get the access keys you need to create an application on the Twitter Developer site.

Create an application - Twitter Developers

Twitter Developers

Once your application is created Twitter will generate your Oauth settings and your access tokens to your new application. You will need to use this data when connecting to the Twitter Oauth to query the Twitter API.

Download Twitter OAUTH PHP Class

With all the data we need to connect to the Twitter OAUTH we now need a way of connecting to the API, Twitter has created a collection of libraries that will allow you to connect to the new API in any language you are using.

Twitter API Libraries

As this application is using WordPress we are going to use one of the PHP libraries called Twitteroauth which you can download for free from Github.

Twitteroauth

This library comes with 2 classes which make it really easy to connect to Twitter using OAuth and in this tutorial we will see how easy it is by getting a list of the latest tweets.

Get Latest Tweets

Now we have a PHP library to get a connection to Twitter we can now use this in our WordPress widget to get the latest tweets.

Version 1 API

In version 1 of the Twitter API you can make a call like below to return your tweets.

$transName = 'list-tweets';
$cacheTime = 10; 
if(false === ($twitterData = get_transient($transName) ) ){
     // Get the tweets from Twitter.
     $json = wp_remote_get("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=".$this->twitter_username."&count=".$this->twitter_postcount);
     // Get tweets into an array.
     $twitterData = json_decode($json['body'], true);
     // Save our new transient.
     set_transient($transName, $twitterData, 60 * $cacheTime);
}
foreach($twitterData as $tweets)
{
     // display a list of your tweets
}

This uses WordPress transient API to cache the results of the Twitter call so that we only have to make a call to the API every 10 minutes to check for new updates. To make the call to the Twitter API we use another built in WordPress function called wp_remote_get() which uses a parameter for the URL, this will make a HTTP request to this URL and will return the contents of the file. As it returns JSON we can populate this into an object by using the json_decode() PHP function. When this data is in a variable we store the new contents in the database cache by using the transient API. Then we can loop through the data to display each tweet on the page.

Version 1.1 API

Thanks to the TwitterOauth class we downloaded from Github the version 1.1 API call is very similar, below is the code we will use for version 1.1.

$transName = 'list_tweets';
$cacheTime = 10;
if(false === ($twitterData = get_transient($transName) ) ){
     // require the twitter auth class
     require_once 'twitteroauth/twitteroauth.php';
     $twitterConnection = new TwitterOAuth(
					'xxxxxxxxxxxxxxxxxxxxxx',	// Consumer Key
					'xxxxxxxxxxxxxxxxxxxxxx',   	// Consumer secret
					'xxxxxxxxxxxxxxxxxxxxxx',       // Access token
					'xxxxxxxxxxxxxxxxxxxxxx'    	// Access token secret
					);
     $twitterData = $twitterConnection->get(
					  'statuses/user_timeline',
					  array(
					    'screen_name'     => $tab['twitter_username'],
					    'count'           => $tab['twitter_post_count'],
					    'exclude_replies' => false
					  )
					);
     if($twitterConnection->http_code != 200)
     {
          $twitterData = get_transient($transName);
     }
     // Save our new transient.
     set_transient($transName, $twitterData, 60 * $cacheTime);
}

As you can see the code is very similar to the version 1 code, we start off the same way using the transient API to check if there is any data in the cache. If there isn't any data or the cache has expired then we need to get the tweets by using the API.

To use the API we first need to authenticate our request with the TwitterOauth class. To do this we need to include it in our code and then instantiate the TwitterOath class, the constructor to this class has 4 parameters which you will get from the developer twitter site.

require_once 'twitteroauth/twitteroauth.php';
     $twitterConnection = new TwitterOAuth(
					'xxxxxxxxxxxxxxxxxxxxxx',	// Consumer Key
					'xxxxxxxxxxxxxxxxxxxxxx',   	// Consumer secret
					'xxxxxxxxxxxxxxxxxxxxxx',       // Access token
					'xxxxxxxxxxxxxxxxxxxxxx'    	// Access token secret
					);

We can now use this $twitterConnection variable to call the new Twitter API by using the get() method. This get() method takes 2 parameters, the first is the call you want to make and the second is the parameters you are passing into the API.

$twitterData = $twitterConnection->get(
				'statuses/user_timeline',
				 array(
					 'screen_name'     => $tab['twitter_username'],
					 'count'           => $tab['twitter_post_count'],
					 'exclude_replies' => false
				)
				);
foreach($twitterData as $tweets)
{
     // Display the tweets
}

The return of the get method will be an object of data from the twitter API populated with the tweets that match the parameters you provided. Once this variable is populated we can loop through the contents to display the tweets.

That's all you need to start using the new API, you need to make this change to your existing Twitter applications by the 5th of March or your application will stop working.

Full Twitter V1.1 WordPress Widget Code

<?php
/*
 * Plugin Name: Paulund Display Latest Tweets
 * Plugin URI: http://www.paulund.co.uk
 * Description: A widget that displays your latest tweets
 * Version: 1.0
 * Author: Paul Underwood
 * Author URI: http://www.paulund.co.uk
 * License: GPL2
    Copyright 2012  Paul Underwood
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License,
    version 2, as published by the Free Software Foundation.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
*/
/**
 * Register the Widget
 */
add_action( 'widgets_init', create_function( '', 'register_widget("pu_tweet_widget");' ) );
/**
 * Create the widget class and extend from the WP_Widget
 */
 class pu_tweet_widget extends WP_Widget {
	private $twitter_title = "My Tweets";
	private $twitter_username = "paulund_";
	private $twitter_postcount = "10";
	private $twitter_follow_text = "Follow Me On Twitter";
	/**
	 * Register widget with WordPress.
	 */
	public function __construct() {
		parent::__construct(
			'pu_tweet_widget',		// Base ID
			'Paulund Twitter Widget',		// Name
			array(
				'classname'		=>	'pu_tweet_widget',
				'description'	=>	__('A widget that displays your latest tweets.', 'framework')
			)
		);
		// Load JavaScript and stylesheets
		$this->register_scripts_and_styles();
	} // end constructor
	/**
	 * Registers and enqueues stylesheets for the administration panel and the
	 * public facing site.
	 */
	public function register_scripts_and_styles() {
	} // end register_scripts_and_styles
	/**
	 * Front-end display of widget.
	 *
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {
		extract( $args );
		/* Our variables from the widget settings. */
		$this->twitter_title = apply_filters('widget_title', $instance['title'] );
		$this->twitter_username = $instance['username'];
		$this->twitter_postcount = $instance['postcount'];
		$this->twitter_follow_text = $instance['tweettext'];
		$transName = 'list_tweets';
	    $cacheTime = 20;
	    if(false === ($twitterData = get_transient($transName) ) ){
	    	require_once 'twitteroauth/twitteroauth.php';
			$twitterConnection = new TwitterOAuth(
								'xxxxxxxxxxxxxxxxxxxxxx',	// Consumer Key
								'xxxxxxxxxxxxxxxxxxxxxx',   	// Consumer secret
								'xxxxxxxxxxxxxxxxxxxxxx',       // Access token
								'xxxxxxxxxxxxxxxxxxxxxx'    	// Access token secret
								);
			$twitterData = $twitterConnection->get(
					  'statuses/user_timeline',
					  array(
					    'screen_name'     => $tab['twitter_username'],
					    'count'           => $tab['twitter_post_count'],
					    'exclude_replies' => false
					  )
					);
			if($twitterConnection->http_code != 200)
			{
				$twitterData = get_transient($transName);
			}
	        // Save our new transient.
	        set_transient($transName, $twitterData, 60 * $cacheTime);
	    }
		/* Before widget (defined by themes). */
		echo $before_widget;
		?>
<div class="twitter_box"><?php
		/* Display the widget title if one was input (before and after defined by themes). */
		if ( $this->twitter_title )
			echo $before_title . $this->twitter_title . $after_title;
		/* Display Latest Tweets */
		 ?>
			<a href="https://twitter.com/<?php echo $this->twitter_username; ?>"
				class="twitter-follow-button"
				data-show-count="true"
				data-lang="en">Follow @<?php echo $this->twitter_username; ?></a>
			<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
            <?php
            	if(!empty($twitterData) || !isset($twitterData['error'])){
            		$i=0;
					$hyperlinks = true;
					$encode_utf8 = true;
					$twitter_users = true;
					$update = true;
					echo '
<ul class="twitter_update_list">';
		            foreach($twitterData as $item){
		                    $msg = $item->text;
		                    $permalink = 'http://twitter.com/#!/'. $this->twitter_username .'/status/'. $item->id_str;
		                    if($encode_utf8) $msg = utf8_encode($msg);
		                    $link = $permalink;
		                     echo '
<li class="twitter-item">';
		                      if ($hyperlinks) {    $msg = $this->hyperlinks($msg); }
		                      if ($twitter_users)  { $msg = $this->twitter_users($msg); }
		                      echo $msg;
		                    if($update) {
		                      $time = strtotime($item->created_at);
		                      if ( ( abs( time() - $time) ) < 86400 )
		                        $h_time = sprintf( __('%s ago'), human_time_diff( $time ) );
		                      else
		                        $h_time = date(__('Y/m/d'), $time);
		                      echo sprintf( __('%s', 'twitter-for-wordpress'),' <span class="twitter-timestamp"><abbr title="' . date(__('Y/m/d H:i:s'), $time) . '">' . $h_time . '</abbr></span>' );
		                     }
		                    echo '</li>
';
		                    $i++;
		                    if ( $i >= $this->twitter_postcount ) break;
		            }
					echo '</ul>
';
            	}
            ?>
       		</div>
		<?php
		/* After widget (defined by themes). */
		echo $after_widget;
	}
	/**
	 * Sanitize widget form values as they are saved.
	 *
	 * @see WP_Widget::update()
	 *
	 * @param array $new_instance Values just sent to be saved.
	 * @param array $old_instance Previously saved values from database.
	 *
	 * @return array Updated safe values to be saved.
	 */
	function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		// Strip tags to remove HTML (important for text inputs)
		foreach($new_instance as $k => $v){
			$instance[$k] = strip_tags($v);
		}
		return $instance;
	}
	/**
	 * Create the form for the Widget admin
	 *
	 * @see WP_Widget::form()
	 *
	 * @param array $instance Previously saved values from database.
	 */
	function form( $instance ) {
		/* Set up some default widget settings. */
		$defaults = array(
		'title' => $this->twitter_title,
		'username' => $this->twitter_username,
		'postcount' => $this->twitter_postcount,
		'tweettext' => $this->twitter_follow_text,
		);
		$instance = wp_parse_args( (array) $instance, $defaults ); ?>
		<!-- Widget Title: Text Input -->

			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'framework') ?></label>
			<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" />
		
		<!-- Username: Text Input -->

			<label for="<?php echo $this->get_field_id( 'username' ); ?>"><?php _e('Twitter Username e.g. paulund_', 'framework') ?></label>
			<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'username' ); ?>" name="<?php echo $this->get_field_name( 'username' ); ?>" value="<?php echo $instance['username']; ?>" />
		
		<!-- Postcount: Text Input -->

			<label for="<?php echo $this->get_field_id( 'postcount' ); ?>"><?php _e('Number of tweets (max 20)', 'framework') ?></label>
			<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'postcount' ); ?>" name="<?php echo $this->get_field_name( 'postcount' ); ?>" value="<?php echo $instance['postcount']; ?>" />
		
		<!-- Tweettext: Text Input -->

			<label for="<?php echo $this->get_field_id( 'tweettext' ); ?>"><?php _e('Follow Text e.g. Follow me on Twitter', 'framework') ?></label>
			<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'tweettext' ); ?>" name="<?php echo $this->get_field_name( 'tweettext' ); ?>" value="<?php echo $instance['tweettext']; ?>" />
		
	<?php
	}
	/**
	 * Find links and create the hyperlinks
	 */
	private function hyperlinks($text) {
	    $text = preg_replace('/\b([a-zA-Z]+:\/\/[\w_.\-]+\.[a-zA-Z]{2,6}[\/\w\-~.?=&%#+$*!]*)\b/i',"<a href=\"$1\" class=\"twitter-link\">$1</a>", $text);
	    $text = preg_replace('/\b(?<!:\/\/)(www\.[\w_.\-]+\.[a-zA-Z]{2,6}[\/\w\-~.?=&%#+$*!]*)\b/i',"<a href=\"http://$1\" class=\"twitter-link\">$1</a>", $text);
	    // match name@address
	    $text = preg_replace("/\b([a-zA-Z][a-zA-Z0-9\_\.\-]*[a-zA-Z]*\@[a-zA-Z][a-zA-Z0-9\_\.\-]*[a-zA-Z]{2,6})\b/i","<a href=\"mailto://$1\" class=\"twitter-link\">$1</a>", $text);
	        //mach #trendingtopics. Props to Michael Voigt
	    $text = preg_replace('/([\.|\,|\:|\¡|\¿|\>|\{|\(]?)#{1}(\w*)([\.|\,|\:|\!|\?|\>|\}|\)]?)\s/i', "$1<a href=\"http://twitter.com/#search?q=$2\" class=\"twitter-link\">#$2</a>$3 ", $text);
	    return $text;
	}
	/**
	 * Find twitter usernames and link to them
	 */
	private function twitter_users($text) {
	       $text = preg_replace('/([\.|\,|\:|\¡|\¿|\>|\{|\(]?)@{1}(\w*)([\.|\,|\:|\!|\?|\>|\}|\)]?)\s/i', "$1<a href=\"http://twitter.com/$2\" class=\"twitter-user\">@$2</a>$3 ", $text);
	       return $text;
	}
 }
?>



Published at DZone with permission of Paul Underwood, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)