Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Caching of External Data


Reply

3 Posts   727 Views

Avatar
mattupstate

11 May 2011 at 10:28am Community Member, 12 Posts

So I'm displaying a few recent tweet's from a user's Twitter profile on a page. I created a class to manage the retrieval of the RSS feed from Twitter and parse it. What I'd like to do is cache the loaded data since there's an API limit on reading the RSS feed. Attached is the class I'm using to do this. It's entirely based on a Model for CakePHP. So then in my controller I have this function:

public function Tweets($limit = 4) {
$twitter = new TwitterFeed();
return new DataObjectSet($twitter->find(array('limit'=>$limit)));
}

I'm obviously doing something wrong because when I loop through the tweets with <% control Tweets %> I'm getting the HTML markup for the entire page. Guessing this has something to do with how I'm caching the data.

Any help would be appreciated.

Avatar
mattupstate

11 May 2011 at 10:29am Community Member, 12 Posts

Doesn't look like the file was attached...here's the code

<?php
class TwitterFeed extends DataObject {

/**
* Your Twitter ID
*
* @var integer
* @access public
*/
public $twitterId = 19296617;

/**
* Remove your name from posts
* Set to false to not remove your name, otherwise set to your name
*
* @var mixed
* @access public
*/
public $twitterName = 'syrupnyc';

/**
* Show replies to people
*
* @var boolean
* @access public
*/
public $showReplies = false;

/**
* Twitter RSS URL
*
* @var string
* @access public
*/
public $rssUrl = 'http://twitter.com/statuses/user_timeline/:twitterId.rss';

/**
* Turn off table usage
*
* @var string
* @access public
*/
public $useTable = false;

/**
* Duration of cache
*
* @var string
* @access public
*/
public $cacheDuration = 300;

public $cacheKey = 'TwitterData';
/**
* Find Twitters
*
* @param array $options Options when getting twits, as followed:
* - cache: Force caching on or off
* - limit: Limit number of records returned
* @access public
* @return array
*/
public function find($options = array()) {
//Get twits
$cache = SS_Cache::factory('TwitterCache', 'Output', array('lifetime' => $this->cacheDuration, 'automatic_serialization' => true));
if( (isset($options['cache']) && $options['cache'] == false) || ($twits = $cache->load($this->cacheKey)) === false) {
$twits = $this->_getTwits();
$cache->save($twits, $this->cacheKey);
}
//Set to limit
if(isset($options['limit']) && count($twits) > $options['limit'])
{
$twits = array_slice($twits, 0, $options['limit']);
}

return $twits;
}

/**
* Get Twitter Lines
*
* @access private
* @return array
*/
private function _getTwits()
{
//Get feed
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, str_replace(':twitterId', $this->twitterId, $this->rssUrl));
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$feed = curl_exec($ch);
curl_close($ch);

if(!$feed) { return false; }

$xml = new SimpleXmlElement($feed);

foreach($xml->channel->item as $item)
{
//
$title = (string)$item->title;

//Skip if it's a reply
if(!$this->showReplies && preg_match('/^'.$this->twitterName.': @/',$title))
continue;

//Remove name
if($this->twitterName)
$title = trim(preg_replace('/^'.$this->twitterName.':/','',$title));

$out[] = array(
'TweetTitle' => $this->_parse_twitter($title),
'TweetDescription' => (string)$item->description,
'TweetPubDate' => $this->_timeAgo(strtotime($item->pubDate), 1),
'TweetLink' => (string)$item->link
);
}

return $out;
}

private function _timeAgo($timestamp, $granularity=2, $format='Y-m-d H:i:s'){
$difference = time() - $timestamp;
if($difference < 0) return '0 seconds ago';
elseif($difference < 864000){
$periods = array('week' => 604800,'day' => 86400,'hr' => 3600,'min' => 60,'sec' => 1);
$output = '';
foreach($periods as $key => $value){
if($difference >= $value){
$time = round($difference / $value);
$difference %= $value;
$output .= ($output ? ' ' : '').$time.' ';
$output .= (($time > 1 && $key == 'day') ? $key.'s' : $key);
$granularity--;
}
if($granularity == 0) break;
}
return ($output ? $output : '0 seconds').' ago';
}
else return date($format, $timestamp);
}

private function _parse_twitter($t) {
// link URLs
$t = " ".preg_replace( "/(([[:alnum:]]+:\/\/)|www\.)([^[:space:]]*)".
"([[:alnum:]#?\/&=])/i", "<a href=\"\\1\\3\\4\" target=\"_blank\">".
"\\1\\3\\4</a>", $t);

// link mailtos
$t = preg_replace( "/(([a-z0-9_]|\\-|\\.)+@([^[:space:]]*)".
"([[:alnum:]-]))/i", "<a href=\"mailto:\\1\">\\1</a>", $t);

//link twitter users
$t = preg_replace( "/ +@([a-z0-9_]*) ?/i", " <a href=\"http://twitter.com/\\1\" target=\"_blank\">@\\1</a> ", $t);

//link twitter arguments
$t = preg_replace( "/ +#([a-z0-9_]*) ?/i", " <a href=\"http://twitter.com/search?q=%23\\1\" target=\"_blank\">#\\1</a> ", $t);

// truncates long urls that can cause display problems (optional)
$t = preg_replace("/>(([[:alnum:]]+:\/\/)|www\.)([^[:space:]]".
"{30,40})([^[:space:]]*)([^[:space:]]{10,20})([[:alnum:]#?\/&=])".
"</", ">\\3...\\5\\6<", $t);
return trim($t);
}

}

Avatar
mattupstate

11 May 2011 at 10:59am Community Member, 12 Posts

Ugh, nevermind... I have a stray ?> in my template.