<?php
/**
 * User Subscriptions Plugin: allows connected user to see which pages / namespaces he have subscribed to and to subscribe or unsubscribe in a quick way
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Etienne Meleard <etienne.meleard@free.fr>
 * 
 * 2009/01/23 : Creation
 * 2009/01/26 : inherited subscription display option added, recursive parent subscription check fixed
 * 2009/01/27 : Added ACL check for quick subscribe dropdown filling
 */
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_usersubscriptions extends DokuWiki_Syntax_Plugin {
	
	/**
	 * return some info
	 */
	function getInfo(){
		return confToHash(dirname(__FILE__).'/INFO');
	}
	
	function getType(){ return 'substition';}
	function getSort(){ return 167; }
	
	/**
	 * Connect pattern to lexer
	 */
	function connectTo($mode){
		$this->Lexer->addSpecialPattern('<usersubscriptions [^/]*/>', $mode, 'plugin_usersubscriptions');
	}

	/**
	 * Handle the match
	 */
	function handle($match, $state, $pos, &$handler) {
		$match = strtolower(trim(substr($match, 19, -2)));
		$options = preg_split('/\s/u', $match);
		$recursive = false;
		$deletelink = false;
		$quicksubscribe = false;
		$displayinheritedsubscriptions = false;
		$ns = '';
		if(count($options) > 0) {
			$ns = trim($options[0]);
			if(count($options) > 1) {
				$os = array_slice($options, 1);
				$opts = array();
				for($i=0; $i<count($os); $i++) {
					$o = explode('=', $os[$i]);
					$opts[$o[0]] = isset($o[1]) ? $o[1] : true;;
				}
				$recursive = isset($opts['r']) ? $opts['r'] : 0;
				if(!is_numeric($recursive)) $recursive = -2;
				$deletelink = isset($opts['deletelink']);
				$quicksubscribe = isset($opts['quicksubscribe']);
				$displayinheritedsubscriptions = isset($opts['displayinheritedsubscriptions']);
			}
		}
		return array($ns, $recursive, $deletelink, $quicksubscribe, $displayinheritedsubscriptions);
	}

	/**
	 * Create output
	 */
	function render($mode, &$renderer, $data) {
		global $INFO;
		
		// prevent caching to ensure the subscriptions list is fresh
		$renderer->info['cache'] = false;
		
		if(($mode == 'xhtml') && isset($INFO['userinfo'])) {
			global $ID;
			
			$ns = $data[0];
			$recursive = $data[1];
			$deletelink = $data[2];
			$quicksubscribe = $data[3];
			$displayinheritedsubscriptions = $data[4];
			
			$status = '';
			
			// check if user requested a subscription deletion
			if($unsubscribe = $_REQUEST['pluginusersubscriptions_unsubscribe']) {
				// user chooses to unsubscribe -> update mlist file
				list($type, $id) = preg_split('/-/u', $unsubscribe, 2);
				if($type == 'pg') {
					$file = metaFN($id, '.mlist');
				}else{
					if(!getNS($id)) {
						$file = metaFN(getNS($id), '.mlist');
					}else{
						$file = metaFN(getNS($id), '/.mlist');
					}
				}
				if(@file_exists($file)) {
					$status = io_deleteFromFile($file, $INFO['client']."\n") ? 'success' : 'failure';
				}
			}
			
			// check if user requested a new subscription
			if($subscribe = $_REQUEST['pluginusersubscriptions_subscribe']) {
				if($subscribe != '') {
					// user chooses to subscribe -> update mlist file
					list($type, $id) = preg_split('/-/u', $subscribe, 2);
					if(auth_quickaclcheck($id) >= AUTH_READ) {
						if($type == 'pg') {
							$file = metaFN($id, '.mlist');
							$update = !is_subscribed($id, $INFO['client'], false);
						}else{
							$file = metaFN($id, '/.mlist');
							$update = !is_subscribed($id.':', $INFO['client'], true);
						}
						if($update) {
							$status = io_saveFile($file, $INFO['client']."\n", @file_exists($file)) ? 'success' : 'failure';
						}
					}
				}
			}	
          
			// output the list
			
			if($ns == '' || $ns == '.') {
				$nss = $this->getLang('current_namespace');
				$ns = getNS($ID);
			}else if($ns == '*') {
				$nss = $this->getLang('all_namespaces');
				$ns = '';
			}else $nss = $this->getLang('the_namespace').' '.$fmtns;
			
			// get subscriptions
			$elements = array();
			
			$elements = $this->_getUserSubscriptions($ns, $recursive);
			ksort($elements);
			
			$tius = false;
			$usersubscriptions = array();
			foreach($elements as $id => $info) {
				$info['inheritedsubscription'] = $info['subscribedfromparent'] && !$info['selfsubscribed'];
				
				$info['deleteoption'] = $info['selfsubscribed'] && $deletelink;
				$info['display'] = $info['usersubscribed'] && ($displayinheritedsubscriptions || (!$displayinheritedsubscriptions && $info['selfsubscribed']));
				$id = preg_replace('/:$/', '', $id);
 				$usersubscriptions[$id] = $info;
 			}
 
			ob_start();
 			if(file_exists(DOKU_TPLINC.'usersubscriptions.tpl.php')) include DOKU_TPLINC.'usersubscriptions.tpl.php';
 			else include DOKU_PLUGIN.'usersubscriptions/usersubscriptions.tpl.php';
			$content = ob_get_contents();
			ob_end_clean();
			$renderer->doc .= $content;

 			return true;
 		}
     	return false;
	}
	
	function _getUserSubscriptions($ns, $recursive, $lvl=0, $nss=false) {
		global $INFO;
		$us = array();
		$exclude = array(
			'`\_+template\.txt:?$`',
			'`sidebar\.txt:?$`'
		);
		$isns = !preg_match('/\.txt:$/', $ns);
		foreach($exclude as $r) if(preg_match($r, $ns)) return $us;
		if(auth_quickaclcheck($ns) < AUTH_READ) return $us;
		$cns = preg_replace('/\.txt:$/', '', $ns);
		$s = is_subscribed($cns, $INFO['client'], false);
		$sns = is_subscribed($cns, $INFO['client'], true);
		$us[$cns] = array(
			'isnamespace' => $isns,
			'usersubscribed' => ($s || $sns || $nss),
			'selfsubscribed' => ($isns && $sns) || (!$isns && $s),
			'subscribedfromparent' => (!$isns && $sns) || $nss,
			'lvl' => $lvl
		);
		if($ns == $cns) {
			foreach(new DirectoryIterator(preg_replace('/\.txt$/', '', wikiFN($cns))) as $item) {
				if(!$item->isDot() && ($recursive != -1)) {
					$scns = strtolower($cns.$item->getFilename().':');
					if($item->isFile() && !preg_match('/\.txt:?$/', $scns)) continue;
					$us = array_merge($us, $this->_getUserSubscriptions($scns, $recursive-1, $lvl+1, $nss || ($sns && !$s)));
				}
			}
		}
		return $us;
	}
}

?>
