1<?php 2/** 3 * DokuWiki Plugin tagfilter (Syntax Component) 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author lisps 7 */ 8 9/* 10 * All DokuWiki plugins to extend the parser/rendering mechanism 11 * need to inherit from this class 12 */ 13class syntax_plugin_tagfilter_filter extends DokuWiki_Syntax_Plugin { 14 15 private $_itemPos = array(); 16 function incItemPos() { 17 global $ID; 18 if(array_key_exists($ID,$this->_itemPos)) { 19 return $this->_itemPos[$ID]++; 20 } else { 21 $this->_itemPos[$ID] = 1; 22 return 0; 23 } 24 } 25 function getItemPos(){ 26 global $ID; 27 if(array_key_exists($ID,$this->_itemPos)) { 28 $this->_itemPos[$ID]; 29 } else { 30 return 0; 31 } 32 } 33 34 /* 35 * What kind of syntax are we? 36 */ 37 function getType() {return 'substition';} 38 39 /* 40 * Where to sort in? 41 */ 42 function getSort() {return 155;} 43 44 /* 45 * Paragraph Type 46 */ 47 function getPType(){return 'block';} 48 49 /* 50 * Connect pattern to lexer 51 */ 52 function connectTo($mode) { 53 $this->Lexer->addSpecialPattern("\{\{tagfilter>.*?\}\}",$mode,'plugin_tagfilter_filter'); 54 } 55 56 /* 57 * Handle the matches 58 */ 59 function handle($match, $state, $pos, Doku_Handler $handler) { 60 global $ID; 61 $HtagfilterSyntax = $this->loadHelper('tagfilter_syntax'); 62 $opts['id']=$this->incItemPos(); 63 64 $match=trim(substr($match,12,-2)); 65 66 list($match, $flags) = explode('&', $match, 2); 67 $flags = explode('&', $flags); 68 list($ns, $tag) = explode('?', $match); 69 70 if (!$tag) { 71 $tag = $ns; 72 $ns = ''; 73 } 74 75 if (($ns == '*') || ($ns == ':')) $ns = ''; 76 elseif ($ns == '.') $ns = getNS($ID); 77 else $ns = cleanID($ns); 78 79 $opts['ns']=$ns; 80 81 //only flags for tagfilter 82 $opts['tfFlags'] = $HtagfilterSyntax->parseFlags($flags); 83 84 //all flags for pagelist plugin 85 $opts['flags']=array_map('trim',$flags); 86 87 //read and parse tag 88 $tagselect_r = array(); 89 $select_expr_r = array_map('trim',explode('|',$tag)); 90 foreach($select_expr_r as $key=>$usr_syntax){ 91 $usr_syntax = explode("=",$usr_syntax);//aufsplitten in Label,RegExp,DefaultWert 92 93 $tagselect_r['label'][$key] = trim($usr_syntax[0]); 94 $tagselect_r['tag_expr'][$key] = trim($usr_syntax[1]); 95 $tagselect_r['selectedTags'][$key] = isset($usr_syntax[2])?explode(' ',$usr_syntax[2]):array(); 96 } 97 98 $opts['tagselect_r'] = $tagselect_r; 99 100 return ($opts); 101 } 102 103 /* 104 * Create output 105 */ 106 function render($mode, Doku_Renderer $renderer, $opt) 107 { 108 global $INFO; 109 global $ID; 110 global $INPUT; 111 global $USERINFO; 112 global $conf; 113 /* @var $HtagfilterSyntax helper_plugin_tagfilter_syntax */ 114 $HtagfilterSyntax = $this->loadHelper('tagfilter_syntax'); 115 $flags = $opt['tfFlags']; 116 117 if($mode === 'metadata') return false; 118 if($mode === 'xhtml') { 119 $renderer->info['cache'] = false; 120 121 /* @var $Htagfilter helper_plugin_tagfilter */ 122 $Htagfilter = $this->loadHelper('tagfilter'); 123 $renderer->cdata("\n"); 124 125 126 $depends = array('files'=>array( 127 $INFO['filepath'], 128 DOKU_CONF . '/acl.auth.php', 129 getConfigFiles('main'), 130 )); 131 132 if($flags['cache']){ 133 $depends['age']=$flags['cache']; 134 } else if($flags['cache'] === false){ 135 //build cache dependencies 136 $dir = utf8_encodeFN(str_replace(':','/',$opt['ns'])); 137 $data = array(); 138 search($data,$conf['datadir'],array($HtagfilterSyntax,'search_all_pages'),array('ns' => $opt['ns'],'excludeNs'=>$flags['excludeNs']),$dir); //all pages inside namespace 139 $depends['files'] = array_merge($depends['files'],$data); 140 } else { 141 $depends['purge'] = true; 142 } 143 144 $cache_key = 'plugin_tagfilter_'.$ID . '_' . $opt['id']; 145 $cache = new cache($cache_key, '.tcache'); 146 if(!$cache->useCache($depends)) { 147 $cachedata = $HtagfilterSyntax->getTagPageRelations($opt); 148 $cachedata[] = $HtagfilterSyntax->prepareList($cachedata[1],$flags); 149 $cache->storeCache(serialize($cachedata)); 150 } else { 151 $cachedata = unserialize($cache->retrieveCache()); 152 } 153 154 list($tagselect_r, $pageids, $preparedPages) = $cachedata; 155 156 $cache_u_key = 'plugin_tagfilter_'.$ID . '_' . $opt['id'] . '_' . $_SERVER['REMOTE_USER'].$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT']; 157 $cache_u = new cache($cache_u_key, '.tucache'); 158 159 foreach($pageids as &$pageid) { 160 if(!page_exists($pageid)) { 161 unset($pageid); 162 $cache->removeCache(); 163 $cache_u->removeCache(); 164 } 165 } unset($pageid); 166 167 if(!$cache_u->useCache(array('files'=>array($cache->cache)))) { 168 $output = ''; 169 170 //check for read access 171 foreach($pageids as $key=>$pageid) { 172 if(! $Htagfilter->canRead($pageid)) { 173 unset($pageids[$key]); 174 } 175 } 176 177 //check tags for visibility 178 foreach($tagselect_r['tagPages'] as &$select_r) { 179 if(!is_array($select_r)) $select_r = array(); 180 foreach($select_r as $tag=>$pageid_r) { 181 if(count(array_intersect(($pageid_r), $pageids)) == 0) { 182 unset($select_r[$tag]); 183 } 184 } 185 } 186 187 foreach($preparedPages as $key=>$page) { 188 if(!in_array($page['id'],$pageids)) { 189 unset($preparedPages[$key]); 190 } 191 } 192 193 $form = new Doku_Form(array( 194 'id'=>'tagdd_'.$opt['id'], 195 'data-idx'=>$opt['id'], 196 'data-plugin'=>'tagfilter', 197 'data-tags' => json_encode($tagselect_r['tagPages']), 198 )); 199 $output .= "\n"; 200 //Fieldset manuell hinzufügen da ein style Parameter übergeben werden soll 201 $form->addElement(array( 202 '_elem'=>'openfieldset', 203 '_legend'=>'Tagfilter', 204 'style'=>'text-align:left;width:99%', 205 'id'=>'__tagfilter_'.$opt['id'], 206 'class'=>($flags['labels']!==false)?'':'hidelabel', 207 208 )); 209 $form->_infieldset=true; //Fieldset starten 210 211 if($flags['pagesearch']){ 212 $label = $flags['pagesearchlabel']; 213 214 $pagetitle_r = array(); 215 foreach($pageids as $pageid) { 216 $pagetitle_r[$pageid] = $Htagfilter->getPageTitle($pageid); 217 } 218 asort($pagetitle_r, SORT_NATURAL|SORT_FLAG_CASE); 219 220 $selectedTags = array(); 221 $id = '__tagfilter_page_'.$opt['id']; 222 223 $options = array(//generelle Optionen für DropDownListe onchange->submit von id namespace und den flags für pagelist 224 'onChange'=>'tagfilter_submit('.$opt['id'].','.json_encode($opt['ns']).','.json_encode(array($opt['flags'],$flags)).')', 225 'class'=>'tagdd_select tagfilter tagdd_select_'.$opt['id'] . ($flags['chosen']?' chosen':''), 226 'data-placeholder'=>hsc($label.' '.$this->getLang('choose')), 227 'data-label'=>hsc(utf8_strtolower(trim($label))), 228 ); 229 if($flags['multi']){ //unterscheidung ob Multiple oder Single 230 $options['multiple']='multiple'; 231 $options['size']=$this->getConf("DropDownList_size"); 232 } else { 233 $options['size']=1; 234 $pagetitle_r = array_reverse($pagetitle_r,true); 235 $pagetitle_r['']=''; 236 $pagetitle_r = array_reverse($pagetitle_r,true); 237 } 238 $form->addElement(form_makeListboxField($label, $pagetitle_r, $selectedTags , $label, $id, 'tagfilter', $options)); 239 } 240 $output .= '<script type="text/javascript">/*<![CDATA[*/ var tagfilter_container = {}; /*!]]>*/</script>'."\n"; 241 //$output .= '<script type="text/javascript">/*<![CDATA[*/ '.'tagfilter_container.tagfilter_'.$opt['id'].' = '.json_encode($tagselect_r['tags2']).'; /*!]]>*/</script>'."\n"; 242 foreach($tagselect_r['tagPages'] as $key=>$pages){ 243 $id=false; 244 $label = $tagselect_r['label'][$key]; 245 $selectedTags = $tagselect_r['selectedTags'][$key]; 246 247 //get tag labels 248 $tags = array(); 249 250 foreach(array_keys($tagselect_r['tagPages'][$key]) as $tagid) { 251 $tags[$tagid] = $Htagfilter->getTagLabel($tagid); 252 } 253 254 foreach($selectedTags as &$item) { 255 $item = utf8_strtolower(trim($item)); 256 } unset($item); 257 258 259 $options = array(//generelle Optionen für DropDownListe onchange->submit von id namespace und den flags für pagelist 260 'onChange'=>'tagfilter_submit('.$opt['id'].','.json_encode($opt['ns']).','.json_encode(array($opt['flags'],$flags)).')', 261 'class'=>'tagdd_select tagfilter tagdd_select_'.$opt['id'] . ($flags['chosen']?' chosen':''), 262 'data-placeholder'=>hsc($label.' '.$this->getLang('choose')), 263 'data-label'=>hsc(str_replace(' ','_',utf8_strtolower(trim($label)))), 264 265 ); 266 if($flags['multi']){ //unterscheidung ob Multiple oder Single 267 $options['multiple']='multiple'; 268 $options['size']=$this->getConf("DropDownList_size"); 269 } else { 270 $options['size']=1; 271 $tags = array_reverse($tags,true); 272 $tags['']=''; 273 $tags = array_reverse($tags,true); 274 } 275 276 if($flags['chosen']){ 277 $links = array(); 278 foreach($tags as $k=>$t){ 279 $links[$k]=array( 280 'link'=>$Htagfilter->getImageLinkByTag($k), 281 ); 282 } 283 $jsVar = 'tagfilter_jsVar_'.rand(); 284 $output .= '<script type="text/javascript">/*<![CDATA[*/ tagfilter_container.'.$jsVar.' =' 285 .json_encode($links). 286 '; /*!]]>*/</script>'."\n"; 287 288 $id='__tagfilter_'.$opt["id"].'_'.rand(); 289 290 if($flags['tagimage']){ 291 $options['data-tagimage'] = $jsVar; 292 } 293 294 } 295 $form->addElement(form_makeListboxField($label, $tags, $selectedTags , $label, $id, 'tagfilter' , $options)); 296 } 297 298 $form->addElement(form_makeButton('button','', $this->getLang('Delete filter'), array('onclick'=>'tagfilter_cleanform('.$opt['id'].',true)'))); 299 if($flags['count']) { 300 $form->addElement('<div class="tagfilter_count">'.$this->getLang('found_count').': ' . '<span class="tagfilter_count_number"></span></div>'); 301 } 302 $form->endFieldset(); 303 $output .= $form->getForm();//Form Ausgeben 304 305 $output.= "<div id='tagfilter_ergebnis_".$opt['id']."' class='tagfilter'>"; 306 //dbg($opt['flags']); 307 $output .= $HtagfilterSyntax->renderList($preparedPages,$flags, $opt['flags']); 308 $output.= "</div>"; 309 310 $cache_u->storeCache($output); 311 312 } else { 313 $output =$cache_u->retrieveCache(); 314 } 315 316 $renderer->doc .= $output; 317 } 318 return true; 319 } 320 321 322 323} 324 325//Setup VIM: ex: et ts=4 enc=utf-8 : 326