PHP Twitter User Timeline Feed Renderer

Published:
Today kiddies, we'll be giving you some code that will enable you to utilize the new Twitter API (which by the way, v1 was removed yesterday un-beknownst to yours truly).  This will use the new authentication methods now required, and pull a users Timeline feed.  This will allow you to pull in yours, mine, who-evers timeline for usage in your web application.  Personally, I use it for a CMS I built and display the latest news about the development of it.

I've commented the snots out of this, so if you don't get it or don't understand it, please take a moment and thoroughly go through this website to familarize yourself with PHP.

So, without blabbing you ears off, here ya go...  the class, how to start, and some sample code on how to use it.

How To Start:

Sign Up for a Twitter account
Login to Twitter
Click 'Create a New Appliction'
Fill out all fields marked with a *
Click 'Create'
Under 'OAuth' settings click 'Create my access token'
may take a few minutes for them to show up, but after a couple of minutes refresh the page and they will show up
Copy the following into the associated fields below
Consumer Key = $Twit->Key
Consumer Secret = $Twit->Secret
Access Token = $Twit->AccessToken
Access Token Secret = $Twit->AccessTokenSecret
Set $Twit->ScreenName to your chosen screen name
Set $Twit->PostCount to the number of items you wish to return
Configure the rest of the settings if you need to
Have fun Programming!

