Location: PHPKode > projects > Gregarius > gregarius/cls/channels.php
<?php
###############################################################################
# Gregarius - A PHP based RSS aggregator.
# Copyright (C) 2003 - 2006 Marco Bonetti
#
###############################################################################
# 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
#
###############################################################################
# E-mail:      mbonetti at gmail dot com
# Web page:    http://gregarius.net/
#
###############################################################################


define('COLLAPSED_FOLDERS_COOKIE', 'collapsedfolders');

/**
 * A FeedListItem object holds a single item in the feeds sidecolumn
 */
class FeedListItem {

	/** Database id (e.g. item.cid, channels.id) for this feed */
	var $id;
	/** Feed title */
	var $title;
	/** URL of this feed */	
	var $url;
	/** URL of this feed, escaped from login/password information, if any */	
	var $publicUrl;
	/** URL of the website publishing this feed */	
	var $siteurl;
	/** Name of the folder holding this feed */	
	var $name;
	/** ID of the folder holding this feed (e.g. channels.parent) */	
	var $parent;
	/** URL of the icon for this feed, probably offsite */	
	var $icon;
	/** The "description" for this feed. (e.g. channel.description) */		
	var $descr = "";
	/** Feed "mode" (e.g. private, deprecated, ...)*/		
	var $mode;
	/** True when the user is reading the current feed in "feed mode" */	
	var $isActiveFeed;
	
	/**
	 * Constructor. Fills in the instance variables, escapes urls accordingly 
	 */
	function FeedListItem($id, $title, $url, $siteurl, $name, $parent, $icon, $descr, $mode, $unreadCount) {
		$this->id = $id;
		$this->title = $title;
		$this->url = $url;
		$this->publicUrl = preg_replace(
			'|(https?://)([^:]+:[^@]+@)(.+)$|','\1\3',$url
		);
		$this->siteurl = $siteurl;
		$this->name = $name;
		$this->parent = $parent;

		
		if ( getConfig('rss.output.showfavicons') && $icon){
			if (substr($icon,0,5) == 'blob:') {
				$this->icon = getPath() . "extlib/favicon.php?url=". rss_real_escape_string(substr($icon,5));
			} else {
				$this->icon = $icon;
			}
		} elseif (getConfig('rss.output.showfavicons')) {
            $this->icon = getExternalThemeFile("media/noicon.png");
		} else {
            $this->icon = false;
		}
		
		$this->descr = $descr;
		$this->mode = $mode;

		if (getConfig('rss.output.usemodrewrite')) {
			$this->rlink = getPath(rss_uri($title)) . "/";
		} else {
			$this->rlink = getPath()."feed.php?channel=$id";
		}


		if ($unreadCount > 0) {
			$this->rdLbl= sprintf(__('<strong id="%s" style="%s">(%d unread)</strong>'), "cid$id","",$unreadCount);
			$this->class_= "feed title unread";
		} else {
			$this->rdLbl= "";
			$this->class_= "feed title";
		}
	}


	/** 
	 * Renders this FeedListItem: Moves the superglobal "current feed" pointer
	 * to this, then includes the relevant template
	 */
	function render() {
		$GLOBALS['rss']->currentFeedsFeed = $this;
		include($GLOBALS['rss'] ->getTemplateFile("feedsfeed.php"));	
	}

}


class FeedFolder {
	var $feeds = array ();
	var $name;
	var $id;
	var $isCollapsed = false;
	var $rlink;
	var $isRootFolder = false;
	var $rootList;
	function FeedFolder($name, $id, &$rootList) {
		$this->name = $name;
		$this->id = $id;
		if (getConfig('rss.output.usemodrewrite')) {
			$this->rlink = $this -> makeFolderUrl($name); // getPath().preg_replace("/[^a-zA-Z0-9_]/", "_", $name)."/";
		} else {
			$this->rlink = getPath()."feed.php?folder=$id";
		}
		$this->isRootFolder = ($id == 0);
		$this->rootList = $rootList;
	}
	
	function makeFolderUrl($fn) {
		return getPath(
			preg_replace('#\s#','_',sanitize($fn,RSS_SANITIZER_URL))
		) .'/';
	}
	
	function render() {
		if ((!getConfig('rss.output.minimalchannellist')) || ($this->feeds)) { 
		 	$GLOBALS['rss']->currentFeedsFolder = $this; 
		 	require($GLOBALS['rss'] ->getTemplateFile("feedsfolder.php")); 
		}
	}
}

class FeedList {

	var $collapsed_folders = array ();
	var $collapsed_ids = array ();
	var $folders = array ();
	var $activeId;
	var $feedCount = 0;
	var $columnTitle;
	var $stats;
	
	function FeedList($activeId) {
		_pf('FeedList() ctor');
		$this ->columnTitle= __('Feeds');
		$this->activeId = $activeId;
		$this->loadCollapsedState();
		$this->populate();
	}
	
