169 lines
4.9 KiB
PHP
169 lines
4.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* RSS Feed Class
|
|
* @author franzz
|
|
* @version 1.1
|
|
*
|
|
* Input:
|
|
* - $asDesc: Array. Description of the feed: fields 'title', 'link' (optional), 'copyright', 'description', 'language', 'webmaster_mail'
|
|
* - $asItems: Array. Feed item data: fields 'title', 'description', 'author', 'link', 'pub_date', 'guid'
|
|
*/
|
|
class Feed extends PhpObject {
|
|
|
|
private $asDesc;
|
|
private $asItems;
|
|
|
|
public function __construct($asDesc, $asItems=array())
|
|
{
|
|
parent::__construct();
|
|
if(!array_key_exists('link', $asDesc))
|
|
{
|
|
$asDesc['link'] = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'].'/rss';
|
|
}
|
|
$this->asDesc = $asDesc;
|
|
array_walk($asItems, array($this, 'addItem'));
|
|
}
|
|
|
|
public function addItem($asItem)
|
|
{
|
|
$this->asItems[] = $asItem;
|
|
return count($this->asItems) - 1;
|
|
}
|
|
|
|
public function removeItem($iItemId)
|
|
{
|
|
$bExist = array_key_exists($iItemId, $this->asItems);
|
|
if($bExist) unset($this->asItems[$iItemId]);
|
|
return $bExist;
|
|
}
|
|
|
|
private function getGlobalPubDate()
|
|
{
|
|
$iGlobalPubDate = 0;
|
|
foreach($this->asItems as $asItem)
|
|
{
|
|
$iItemPubDate = strtotime($asItem['pub_date']);
|
|
if($iItemPubDate>$iGlobalPubDate)
|
|
{
|
|
$iGlobalPubDate = $iItemPubDate;
|
|
}
|
|
}
|
|
return self::cleanRss(self::getDate($iGlobalPubDate));
|
|
}
|
|
|
|
public function getFeed()
|
|
{
|
|
|
|
//feed header
|
|
$sRssFeedHeader = self::getHtml($this->asDesc['title'], 'title');
|
|
$sRssFeedHeader .= self::getHtml($this->asDesc['link'], 'link');
|
|
$sRssFeedHeader .= self::getHtml($this->asDesc['copyright'], 'copyright');
|
|
$sRssFeedHeader .= self::getHtml($this->asDesc['description'], 'description');
|
|
$sRssFeedHeader .= self::getHtml('', 'atom:link', '', '', array('href'=>$this->asDesc['link'], 'rel'=>'self', 'type'=>'application/atom+xml'), true);
|
|
$sRssFeedHeader .= self::getHtml($this->asDesc['language'], 'language');
|
|
$sRssFeedHeader .= self::getHtml($this->getGlobalPubDate(), 'pubDate');
|
|
$sRssFeedHeader .= self::getHtml('Lutran.fr RSS Feed Generator', 'generator');
|
|
$sRssFeedHeader .= self::getHtml($this->asDesc['webmaster_mail'].' (Webmaster)', 'webMaster');
|
|
|
|
//feed items
|
|
$asSortedItems = $this->rSortTimeMatrix($this->asItems, 'pub_date');
|
|
$sItems = implode("\n", array_map(array($this, 'buildItem'), $asSortedItems));
|
|
|
|
//Global Feed
|
|
$sFeed = '<?xml version="1.0" encoding="UTF-8" ?>';
|
|
$sFeed .= self::getHtml(self::getHtml($sRssFeedHeader.$sItems, 'channel'), 'rss', '', '', array('version'=>'2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom'));
|
|
|
|
return $sFeed;
|
|
}
|
|
|
|
private static function getDate($sDate)
|
|
{
|
|
if(!is_numeric($sDate))
|
|
{
|
|
$sDate = strtotime($sDate);
|
|
}
|
|
return date('r', $sDate);
|
|
}
|
|
|
|
private function buildItem($asItem)
|
|
{
|
|
$sRssItem = self::getHtml(self::cleanRss($asItem['title']), 'title');
|
|
$sRssItem .= self::getHtml(self::cleanRss($asItem['author']), 'author');
|
|
$sRssItem .= self::getHtml($asItem['link'], 'link');
|
|
$sRssItem .= self::getHtml($asItem['category'], 'category');
|
|
$sRssItem .= self::getHtml(self::cleanRss($asItem['description'].'.'), 'description');
|
|
$sRssItem .= self::getHtml(self::getDate($asItem['pub_date']), 'pubDate');
|
|
$sRssItem .= self::getHtml($asItem['guid'], 'guid', '', '', array('isPermaLink'=>'true'));
|
|
return self::getHtml($sRssItem, 'item');
|
|
}
|
|
|
|
private static function getHtml($oText, $sTag, $sClass='', $sStyle='', $asExtraAttr=array(), $bAutoClose=false, $sInter='')
|
|
{
|
|
$sHtmlAttr = '';
|
|
if($sClass!='')
|
|
{
|
|
$asExtraAttr['class'] = $sClass;
|
|
}
|
|
if($sStyle!='')
|
|
{
|
|
$asExtraAttr['style'] = $sStyle;
|
|
}
|
|
foreach($asExtraAttr as $sAttrName=>$sAttrValue)
|
|
{
|
|
$sHtmlAttr .= ' '.$sAttrName.'="'.$sAttrValue.'"';
|
|
}
|
|
if($bAutoClose)
|
|
{
|
|
$sHtml = self::encapsulate('', "\n".'<'.$sTag.$sHtmlAttr, ' />');
|
|
}
|
|
else
|
|
{
|
|
$sHtml = self::encapsulate($oText, "\n".'<'.$sTag.$sHtmlAttr.'>', '</'.$sTag.'>', $sInter);
|
|
}
|
|
return $sHtml;
|
|
}
|
|
|
|
private static function cleanRss($oText)
|
|
{
|
|
$asForbiddenChars = array('&', '<', '>', '"', "'");
|
|
$asReplacementCode = array('&', '<', '>', '"', ''');
|
|
if(!is_array($oText))
|
|
{
|
|
return str_replace($asForbiddenChars, $asReplacementCode, $oText);
|
|
}
|
|
elseif(count($oText)>0)
|
|
{
|
|
$oTextKeys = array_map(array($this, 'cleanRss'), array_keys($oText));
|
|
$oTextValues = array_map(array($this, 'cleanRss'), array_values($oText));
|
|
return array_combine($oTextKeys, $oTextValues);
|
|
}
|
|
else
|
|
{
|
|
return $oText;
|
|
}
|
|
}
|
|
|
|
private static function encapsulate($oText, $sPre='', $sPost=false, $sInter='')
|
|
{
|
|
if($sPost===false)
|
|
{
|
|
$sPost = $sPre;
|
|
}
|
|
if(is_array($oText))
|
|
{
|
|
$oText = implode($sPost.$sInter.$sPre, $oText);
|
|
}
|
|
return $sPre.$oText.$sPost;
|
|
}
|
|
|
|
private static function rSortTimeMatrix($asMatrix, $sTimeCol)
|
|
{
|
|
$asResult = array();
|
|
foreach($asMatrix as $iRowId=>$asLine) $asKeys[$iRowId] = strtotime($asLine[$sTimeCol]);
|
|
arsort($asKeys);
|
|
foreach($asKeys as $iRowId=>$iTimeStamp) $asResult[$iRowId] = $asMatrix[$iRowId];
|
|
return $asResult;
|
|
}
|
|
}
|
|
?>
|