1<?php
2/**
3 * User Subscriptions Plugin: allows connected user to see which pages / namespaces he have subscribed to and to subscribe or unsubscribe in a quick way
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Etienne Meleard <etienne.meleard@free.fr>
7 *
8 * 2009/01/23 : Creation
9 * 2009/01/26 : inherited subscription display option added, recursive parent subscription check fixed
10 * 2009/01/27 : Added ACL check for quick subscribe dropdown filling
11 */
12
13if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
14if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
15require_once(DOKU_PLUGIN.'syntax.php');
16
17/**
18 * All DokuWiki plugins to extend the parser/rendering mechanism
19 * need to inherit from this class
20 */
21class syntax_plugin_usersubscriptions extends DokuWiki_Syntax_Plugin {
22
23	/**
24	 * return some info
25	 */
26	function getInfo(){
27		return confToHash(dirname(__FILE__).'/INFO');
28	}
29
30	function getType(){ return 'substition';}
31	function getSort(){ return 167; }
32
33	/**
34	 * Connect pattern to lexer
35	 */
36	function connectTo($mode){
37		$this->Lexer->addSpecialPattern('<usersubscriptions [^/]*/>', $mode, 'plugin_usersubscriptions');
38	}
39
40	/**
41	 * Handle the match
42	 */
43	function handle($match, $state, $pos, &$handler) {
44		$match = strtolower(trim(substr($match, 19, -2)));
45		$options = preg_split('/\s/u', $match);
46		$recursive = false;
47		$deletelink = false;
48		$quicksubscribe = false;
49		$displayinheritedsubscriptions = false;
50		$ns = '';
51		if(count($options) > 0) {
52			$ns = trim($options[0]);
53			if(count($options) > 1) {
54				$os = array_slice($options, 1);
55				$opts = array();
56				for($i=0; $i<count($os); $i++) {
57					$o = explode('=', $os[$i]);
58					$opts[$o[0]] = isset($o[1]) ? $o[1] : true;;
59				}
60				$recursive = isset($opts['r']) ? $opts['r'] : 0;
61				if(!is_numeric($recursive)) $recursive = -2;
62				$deletelink = isset($opts['deletelink']);
63				$quicksubscribe = isset($opts['quicksubscribe']);
64				$displayinheritedsubscriptions = isset($opts['displayinheritedsubscriptions']);
65			}
66		}
67		return array($ns, $recursive, $deletelink, $quicksubscribe, $displayinheritedsubscriptions);
68	}
69
70	/**
71	 * Create output
72	 */
73	function render($mode, &$renderer, $data) {
74		global $INFO;
75
76		// prevent caching to ensure the subscriptions list is fresh
77		$renderer->info['cache'] = false;
78
79		if(($mode == 'xhtml') && isset($INFO['userinfo'])) {
80			global $ID;
81
82			$ns = $data[0];
83			$recursive = $data[1];
84			$deletelink = $data[2];
85			$quicksubscribe = $data[3];
86			$displayinheritedsubscriptions = $data[4];
87
88			$status = '';
89
90			// check if user requested a subscription deletion
91			if($unsubscribe = $_REQUEST['pluginusersubscriptions_unsubscribe']) {
92				// user chooses to unsubscribe -> update mlist file
93				list($type, $id) = preg_split('/-/u', $unsubscribe, 2);
94				if($type == 'pg') {
95					$file = metaFN($id, '.mlist');
96				}else{
97					if(!getNS($id)) {
98						$file = metaFN(getNS($id), '.mlist');
99					}else{
100						$file = metaFN(getNS($id), '/.mlist');
101					}
102				}
103				if(@file_exists($file)) {
104					$status = io_deleteFromFile($file, $INFO['client']."\n") ? 'success' : 'failure';
105				}
106			}
107
108			// check if user requested a new subscription
109			if($subscribe = $_REQUEST['pluginusersubscriptions_subscribe']) {
110				if($subscribe != '') {
111					// user chooses to subscribe -> update mlist file
112					list($type, $id) = preg_split('/-/u', $subscribe, 2);
113					if(auth_quickaclcheck($id) >= AUTH_READ) {
114						if($type == 'pg') {
115							$file = metaFN($id, '.mlist');
116							$update = !is_subscribed($id, $INFO['client'], false);
117						}else{
118							$file = metaFN($id, '/.mlist');
119							$update = !is_subscribed($id.':', $INFO['client'], true);
120						}
121						if($update) {
122							$status = io_saveFile($file, $INFO['client']."\n", @file_exists($file)) ? 'success' : 'failure';
123						}
124					}
125				}
126			}
127
128			// output the list
129
130			if($ns == '' || $ns == '.') {
131				$nss = $this->getLang('current_namespace');
132				$ns = getNS($ID);
133			}else if($ns == '*') {
134				$nss = $this->getLang('all_namespaces');
135				$ns = '';
136			}else $nss = $this->getLang('the_namespace').' '.$fmtns;
137
138			// get subscriptions
139			$elements = array();
140
141			$elements = $this->_getUserSubscriptions($ns, $recursive);
142			ksort($elements);
143
144			$tius = false;
145			$usersubscriptions = array();
146			foreach($elements as $id => $info) {
147				$info['inheritedsubscription'] = $info['subscribedfromparent'] && !$info['selfsubscribed'];
148
149				$info['deleteoption'] = $info['selfsubscribed'] && $deletelink;
150				$info['display'] = $info['usersubscribed'] && ($displayinheritedsubscriptions || (!$displayinheritedsubscriptions && $info['selfsubscribed']));
151				$id = preg_replace('/:$/', '', $id);
152 				$usersubscriptions[$id] = $info;
153 			}
154
155			ob_start();
156 			if(file_exists(DOKU_TPLINC.'usersubscriptions.tpl.php')) include DOKU_TPLINC.'usersubscriptions.tpl.php';
157 			else include DOKU_PLUGIN.'usersubscriptions/usersubscriptions.tpl.php';
158			$content = ob_get_contents();
159			ob_end_clean();
160			$renderer->doc .= $content;
161
162 			return true;
163 		}
164     	return false;
165	}
166
167	function _getUserSubscriptions($ns, $recursive, $lvl=0, $nss=false) {
168		global $INFO;
169		$us = array();
170		$exclude = array(
171			'`\_+template\.txt:?$`',
172			'`sidebar\.txt:?$`'
173		);
174		$isns = !preg_match('/\.txt:$/', $ns);
175		foreach($exclude as $r) if(preg_match($r, $ns)) return $us;
176		if(auth_quickaclcheck($ns) < AUTH_READ) return $us;
177		$cns = preg_replace('/\.txt:$/', '', $ns);
178		$s = is_subscribed($cns, $INFO['client'], false);
179		$sns = is_subscribed($cns, $INFO['client'], true);
180		$us[$cns] = array(
181			'isnamespace' => $isns,
182			'usersubscribed' => ($s || $sns || $nss),
183			'selfsubscribed' => ($isns && $sns) || (!$isns && $s),
184			'subscribedfromparent' => (!$isns && $sns) || $nss,
185			'lvl' => $lvl
186		);
187		if($ns == $cns) {
188			foreach(new DirectoryIterator(preg_replace('/\.txt$/', '', wikiFN($cns))) as $item) {
189				if(!$item->isDot() && ($recursive != -1)) {
190					$scns = strtolower($cns.$item->getFilename().':');
191					if($item->isFile() && !preg_match('/\.txt:?$/', $scns)) continue;
192					$us = array_merge($us, $this->_getUserSubscriptions($scns, $recursive-1, $lvl+1, $nss || ($sns && !$s)));
193				}
194			}
195		}
196		return $us;
197	}
198}
199
200?>
201