<?php

class NP_RSSAtomAggregator extends NucleusPlugin {

   /* ==========================================================================================
	* RSS/Atom Aggregator 0.14 for Nuclues CMS
	* Aggregate and display multiple RSS and Atom feeds on your blog
	*
	* Copyright 2004 by Niels Leenheer
	* ==========================================================================================
	* This program is free software and open source software; you can redistribute
	* it and/or modify it under the terms of the GNU General Public License as
	* published by the Free Software Foundation; either version 2 of the License,
	* or (at your option) any later version.
	*
	* This program is distributed in the hope that it will be useful, but WITHOUT
	* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
	* more details.
	*
	* You should have received a copy of the GNU General Public License along
	* with this program; if not, write to the Free Software Foundation, Inc.,
	* 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  or visit
	* http://www.gnu.org/licenses/gpl.html
	* ==========================================================================================
	*
	* 0.14   - Again rewritten large parts of the charset conversion
	* 0.13   - Replaced code for charset conversion with faster optimized version
	* 0.12   - Added proper support for UTF-8 encoded RSS and Atom feeds
	*        - Added charset conversion for more exotic feeds
	* 0.11   - Changed version number to reflect updated XMLSupport
	* 0.10   - Large rewrite of the plugin code
	*        - Reorganized template settings
	*        - Now making use of the TEMPLATE class to fill values in templates
	* 0.9.1  - Added error reporting for OPML parsing
	* 0.9.0  - Initial release
	*/
	


	// PLUGIN INFORMATION
	function getName() {
		return 'RSS/Atom Aggregator';
	}

	function getAuthor()  {
		return 'Niels Leenheer';
	}

	function getURL() {
		return 'http://www.rakaz.nl/nucleus/extra/plugins';
	}

	function getVersion() {
		return '0.14';
	}

	function getDescription() {
		return 'This plugin reads multiple RSS and Atom feeds and shows the
		        entries as links on your blog. The feed can be 
				shown in any skin using the skinvar 
				&lt;%RSSAtomAggregator%&gt;. ';
	}
	
	function supportsFeature($feature) {
    	switch($feature) {
	        case 'SqlTablePrefix':
	        	return 1;
	        default:
	    		return 0;
		}
	}


	
	// CONFIGURATION VARIABLES
	var $showDebug = false;
	var $showEmpty;
	var $showErrors;

	var $opml;
	var $opmlFilename;

	var $defaultTitle;
	var $defaultFeeds;
	var $defaultCount;
	var $defaultLength;

	var $XMLSupport;
		


	// PLUGIN INITIALISATION
	function init() {
		global $manager;

		$this->opml = ($this->getOption('opml') == 'yes') ? true : false; 
		$this->opmlFilename = $this->getOption('opmlFilename');
		$this->defaultTitle = $this->getOption('defaultTitle');
		$this->defaultFeeds = $this->getOption('defaultFeeds');
		$this->defaultCount = (int) $this->getOption('defaultCount');
		$this->defaultLength = (int) $this->getOption('defaultLength'); 
		$this->showEmpty = ($this->getOption('showEmpty') == 'yes') ? true : false; 
		$this->showErrors = ($this->getOption('showErrors') == 'yes') ? true : false; 
		
		if ($manager) if ($manager->pluginInstalled('NP_XMLSupport')) 
			$this->XMLSupport =& $manager->getPlugin('NP_XMLSupport');
	}	
	
	function install() {
		$this->createOption('opml','Use an OPML file?','yesno','yes');
    	$this->createOption('opmlFilename','OPML file location','text','feeds.opml');

    	$this->createOption('defaultTitle','Manual Title','text',"Aggregated feeds");
		$this->createOption('defaultFeeds','Manual Feeds','textarea',"rakaz|http://www.rakaz.nl/nucleus/xml-rss2.php");
    	$this->createOption('defaultCount','Maximum number of entries','text','10');
    	$this->createOption('defaultLength','Maximum length of entries (0 = no limit)','text','0');
		$this->createOption('showEmpty',"Show box when there are no items available",'yesno','yes');

		$this->createOption('tplBoxHeader','Box Header','textarea',"<div class='RSSAtom'>");
		$this->createOption('tplTitle','Title','textarea',"<h4><%title%></h4>");
		$this->createOption('tplHeader','Header','textarea',"<ul class='feeds'>");
    	$this->createOption('tplItem','Item','textarea',"<li><a href='<%url%>' target='_blank' title='<%description%>'><%owner%>: <%title%></a></li>");
		$this->createOption('tplFooter','Footer','textarea','</ul>');
		$this->createOption('tplEmpty',"'No items available' message",'textarea',"<p>No items available</p>");
    	$this->createOption('tplBoxFooter','Box Footer','textarea',"</div>");

    	$this->createOption('showErrors','Show errors','yesno','no');
	} 
	 
