1<?php 2 3/** 4 * Info Alphaindex: Displays the alphabetical index of a specified namespace. 5 * 6 * Version: 1.2 7 * last modified: 2006-06-14 12:00:00 8 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 9 * @author Hubert Molière <hubert.moliere@alternet.fr> 10 * Modified by Nicolas H. <prog@a-et-n.com> 11 * Modified by Jonesy <jonesy@oryma.org> 12 * Modified by Samuele Tognini <samuele@netsons.org> 13 */ 14 15if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 16if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 17require_once(DOKU_PLUGIN.'syntax.php'); 18require_once(DOKU_INC.'inc/search.php'); 19 20/** 21 * All DokuWiki plugins to extend the parser/rendering mechanism 22 * need to inherit from this class 23 */ 24class syntax_plugin_alphaindex extends DokuWiki_Syntax_Plugin { 25 26 function getType(){ return 'substition';} 27 28 function getAllowedTypes() { return array('baseonly', 'substition', 'formatting', 'paragraphs', 'protected'); } 29 30 function getPType() { return 'block'; } 31 32 /** 33 * Where to sort in? 34 */ 35 function getSort(){ 36 return 139; 37 } 38 39 /** 40 * Connect pattern to lexer 41 */ 42 function connectTo($mode) { 43 $this->Lexer->addSpecialPattern('{{alphaindex>.+?}}',$mode,'plugin_alphaindex'); 44 } 45 46 /** 47 * Handle the match 48 */ 49 function handle($match, $state, $pos, Doku_Handler $handler){ 50 $level = 0; 51 $nons = true; 52 $match = substr($match, 13, -2); 53 54 // split namespaces 55 $match = preg_split('/\|/u', $match, 2); 56 57 // split level 58 $ns_opt = preg_split('/\#/u', $match[0], 2); 59 60 // namespace name 61 $ns = $ns_opt[0]; 62 63 // add @NS@ option 64 if(empty($ns) || $ns == '@NS@') { 65 $pos = strrpos($ID,':'); 66 if($pos != false){ 67 $ns = substr($ID,0,$pos); 68 } else { 69 $ns = '.'; 70 } 71 } 72 73 // level; 74 if (is_numeric($ns_opt[1])) { 75 $level = $ns_opt[1]; 76 } 77 78 $match = explode(" ", $match[1]); 79 80 // namespaces option 81 $nons = in_array('nons', $match); 82 83 // multi-columns option 84 $incol = in_array('incol', $match); 85 86 return array($ns, array('level' => $level, 'nons' => $nons, 'incol' => $incol)); 87 } 88 89 /** 90 * Render output 91 */ 92 function render($mode, Doku_Renderer $renderer, $data) { 93 global $conf; 94 95 if($mode == 'xhtml'){ 96 $alpha_data = $this->_alpha_index($data, $renderer); 97 if ((!@$n)) { 98 if ($this->getConf('empty_msg')) { 99 $n = $this->getConf('empty_msg'); 100 } else { 101 $n = 'No index for <b>{{ns}}</b>'; 102 } 103 } 104 105 $alpha_data = str_replace('{{ns}}', cleanID($data[0]), $alpha_data); 106 107 $alpha_data = p_render('xhtml', p_get_instructions($alpha_data), $info); 108 109 // remove toc, section edit buttons and category tags 110 $patterns = array('!<div class="toc">.*?(</div>\n</div>)!s', 111 '#<!-- SECTION \[(\d*-\d*)\] -->#e', 112 '!<div class="category">.*?</div>!s'); 113 $replace = array('','',''); 114 $alpha_data = preg_replace($patterns, $replace, $alpha_data); 115 $renderer->doc .= '<div id="alphaindex_content">' ; 116 $renderer->doc .= $ns_data; 117 $renderer->doc .= '<hr />'; 118 $renderer->doc .= $alpha_data; 119 $renderer->doc .= '</div>' ; 120 return true; 121 } 122 123 return false; 124 } 125 126 /** 127 * Return the alphabetical index 128 * @author Hubert MOLIERE <hubert.moliere@alternet.fr> 129 * 130 * This function is a hack of Indexmenu _tree_menu($ns) 131 * @author Samuele Tognini <samuele@samuele.netsons.org> 132 * 133 * This function is a simple hack of DokuWiki html_index($ns) 134 * @author Andreas Gohr <andi@splitbrain.org> 135 */ 136 function _alpha_index($myns, &$renderer) { 137 global $conf; 138 global $ID; 139 140 $ns = $myns[0]; 141 $opts = $myns[1]; 142 143 // Articles deletion configuration 144 $articlesDeletionPatterns = array(); 145 if($this->getConf('articles_deletion')) { 146 $articlesDeletionPatterns = explode('|', $this->getConf('articles_deletion')); 147 $articlesDeletion = true; 148 } else { 149 $articlesDeletion = false; 150 } 151 152 // Hide pages configuration 153 $hidepages = array(); 154 if($this->getConf('hidepages')) { 155 $hidepages = explode('|', $this->getConf('hidepages')); 156 } 157 158 // template configuration 159 if($this->getConf('title_tpl')) { 160 $titleTpl = $this->getConf('title_tpl'); 161 } else { 162 $titleTpl = '===== Index ====='; 163 } 164 165 if($this->getConf('begin_letter_tpl')) { 166 $beginLetterTpl = $this->getConf('begin_letter_tpl'); 167 } else { 168 $beginLetterTpl = '==== {{letter}} ===='; 169 } 170 171 if($this->getConf('entry_tpl')) { 172 $entryTpl = $this->getConf('entry_tpl'); 173 } else { 174 $entryTpl = ' * [[{{link}}|{{name}}]]'; 175 } 176 177 if($this->getConf('end_letter_tpl')) { 178 $endLetterTpl = $this->getConf('end_letter_tpl'); 179 } else { 180 $endLetterTpl = ''; 181 } 182 183 if($ns == '.') { 184 $ns = dirname(str_replace(':','/',$ID)); 185 if ($ns == '.') $ns = ''; 186 } else { 187 $ns = cleanID($ns); 188 } 189 190 $ns = utf8_encodeFN(str_replace(':','/',$ns)); 191 $data = array(); 192 // Searches for files below the given datadir and calls for every file the function alphaindex_search_index 193 search($data, $conf['datadir'], 'alphaindex_search_index', $opts, "/" . $ns); 194 195 $nb_data = count($data); 196 $alpha_data = array(); 197 198 // alphabetical ordering 199 for($cpt = 0; $cpt <$nb_data; $cpt++) { 200 $tmpData = $data[$cpt]['id']; 201 202 $pos = strrpos(utf8_decode($tmpData), ':'); 203 if($conf['useheading']) { 204 $pageName = p_get_first_heading($tmpData); 205 206 if($pageName == NULL) { 207 if($pos != FALSE) { 208 $pageName = utf8_substr($tmpData, $pos+1, utf8_strlen($tmpData)); 209 } else { 210 $pageName = $tmpData; 211 } 212 $pageName = str_replace('_', ' ', $pageName); 213 } 214 } else { 215 if($pos != FALSE) { 216 $pageName = utf8_substr($tmpData, $pos+1, utf8_strlen($tmpData)); 217 } else { 218 $pageName = $tmpData; 219 } 220 221 $pageName = str_replace('_', ' ', $pageName); 222 } 223 $pageNameArticle = ''; 224 225 // if the current page is not a page to hide 226 if(!in_array($pageName, $hidepages)) { 227 // Articles deletion 228 if($articlesDeletion) { 229 foreach($articlesDeletionPatterns as $pattern) { 230 if(eregi($pattern, $pageName, $result)) { 231 $pageName = eregi_replace($pattern, '', $pageName); 232 $pageNameArticle = ucfirst(trim($result[0])); 233 } 234 } 235 } 236 237 // Fix for useheading - Decide if the heading is used or the pagename 238 if($this->getConf('metadata_title')) { 239 $tmp = p_get_metadata($data[$cpt]['id']); 240 if(isset($tmp['title'])) $pageName = $tmp['title']; 241 } 242 243 // R�cup�ration de la premi�re lettre du mot et classement 244 $firstLetter = utf8_deaccent(utf8_strtolower(utf8_substr($pageName, 0, 1))); 245 246 if(is_numeric($firstLetter)) { 247 if($this->getConf('numerical_index')) { 248 $firstLetter = $this->getConf('numerical_index'); 249 } else { 250 $firstLetter = '0-9'; 251 } 252 } 253 254 if($this->getConf('articles_moving')) { 255 $articleMoving = $this->getConf('articles_moving'); 256 } else { 257 $articleMoving = 1; 258 } 259 if($articleMoving == 0) { 260 $pageName = $pageNameArticle.' '.$pageName; 261 } else if (($articleMoving == 1)&&($pageNameArticle != '')) { 262 $pageName = $pageName.' ('.$pageNameArticle.')'; 263 } 264 265 $data[$cpt]['id2'] = ucfirst($pageName); 266 $alpha_data[$firstLetter][] = $data[$cpt]; 267 } 268 } 269 270 // array sorting by key 271 ksort($alpha_data); 272 273 // Display of results 274 275 // alphabetical index 276 $alphaOutput .= $titleTpl . "\n"; 277 $nb_data = count($alpha_data); 278 279 foreach($alpha_data as $key => $currentLetter) { 280 // Sorting of $currentLetter array 281 usort($currentLetter, create_function('$a, $b', "return strnatcasecmp(\$a['id2'], \$b['id2']);")); 282 283 $begin = str_replace("{{letter}}" ,utf8_strtoupper($key), $beginLetterTpl); 284 $alphaOutput .= $begin."\n"; 285 foreach($currentLetter as $currentLetterEntry) { 286 $link = str_replace("{{link}}" ,$currentLetterEntry['id'], $entryTpl); 287 $alphaOutput .= str_replace("{{name}}" ,$currentLetterEntry['id2'], $link); 288 $alphaOutput .= "\n"; 289 } 290 291 $end = str_replace("{{letter}}" ,utf8_strtoupper($key), $endLetterTpl); 292 $alphaOutput .= $end."\n"; 293 } 294 295 return $alphaOutput; 296 } 297 298} // Alphaindex class end 299 300/** 301 * Build the browsable index of pages 302 * 303 * $opts['ns'] is the current namespace 304 * 305 * @author Andreas Gohr <andi@splitbrain.org> 306 * modified by Samuele Tognini <samuele@samuele.netsons.org> 307 */ 308function alphaindex_search_index(&$data, $base, $file, $type, $lvl, $opts) { 309 $return = true; 310 $item = array(); 311 312 if($type == 'd'){ 313 if ($opts['level'] == $lvl) $return = false; 314 if ($opts['nons']) return $return; 315 }elseif($type == 'f' && !preg_match('#\.txt$#',$file)){ 316 // don't add the page 317 return false; 318 } 319 320 $id = pathID($file); 321 322 // check hidden 323 if($type=='f' && isHiddenPage($id)){ 324 return false; 325 } 326 327 // check ACL 328 if($type == 'f' && auth_quickaclcheck($id) < AUTH_READ) { 329 return false; 330 } 331 332 // Set all pages at first level 333 if ($opts['nons']) { 334 $lvl = 1; 335 } 336 337 $data[] = array( 'id' => $id, 338 'type' => $type, 339 'level' => $lvl, 340 'open' => $return); 341 342 return $return; 343}