Twitter latest updates from a Twitter user inside your theme's widgets with the option of using Authenticated API calls. Customize the number of displayed Tweets, filter out replies, and include retweets.
*Can set a cache expire time (in seconds) to stay under Twitter's rate limit for authorized API calls.
Author: Brian Cerceo
Author URI: http://www.black-tooth.com
Version: 1.0
License: GPLv2
*/
/*
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* TWITTER Account OAuth Settings (https://dev.twitter.com/apps/) */
// inits json decoder/encoder object if not already available
global $wp_version;
if(!class_exists('TwitterOAuth')){
include_once( dirname( __FILE__ ) . '/twitteroauth.php' );
include_once( dirname( __FILE__ ) . '/OAuth.php' );
}
if ( version_compare( $wp_version, '2.9', '<' ) && !class_exists( 'Services_JSON' ) ) {
include_once( dirname( __FILE__ ) . '/class.json.php' );
}
if ( !function_exists('wpcom_time_since') ) :
/*
* Time since function taken from WordPress.com
*/
function wpcom_time_since( $original, $do_more = 0 ) {
// array of time period chunks
$chunks = array(
array(60 * 60 * 24 * 365 , 'year'),
array(60 * 60 * 24 * 30 , 'month'),
array(60 * 60 * 24 * 7, 'week'),
array(60 * 60 * 24 , 'day'),
array(60 * 60 , 'hour'),
array(60 , 'minute'),
);
$today = time();
$since = $today - $original;
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
$seconds = $chunks[$i][0];
$name = $chunks[$i][1];
if (($count = floor($since / $seconds)) != 0)
break;
}
$print = ($count == 1) ? '1 '.$name : "$count {$name}s";
if ($i + 1 < $j) {
$seconds2 = $chunks[$i + 1][0];
$name2 = $chunks[$i + 1][1];
// add second item if it's greater than 0
if ( (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) && $do_more )
$print .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s";
}
return $print;
}
endif;
if ( !function_exists('http_build_query') ) :
function http_build_query( $query_data, $numeric_prefix='', $arg_separator='&' ) {
$arr = array();
foreach ( $query_data as $key => $val )
$arr[] = urlencode($numeric_prefix.$key) . '=' . urlencode($val);
return implode($arr, $arg_separator);
}
endif;
class Auth_Twitter_Widget extends WP_Widget {
function Auth_Twitter_Widget() {
$widget_ops = array('classname' => 'widget_twitter', 'description' => __( 'Display your tweets from Twitter') );
parent::WP_Widget('twitter', __('Twitter'), $widget_ops);
}
function getConnectionWithAccessToken($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret) {
$connection = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
return $connection;
}
function widget( $args, $instance ) {
extract( $args );
$account = trim( urlencode( $instance['account'] ) );
if ( empty($account) ) return;
$title = apply_filters('widget_title', $instance['title']);
if ( empty($title) ) $title = __( 'Twitter Updates' );
$show = absint( $instance['show'] ); // # of Updates to show
if ( $show > 200 ) // Twitter paginates at 200 max tweets. update() should not have accepted greater than 20
$show = 200;
$hidereplies = (bool) $instance['hidereplies'];
$include_retweets = (bool) $instance['includeretweets'];
$useAuth = (bool) $instance['useAuth'];
$consumer_key = $instance['consumer_key'];
$consumer_secret = $instance['consumer_secret'];
$oauth_token = $instance['oauth_token'];
$oauth_token_secret = $instance['oauth_token_secret'];
$expire_time = $instance['expire_time'];
echo "{$before_widget}{$before_title}" . esc_html($title) . "{$after_title}";
// TWITTER RATE LIMIT: get twitter rate limit for unauthorized calls
if(!$useAuth){
$tweet_rate_limit = '';
$twitter_rate_limit_url = 'http://api.twitter.com/1/account/rate_limit_status.json';
$response = wp_remote_get( $twitter_rate_limit_url, array( 'User-Agent' => 'WordPress.com Twitter Widget' ) );
$response_code = wp_remote_retrieve_response_code( $response );
if ( 200 == $response_code ) {
$tweet_rate_limit = wp_remote_retrieve_body( $response );
$tweet_rate_limit = json_decode( $tweet_rate_limit, true );
if ( !is_array( $tweet_rate_limit ) || isset( $tweet_rate_limit['error'] ) ) {
$tweet_rate_limit = 'error';
}
} else {
$tweet_rate_limit = 'error';
}
}
// END TWITTER RATE LIMIT
// Get any existing copy of our transient data from the db
if ( false === ( $tweets = get_transient( 'twitter_results' ) ) ) {
// if no cached results in db then fetch the latest
if($useAuth){
/* OAuth Calls */
/* statuses/public_timeline */
$connection = $this->getConnectionWithAccessToken($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
$tweets = $connection->get("statuses/user_timeline");
$tweet_rate_limit['remaining_hits'] = $connection->http_header['x_ratelimit_remaining'];
$tweet_rate_limit['hourly_limit'] = $connection->http_header['x_ratelimit_limit'];
$tweet_rate_limit['expire_time'] = $expire_time;
$params = array(
'screen_name'=>$account, // Twitter account name
'trim_user'=>true, // only basic user data (slims the result)
'include_entities'=>false // as of Sept 2010 entities were not included in all applicable Tweets. regex still better
);
set_transient( 'twitter_results', $tweets, $expire_time );
set_transient( 'twitter_rate_results', $tweet_rate_limit, $expire_time );
}else{
/**
* The exclude_replies parameter filters out replies on the server. If combined with count it only filters that number of tweets (not all tweets up to the requested count)
* If we are not filtering out replies then we should specify our requested tweet count
*/
if ( $hidereplies )
$params['exclude_replies'] = true;
else
$params['count'] = $show;
if ( $include_retweets )
$params['include_rts'] = true;
$twitter_json_url = esc_url_raw( 'http://api.twitter.com/1/statuses/user_timeline.json?' . http_build_query($params), array('http', 'https') );
unset($params);
$response = wp_remote_get( $twitter_json_url, array( 'User-Agent' => 'WordPress.com Twitter Widget' ) );
$response_code = wp_remote_retrieve_response_code( $response );
if ( 200 == $response_code ) {
// It transient was not there, regenerate the data and save the transient
$tweets = wp_remote_retrieve_body( $response );
$tweets = json_decode( $tweets, true );
if ( !is_array( $tweets ) || isset( $tweets['error'] ) ) {
$tweets = 'error';
}
} else {
$tweets = 'error';
set_transient( 'twitter-response-code', $response_code, $expire_time);
}
set_transient( 'twitter_results', $tweets, $expire_time );
set_transient( 'twitter_rate_results', "$tweet_rate_limit[remaining_hits]/$tweet_rate_limit[hourly_limit] ($expire_time sec)", $expire_time );
}
}else{
$isCached = "(cached)";
$tweet_rate_limit = get_transient( 'twitter_rate_results' );
}
$cacheResult = (isset($isCached))? 'true':'false';
// debugging rate limit calls
//echo "
" . ( sprintf( __( 'Error: Please make sure the Twitter account is public.'), 'http://support.twitter.com/forums/10711/entries/14016' ) ) . '
'; else echo "" . esc_html__('Error: Twitter did not respond. Please wait a few minutes and refresh this page.') . '
'; endif; echo $after_widget; } function update( $new_instance, $old_instance ) { $instance = $old_instance; $instance['account'] = trim( strip_tags( stripslashes( $new_instance['account'] ) ) ); $instance['account'] = str_replace('http://twitter.com/', '', $instance['account']); $instance['account'] = str_replace('/', '', $instance['account']); $instance['account'] = str_replace('@', '', $instance['account']); $instance['account'] = str_replace('#!', '', $instance['account']); // account for the Ajax URI $instance['title'] = strip_tags(stripslashes($new_instance['title'])); $instance['show'] = absint($new_instance['show']); $instance['hidereplies'] = isset($new_instance['hidereplies']); $instance['includeretweets'] = isset($new_instance['includeretweets']); $instance['beforetimesince'] = $new_instance['beforetimesince']; if((bool) $instance['useAuth'] != isset($new_instance['useAuth'])){ delete_transient( 'twitter_results' ); delete_transient( 'twitter_rate_results' ); } $instance['useAuth'] = isset($new_instance['useAuth']); $instance['consumer_key'] = ($new_instance['consumer_key']); $instance['consumer_secret'] = ($new_instance['consumer_secret']); $instance['oauth_token'] = ($new_instance['oauth_token']); $instance['oauth_token_secret'] = ($new_instance['oauth_token_secret']); $instance['expire_time'] = ($new_instance['expire_time']); return $instance; } function form( $instance ) { //Defaults $instance = wp_parse_args( (array) $instance, array('account' => '', 'title' => '', 'show' => 5, 'hidereplies' => false, 'expire_time' => 300) ); $account = esc_attr($instance['account']); $title = esc_attr($instance['title']); $show = absint($instance['show']); if ( $show < 1 || 20 < $show ) $show = 5; $hidereplies = (bool) $instance['hidereplies']; $include_retweets = (bool) $instance['includeretweets']; $before_timesince = esc_attr($instance['beforetimesince']); $useAuth = (bool) $instance['useAuth']; $consumer_key = esc_attr($instance['consumer_key']); $consumer_secret = esc_attr($instance['consumer_secret']); $oauth_token = esc_attr($instance['oauth_token']); $oauth_token_secret = esc_attr($instance['oauth_token_secret']); $expire_time = esc_attr($instance['expire_time']); echo ''; echo '"; echo "