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