	function getStats() {
		_pf('getStats()');
		_pf(' ... unreadCount');

		$unread = getUnreadCount(null, null);
		_pf(' ... done: unreadCount');		

		_pf(' ... totalCount');		
		$sql ="select count(*) from ".getTable("item") . "i " 
			   ."inner join " . getTable('channels') . " c "
         ."  on c.id = i.cid "
				 ." where not(i.unread & ".RSS_MODE_DELETED_STATE.") "
			   ." and not (c.mode & " .RSS_MODE_DELETED_STATE.")"
			. (hidePrivate()? " and not(unread & ".RSS_MODE_PRIVATE_STATE.")":"");
			
			//echo $sql;
			$res = rss_query($sql);
		list ($total) = rss_fetch_row($res);
		_pf(' ... done: totalCount');		
		

		_pf(' ... feedsCount');				
		$res = rss_query("select count(*) from "
			.getTable("channels")." where not(mode & ".RSS_MODE_DELETED_STATE.")"
			. (hidePrivate()? " and not(mode & ".RSS_MODE_PRIVATE_STATE.")":"")
			);
			
		list ($channelcount) = rss_fetch_row($res);
		_pf(' ... done: feedsCount');				
		
		$this ->stats = sprintf(__('<strong>%d</strong> items (<strong id="fucnt">%d</strong> unread) in <strong>%d</strong> feeds'), $total, $unread, $channelcount);
		_pf('done: getStats()');
		return $this -> stats;
	}
	
	
	function loadCollapsedState() {
	    _pf('FeedList->loadCollapsedState()...');
	    
		if (getConfig('rss.output.channelcollapse')) {
	
			//read per-user stored collapsed folders
			if (array_key_exists(COLLAPSED_FOLDERS_COOKIE, $_COOKIE)) {
				$this->collapsed_ids = explode(":", $_COOKIE[COLLAPSED_FOLDERS_COOKIE]);
			}  elseif (empty($this->collapsed_ids) && getConfig("rss.output.channelcollapsedefault")) {
			   // Lets collapse all folders
			   $res = rss_query("select id from " . getTable('folders') . " where id != 0");
			   while (list ($this->collapsed_ids[]) = rss_fetch_row($res)) {}
			   if (!headers_sent()) { // Sajax does not allow us to set cookies
			    setcookie(COLLAPSED_FOLDERS_COOKIE, 
				  implode(":", $this->collapsed_ids ) , time()+COOKIE_LIFESPAN,getPath());
			   }
			}
	
			//get unread count per folder                                                                        
			$sql = "select f.id, f.name, count(*) as cnt "
			." from " .getTable('item') ." i "
			." inner join " . getTable('channels') . " c on c.id = i.cid "
			." inner join " . getTable('folders') ." f on f.id = c.parent "
			." where i.unread & ". RSS_MODE_UNREAD_STATE
			." and not(i.unread & ". RSS_MODE_DELETED_STATE .")";
			if (hidePrivate()) {
				$sql .=" and not(unread & " . RSS_MODE_PRIVATE_STATE .") ";
			}
			$sql .= " and not(c.mode & " . RSS_MODE_DELETED_STATE .") ";
			$sql .= " group by f.id";
	        _pf('query');
			$res = rss_query($sql);
	        _pf('ok');	
			while (list ($cid, $cname, $cuc) = rss_fetch_row($res)) {
				$this->collapsed_folders[$cid] = $cuc;
			}
	       
			sort($this->collapsed_ids);
		}
	    _pf('done');

	}
	
	function getFeedCount() {
		return $this -> feedCount;
	}

	function populate() {
		_pf('FeedList->populate() ...');
		$sql = "select "." c.id, c.title, c.url, c.siteurl, f.name, c.parent, c.icon, c.descr, c.mode "." from ".getTable("channels")." c "
		."inner join " . getTable("folders")." f on f.id = c.parent";

		if (hidePrivate()) {
			$sql .= " and not(c.mode & ".RSS_MODE_PRIVATE_STATE.") ";
		}

		$sql .= " and not(c.mode & ".RSS_MODE_DELETED_STATE.") ";

		if (getConfig('rss.config.absoluteordering')) {
			$sql .= " order by f.position asc, c.position asc";
		} else {
			$sql .= " order by f.name, c.title asc";
		}
		$res = rss_query($sql);
		$this -> feedCount = rss_num_rows($res);
		
		$ucres = rss_query ("select cid, count(*) from " .getTable("item")
        ." where unread & "  . RSS_MODE_UNREAD_STATE
        . " and not(unread & " . RSS_MODE_DELETED_STATE .") group by cid");
		$uc = array();
		while (list($uccid,$ucuc) = rss_fetch_row($ucres)) {
			$uc[$uccid]=$ucuc;
		}
		  
		while (list ($cid, $ctitle, $curl, $csiteurl, $fname, $cparent, $cico, $cdescr, $cmode) = rss_fetch_row($res)) {
			$ucc= 0;
			if (array_key_exists($cid,$uc)) {
				$ucc=$uc[$cid];
			} 
			$f = new FeedListItem($cid, $ctitle, $curl, $csiteurl, $fname, $cparent, $cico, $cdescr, $cmode, $ucc);
			$f -> isActiveFeed = ($this->activeId && $cid == $this->activeId ); 
			if (!array_key_exists($cparent, $this->folders)) {
				$this->folders[$cparent] = new FeedFolder($fname, $cparent,$this);
			}
			//$this->folders[$cparent]->feeds[] = $f;
			if(($ucc != 0) || (!getConfig('rss.output.minimalchannellist'))) { 
			 	$this->folders[$cparent]->feeds[] = $f; 
			}
			$this->folders[$cparent]->isCollapsed = in_array($cparent, $this->collapsed_ids) && ($cparent > 0);

		}
		_pf('done');
	}

	function render() {
		_pf('FeedList->render() ...');
		include($GLOBALS['rss'] ->getTemplateFile("feeds.php"));
		_pf('done');		
	}
}
?>
Return current item: Gregarius