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_CONF.'dokuwiki.php')) // newer than the config file 82 && ($cachetime > @filemtime(DOKU_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_CONF.'dokuwiki.php')) // newer than the config file 132 && ($cachetime > @filemtime(DOKU_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 if(!$obj =& plugin_load('syntax',$p)) continue; //attempt to 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 unset($obj); //remove the reference 211 } 212 } 213 214 // add default modes 215 $std_modes = array('listblock','preformatted','notoc','nocache', 216 'header','table','linebreak','footnote','hr', 217 'unformatted','php','html','code','file','quote', 218 'multiplyentity','quotes','internallink','rss', 219 'media','externallink','emaillink','windowssharelink', 220 'eol'); 221 foreach($std_modes as $m){ 222 $class = "Doku_Parser_Mode_$m"; 223 $obj = new $class(); 224 $modes[] = array( 225 'sort' => $obj->getSort(), 226 'mode' => $m, 227 'obj' => $obj 228 ); 229 } 230 231 // add formatting modes 232 $fmt_modes = array('strong','emphasis','underline','monospace', 233 'subscript','superscript','deleted'); 234 foreach($fmt_modes as $m){ 235 $obj = new Doku_Parser_Mode_formatting($m); 236 $modes[] = array( 237 'sort' => $obj->getSort(), 238 'mode' => $m, 239 'obj' => $obj 240 ); 241 } 242 243 // add modes which need files 244 $obj = new Doku_Parser_Mode_smiley(array_keys(getSmileys())); 245 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'smiley','obj' => $obj ); 246 $obj = new Doku_Parser_Mode_acronym(array_keys(getAcronyms())); 247 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'acronym','obj' => $obj ); 248 $obj = new Doku_Parser_Mode_entity(array_keys(getEntities())); 249 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'entity','obj' => $obj ); 250 251 252 // add optional camelcase mode 253 if($conf['camelcase']){ 254 $obj = new Doku_Parser_Mode_camelcaselink(); 255 $modes[] = array('sort' => $obj->getSort(), 'mode' => 'camelcaselink','obj' => $obj ); 256 } 257 258 //sort modes 259 usort($modes,'p_sort_modes'); 260 261 return $modes; 262} 263 264/** 265 * Callback function for usort 266 * 267 * @author Andreas Gohr <andi@splitbrain.org> 268 */ 269function p_sort_modes($a, $b){ 270 if($a['sort'] == $b['sort']) return 0; 271 return ($a['sort'] < $b['sort']) ? -1 : 1; 272} 273 274/** 275 * Renders a list of instruction to the specified output mode 276 * 277 * In the $info array are informations from the renderer returned 278 * 279 * @author Harry Fuecks <hfuecks@gmail.com> 280 * @author Andreas Gohr <andi@splitbrain.org> 281 */ 282function p_render($mode,$instructions,& $info){ 283 if(is_null($instructions)) return ''; 284 285 // Create the renderer 286 if(!@file_exists(DOKU_INC."inc/parser/$mode.php")){ 287 msg("No renderer for $mode found",-1); 288 return null; 289 } 290 291 require_once DOKU_INC."inc/parser/$mode.php"; 292 $rclass = "Doku_Renderer_$mode"; 293 $Renderer = & new $rclass(); #FIXME any way to check for class existance? 294 295 $Renderer->smileys = getSmileys(); 296 $Renderer->entities = getEntities(); 297 $Renderer->acronyms = getAcronyms(); 298 $Renderer->interwiki = getInterwiki(); 299 #$Renderer->badwords = getBadWords(); 300 301 // Loop through the instructions 302 foreach ( $instructions as $instruction ) { 303 // Execute the callback against the Renderer 304 call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]); 305 } 306 307 //set info array 308 $info = $Renderer->info; 309 310 // Return the output 311 return $Renderer->doc; 312} 313 314/** 315 * Gets the first heading from a file 316 * 317 * @author Jan Decaluwe <jan@jandecaluwe.com> 318 */ 319function p_get_first_heading($id){ 320 $file = wikiFN($id); 321 if (@file_exists($file)) { 322 $instructions = p_cached_instructions($file,true); 323 foreach ( $instructions as $instruction ) { 324 if ($instruction[0] == 'header') { 325 return trim($instruction[1][0]); 326 } 327 } 328 } 329 return NULL; 330} 331 332//Setup VIM: ex: et ts=2 enc=utf-8 : 333