* Version: 0.1 * License: GPL * * The lastest version of MagpieRSS can be obtained from: * http://magpierss.sourceforge.net * * For questions, help, comments, discussion, etc., please join the * Gregarius dev mailing list. */ class RSSdbCache { var $MAX_AGE = 60; // when are files stale (in minutes), default one hour var $ERROR = ""; // accumulate error messages var $translateUrltoCid = array(); // which URL correspondes to which channel ID function RSSdbCache ($base='', $age='') { // $base is kept for compatibility purposes only if ( $age ) { $this->MAX_AGE = $age; } } /*=======================================================================*\ Function: set Purpose: add an item to the cache, keyed on url Input: url from wich the rss file was fetched Output: true on sucess \*=======================================================================*/ function set ($url, $rss) { $this->ERROR = ""; if(!array_key_exists($url, $this -> translateUrltoCid) ) { $cid = $this->translateUrl($url); } else { $cid = $this->translateUrltoCid[$url]; } if ( ! $cid ) { $this->debug( "Cannot translate: $url (to cid)"); return 0; } $sql = "update ".getTable("channels") ." set "." lastmodified='" . rss_real_escape_string(trim($rss->last_modified)) . "', " ." etag='" . rss_real_escape_string(trim($rss->etag)) ."', daterefreshed = now()" . " where id=$cid"; rss_query($sql); if (! rss_is_sql_error(RSS_SQL_ERROR_NO_ERROR)) { $this->error( "Unable to write to db cache: $url : cid: $cid"); return 0; } return true; } /*=======================================================================*\ Function: get Purpose: fetch an item from the cache Input: url from wich the rss file was fetched Output: cached object on HIT, false on MISS \*=======================================================================*/ function get ($url) { $this->ERROR = ""; if(!array_key_exists($url, $this -> translateUrltoCid) ) { $cid = $this->translateUrl($url); } else { $cid = $this -> translateUrltoCid[$url]; } if ( ! $cid ) { $this->debug( "Cannot translate: $url (to cid)"); return 0; } $res = rss_query("select etag, lastmodified from " . getTable("channels") . " where id=$cid"); if ( ! $res ) { $this->error("Failed to read from db cache. channel id: $cid"); return 0; } list($etag, $lastmodified) = rss_fetch_row($res); $rss = new FakeMagpieRSS(); $rss ->etag = trim($etag); $rss ->last_modified = trim($lastmodified); return $rss; } /*=======================================================================*\ Function: check_cache Purpose: check a url for membership in the cache and whether the object is older then MAX_AGE (ie. STALE) Input: url from wich the rss file was fetched Output: cached object on HIT, false on MISS \*=======================================================================*/ function check_cache ( $url, $nbbsparams = null ) { $this->ERROR = ""; if(!array_key_exists($url, $this -> translateUrltoCid) ) { $cid = $this->translateUrl($url, $nbbsparams); } else { $cid = $this -> translateUrltoCid[$url]; } if ( ! $cid ) { $this->debug( "Cannot translate: $url (to cid)"); return 'MISS'; } $res = rss_query("select UNIX_TIMESTAMP(daterefreshed) as ts, refreshinterval from " . getTable("channels") . " where id=$cid"); if ( ! $res ) { $this->error("Failed to read from db cache. channel id: $cid"); return 'MISS'; } list($dateRefreshed, $refreshInterval) = rss_fetch_row($res); // Lets hope that the web server and sql server have their clocks in sync $age = time() - $dateRefreshed; if (!$refreshInterval || ($refreshInterval < 10)) { // We should change the Gregarius UA if we allow refreshInterval to be small $refreshInterval = $this->MAX_AGE; } if ( $refreshInterval * 60 > $age ) { // object exists and is current return 'HIT'; } else { // object exists but is old return 'STALE'; } } /*=======================================================================*\ Function: translateUrl Purpose: internally map url to channel id Input: url from wich the rss file was fetched Output: returns cid if it succeeds, else 0. \*=======================================================================*/ function translateUrl ($url, $nbbsparams = null) { $url = rss_real_escape_string($url); $sql = "SELECT id FROM " . getTable("channels") . " WHERE url='$url'"; $res = rss_query($sql); if(1 == rss_num_rows($res)) { list ($cid) = rss_fetch_row($res); $this -> translateUrltoCid[$url] = $cid; return $cid; // should always be positive } else { if($nbbsparams==null) { $this->error("Cache unable translate to cid: $url"); return 0; } if(empty($nbbsparams['title'])) $nbbsparams['title'] = 'Feed'; if(empty($nbbsparams['refreshinterval'])) $nbbsparams['refreshinterval'] = 60; rss_query("INSERT INTO ".getTable("channels")." (title, url, refreshinterval) VALUES('". $nbbsparams['title']."','". $url."','". $nbbsparams['refreshinterval']."')"); return 0; // Force caching == 'MISS' } } /*=======================================================================*\ Function: error Purpose: register error \*=======================================================================*/ function error ($errormsg, $lvl=E_USER_WARNING) { // append PHP's error message if track_errors enabled if ( isset($php_errormsg) ) { $errormsg .= " ($php_errormsg)"; } $this->ERROR = $errormsg; if ( MAGPIE_DEBUG ) { trigger_error( $errormsg, $lvl); } else { error_log( $errormsg, 0); } } function debug ($debugmsg, $lvl=E_USER_NOTICE) { if ( MAGPIE_DEBUG ) { $this->error("MagpieRSS [debug] $debugmsg", $lvl); } } } /*=======================================================================*\ Class: Fake MapieRSS class Purpose: to send a barebones rss object back from the db \*=======================================================================*/ class FakeMagpieRSS extends MagpieRSS { function FakeMagpieRSS() { // just need to avoid calling the parent's constructor // because we have nothing to parse } } ?>