Class:
<?php
                      
                      class o7thTwitterTimeLine {
                      	
                      	// Settings
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// Required
                      	public $Key = 					null; // Consumer Key Provided by Twitter
                      	public $Secret = 	 		 	 null; // Consumer Secret Provided by Twitter
                      	public $AccessToken = 			null; // Consumer Key Provided by Twitter
                      	public $AccessTokenSecret =  	  null; // Consumer Secret Provided by Twitter
                      	public $ScreenName = 		 	 null; // Screen Name of the Timeline to return - optional (but required if no User ID provided
                      	public $PostCount = 		  	  null; // How many posts to pull
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// Optional
                      	public $WrapperID = 		  	  ''; // ID of the wrapper Section (needs to be unique, per CSS rules)
                      	public $WrapperClass = 	   	   ''; // Class of the wrapper Section
                      	public $WrapperExtras = 	  	  ''; // Any extras - format: data-role="blah"; onclick="return false;"
                      	public $ItemID = 			 	 ''; // ID of the item Article (needs to be unique, per CSS rules)
                      	public $ItemClass = 		  	  ''; // Class of the item Article
                      	public $ItemExtras = 		 	 ''; // Any extras - format: data-role="blah"; onclick="return false;", etc...
                      	public $ShowPostedDate = 	 	 true; // Show the Posted On Date (or retweeted date)
                      	public $DateFormat = 			 1; // Format the date string: 1 = US Date/Time, 2 = UK Date/Time, 3 = Small US Date, 4 = Small UK Date, 5 = UTC (does not matter if formatting like Twitter)
                      	public $ShowTwitterFormatDate =  true; // Show the Posted Date formatted like: 1 day ago, 1 year ago, etc...
                      	public $PostedDateTpl = 		  'Posted: %s by %s'; // Template format for the Posted Date, can use HTML if needed: first argument is date/time, second is screen name
                      	public $ShowProfileUrl = 	 	 true; // Show the Profile URL
                      	public $ShowProfileDetails = 	 true; // Show the profiles Location, Description, and Link if any: NOTE: If list, may not render
                      	public $ShowProfileImage =   	   true; // Show the profiles main Image: NOTE: If list, may not render
                      	public $ShowImageInPost = 		true; // If we're showing the profile image, should we show it in each post?
                      	public $ShowFollowerCount =  	  true; // Show the profiles follower count
                      	public $ShowFriendCount = 		true; // Show the profiles friends count
                      	public $RenderHashTagUrls =  	  true; // Parse the text for hash tags, and render them?
                      	public $RenderProfileUrls =  	  true; // Parse the text for profiles, and render them?
                      	public $RenderContentLinks = 	 true; // Parse the text looking for any links, and render them?
                      	public $ListOrArticles = 		 1; // Render the items as a list(1), or as Article(2) containers?
                      	public $OpenURLsInNewWindow = 	true; // Should we open any URLs we find in a new window?
                      	public $PostExtraItemContent =   null; // Any extra content for each item?  Can use HTML.  Goes after the item, inside the wrapping.
                      	public $PostExtraFeedContent =   null; // Any extra content for the feed?  Can use HTML.  Goes after the feed, inside the wrapping: NOTE: If list, may not render.
                      	public $PreExtraItemContent =    null; // Any extra content for each item?  Can use HTML.  Goes before the item, inside the wrapping.
                      	public $PreExtraFeedContent =    null; // Any extra content for the feed?  Can use HTML.  Goes before the feed, inside the wrapping: NOTE: If list, may not render.
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
                      	// Twitter User Timeline API URL
                      	protected $APIUrl = 'https://api.twitter.com/1.1/statuses/user_timeline.json';
                      	
                      	public function __construct(){
                      		if(!in_array('curl', get_loaded_extensions())){
                                  throw new Exception('You need to install cURL, see: http://curl.haxx.se/docs/install.html');
                              }
                      	}
                      	
                      	// Return it
                      	public function ReturnTheTimeline(){
                      		// Pull our feed, and return it is as an associative array
                      		return $this->PullTheFeed();
                      	}
                      	
                      	// Render the feed, instead of just returning it
                      	public function RenderTheFeed(){
                      		// Pull our feed as an associative array
                      		$feed = $this->PullTheFeed();
                      		// Count the items returned
                      		$fCt = count($feed);
                      		$ret = null;
                      		// Are we opening links in a new window
                      		$nw = ($this->OpenURLsInNewWindow) ? ' target="_blank"' : '' ;
                      		// Set the container based on what is chosen in our settings
                      		$ret .= ($this->ListOrArticles == 1) ? '<ul id="' . $this->WrapperID . '" class="' . $this->WrapperClass . '"' . $this->WrapperExtras . '>' : '<section id="' . $this->WrapperID . '" class="' . $this->WrapperClass . '"' . $this->WrapperExtras . '>' ;
                      		// Pre-Feed Content
                      		$ret .= $this->PreExtraFeedContent;
                      		// section for profile details, follower & friend counts, and profile image if not in post: if allowed through our settings
                      		if($this->ShowProfileDetails){
                      			$ret .= '	<div id="profile_' . $this->WrapperID . '" class="profile_' . $this->WrapperClass . '">';
                      			$ret .= '		<div class="profile_name">' . $this->ScreenName . '</div>';
                      			// Show the Follower Count if allowed through our settings
                      			$ret .= ($this->ShowFollowerCount) ? '<span class="profile_followers_count">Followers: ' . $feed[0]['user']['followers_count'] . '</span>' : null;
                      			// Show the Friend Count if allowed through our settings
                      			$ret .= ($this->ShowFriendCount) ? '<span class="profile_friends_count">Friends: ' . $feed[0]['user']['friends_count'] . '</span>' : null;
                      			$ret .= '		<div class="profile_description">' . $feed[0]['user']['description'] . '</div>';
                      			$ret .= '		<div class="profile_location">' . $feed[0]['user']['location'] . '</div>';
                      			// Show the Profile Image if allowed through our settings
                      			$ret .= ($this->ShowProfileImage) ? '		<div class="profile_image"><img src="' . $feed[0]['user']['profile_image_url'] . '" alt="' . $this->ScreenName . '" /></div>' : null;
                      			$ret .= '		<div class="profile_link"><a href="' . $feed[0]['user']['entities']['url']['urls'][0]['expanded_url'] . '"' . $nw . '>' . $feed[0]['user']['entities']['url']['urls'][0]['expanded_url'] . '</a></div>';
                      			$ret .= '	</div>';	
                      		}
                      		// Feed Items
                      		for($i = 0; $i < $fCt; ++$i){
                      			// Set the Item container based on what is chosen in our settings
                      			$ret .= ($this->ListOrArticles == 1) ? '	<li id="' . $this->ItemID . '" class="' . $this->ItemClass . '"' . $this->ItemExtras . '>' : '	<article id="' . $this->ItemID . '" class="' . $this->ItemClass . '"' . $this->ItemExtras . '>';
                      			// Pre-Item Content
                      			$ret .= $this->PreExtraItemContent;
                      			// Show the Profile Image if allowed through our settings
                      			$ret .= ($this->ShowProfileImage && $this->ShowImageInPost) ? '<div id="" class=""><img src="' . $feed[$i]['user']['profile_image_url'] . '" alt="' . $this->ScreenName . '" /></div>' : null ;
                      			// Show the Profile URL if allowed through our settings
                      			$ret .= ($this->ShowProfileUrl) ? '<div id="profilelink_' . $this->ItemID . '" class="text_' . $this->ItemClass . '"><a href="http://twitter.com/' . $this->ScreenName . '"' . $nw . '>@' . $this->ScreenName . '</a></div>' : null;
                      			// Show the text of the post, formatting it necessary
                      			$ret .= '<div id="text_' . $this->ItemID . '" class="text_' . $this->ItemClass . '">' . $this->FormatPostText($feed[$i]['text']) . '</div>';
                      			// Section for the date
                      			if($this->ShowPostedDate){
                      				if(!$this->ShowTwitterFormatDate){
                      					// Format the date/time based on our settings
                      					switch($this->DateFormat){
                      						case 1: // US Date/Time
                      							$dt = date('m/d/Y h:i A', $feed[$i]['created_at']);
                      							break;	
                      						case 2: // UK Date/Time
                      							$dt = date('d/m/Y h:i A', $feed[$i]['created_at']);
                      							break;	
                      						case 3: // US Short Date
                      							$dt = date('m/d/Y', $feed[$i]['created_at']);
                      							break;	
                      						case 4: // UK Short Date
                      							$dt = date('d/m/Y', $feed[$i]['created_at']);
                      							break;	
                      						default:
                      							$dt = $feed[$i]['created_at'];
                      					}
                      				}else{
                      					// Format the date/time as shown on Twitter
                      					$dt = $this->ShowTwitterFormattedDate($feed[$i]['created_at']);
                      				}
                      				$ret .= '<div id="date_' . $this->ItemID . '" class="date_' . $this->ItemClass . '">' . sprintf($this->PostedDateTpl, $dt, $this->ScreenName) . '</div>';
                      			}
                      			// Post-Item Content
                      			$ret .= $this->PostExtraItemContent;
                      			// Close the Item container based on what is chosen in our settings
                      			$ret .= ($this->ListOrArticles == 1) ? '	</li>' : '	</article>' ;
                      		}
                      		// Post-Feed Content
                      		$ret .= $this->PostExtraFeedContent;
                      		// Close the container based on what is chosen in our settings
                      		$ret .= ($this->ListOrArticles == 1) ? '</ul>' : '</section>' ;
                      		return $ret;
                      	}
                      	
                      	// Format post text accordingly (this just does some replacements for profiles, hashtags, and links (if allowed)
                      	protected function FormatPostText($txt){
                      		try{
                      			if($this->RenderProfileUrls || $this->RenderHashTagUrls || $this->RenderContentLinks){
                      				$ret = $txt;
                      				$nw = ($this->OpenURLsInNewWindow) ? ' target="_blank"' : '' ;
                      				// Parse any http and https links that may occur in our content
                      				if($this->RenderContentLinks){
                      					$ret = preg_replace('/http:\/\/([a-z0-9_\.\-\+\&\!\#\~\/\,]+)/i', '<a href="http://$1"' . $nw . '>http://$1</a>', $ret);				
                      					$ret = preg_replace('/https:\/\/([a-z0-9_\.\-\+\&\!\#\~\/\,]+)/i', '<a href="https://$1"' . $nw . '>https://$1</a>', $ret);				
                      				}
                      				// Parse any profile tags that may occur
                      				if($this->RenderProfileUrls){
                      					$ret = preg_replace('/[@]+([A-Za-z0-9-_]+)/', '<a href="http://twitter.com/$1"' . $nw . '>$0</a>', $ret);
                      				}
                      				// Parse any hastags that may occur
                      				if($this->RenderHashTagUrls){
                      					$ret = preg_replace('/[#]+([\d\w]+)/', '<a href="https://twitter.com/search?q=%23$1&src=hash"' . $nw . '>$0</a>', $ret);				
                      				}
                      				return $ret;
                      			}else{
                      				// Returnt the original if none of these are allowed through the settings
                      				return $txt;
                      			}
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}
                      	
                      	// Format the Date
                      	protected function ShowTwitterFormattedDate($a) {
                      		try{
                      			$b = strtotime("now"); 
                      			$c = strtotime($a);
                      			$d = $b - $c;
                      			$minute = 60;
                      			$hour = $minute * 60;
                      			$day = $hour * 24;
                      			$week = $day * 7;
                      			if(is_numeric($d) && $d > 0) {
                      				if($d < 3) return "right now";
                      				if($d < $minute) return floor($d) . " seconds ago";
                      				if($d < $minute * 2) return "about 1 minute ago";
                      				if($d < $hour) return floor($d / $minute) . " minutes ago";
                      				if($d < $hour * 2) return "about 1 hour ago";
                      				if($d < $day) return floor($d / $hour) . " hours ago";
                      				if($d > $day && $d < $day * 2) return "yesterday";
                      				if($d < $day * 365) return floor($d / $day) . " days ago";
                      				return "over a year ago";
                      			}
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}	
                      	
                      	// Do the heavy lifting
                      	protected function PullTheFeed(){
                      		// Make sure the required settings
                      		if(!isset($this->Key) || !isset($this->Secret) || !isset($this->AccessToken) || !isset($this->AccessTokenSecret) || !isset($this->ScreenName) || !isset($this->PostCount)){
                                  throw new Exception('You need to set the "Required" settings in order to use this.');
                      		}
                      		// Set our CURL Options
                      		try{
                      			$opts = array(CURLOPT_HTTPHEADER => $this->Auth(),
                      						  CURLOPT_HEADER => false,
                      						  CURLOPT_URL => $this->APIUrl . '?screen_name=' . $this->ScreenName . '&count=' . $this->PostCount . '',
                      						  CURLOPT_RETURNTRANSFER => true,
                      						  CURLOPT_SSL_VERIFYPEER => false);
                      			// Initialize our Curl Handle
                      			$ch = curl_init();
                      			// Pass in our options
                      			curl_setopt_array($ch, $opts);
                      			// Execute the request and get back the response
                      			$json = curl_exec($ch);
                      			// Clean up...
                      			curl_close($ch);
                      			unset($opts);
                      			// Return an associated array (json decoded)	
                      			return json_decode($json, true);
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}
                      	
                      	// Authorize Us
                      	protected function Auth(){
                      		try{
                      			$oauth = array(
                      					'screen_name' => $this->ScreenName,
                      					'count' => $this->PostCount,
                      					'oauth_consumer_key' => $this->Key,
                      					'oauth_nonce' => time(),
                      					'oauth_signature_method' => 'HMAC-SHA1',
                      					'oauth_token' => $this->AccessToken,
                      					'oauth_timestamp' => time(),
                      					'oauth_version' => '1.0');
                      			// Build the base string we will need to pass to Twitter's OAuth
                      			$base_info = $this->buildBaseString($this->APIUrl, 'GET', $oauth);
                      			$composite_key = rawurlencode($this->Secret) . '&' . rawurlencode($this->AccessTokenSecret);
                      			$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
                      			$oauth['oauth_signature'] = $oauth_signature;		
                      			return array($this->buildAuthorizationHeader($oauth), 'Expect:');
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}
                      	
                      	// Build our base Auth String
                      	protected function buildBaseString($baseURI, $method, $params) {
                      		try{
                      			$r = array();
                      			ksort($params);
                      			foreach($params as $key => $value){
                      				$r[] = "$key=" . rawurlencode($value);
                      			}
                      			return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}
                      	
                      	// Build our Authorization headers
                      	protected function buildAuthorizationHeader($oauth) {
                      		try{
                      			$r = 'Authorization: OAuth ';
                      			$values = array();
                      			foreach($oauth as $key => $value)
                      				$values[] = "$key=\"" . rawurlencode($value) . "\"";
                      			$r .= implode(', ', $values);
                      			return $r;
                      		}catch(Exception $e){
                                  throw new Exception($e->getMessage());
                      		}
                      	}	
                      	
                      }

Open in new window


Sample Usage:
<?php
                      
                      	/*
                      	Install Steps
                      	
                      	1. Sign Up for a Twitter account
                      	2. Login to Twitter
                      	3. Go to https://dev.twitter.com/apps
                      	4. Click 'Create a New Appliction'
                      		4a. Fill out all fields marked with a *
                      		4b. Click 'Create'
                      	5. Under 'OAuth' settings click 'Create my access token'
                      		5a. may take a few minutes for them to show up, but after a couple of minutes refresh the page and they will show up
                      	6. Copy the following into the associated fields below
                      		6a. Consumer Key = $Twit->Key
                      		6b. Consumer Secret = $Twit->Secret
                      		6c. Access Token = $Twit->AccessToken
                      		6d. Access Token Secret = $Twit->AccessTokenSecret
                      	7. Set $Twit->ScreenName to your chosen screen name
                      	8. Set $Twit->PostCount to the number of items you wish to return
                      	9. Configure the rest of the settings if you need to
                      	10. Have fun Programming!
                      	
                      	*/
                      
                      	// Require our class
                      	require_once($_SERVER['DOCUMENT_ROOT'] . '/twitter/o7th.twitter.api.class.php');
                      	
                      	// Fire up the class
                      	$Twit = new o7thTwitterTimeLine();
                      	
                      	// -------------------------------------------------------------------------------------------------------------------
                      	// -------------------------------------------------------------------------------------------------------------------
                      	// Required Settings
                      	$Twit->Key = 'XXX'; // Consumer Key Provided by Twitter
                      	$Twit->Secret = 'XXX'; // Consumer Secret Provided by Twitter
                      	$Twit->AccessToken = 'XXX'; // Access Token Provided by Twitter
                      	$Twit->AccessTokenSecret = 'XXX'; // Access Token Secret Provided by Twitter
                      	$Twit->ScreenName = 'o7thwd'; // Screen Name of the Timeline to return - optional (but required if no User ID provided
                      	$Twit->PostCount = 15; // How many results do we return?
                      	// -------------------------------------------------------------------------------------------------------------------
                      	// -------------------------------------------------------------------------------------------------------------------
                      	// Optional Settings
                      	$Twit->WrapperID = 		  	  'o7_twit_feed_id'; // ID of the wrapper Section (needs to be unique, per CSS rules)
                      	$Twit->WrapperClass = 	   	   'o7_twit_feed_class'; // Class of the wrapper Section
                      	$Twit->WrapperExtras = 	  	  ' style="cursor:help"'; // Any extras - format: data-role="blah"; onclick="return false;"
                      	$Twit->ItemID = 			 	 ''; // ID of the item Article (needs to be unique per item, per CSS rules)
                      	$Twit->ItemClass = 		  	  'o7_twit_item_class'; // Class of the item Article
                      	$Twit->ItemExtras = 		 	 ' style="cursor:pointer" onclick="alert(\'Item Clicked!\');"'; // Any extras - format: data-role="blah"; onclick="return false;", etc...
                      	$Twit->ShowPostedDate = 	 	 true; // Show the Posted On Date (or retweeted date)
                      	$Twit->DateFormat = 			 1; // Format the date string: 1 = US Date/Time, 2 = UK Date/Time, 3 = Small US Date, 4 = Small UK Date, 5 = UTC (does not matter if formatting like Twitter)
                      	$Twit->ShowTwitterFormatDate =  true; // Show the Posted Date formatted like: 1 day ago, 1 year ago, etc...
                      	$Twit->PostedDateTpl = 		  'Posted: %s by %s'; // Template format for the Posted Date, can use HTML if needed: first argument is date/time, second is screen name
                      	$Twit->ShowProfileUrl = 	 	 true; // Show the Profile URL
                      	$Twit->ShowProfileDetails = 	 true; // Show the profiles Location, Description, and Link if any: NOTE: If list, may not render
                      	$Twit->ShowProfileImage =   	   true; // Show the profiles main Image: NOTE: If list, may not render
                      	$Twit->ShowImageInPost = 		true; // If we're showing the profile image, should we show it in each post?
                      	$Twit->ShowFollowerCount =  	  true; // Show the profiles follower count
                      	$Twit->ShowFriendCount = 		true; // Show the profiles friends count
                      	$Twit->RenderHashTagUrls =  	  true; // Parse the text for hash tags, and render them?
                      	$Twit->RenderProfileUrls =  	  true; // Parse the text for profiles, and render them?
                      	$Twit->RenderContentLinks = 	 true; // Parse the text looking for any links, and render them?
                      	$Twit->ListOrArticles = 		 1; // Render the items as a list(1), or as Article(2) containers?
                      	$Twit->OpenURLsInNewWindow = 	true; // Should we open any URLs we find in a new window?
                      	$Twit->PostExtraItemContent =   '<strong>POST ITEM CONTENT</strong>'; // Any extra content for each item?  Can use HTML.  Goes after the item, inside the wrapping.
                      	$Twit->PostExtraFeedContent =   '<strong>POST FEED CONTENT</strong>'; // Any extra content for the feed?  Can use HTML.  Goes after the feed, inside the wrapping: NOTE: If list, may not render.
                      	$Twit->PreExtraItemContent =    '<strong>PRE ITEM CONTENT</strong>'; // Any extra content for each item?  Can use HTML.  Goes before the item, inside the wrapping.
                      	$Twit->PreExtraFeedContent =    '<strong>PRE FEED CONTENT</strong>'; // Any extra content for the feed?  Can use HTML.  Goes before the feed, inside the wrapping: NOTE: If list, may not render.
                      	// End Settings
                      	// -------------------------------------------------------------------------------------------------------------------
                      	// -------------------------------------------------------------------------------------------------------------------
                      	
                      	// Return the associative array, so you can process it any way you like =}
                      	$Feed = $Twit->ReturnTheTimeline();
                      
                      	// Render the feed
                      	$RenderedFeed = $Twit->RenderTheFeed();
                      	echo $RenderedFeed;
                      
                      	// Just printing out the returned array
                      	echo '<hr />';
                      	echo '<pre>';
                      	print_r($Feed);
                      	echo '</pre>';
                      
                      	// Cleaning up (not really necessary though, PHP does a great job at this all by itself...
                      	unset($Feed, $RenderedFeed);
                      	
                      ?>

Open in new window


So there you go folks, a nice simple replacement for all of you who were used to being able to pull this in via the old RSS feed from Twitter API v1.   While I do miss the old ways, this newer methodology seems quite a bit faster in pulling down the feed.   Yes I know it's more work, but then again, such is life :)

~K
2
3,261 Views

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.