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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

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

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

Caching of External Data


Go to End


3 Posts   1577 Views

Avatar
mattupstate

Community Member, 12 Posts

11 May 2011 at 10:28am

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

Community Member, 12 Posts

11 May 2011 at 10:29am

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

Community Member, 12 Posts

11 May 2011 at 10:59am

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