1<?php 2/** 3 * Utilities for collecting data from config files 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Harry Fuecks <hfuecks@gmail.com> 7 * @author Andreas Gohr <andi@splitbrain.org> 8 */ 9 10 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 11 12 require_once(DOKU_INC.'inc/confutils.php'); 13 require_once(DOKU_INC.'inc/pageutils.php'); 14 require_once(DOKU_INC.'inc/pluginutils.php'); 15 16/** 17 * Returns the parsed Wikitext in XHTML for the given id and revision. 18 * 19 * If $excuse is true an explanation is returned if the file 20 * wasn't found 21 * 22 * @author Andreas Gohr <andi@splitbrain.org> 23 */ 24function p_wiki_xhtml($id, $rev='', $excuse=true){ 25 $file = wikiFN($id,$rev); 26 $ret = ''; 27 28 //ensure $id is in global $ID (needed for parsing) 29 global $ID; 30 $ID = $id; 31 32 if($rev){ 33 if(@file_exists($file)){ 34 $ret = p_render('xhtml',p_get_instructions(io_readfile($file)),$info); //no caching on old revisions 35 }elseif($excuse){ 36 $ret = p_locale_xhtml('norev'); 37 } 38 }else{ 39 if(@file_exists($file)){ 40 $ret = p_cached_xhtml($file); 41 }elseif($excuse){ 42 $ret = p_locale_xhtml('newpage'); 43 } 44 } 45 46 return $ret; 47} 48 49/** 50 * Returns the specified local text in parsed format 51 * 52 * @author Andreas Gohr <andi@splitbrain.org> 53 */ 54function p_locale_xhtml($id){ 55 //fetch parsed locale 56 $html = p_cached_xhtml(localeFN($id)); 57 return $html; 58} 59 60/** 61 * Returns the given file parsed to XHTML 62 * 63 * Uses and creates a cachefile 64 * 65 * @author Andreas Gohr <andi@splitbrain.org> 66 * @todo rewrite to use mode instead of hardcoded XHTML 67 */ 68function p_cached_xhtml($file){ 69 global $conf; 70 $cache = getCacheName($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.xhtml'); 71 $purge = $conf['cachedir'].'/purgefile'; 72 73 // check if cache can be used 74 $cachetime = @filemtime($cache); // 0 if not exists 75 76 if( @file_exists($file) // does the source exist 77 && $cachetime > @filemtime($file) // cache is fresh 78 && ((time() - $cachetime) < $conf['cachetime']) // and is cachefile young enough 79 && !isset($_REQUEST['purge']) // no purge param was set 80 && ($cachetime > @filemtime($purge)) // and newer than the purgefile 81 && ($cachetime > @filemtime(DOKU_INC.'conf/dokuwiki.php')) // newer than the config file 82 && ($cachetime > @filemtime(DOKU_INC.'conf/local.php')) // newer than the local config file 83 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/xhtml.php')) // newer than the renderer 84 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/parser.php')) // newer than the parser 85 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/handler.php')))// newer than the handler 86 { 87 //well then use the cache 88 $parsed = io_readfile($cache); 89 $parsed .= "\n<!-- cachefile $cache used -->\n"; 90 }else{ 91 $parsed = p_render('xhtml', p_cached_instructions($file),$info); //try to use cached instructions 92 93 if($info['cache']){ 94 io_saveFile($cache,$parsed); //save cachefile 95 $parsed .= "\n<!-- no cachefile used, but created -->\n"; 96 }else{ 97 @unlink($cache); //try to delete cachefile 98 $parsed .= "\n<!-- no cachefile used, caching forbidden -->\n"; 99 } 100 } 101 102 return $parsed; 103} 104 105/** 106 * Returns the render instructions for a file 107 * 108 * Uses and creates a serialized cache file 109 * 110 * @author Andreas Gohr <andi@splitbrain.org> 111 */ 112function p_cached_instructions($file,$cacheonly=false){ 113 global $conf; 114 $cache = getCacheName($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.i'); 115 116 // check if cache can be used 117 $cachetime = @filemtime($cache); // 0 if not exists 118 119 // cache forced? 120 if($cacheonly){ 121 if($cachetime){ 122 return unserialize(io_readfile($cache)); 123 }else{ 124 return array(); 125 } 126 } 127 128 if( @file_exists($file) // does the source exist 129 && $cachetime > @filemtime($file) // cache is fresh 130 && !isset($_REQUEST['purge']) // no purge param was set 131 && ($cachetime > @filemtime(DOKU_INC.'conf/dokuwiki.php')) // newer than the config file 132 && ($cachetime > @filemtime(DOKU_INC.'conf/local.php')) // newer than the local config file 133 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/parser.php')) // newer than the parser 134 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/handler.php')))// newer than the handler 135 { 136 //well then use the cache 137 return unserialize(io_readfile($cache)); 138 }elseif(@file_exists($file)){ 139 // no cache - do some work 140 $ins = p_get_instructions(io_readfile($file)); 141 io_savefile($cache,serialize($ins)); 142 return $ins; 143 } 144 145 return NULL; 146} 147 148/** 149 * turns a page into a list of instructions 150 * 151 * @author Harry Fuecks <hfuecks@gmail.com> 152 * @author Andreas Gohr <andi@splitbrain.org> 153 */ 154function p_get_instructions($text){ 155 156 $modes = p_get_parsermodes(); 157 158 // Create the parser 159 $Parser = & new Doku_Parser(); 160 161 // Add the Handler 162 $Parser->Handler = & new Doku_Handler(); 163 164 //add modes to parser 165 foreach($modes as $mode){ 166 $Parser->addMode($mode['mode'],$mode['obj']); 167 } 168 169 // Do the parsing 170 $p = $Parser->parse($text); 171// dbg($p); 172 return $p; 173} 174 175/** 176 * returns all available parser syntax modes in correct order 177 * 178 * @author Andreas Gohr <andi@splitbrain.org> 179 */ 180function p_get_parsermodes(){ 181 global $conf; 182 183 //reuse old data 184 static $modes = null; 185 if($modes != null){ 186 return $modes; 187 } 188 189 //import parser classes and mode definitions 190 require_once DOKU_INC . 'inc/parser/parser.php'; 191 192 // we now collect all syntax modes and their objects, then they will 193 // be sorted and added to the parser in correct order 194 $modes = array(); 195 196 // add syntax plugins 197 $pluginlist = plugin_list('syntax'); 198 if(count($pluginlist)){ 199 global $PARSER_MODES; 200 $obj = null; 201 foreach($pluginlist as $p){ 202 plugin_load('syntax',$p,$obj); //load plugin into $obj 203 $PARSER_MODES[$obj->getType()][] = "plugin_$p"; //register mode type 204 //add to modes 205 $modes[] = array( 206 'sort' => $obj->getSort(), 207 'mode' => "plugin_$p", 208 'obj' => $obj, 209 ); 210 } 211 } 212 213 // add default modes 214 $std_modes = array('listblock','preformatted','notoc','nocache', 215 'header','table','linebreak','footnote','hr', 216 'unformatted','php','html','code','file','quote', 217 'multiplyentity','quotes','internallink','rss', 218 'media','externallink','emaillink','windowssharelink', 219 'eol'); 220 foreach($std_modes as $m){ 221 $class = "Doku_Parser_Mode_$m"; 222 $obj = new $class(); 223 $modes[] = array( 224 'sort' => $obj->getSort(), 225 'mode' => $m, 226 'obj' => $obj 227 ); 228 } 229 230 // add formatting modes 231 $fmt_modes = array('strong','emphasis','underline','monospace', 232 'subscript','superscript','deleted'); 233 foreach($fmt_modes as $m){ 234 $obj = new Doku_Parser_Mode_formatting($m); 235 $modes[] = array( 236 'sort' => $obj->getSort(), 237 'mode' => $m, 238 'obj' => $obj 239 ); 240 } 241 242 // add modes which need files 243 $obj = new Doku_Parser_Mode_smiley(array_keys(getSmileys())); 244 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'smiley','obj' => $obj ); 245 $obj = new Doku_Parser_Mode_acronym(array_keys(getAcronyms())); 246 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'acronym','obj' => $obj ); 247 $obj = new Doku_Parser_Mode_entity(array_keys(getEntities())); 248 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'entity','obj' => $obj ); 249 250 251 // add optional camelcase mode 252 if($conf['camelcase']){ 253 $obj = new Doku_Parser_Mode_camelcaselink(); 254 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'camelcaselink','obj' => $obj ); 255 } 256 257 //sort modes 258 usort($modes,'p_sort_modes'); 259 260 return $modes; 261} 262 263/** 264 * Callback function for usort 265 * 266 * @author Andreas Gohr <andi@splitbrain.org> 267 */ 268function p_sort_modes($a, $b){ 269 if($a['sort'] == $b['sort']) return 0; 270 return ($a['sort'] < $b['sort']) ? -1 : 1; 271} 272 273/** 274 * Renders a list of instruction to the specified output mode 275 * 276 * In the $info array are informations from the renderer returned 277 * 278 * @author Harry Fuecks <hfuecks@gmail.com> 279 * @author Andreas Gohr <andi@splitbrain.org> 280 */ 281function p_render($mode,$instructions,& $info){ 282 if(is_null($instructions)) return ''; 283 284 // Create the renderer 285 if(!@file_exists(DOKU_INC."inc/parser/$mode.php")){ 286 msg("No renderer for $mode found",-1); 287 return null; 288 } 289 290 require_once DOKU_INC."inc/parser/$mode.php"; 291 $rclass = "Doku_Renderer_$mode"; 292 $Renderer = & new $rclass(); #FIXME any way to check for class existance? 293 294 $Renderer->smileys = getSmileys(); 295 $Renderer->entities = getEntities(); 296 $Renderer->acronyms = getAcronyms(); 297 $Renderer->interwiki = getInterwiki(); 298 #$Renderer->badwords = getBadWords(); 299 300 // Loop through the instructions 301 foreach ( $instructions as $instruction ) { 302 // Execute the callback against the Renderer 303 call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]); 304 } 305 306 //set info array 307 $info = $Renderer->info; 308 309 // Return the output 310 return $Renderer->doc; 311} 312 313/** 314 * Gets the first heading from a file 315 * 316 * @author Jan Decaluwe <jan@jandecaluwe.com> 317 */ 318function p_get_first_heading($id){ 319 $file = wikiFN($id); 320 if (@file_exists($file)) { 321 $instructions = p_cached_instructions($file,true); 322 foreach ( $instructions as $instruction ) { 323 if ($instruction[0] == 'header') { 324 return $instruction[1][0]; 325 } 326 } 327 } 328 return NULL; 329} 330 331//Setup VIM: ex: et ts=2 enc=utf-8 : 332