	function doSkinVar($skinType) {

		/* Get the data from the cache */
		$output = array (
			'type' => 'aggregate',
			'items' => array ()
		);		
		
		if ($this->opml)
		{
			$opml = $this->XMLSupport->createOPMLParser();
			$opml->setError($this->showErrors);
			$opml->setDebug($this->showDebug);
			$feeds = $opml->readFile($this->opmlFilename);
			
			if (isset($feeds['feeds']))
			{
				while (list(,$v) = each($feeds['feeds']))
				{
					$feed = $this->XMLSupport->createRSSAtomParser();
					$feed->setError($this->showErrors);
					$feed->setDebug($this->showDebug);
					$feeddata = $feed->readURL (trim($v['feed']));
	
					if (count($feeddata['items']))
					{
						while (list($k,) = each ($feeddata['items']))
							$feeddata['items'][$k]['owner'] = trim($v['owner']);
						
						$output['items'] = array_merge($output['items'], $feeddata['items']);
					}
				}
			}

			if (isset($feeds['title']))
				$output['title'] = trim($feeds['title']);
			else
				$output['title'] = trim($this->defaultTitle);
		}
		else
		{
			$feeds = split ("(\n|\r)", $this->defaultFeeds);
			while (list(,$v) = each ($feeds))
			{
				list($feedtitle, $feedurl) = explode('|', $v);

				$feed = $this->XMLSupport->createRSSAtomParser();
				$feed->setError($this->showErrors);
				$feed->setDebug($this->showDebug);
				$feed->setFolder($this->cacheFolder);
				$feed->setTTL($this->cacheTTL);
				$feeddata = $feed->readURL (trim($feedurl));
				
				if (count($feeddata['items']))
				{
					while (list($k,) = each ($feeddata['items']))
						$feeddata['items'][$k]['owner'] = trim($feedtitle);
					
					$output['items'] = array_merge($output['items'], $feeddata['items']);
				}
			}

			$output['title'] = trim($this->defaultTitle);
		}

		// Output
		$noItems = is_array($output['items']) ? count($output['items']) : 0;

		if ($noItems > 0) 
		{
			usort($output['items'], array($this,"_sort_output"));
			$output['items'] = array_slice($output['items'], 0, $this->defaultCount);
			$noItems = count($output['items']);
		}

	
		if ($noItems > 0 || $this->showEmpty) 
		{
			$aGeneralVars = array (
				'title' => $output['title']
			);

			echo TEMPLATE::fill($this->getOption('tplBoxHeader'), $aGeneralVars);
			echo TEMPLATE::fill($this->getOption('tplTitle'), $aGeneralVars);

			if ($noItems > 0)
			{
				echo TEMPLATE::fill($this->getOption('tplHeader'), $aGeneralVars);
				
				while (list($k,$v) = each ($output['items']))
				{
					if (isset($v['href']))
					{
						$aVars = array (
							'url' 			=> $v['href'],
							'title' 		=> $this->_cut_string($v['title']),
							'description' 	=> $this->_strip_newline($v['title']),
							'date' 			=> $v['date'],
							'bidi' 			=> $v['bidi'],
							'owner' 		=> $v['owner']
						);
						
						echo TEMPLATE::fill($this->getOption('tplItem'), $aVars);
					}
				}
				
				echo TEMPLATE::fill($this->getOption('tplFooter'), $aGeneralVars);
			}
			else
			{
				echo TEMPLATE::fill($this->getOption('tplEmpty'), $aGeneralVars);
			}
			
			echo TEMPLATE::fill($this->getOption('tplBoxFooter'), $aGeneralVars);
		}
	}
	
	function _sort_output($a, $b) {
	   if ($a['date'] == $b['date']) return 0;
	   return ($a['date'] > $b['date']) ? -1 : 1;
	}

	function _cut_string($string) {
	
		if ($this->defaultLength < 1)
			return $string;

		$i        = 0;
		$count    = 0;
		$ent_mode = false;
		$output   = '';

		while ($i < strlen($string) && $count <= $this->defaultLength)
		{
			$char = substr($string, $i, 1);
			if ($ent_mode == false && $char == '&') $ent_mode = true;
			if ($ent_mode == true && $char == ';') $ent_mode = false;
			if ($ent_mode == false) $count++;
			if ($char == ' ' && $count >= $this->defaultLength - 10) break;
			$output .= $char;
			$i++;
		}
		
		if (strlen($string) != strlen($output)) $output .= '...';
	
		return ($output);
	}
	
	function _strip_newline($string) {
		return preg_replace( "/(\r\n|\n|\r)/", " ", $string );    
	}
}

?>