Hi,

Yesterday my Twitter widget on my Wordpress site stopped linking to my latest Twitter feeds. Is there currently a blackout for this service or is it likely something has changed on my site? Here’s the code for the widget:

<?php
class twitter_widget extends WP_Widget 
{
	/** constructor */
    function twitter_widget() 
	{
		global $themename;
		$widget_options = array(
			'classname' => 'twitter_widget',
			'description' => 'Displays Twitter Feed'
		);
        parent::WP_Widget('gymbase_twitter', __('Twitter Feed', $themename), $widget_options);
    }
	
	/** @see WP_Widget::widget */
    function widget($args, $instance) 
	{
        extract($args);

		//these are our widget options
		$title = $instance['title'];
		$login = $instance['login'];
		$count = $instance['count'];

		echo $before_widget;
		?>
		<div class="clearfix">
			<div class="header_left">
				<?php
				if($title) 
				{
					echo $before_title . $title . $after_title;
				}
				?>
			</div>
			<div class="header_right">
				<a href="#" id="latest_tweets_prev" class="scrolling_list_control_left icon_small_arrow left_white"></a>
				<a href="#" id="latest_tweets_next" class="scrolling_list_control_right icon_small_arrow right_white"></a>
			</div>
		</div>
		<div class="scrolling_list_wrapper">
			<ul class="scrolling_list latest_tweets">
			</ul>
		</div>
		<script type="text/javascript">
		jQuery(document).ready(function($){
			//tweets
			$.getJSON('http://twitter.com/statuses/user_timeline.json?screen_name=<?php echo $login; ?>&count=<?php echo $count; ?>&callback=?', function(data) 
			{
				if(data.length)
				{
					var list=$(".latest_tweets");
					var date;
					$(data).each(function(index,value)
					{
						date = new Date(value.created_at);
						list.append($('<li class="icon_small_arrow right_white">').append($('<p>').html(linkify(value.text)+'<abbr class="timeago" title="'+date.toISOString()+'">'+date.toISOString()+'</abbr>')));
					});

					$('.latest_tweets a').attr('target','_blank');

					list.carouFredSel({
						direction: "up",
						items: {
							visible: 3
						},
						scroll: {
							items: 1,
							easing: "swing",
							pauseOnHover: true,
							height: "variable"
						},
						prev: '#latest_tweets_prev',
						next: '#latest_tweets_next',
						auto: {
							play: false
						}
					});	
					$("abbr.timeago").timeago();
				}
			});
		});
		</script>
		<?php
        echo $after_widget;
    }
	
	/** @see WP_Widget::update */
    function update($new_instance, $old_instance) 
	{
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['login'] = strip_tags($new_instance['login']);
		$instance['count'] = strip_tags($new_instance['count']);
		return $instance;
    }
	
	 /** @see WP_Widget::form */
	function form($instance) 
	{	
		global $themename;
		$title = esc_attr($instance['title']);
		$login = esc_attr($instance['login']);
		$count = esc_attr($instance['count']);
		?>
		<p>
			<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title', $themename); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('login'); ?>"><?php _e('Login', $themename); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id('login'); ?>" name="<?php echo $this->get_field_name('login'); ?>" type="text" value="<?php echo $login; ?>" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('count'); ?>"><?php _e('Count', $themename); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id('count'); ?>" name="<?php echo $this->get_field_name('count'); ?>" type="text" value="<?php echo $count; ?>" />
		</p>
		<?php
	}
}
//register widget
add_action('widgets_init', create_function('', 'return register_widget("twitter_widget");'));
?>

See [node:10803] for more information.

Your code makes use of an unversioned endpoint that has been retired.

Instead of:

$.getJSON('http://twitter.com/statuses/user_timeline.json?screen_name=<?php echo $login; ?>&count=<?

You want:

$.getJSON('https://api.twitter.com/1/statuses/user_timeline.json?screen_name=<?php echo $login; ?>&count=<?

Keep in mind that version 1 of the API is also now deprecated and will be retired in March 2013. You may want to use our [node:10248] instead.

I think i’m having similar issues with the Twitter feed I’m using on my site. The feed has stopped pulling in individual posts. I’m avoiding the timeline because I need a solution that provides SEO benefit to our site.

Here’s my code:
<?php
/* Class to embed twitter comments for a user into a website page (PHP) */
class myTwit{
var $user = false; // User to show public posts
var $cacheFile = ‘twitcache.txt’; // File to save local cache of Twitter update
var $cachExpire = 600; // Seconds that cache is classed as "old"
var $myTwitHeader = false;
var $postLimit = 20; // 20 = max
var $debug = false;
var $targetBlank = true;
var $postClass = false;

function printError($message){ echo htmlspecialchars($message);	exit;}

function debugMsg($message){if ($this->debug == true) echo htmlspecialchars($message).'<br />';}

function formatPlural($val, $qty){
	if ($val > 1) return $val.' '.$qty.'s';
	else return $val.' '.$qty;
}

function intoRelativeTime($seconds){
	if (($seconds / 60 / 60 / 24) > 1) return $this->formatPlural(round($seconds / 60 / 60 / 24), 'day').' ago';
	elseif (($seconds / 60 / 60) > 1) return 'about '.$this->formatPlural(round($seconds / 60 / 60), 'hour').' ago';
	else if (($seconds / 60 ) > 1) return 'about '.$this->formatPlural(round($seconds / 60), 'minute').' ago';
	else return 'about '.round($seconds).' seconds ago';
}

function linkURLs($text){
	$in=array( '`((?:https?|ftp)://\S+[[:alnum:]]/?)`si', '`((?<!//)(www\.\S+[[:alnum:]]/?))`si' );
	$out=array( '<a href="$1"'.$this->targetAppend.'>$1</a> ', '<a href="http://$1" target="_blank">$1</a>' );
	$text = preg_replace($in,$out,$text);
	$text = preg_replace('/@([a-zA-Z0-9-_]+)/','@<a href="http://twitter.com/$1"'.$this->targetAppend.'>$1</a>',$text);
	return $text;
}

function checkCacheFile(){
	if ( (@filemtime($this->cacheFile) < (mktime() - $this->cachExpire) ) || (!is_file($this->cacheFile)) ){
		$this->debugMsg('Cache file outdated');
		$this->updateCache();
	} else {
		$this->debugMsg('Cache file still valid');
	}
}

function updateCache(){
	$uri = 'http://twitter.com/statuses/user_timeline/'.$this->user.'.json';
	$req = new HTTPRequest($uri);
	$tmpdata = $req->DownloadToString();
	$resp = json_decode($tmpdata, true);
	if (isset($resp['error'])) $this->printError('Error getting information from Twitter ['.$resp['error'].']. Please check the username ('.$this->user.')');
	elseif (!is_array($resp)) $this->printError('Error getting information from Twitter. File is not JSON.');
	$handle = @fopen($this->cacheFile, 'w');
	if (!$handle) $this->printError('Could not write to cache file: '.$this->cacheFile.'. Please check read/write permissions.');
	fwrite($handle, $tmpdata);
	fclose($handle);
	$this->debugMsg('Updated cache file: '.$this->cacheFile);
}

function readCache(){
	if( false == ($this->jsonData = @file_get_contents( $this->cacheFile )))
		$this->printError('Could not read cache file: '.$this->cacheFile);
}

function initMyTwit(){
	if (!is_string($this->user)) $this->printError('Please set a user.');
	$this->targetAppend = ($this->targetBlank) ? ' target="_blank"' : '';
	$this->postClassAppend = ($this->postClass) ? ' class="'.$this->postClass.'"' : '';
	$this->checkCacheFile();
	$this->readCache();
	$this->jsonArray = json_decode($this->jsonData, true);
	$output = '<ul class="twitbox">';
	if ($this->myTwitHeader && isset($this->jsonArray[0])){
		$output .= '<li class="mytwitHead"><a href="http://twitter.com/'.$this->user.'"'.$this->targetAppend.'><img src="'.$this->jsonArray[0]['user']['profile_image_url'].'" style="border:0" alt="'.$this->user.'" /></a>'.
		'<div><a href="http://twitter.com/'.$this->user.'"'.$this->targetAppend.'>'.$this->user.'</a><br />'.
		$this->formatPlural($this->jsonArray[0]['user']['followers_count'], 'follower').'</div></li>';
	}		
	for($x=0; $x < count($this->jsonArray) && $x < $this->postLimit; $x++){
		$seconds_ago = mktime() - strtotime($this->jsonArray[$x]['created_at']);
		$ts = strtotime($this->jsonArray[$x]['created_at'])+$this->jsonArray[$x]['user']['utc_offset'];
		$cur_ts = mktime();
		$output .= '<li'.$this->postClassAppend.'>'.$this->linkURLs($this->jsonArray[$x]['text']).
		' <span class="twhen">by <a href="http://twitter.com/'.$this->jsonArray[$x]['user']['screen_name'].'"'.$this->targetAppend.'>'.$this->jsonArray[$x]['user']['screen_name'].'</a> '.
		$this->intoRelativeTime($seconds_ago)."</span></li>\n";
	}
	$output .= '</ul>';
	$this->myTwitData = $output;
}	

}

class HTTPRequest{
var $_fp; // HTTP socket
var $_url; // full URL
var $_host; // HTTP host
var $_protocol; // protocol (HTTP/HTTPS)
var $_uri; // request URI
var $_port; // port
// scan url
function _scan_url(){
$req = $this->_url;
$pos = strpos($req, ‘://’);
$this->_protocol = strtolower(substr($req, 0, $pos));
$req = substr($req, $pos+3);
$pos = strpos($req, ‘/’);
if($pos === false)
$pos = strlen($req);
$host = substr($req, 0, $pos);
if(strpos($host, ‘:’) !== false) {
list($this->_host, $this->_port) = explode(’:’, $host);
}else{
$this->_host = $host;
$this->_port = ($this->_protocol == ‘https’) ? 443 : 80;
}
$this->_uri = substr($req, $pos);
if($this->_uri == ‘’)
$this->_uri = ‘/’;
}
// constructor
function HTTPRequest($url){
$this->_url = $url;
$this->_scan_url();
}
// download URL to string
function DownloadToString(){
$crlf = “\r\n”;
// generate request
$req = ‘GET ’ . $this->_uri . ’ HTTP/1.0’ . $crlf
. 'Host: ’ . $this->_host . $crlf
. ‘User-Agent: PHP’ . $crlf
. $crlf;
// fetch
$this->_fp = @fsockopen(($this->_protocol == ‘https’ ? ‘ssl://’ : ‘’) . $this->_host, $this->_port);
if ($this->_fp){
fwrite($this->_fp, $req);
$response = “”;
while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
$response .= fread($this->_fp, 1024);
fclose($this->_fp);
// split header and body
$pos = strpos($response, $crlf . $crlf);
if($pos === false)
return($response);
$header = substr($response, 0, $pos);
$body = substr($response, $pos + 2 * strlen($crlf));
// parse headers
$headers = array();
$lines = explode($crlf, $header);
foreach($lines as $line)
if(($pos = strpos($line, ‘:’)) !== false)
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
// redirection?
if(isset($headers[‘location’])){
$http = new HTTPRequest($headers[‘location’]);
return($http->DownloadToString($http));
} else{
return($body);
}
} else {
return false;
}
}
}
?>

In this code, you probably want to replace:
$uri = ‘http://twitter.com/statuses/user_timeline/’.$this->user.’.json’;

with

$uri = ‘https://api.twitter.com/1/statuses/user_timeline/’.$this->user.’.json’;

Keep in mind though that v1 is also deprecated and it’s time to move on to API v1.1 by March 2012.

you might also want to check the plugin discribed in this page:
http://www.ramsich.com