0byt3m1n1
Path:
/
data
/
applications
/
aps
/
tikiwiki
/
7.0-0
/
standard
/
htdocs
/
lib
/
rss
/
[
Home
]
File: rsslib.php
<?php // (c) Copyright 2002-2011 by authors of the Tiki Wiki CMS Groupware Project // // All Rights Reserved. See copyright.txt for details and a complete list of authors. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. // $Id: rsslib.php 33261 2011-03-06 18:02:56Z lphuberdeau $ //this script may only be included - so its better to die if called directly. if (strpos($_SERVER["SCRIPT_NAME"], basename(__FILE__)) !== false) { header("location: index.php"); exit; } class RSSLib extends TikiDb_Bridge { private $items; private $feeds; private $modules; function __construct() { $this->items = $this->table('tiki_rss_items'); $this->feeds = $this->table('tiki_rss_feeds'); $this->modules = $this->table('tiki_rss_modules'); } // ------------------------------------ // functions for rss feeds we syndicate // ------------------------------------ /** * Return the feed format name * * @return string feed format name */ function get_current_feed_format_name() { $ver = $this->get_current_feed_format(); if ($ver == '2') { $name = 'rss'; } else if ($ver == '5') { $name = 'atom'; } return $name; } /** * Return the feed format code (2 for rss and 5 for atom) * we currently use (user param or default value) * * @return int $ver */ function get_current_feed_format() { global $prefs; if (isset($_REQUEST['ver'])) { $ver = $_REQUEST['ver']; } else { $ver = $prefs['feed_default_version']; } return $ver; } /* check for cached rss feed data */ function get_from_cache($uniqueid, $rss_version="9") { global $tikilib, $user, $prefs; $rss_version=$this->get_current_feed_format(); $output = array(); $output["content-type"] = "application/xml"; $output["encoding"] = "UTF-8"; $output["data"] = "EMPTY"; // caching rss data for anonymous users only if (isset($user) && $user<>"") return $output; $res = $this->feeds->fetchFullRow(array('name' => $uniqueid, 'rssVer' => $rss_version)); if (!$res) { // nothing found, then insert empty row for this feed+rss_ver $this->feeds->insert(array( 'name' => $uniqueid, 'rssVer' => $rss_version, 'refresh' => (int) $prefs['feed_cache_time'], 'lastUpdated' => 1, 'cache' => '-', )); } else { // entry found in db: $output["data"] = $res["cache"]; // $refresh = $res["refresh"]; // global cache time currently $refresh = $prefs['feed_cache_time']; // global cache time currently $lastUpdated = $res["lastUpdated"]; // up to date? if not, then set trigger to reload data: if ($tikilib->now - $lastUpdated >= $refresh ) { $output["data"]="EMPTY"; } } return $output; } /* put to cache */ function put_to_cache($uniqueid, $rss_version="9", $output) { global $user, $tikilib; // caching rss data for anonymous users only if (isset($user) && $user<>"") return; if ($output=="" || $output=="EMPTY") return; $rss_version=$this->get_current_feed_format(); // update cache with new generated data if data not empty $this->feeds->update(array( 'cache' => $output, 'lastUpdated' => $tikilib->now, ), array( 'name' => $uniqueid, 'rssVer' => $rss_version, )); } /** * Generate a feed (ATOM 1.0 or RSS 2.0 using Zend_Feed_Writer_Feed * * @param string $section Tiki feature the feed is related to * @param string $uniqueid * @param string $feed_version DEPRECATED * @param array $changes the content that will be used to generate the feed * @param string $itemurl base url for items (e.g. "tiki-view_blog_post.php?postId=%s") * @param string $urlparam * @param string $id name of the id field used to identify each feed item (e.g. "postId") * @param string $title title for the feed * @param string $titleId name of the key in the $changes array with the title of each item * @param string $desc description for the feed * @param string $descId name of the key in the $changes array with the description of each item * @param string $dateId name of the key in the $changes array with the date of each item * @param string $authorId name of the key in the $changes array with the author of each item * @param bool $fromcache if true recover the feed from cache * * @return array the generated feed */ function generate_feed($section, $uniqueid, $feed_version, $changes, $itemurl , $urlparam, $id, $title, $titleId, $desc, $descId, $dateId, $authorId , $fromcache=false ) { global $tikilib, $tiki_p_admin, $prefs, $userlib, $prefs, $smarty; // both title and description fields cannot be null if (empty($title) || empty($desc)) { $msg = tra('The fields title and description are mandatory to generate a feed.'); if ($tiki_p_admin) { $msg .= ' ' . tra('To fix this error go to Admin -> Feeds.'); } else { $msg .= ' ' . tra('Please contact the site administrator and ask him to fix this error'); } $smarty->assign('msg', $msg); $smarty->display('error.tpl'); die; } $feed_format = $this->get_current_feed_format(); $feed_format_name = $this->get_current_feed_format_name(); if ($prefs['feed_cache_time'] < 1) $fromcache=false; // only get cache data if rss cache is enabled if ($fromcache) { $output = $this->get_from_cache($uniqueid, $feed_format); if ($output['data'] != 'EMPTY') return $output; } $urlarray = parse_url($_SERVER["REQUEST_URI"]); $rawPath = str_replace('\\','/', dirname($urlarray["path"])); $URLPrefix = $tikilib->httpPrefix() . $rawPath; if ($rawPath != "/") { $URLPrefix .= "/"; // Append a slash unless Tiki is in the document root. dirname() removes a slash except in that case. } if ($prefs['feed_'.$section.'_index'] != '') { $feedLink = $prefs['feed_'.$section.'_index']; } else { $feedLink = htmlspecialchars($tikilib->httpPrefix().$_SERVER["REQUEST_URI"]); } $img = htmlspecialchars($URLPrefix.$prefs['feed_img']); $title = htmlspecialchars($title); $desc = htmlspecialchars($desc); $read = $URLPrefix.$itemurl; $feed = new Zend_Feed_Writer_Feed(); $feed->setTitle($title); $feed->setDescription($desc); if (!empty($prefs['feed_language'])) { $feed->setLanguage($prefs['feed_language']); } $feed->setLink($tikilib->tikiUrl()); $feed->setFeedLink($feedLink, $feed_format_name); $feed->setDateModified($tikilib->now); if ($feed_format_name == 'atom') { $author = array(); if (!empty($prefs['feed_atom_author_name'])) { $author['name'] = $prefs['feed_atom_author_name']; } if (!empty($prefs['feed_atom_author_email'])) { $author['email'] = $prefs['feed_atom_author_email']; } if (!empty($prefs['feed_atom_author_url'])) { $author['url'] = $prefs['feed_atom_author_url']; } if (!empty($author)) { if (empty($author['name'])) { $msg = tra('If you set feed author email or url you have to set feed author name.'); $smarty->assign('msg', $msg); $smarty->display('error.tpl'); die; } $feed->addAuthor($author); } } else { $authors = array(); if (!empty($prefs['feed_rss_editor_email'])) { $authors[]['name'] = $prefs['feed_rss_editor_email']; } if (!empty($prefs['feed_rss_webmaster_email'])) { $authors[]['name'] = $prefs['feed_rss_webmaster_email']; } if (!empty($authors)) { $feed->addAuthors($authors); } } if (!empty($prefs['feed_img'])) { $image = array(); $image['uri'] = $tikilib->tikiUrl() . $prefs['feed_img']; $image['title'] = tra('Feed logo'); $image['link'] = $tikilib->tikiUrl(); $feed->setImage($image); } foreach ($changes["data"] as $data) { $item = $feed->createEntry(); $item->setTitle($data[$titleId]); if (isset($data['sefurl'])) { $item->setLink($URLPrefix.$data['sefurl']); } elseif ($urlparam != '') { // 2 parameters to replace $item->setlink(sprintf($read, urlencode($data["$id"]), urlencode($data["$urlparam"]))); } else { $item->setLink(sprintf($read, urlencode($data["$id"]))); } if (isset($data[$descId]) && $data[$descId] != '') { $item->setDescription($data[$descId]); } $item->setDateCreated($data[$dateId]); $item->setDateModified($data[$dateId]); if ($authorId != '' && $prefs['feed_'.$section.'_showAuthor'] == 'y') { $author = $this->process_item_author($data[$authorId]); $item->addAuthor($author); } $feed->addEntry($item); } $data = $feed->export($feed_format_name); $this->put_to_cache($uniqueid, $feed_format, $data); $output = array(); $output["data"] = $data; $output["content-type"] = 'application/xml'; return $output; } /** * Return information about the user acording to its preferences * * @param string $login * @return array author data (can be the login name or the realName if set and email if public) */ function process_item_author($login) { global $userlib, $tikilib; $author = array(); if ($userlib->user_exists($login) && $tikilib->get_user_preference($login, 'user_information', 'private') == 'public') { // if realName is not set use $login $author['name'] = $tikilib->get_user_preference($login, 'realName', $login); if ($tikilib->get_user_preference($login, 'email is public', 'n') != 'n') { $res = $userlib->get_user_info($login, false); require_once('lib/userprefs/scrambleEmail.php'); $author['email'] = scrambleEmail($res['email']); } } else { $author['name'] = $login; } return $author; } // -------------------------------------------- // functions for rss feeds syndicated by others // -------------------------------------------- /* get (a part of) the list of existing rss feeds from db */ function list_rss_modules($offset, $maxRecords, $sort_mode, $find) { $conditions = array(); if ($find) { $conditions['search'] = $this->modules->expr('(`name` LIKE ? OR `description` LIKE ?)', array("%$find%", "%$find%")); } $ret = $this->modules->fetchAll($this->modules->all(), $conditions, -1, -1, $this->modules->sortMode($sort_mode)); foreach ($ret as & $res) { $res["minutes"] = $res["refresh"] / 60; } return array( 'data' => $ret, 'cant' => count($ret), ); } /* replace rss feed in db */ function replace_rss_module($rssId, $name, $description, $url, $refresh, $showTitle, $showPubDate, $noUpdate = false) { //if($this->rss_module_name_exists($name)) return false; // TODO: Check the name $refresh = 60 * $refresh; $data = array( 'name' => $name, 'description' => $description, 'refresh' => $refresh, 'url' => $url, 'showTitle' => $showTitle, 'showPubDate' => $showPubDate, ); if ($rssId) { $this->modules->update($data, array( 'rssId' => (int) $rssId, )); } else { $data['lastUpdated'] = 1; $rssId = $this->modules->insert($data); } if (!$noUpdate) { // Updating is normally required, except for cases where we know it will be updated later (e.g. after article generation is set, so that articles are created immediately) $this->update_feeds( array( $rssId ), true ); } return $rssId; } /* remove rss feed from db */ function remove_rss_module($rssId) { $this->modules->delete(array( 'rssId' => $rssId, )); return true; } /* read rss feed data from db */ function get_rss_module($rssId) { return $this->modules->fetchFullRow(array('rssId' => $rssId)); } function refresh_rss_module($rssId) { $this->update_feeds( array( $rssId ), true ); } function clear_rss_cache($rssId) { $this->items->deleteMultiple(array('rssId' => (int) $rssId)); } /* check if an rss feed name already exists */ function rss_module_name_exists($name) { return $this->modules->fetchCount(array('name' => $name)); } /* get rss feed id by name */ function get_rss_module_id($name) { return $this->modules->fetchOne('rssId', array('name' => $name)); } /* check if 'showTitle' for an rss feed is enabled */ function get_rss_showTitle($rssId) { return $this->modules->fetchOne('showTitle', array('rssId' => $rssId)); } /* check if 'showPubdate' for an rss feed is enabled */ function get_rss_showPubDate($rssId) { return $this->modules->fetchOne('showPubDate', array('rssId' => $rssId)); } function get_feed_items( $feeds, $count = 10 ) { $feeds = (array) $feeds; $this->update_feeds( $feeds ); return $this->items->fetchAll($this->items->all(), array( 'rssId' => $this->items->in($feeds), ), $count, 0, array('publication_date' => 'DESC')); } private function update_feeds( $feeds, $force = false ) { global $tikilib; $conditions = array( 'rssId' => $this->modules->in($feeds), ); if( ! $force ) { $conditions['date'] = $this->modules->expr('`lastUpdated` < ? - `refresh`', array($tikilib->now)); } $result = $this->modules->fetchAll(array('rssId', 'url', 'actions'), $conditions); foreach( $result as $row ) { $this->update_feed( $row['rssId'], $row['url'], $row['actions'] ); } } private function update_feed( $rssId, $url, $actions ) { global $tikilib; $filter = new DeclFilter; $filter->addStaticKeyFilters( array( 'url' => 'url', 'title' => 'striptags', 'author' => 'striptags', 'description' => 'striptags', 'content' => 'purifier', ) ); $guidFilter = TikiFilter::get('url'); try { $feed = Zend_Feed_Reader::import( $url ); } catch( Zend_Exception $e ) { $this->modules->update(array( 'lastUpdated' => $tikilib->now, 'sitetitle' => 'N/A', 'siteurl' => '#', ), array( 'rssId' => $rssId, )); return; } $siteTitle = TikiFilter::get('striptags')->filter( $feed->getTitle() ); $siteUrl = TikiFilter::get('url')->filter( $feed->getLink() ); $this->modules->update(array( 'lastUpdated' => $tikilib->now, 'sitetitle' => $siteTitle, 'siteurl' => $siteUrl, ), array( 'rssId' => $rssId, )); foreach( $feed as $entry ) { $guid = $guidFilter->filter( $entry->getId() ); $count = $this->items->fetchCount(array('rssId' => $rssId, 'guid' => $guid)); if( 0 == $count ) { $authors = $entry->getAuthors(); $data = $filter->filter( array( 'title' => $entry->getTitle(), 'url' => $entry->getLink(), 'description' => $entry->getDescription(), 'content' => $entry->getContent(), 'author' => $authors ? implode( ', ', $authors->getValues() ) : '', ) ); $data['guid'] = $guid; if( method_exists( $entry, 'getDateCreated' ) && $createdDate = $entry->getDateCreated() ) { $data['publication_date'] = $createdDate->get( Zend_Date::TIMESTAMP ); } else { global $tikilib; $data['publication_date'] = $tikilib->now; } $this->insert_item( $rssId, $data, $actions ); } } } private function insert_item( $rssId, $data, $actions ) { $this->items->insert(array( 'rssId' => $rssId, 'guid' => $data['guid'], 'url' => $data['url'], 'publication_date' => $data['publication_date'], 'title' => $data['title'], 'author' => $data['author'], 'description' => $data['description'], 'content' => $data['content'], )); $actions = json_decode( $actions, true ); foreach( $actions as $action ) { $method = 'process_action_' . $action['type']; unset( $action['type'] ); if( $action['active'] ) { $this->$method( $action, $data ); } } } private function process_action_article( $configuration, $data ) { $tikilib = TikiLib::lib('tiki'); $artlib = TikiLib::lib('art'); $publication = $data['publication_date']; if( $configuration['future_publish'] > 0 ) { $publication = $tikilib->now + $configuration['future_publish']*60; } $expire = $publication + 3600*24*$configuration['expiry']; if (strpos( $data['content'], trim($data['description'])) === 0 && strlen($data['description']) < 1024) { $data['content'] = substr( $data['content'], strlen(trim($data['description']))); } $data['content'] = trim($data['content']) == '' ? $data['content'] : '~np~' . $data['content'] . '~/np~'; if($configuration['submission'] == true) { $subid = $artlib->replace_submission( $data['title'], $data['author'], $configuration['topic'], 'n', '', 0, '', '', $data['description'], $data['content'], $publication, $expire, 'admin', 0, 0, 0, $configuration['atype'], '', '', $data['url'], '', '', $configuration['rating'] ); if( count( $configuration['categories'] ) ) { $categlib = TikiLib::lib('categ'); $objectId = $categlib->add_categorized_object( 'submission', $subid, $data['title'], $data['title'], 'tiki-edit_submission.php?subId=' . $subid ); foreach( $configuration['categories'] as $categId ) { $categlib->categorize( $objectId, $categId ); } } } else { $id = $artlib->replace_article( $data['title'], $data['author'], $configuration['topic'], 'n', '', 0, '', '', $data['description'], $data['content'], $publication, $expire, 'admin', 0, 0, 0, $configuration['atype'], '', '', $data['url'], '', '', $configuration['rating'] ); if( count( $configuration['categories'] ) ) { $categlib = TikiLib::lib('categ'); $objectId = $categlib->add_categorized_object( 'article', $id, $data['title'], $data['title'], 'tiki-read_article.php?articleId=' . $id ); foreach( $configuration['categories'] as $categId ) { $categlib->categorize( $objectId, $categId ); } } } } function set_article_generator( $rssId, $configuration ) { $configuration['type'] = 'article'; if( $module['actions'] ) { $actions = json_decode( $module['actions'], true ); } else { $actions = array(); } $out = array(); foreach( $actions as $action ) { if( $action['type'] != 'article' ) { $out[] = $action; } } $out[] = $configuration; $this->modules->update(array( 'actions' => json_encode($out), ), array( 'rssId' => $rssId, )); } function get_article_generator( $rssId ) { $module = $this->get_rss_module( $rssId ); if( $module['actions'] ) { $actions = json_decode( $module['actions'], true ); } else { $actions = array(); } $default = array( 'active' => false, 'expiry' => 365, 'atype' => 'Article', 'topic' => 0, 'future_publish' => -1, 'categories' => array(), 'rating' => 5, ); foreach( $actions as $action ) { if( $action['type'] == 'article' ) { unset( $action['type'] ); return array_merge( $default, $action ); } } return $default; } } global $rsslib; $rsslib = new RSSLib;