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 = $conf['datadir'].'/_cache/xhtml/'; 71 $cache .= md5($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT']); 72 $purge = $conf['datadir'].'/_cache/purgefile'; 73 74 // check if cache can be used 75 $cachetime = @filemtime($cache); // 0 if not exists 76 77 if( @file_exists($file) // does the source exist 78 && $cachetime > @filemtime($file) // cache is fresh 79 && ((time() - $cachetime) < $conf['cachetime']) // and is cachefile young enough 80 && !isset($_REQUEST['purge']) // no purge param was set 81 && ($cachetime > @filemtime($purge)) // and newer than the purgefile 82 && ($cachetime > @filemtime(DOKU_INC.'conf/dokuwiki.php')) // newer than the config file 83 && ($cachetime > @filemtime(DOKU_INC.'conf/local.php')) // newer than the local config file 84 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/xhtml.php')) // newer than the renderer 85 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/parser.php')) // newer than the parser 86 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/handler.php')))// newer than the handler 87 { 88 //well then use the cache 89 $parsed = io_readfile($cache); 90 $parsed .= "\n<!-- cachefile $cache used -->\n"; 91 }else{ 92 $parsed = p_render('xhtml', p_cached_instructions($file),$info); //try to use cached instructions 93 94 if($info['cache']){ 95 io_saveFile($cache,$parsed); //save cachefile 96 $parsed .= "\n<!-- no cachefile used, but created -->\n"; 97 }else{ 98 @unlink($cache); //try to delete cachefile 99 $parsed .= "\n<!-- no cachefile used, caching forbidden -->\n"; 100 } 101 } 102 103 return $parsed; 104} 105 106/** 107 * Returns the render instructions for a file 108 * 109 * Uses and creates a serialized cache file 110 * 111 * @author Andreas Gohr <andi@splitbrain.org> 112 */ 113function p_cached_instructions($file,$cacheonly=false){ 114 global $conf; 115 $cache = $conf['datadir'].'/_cache/instructions/'; 116 $cache .= md5($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT']); 117 118 // check if cache can be used 119 $cachetime = @filemtime($cache); // 0 if not exists 120 121 // cache forced? 122 if($cacheonly){ 123 if($cachetime){ 124 return unserialize(io_readfile($cache)); 125 }else{ 126 return array(); 127 } 128 } 129 130 if( @file_exists($file) // does the source exist 131 && $cachetime > @filemtime($file) // cache is fresh 132 && !isset($_REQUEST['purge']) // no purge param was set 133 && ($cachetime > @filemtime(DOKU_INC.'conf/dokuwiki.php')) // newer than the config file 134 && ($cachetime > @filemtime(DOKU_INC.'conf/local.php')) // newer than the local config file 135 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/parser.php')) // newer than the parser 136 && ($cachetime > @filemtime(DOKU_INC.'inc/parser/handler.php')))// newer than the handler 137 { 138 //well then use the cache 139 return unserialize(io_readfile($cache)); 140 }elseif(@file_exists($file)){ 141 // no cache - do some work 142 $ins = p_get_instructions(io_readfile($file)); 143 io_savefile($cache,serialize($ins)); 144 return $ins; 145 } 146 147 return NULL; 148} 149 150/** 151 * turns a page into a list of instructions 152 * 153 * @author Harry Fuecks <hfuecks@gmail.com> 154 * @author Andreas Gohr <andi@splitbrain.org> 155 */ 156function p_get_instructions($text){ 157 global $conf; 158 159 //import parser classes and mode definitions 160 require_once DOKU_INC . 'inc/parser/parser.php'; 161 162 // load syntax plugins 163 $pluginlist = plugin_list('syntax'); 164 if(count($pluginlist)){ 165 global $PARSER_MODES; 166 $plugins = array(); 167 foreach($pluginlist as $p){ 168 plugin_load('syntax',$p,$plugin[$p]); //load plugin into $plugin array 169 $PARSER_MODES[$plugin[$p]->getType()][] = "plugin_$p"; //register mode type 170 } 171 } 172 173 // Create the parser 174 $Parser = & new Doku_Parser(); 175 176 // Add the Handler 177 $Parser->Handler = & new Doku_Handler(); 178 179 // Load all the modes 180 $Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock()); 181 $Parser->addMode('preformatted',new Doku_Parser_Mode_Preformatted()); 182 $Parser->addMode('notoc',new Doku_Parser_Mode_NoToc()); 183 $Parser->addMode('nocache',new Doku_Parser_Mode_NoCache()); 184 $Parser->addMode('header',new Doku_Parser_Mode_Header()); 185 $Parser->addMode('table',new Doku_Parser_Mode_Table()); 186 187 $formats = array ( 188 'strong', 'emphasis', 'underline', 'monospace', 189 'subscript', 'superscript', 'deleted', 190 ); 191 foreach ( $formats as $format ) { 192 $Parser->addMode($format,new Doku_Parser_Mode_Formatting($format)); 193 } 194 195 $Parser->addMode('linebreak',new Doku_Parser_Mode_Linebreak()); 196 $Parser->addMode('footnote',new Doku_Parser_Mode_Footnote()); 197 $Parser->addMode('hr',new Doku_Parser_Mode_HR()); 198 199 $Parser->addMode('unformatted',new Doku_Parser_Mode_Unformatted()); 200 $Parser->addMode('php',new Doku_Parser_Mode_PHP()); 201 $Parser->addMode('html',new Doku_Parser_Mode_HTML()); 202 $Parser->addMode('code',new Doku_Parser_Mode_Code()); 203 $Parser->addMode('file',new Doku_Parser_Mode_File()); 204 $Parser->addMode('quote',new Doku_Parser_Mode_Quote()); 205 206 $Parser->addMode('smiley',new Doku_Parser_Mode_Smiley(array_keys(getSmileys()))); 207 $Parser->addMode('acronym',new Doku_Parser_Mode_Acronym(array_keys(getAcronyms()))); 208 #$Parser->addMode('wordblock',new Doku_Parser_Mode_Wordblock($Modes,getBadWords())); 209 $Parser->addMode('entity',new Doku_Parser_Mode_Entity(array_keys(getEntities()))); 210 211 $Parser->addMode('multiplyentity',new Doku_Parser_Mode_MultiplyEntity()); 212 $Parser->addMode('quotes',new Doku_Parser_Mode_Quotes()); 213 214 if($conf['camelcase']){ 215 $Parser->addMode('camelcaselink',new Doku_Parser_Mode_CamelCaseLink()); 216 } 217 218 //add plugins FIXME since order is important we, need to find a better way! 219 foreach ( array_keys($plugin) as $p ) { 220 $Parser->addMode("plugin_$p",$plugin[$p]); 221 } 222 223 $Parser->addMode('internallink',new Doku_Parser_Mode_InternalLink()); 224 $Parser->addMode('rss',new Doku_Parser_Mode_RSS()); 225 $Parser->addMode('media',new Doku_Parser_Mode_Media()); 226 $Parser->addMode('externallink',new Doku_Parser_Mode_ExternalLink()); 227 $Parser->addMode('emaillink',new Doku_Parser_Mode_EmailLink()); 228 $Parser->addMode('windowssharelink',new Doku_Parser_Mode_WindowsShareLink()); 229 //$Parser->addMode('filelink',new Doku_Parser_Mode_FileLink()); //FIXME ??? 230 $Parser->addMode('eol',new Doku_Parser_Mode_Eol()); 231 232 // Do the parsing 233 $p = $Parser->parse($text); 234// dbg($p); 235 return $p; 236} 237 238/** 239 * Renders a list of instruction to the specified output mode 240 * 241 * In the $info array are informations from the renderer returned 242 * 243 * @author Harry Fuecks <hfuecks@gmail.com> 244 * @author Andreas Gohr <andi@splitbrain.org> 245 */ 246function p_render($mode,$instructions,& $info){ 247 if(is_null($instructions)) return ''; 248 249 // Create the renderer 250 if(!@file_exists(DOKU_INC."inc/parser/$mode.php")){ 251 msg("No renderer for $mode found",-1); 252 return null; 253 } 254 255 require_once DOKU_INC."inc/parser/$mode.php"; 256 $rclass = "Doku_Renderer_$mode"; 257 $Renderer = & new $rclass(); #FIXME any way to check for class existance? 258 259 $Renderer->smileys = getSmileys(); 260 $Renderer->entities = getEntities(); 261 $Renderer->acronyms = getAcronyms(); 262 $Renderer->interwiki = getInterwiki(); 263 #$Renderer->badwords = getBadWords(); 264 265 // Loop through the instructions 266 foreach ( $instructions as $instruction ) { 267 // Execute the callback against the Renderer 268 call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]); 269 } 270 271 //set info array 272 $info = $Renderer->info; 273 274 // Return the output 275 return $Renderer->doc; 276} 277 278/** 279 * Gets the first heading from a file 280 * 281 * @author Jan Decaluwe <jan@jandecaluwe.com> 282 */ 283function p_get_first_heading($id){ 284 $file = wikiFN($id); 285 if (@file_exists($file)) { 286 $instructions = p_cached_instructions($file,true); 287 foreach ( $instructions as $instruction ) { 288 if ($instruction[0] == 'header') { 289 return $instruction[1][0]; 290 } 291 } 292 } 293 return NULL; 294} 295 296//Setup VIM: ex: et ts=2 enc=utf-8 : 297