1<?php 2/* 3 * e107 website system 4 * 5 * Copyright (C) 2008-2009 e107 Inc (e107.org) 6 * Released under the terms and conditions of the 7 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) 8 * 9 * Plugin - newsfeeds 10 * 11 * $Source: /cvs_backup/e107_0.8/e107_plugins/newsfeed/newsfeed_functions.php,v $ 12 * $Revision$ 13 * $Date$ 14 * $Author$ 15 * 16*/ 17 18/* 19If cache is disabled, first call to this object reads the complete database of active feeds, including the actual news feed. So all data is available for 20the rest of the page. 21 22If cache is enabled, only the feed list (excluding the news feed data) is loaded. Individual news feeds are stored in separate cache files, and loaded on demand. If the 23feed refresh time has expired, the cache is updated. 24*/ 25 26if (!defined('e107_INIT')) { exit; } 27if (!e107::isInstalled('newsfeed')) 28{ 29 return; 30} 31 32define('NEWSFEED_LIST_CACHE_TAG', 'newsfeeds'.e_LAN."_"); 33define('NEWSFEED_NEWS_CACHE_TAG', 'newsfeeds_news_'.e_LAN."_"); 34 35define('NEWSFEED_DEBUG', false); 36 37 38class newsfeedClass 39{ 40 var $validFeedList; // True once feeds read 41 var $feedList = array(); // List of available feeds read from DB - everything from DB apart from the actual news 42 var $feedIcon = array(); // Pre-calculated link to each feed's icon 43 var $newsList = array(); // Actual news element for each feed 44 var $lastProcessed; // Note time when processFeeds() last run 45 var $truncateCount; // Number of characters to show in feeds in menus 46 var $truncateMore; // '...more' string 47 var $useCache; // Set if cache is available 48 49 // Constructor 50 function __construct() 51 { 52 $this->validFeedList = FALSE; 53 $this->newsList = array(); 54 $this->feedList = array(); 55 $this->feedIcon = array(); 56 $this->lastProcessed = 0; 57 $this->truncateCount = 150; // Set a pref for these two later 58 $this->truncateMore = '...'; 59 $this->useCache = true; // e107::getCache()->UserCacheActive; // Have our own local copy - should be faster to access 60 } 61 62 // Ensures the feed list is loaded - uses cache if available 63 function readFeedList($force=FALSE) 64 { 65 $sql = e107::getDb(); 66 67 if ($this->validFeedList && !$force) 68 { 69 return; // Already got list 70 } 71 if($this->useCache) // Cache enabled - try to read from that first 72 { 73 74 if (!$force && $temp = e107::getCache()->retrieve(NEWSFEED_LIST_CACHE_TAG)) 75 { 76 $this->feedList = e107::unserialize($temp); 77 return; 78 } 79 } 80 81 $fieldList = '*'; 82 83 if ($this->useCache) 84 { // Get all fields except the actual news 85 $fieldList = 'newsfeed_id, newsfeed_name, newsfeed_url, newsfeed_timestamp, newsfeed_description, newsfeed_image, newsfeed_active, newsfeed_updateint'; 86 } 87 88 if ($sql->select("newsfeed", $fieldList, '`newsfeed_active` > 0')) // Read in all the newsfeed info on the first go 89 { 90 while ($row = $sql->fetch()) 91 { 92 $nfID = $row['newsfeed_id']; 93 94 if (!empty($row['newsfeed_data'])) 95 { 96 $this->newsList[$nfID]['newsfeed_data'] = $row['newsfeed_data']; // Pull out the actual news - might as well since we're here 97 98 99 unset($row['newsfeed_data']); // Don't keep this in memory twice! 100 } 101 102 $this->newsList[$nfID]['newsfeed_timestamp'] = $row['newsfeed_timestamp']; 103 104 $this->feedList[$nfID] = $row; // Put the rest into the feed data 105 } 106 $this->validFeedList = TRUE; 107 } 108 109 if ($this->useCache) // Cache enabled - we need to save some updated info 110 { 111 $temp = e107::serialize($this->feedList, FALSE); 112 e107::getCache()->set(NEWSFEED_LIST_CACHE_TAG,$temp); 113 } 114 } 115 116 117 // Returns the info for a single feed - from cache or memory as appropriate. If time expired, updates the feed. 118 function getFeed($feedID, $force = FALSE) 119 { 120 $tp = e107::getParser(); 121 $sql = e107::getDb(); 122 123 $this->readFeedList(); // Make sure we've got the feed data. 124 125 if (!isset($this->feedList[$feedID])) 126 { 127 if (NEWSFEED_DEBUG) echo "Invalid feed number: {$feedID}<br />"; 128 return FALSE; 129 } 130 131 $maxAge = ($this->feedList[$feedID]['newsfeed_updateint']/60); 132 133 if($maxAge < 1){ $maxAge = 1; } 134 135 // e107::getDebug()->log("NewsFeed #".$feedID." MaxAge: ".$maxAge); 136 137 $cachedData = e107::getCache()->retrieve(NEWSFEED_NEWS_CACHE_TAG.$feedID,$maxAge, true); 138 139 if(empty($this->newsList[$feedID]['newsfeed_timestamp']) || empty($cachedData) || strpos($this->newsList[$feedID]['newsfeed_data'],'MagpieRSS')) //BC Fix to update newsfeed_data from v1 to v2 spec. 140 { 141 $force = true; 142 // e107::getDebug()->log("NewsFeed Force"); 143 } 144 145 if($cachedData !== false && $force === false) 146 { 147 e107::getDebug()->log("NewsFeed Cache Used"); 148 $this->newsList[$feedID]['newsfeed_data'] = $cachedData; 149 } 150 151 if ($force === true) // Need to re-read from source - either no cached data yet, or cache expired 152 { 153 e107::getDebug()->log("NewsFeed Update: Item #".$feedID." ".NEWSFEED_NEWS_CACHE_TAG); 154 155 if (NEWSFEED_DEBUG) 156 { 157 e107::getLog()->e_log_event(10,debug_backtrace(),"DEBUG","Newsfeed update","Refresh item: ".$feedID,FALSE,LOG_TO_ROLLING); 158 } 159 160 require_once(e_HANDLER.'xml_class.php'); 161 $xml = new xmlClass; 162 require_once(e_HANDLER.'magpie_rss.php'); 163 164 $dbData = array(); // In case we need to update DB 165 166 if($rawData = $xml->getRemoteFile($this->feedList[$feedID]['newsfeed_url'])) // Need to update feed 167 { 168 $rss = new MagpieRSS( $rawData ); 169 list($newsfeed_image, $newsfeed_showmenu, $newsfeed_showmain) = explode("::", $this->feedList[$feedID]['newsfeed_image']); 170 171 $temp['channel'] = $rss->channel; 172 173 if (($newsfeed_showmenu == 0) || ($newsfeed_showmain == 0)) 174 { 175 $temp['items'] = $rss->items; // Unlimited items 176 } 177 else 178 { 179 $temp['items'] = array_slice($rss->items, 0, max($newsfeed_showmenu, $newsfeed_showmain)); // Limited items 180 } 181 182 $newsfeed_des = FALSE; 183 184 if($this->feedList[$feedID]['newsfeed_description'] == 'default') 185 { 186 $temp['newsfeed_description'] = 'default'; // This prevents db writes if no better data found 187 188 if($rss->channel['description']) 189 { 190 $newsfeed_des = $tp -> toDB($rss->channel['description']); 191 $temp['newsfeed_description'] = $newsfeed_des; 192 } 193 elseif($rss->channel['tagline']) 194 { 195 $newsfeed_des = $tp -> toDB($rss -> channel['tagline']); 196 $temp['newsfeed_description'] = $newsfeed_des; 197 } 198 199 if ($temp['newsfeed_description'] != $this->feedList[$feedID]['newsfeed_description']) 200 { // Need to write updated feed name to DB 201 $this->feedList[$feedID]['newsfeed_description'] = $temp['newsfeed_description']; 202 $dbData['newsfeed_description'] = $temp['newsfeed_description']; 203 if ($this->useCache) 204 { 205 e107::getCache()->clear(NEWSFEED_LIST_CACHE_TAG); // Clear the newsfeed cache so its re-read next time 206 } 207 } 208 } 209 210 if ($newsfeed_image == 'default') 211 { 212 $temp['newsfeed_image_link'] = "<a href='".$rss->image['link']."' rel='external'><img src='".$rss->image['url']."' alt='".$rss->image['title']."' style='vertical-align: middle;' /></a>"; 213 } 214 else 215 { 216 $temp['newsfeed_image_link'] = !empty($newsfeed_image) ? "<img src='".$newsfeed_image."' alt='' />" : ''; 217 } 218 219 $serializedArray = e107::serialize($temp, false); 220 221 $now = time(); 222 $this->newsList[$feedID]['newsfeed_data'] = $serializedArray; 223 $this->newsList[$feedID]['newsfeed_timestamp'] = $now; 224 225 if ($this->useCache) 226 { 227 // e107::getDebug()->log("Saving Cache"); 228 e107::getCache()->set(NEWSFEED_NEWS_CACHE_TAG.$feedID, $serializedArray, true); 229 } 230 231 $dbData['newsfeed_data'] = $serializedArray; 232 $dbData['newsfeed_timestamp'] = $now; 233 234 235 if (count($dbData)) // Only write the feed data to DB if not using cache. Write description if changed 236 { 237 238 $dbData['WHERE'] = "newsfeed_id=".$feedID; 239 240 241 242 if(FALSE === $sql->update('newsfeed', $dbData)) 243 { 244 // e107::getDebug()->log("NewsFeed DB Update Failed"); 245 if (NEWSFEED_DEBUG) echo NFLAN_48."<br /><br />".var_dump($dbData); 246 } 247 } 248 unset($rss); 249 } 250 else 251 { 252 if (NEWSFEED_DEBUG) echo $xml -> error; 253 return FALSE; 254 } 255 } 256 257 return e107::unserialize($this->newsList[$feedID]['newsfeed_data']); 258 } 259 260 261 262 263 // Return text for the required news feeds (loads info as necessary) 264 // Uses different templates for main and menu areas 265 function newsfeedInfo($which, $where = 'main') 266 { 267 268 $tp = e107::getParser(); 269 270 global $NEWSFEED_MAIN_START, $NEWSFEED_MAIN, $NEWSFEED_MAIN_END; 271 global $NEWSFEED_MENU_START, $NEWSFEED_MENU, $NEWSFEED_MENU_END; 272 273 if($which == 'all') 274 { 275 $filter = 0; 276 } 277 else 278 { 279 $filter = intval($which); 280 } 281 282 $text = ""; 283 $this->readFeedList(); // Make sure we've got all the news feeds loaded 284 285 /* get template */ 286 287 if(file_exists(THEME."templates/newsfeed/newsfeed_menu_template.php")) //v2.x 288 { 289 include(THEME."templates/newsfeed/newsfeed_menu_template.php"); 290 } 291 elseif(file_exists(THEME."newsfeed_menu_template.php")) //v1.x 292 { 293 include(THEME."newsfeed_menu_template.php"); 294 } 295 else 296 { 297 include(e_PLUGIN."newsfeed/templates/newsfeed_menu_template.php"); 298 } 299 300 $vars = array(); 301 302 foreach($this->feedList as $nfID => $feed) 303 { 304 305 $feed['newsfeed_sef'] = eHelper::title2sef($feed['newsfeed_name'], 'dashl'); 306 307 if (($filter == 0) || ($filter == $feed['newsfeed_id'])) 308 { 309 if (($rss = $this->getFeed($nfID))) // Call ensures that feed is updated if necessary 310 { 311 list($newsfeed_image, $newsfeed_showmenu, $newsfeed_showmain) = explode("::", $feed['newsfeed_image']); 312 313 $numtoshow = intval($where == 'main' ? $newsfeed_showmain : $newsfeed_showmenu); 314 $numtoshow = ($numtoshow > 0 ? $numtoshow : 999); 315 316 // $url = e_PLUGIN_ABS."newsfeed/newsfeed.php?show.".$feed['newsfeed_id']; 317 $url = e107::url('newsfeed','source',$feed); 318 319 $vars['FEEDNAME'] = "<a href='".$url."'>".$tp->toHTML($feed['newsfeed_name'],false,'TITLE')."</a>"; 320 $vars['FEEDDESCRIPTION'] = $feed['newsfeed_description']; 321 $vars['FEEDIMAGE'] = $rss['newsfeed_image_link']; 322 $vars['FEEDLANGUAGE'] = $rss['channel']['language']; 323 324 if($rss['channel']['lastbuilddate']) 325 { 326 $pubbed = $rss['channel']['lastbuilddate']; 327 } 328 else if($rss['channel']['dc']['date']) 329 { 330 $pubbed = $rss['channel']['dc']['date']; 331 } 332 else 333 { 334 $pubbed = NFLAN_34; 335 } 336 337 if(empty($rss['channel']['link']) || ($rss['channel']['link'] === '/')) 338 { 339 $rss['channel']['link'] = $feed['newsfeed_url']; 340 } 341 342 $vars['FEEDLASTBUILDDATE'] = NFLAN_33.$pubbed; 343 $vars['FEEDCOPYRIGHT'] = $tp -> toHTML(vartrue($rss['channel']['copyright']), FALSE); 344 $vars['FEEDTITLE'] = "<a href='".$rss['channel']['link']."' rel='external'>".vartrue($rss['channel']['title'])."</a>"; 345 $vars['FEEDLINK'] = $rss['channel']['link'] ; 346 347 348 if($feed['newsfeed_active'] == 2 or $feed['newsfeed_active'] == 3) 349 { 350 $vars['LINKTOMAIN'] = "<a href='".$url."'>".NFLAN_39."</a>"; 351 } 352 else 353 { 354 $vars['LINKTOMAIN'] = ""; 355 } 356 357 $data = ""; 358 359 $numtoshow = min($numtoshow, count($rss['items'])); 360 $i = 0; 361 while($i < $numtoshow) 362 { 363 $item = $rss['items'][$i]; 364 365 366 367 $vars['FEEDITEMLINK'] = "<a href='".$item['link']."' rel='external'>".$tp -> toHTML($item['title'], FALSE)."</a>\n"; 368 $vars['FEEDITEMLINK'] = str_replace('&', '&', $vars['FEEDITEMLINK']); 369 $feeditemtext = preg_replace("#\[[a-z0-9=]+\]|\[\/[a-z]+\]|\{[A-Z_]+\}#si", "", strip_tags($item['description'])); 370 $vars['FEEDITEMCREATOR'] = $tp -> toHTML(vartrue($item['author']), FALSE); 371 372 if ($where == 'main') 373 { 374 if(!empty($NEWSFEED_COLLAPSE)) 375 { 376 $vars['FEEDITEMLINK'] = "<a href='#' onclick='expandit(this)'>".$tp -> toHTML($item['title'], FALSE)."</a> 377 <div style='display:none' > 378 "; 379 380 $vars['FEEDITEMTEXT'] = preg_replace("/[.*]/", "", $tp -> toHTML($item['description'], FALSE))." 381 <br /><br /><a href='".$item['link']."' rel='external'>".LAN_CLICK_TO_VIEW."</a><br /><br /> 382 </div>"; 383 } 384 else 385 { 386 $vars['FEEDITEMLINK'] = "<a href='".$item['link']."' rel='external'>".$tp -> toHTML($item['title'], FALSE)."</a>\n"; 387 $vars['FEEDITEMLINK'] = str_replace('&', '&', $vars['FEEDITEMLINK']); 388 $feeditemtext = preg_replace("#\[[a-z0-9=]+\]|\[\/[a-z]+\]|\{[A-Z_]+\}#si", "", $item['description']); 389 $vars['FEEDITEMTEXT'] = $tp -> toHTML($feeditemtext, FALSE)."\n"; 390 } 391 $data .= $tp->simpleParse( $NEWSFEED_MAIN, $vars); 392 } 393 else 394 { 395 if ($this->truncateCount) 396 { 397 $vars['FEEDITEMTEXT'] = $tp->text_truncate($feeditemtext, $this->truncateCount, $this->truncateMore); 398 } 399 else 400 { 401 $vars['FEEDITEMTEXT'] = ''; // Might just want title 402 } 403 $data .= $tp->simpleParse($NEWSFEED_MENU, $vars); 404 } 405 $i++; 406 } 407 } 408 } 409 410 if ($where == 'main') 411 { 412 $vars['BACKLINK'] = "<a href='".e_SELF."'>".NFLAN_31."</a>"; 413 $text = $tp->simpleParse($NEWSFEED_MAIN_START, $vars).$data.$tp->simpleParse( $NEWSFEED_MAIN_END, $vars); 414 } 415 else 416 { 417 $text .= $tp->simpleParse($NEWSFEED_MENU_START, $vars) . $data . $tp->simpleParse($NEWSFEED_MENU_END, $vars); 418 } 419 420 //TODO Move the $vars into their own shortcode class and change simpleParse to parseTemplate(); 421 } 422 423 if($which == 'all') 424 { 425 $ret['title'] = (!empty($NEWSFEED_MENU_CAPTION)) ? $NEWSFEED_MENU_CAPTION : ''; 426 } 427 else 428 { 429 $ret['title'] = $feed['newsfeed_name']." ".varset($NEWSFEED_MAIN_CAPTION); 430 } 431 $ret['text'] = $text; 432 433 return $ret; 434 } 435} 436 437 438 439