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