1<?php 2/** 3 * Renderer for metadata 4 * 5 * @author Esther Brunner <wikidesign@gmail.com> 6 */ 7if(!defined('DOKU_INC')) die('meh.'); 8 9if ( !defined('DOKU_LF') ) { 10 // Some whitespace to help View > Source 11 define ('DOKU_LF',"\n"); 12} 13 14if ( !defined('DOKU_TAB') ) { 15 // Some whitespace to help View > Source 16 define ('DOKU_TAB',"\t"); 17} 18 19require_once DOKU_INC . 'inc/parser/renderer.php'; 20 21/** 22 * The Renderer 23 */ 24class Doku_Renderer_metadata extends Doku_Renderer { 25 26 var $doc = ''; 27 var $meta = array(); 28 var $persistent = array(); 29 30 var $headers = array(); 31 var $capture = true; 32 var $store = ''; 33 var $firstimage = ''; 34 35 function getFormat(){ 36 return 'metadata'; 37 } 38 39 function document_start(){ 40 global $ID; 41 42 $this->headers = array(); 43 44 // external pages are missing create date 45 if(!$this->persistent['date']['created']){ 46 $this->persistent['date']['created'] = filectime(wikiFN($ID)); 47 } 48 if(!isset($this->persistent['user'])){ 49 $this->persistent['user'] = ''; 50 } 51 if(!isset($this->persistent['creator'])){ 52 $this->persistent['creator'] = ''; 53 } 54 // reset metadata to persistent values 55 $this->meta = $this->persistent; 56 } 57 58 function document_end(){ 59 global $ID; 60 61 // store internal info in metadata (notoc,nocache) 62 $this->meta['internal'] = $this->info; 63 64 if (!isset($this->meta['description']['abstract'])){ 65 // cut off too long abstracts 66 $this->doc = trim($this->doc); 67 if (strlen($this->doc) > 500) 68 $this->doc = utf8_substr($this->doc, 0, 500).'…'; 69 $this->meta['description']['abstract'] = $this->doc; 70 } 71 72 $this->meta['relation']['firstimage'] = $this->firstimage; 73 74 if(!isset($this->meta['date']['modified'])){ 75 $this->meta['date']['modified'] = filemtime(wikiFN($ID)); 76 } 77 78 } 79 80 function toc_additem($id, $text, $level) { 81 global $conf; 82 83 //only add items within configured levels 84 if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){ 85 // the TOC is one of our standard ul list arrays ;-) 86 $this->meta['description']['tableofcontents'][] = array( 87 'hid' => $id, 88 'title' => $text, 89 'type' => 'ul', 90 'level' => $level-$conf['toptoclevel']+1 91 ); 92 } 93 94 } 95 96 function header($text, $level, $pos) { 97 if (!isset($this->meta['title'])) $this->meta['title'] = $text; 98 99 // add the header to the TOC 100 $hid = $this->_headerToLink($text,'true'); 101 $this->toc_additem($hid, $text, $level); 102 103 // add to summary 104 if ($this->capture && ($level > 1)) $this->doc .= DOKU_LF.$text.DOKU_LF; 105 } 106 107 function section_open($level){} 108 function section_close(){} 109 110 function cdata($text){ 111 if ($this->capture) $this->doc .= $text; 112 } 113 114 function p_open(){ 115 if ($this->capture) $this->doc .= DOKU_LF; 116 } 117 118 function p_close(){ 119 if ($this->capture){ 120 if (strlen($this->doc) > 250) $this->capture = false; 121 else $this->doc .= DOKU_LF; 122 } 123 } 124 125 function linebreak(){ 126 if ($this->capture) $this->doc .= DOKU_LF; 127 } 128 129 function hr(){ 130 if ($this->capture){ 131 if (strlen($this->doc) > 250) $this->capture = false; 132 else $this->doc .= DOKU_LF.'----------'.DOKU_LF; 133 } 134 } 135 136 function strong_open(){} 137 function strong_close(){} 138 139 function emphasis_open(){} 140 function emphasis_close(){} 141 142 function underline_open(){} 143 function underline_close(){} 144 145 function monospace_open(){} 146 function monospace_close(){} 147 148 function subscript_open(){} 149 function subscript_close(){} 150 151 function superscript_open(){} 152 function superscript_close(){} 153 154 function deleted_open(){} 155 function deleted_close(){} 156 157 /** 158 * Callback for footnote start syntax 159 * 160 * All following content will go to the footnote instead of 161 * the document. To achieve this the previous rendered content 162 * is moved to $store and $doc is cleared 163 * 164 * @author Andreas Gohr <andi@splitbrain.org> 165 */ 166 function footnote_open() { 167 if ($this->capture){ 168 // move current content to store and record footnote 169 $this->store = $this->doc; 170 $this->doc = ''; 171 } 172 } 173 174 /** 175 * Callback for footnote end syntax 176 * 177 * All rendered content is moved to the $footnotes array and the old 178 * content is restored from $store again 179 * 180 * @author Andreas Gohr 181 */ 182 function footnote_close() { 183 if ($this->capture){ 184 // restore old content 185 $this->doc = $this->store; 186 $this->store = ''; 187 } 188 } 189 190 function listu_open(){ 191 if ($this->capture) $this->doc .= DOKU_LF; 192 } 193 194 function listu_close(){ 195 if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; 196 } 197 198 function listo_open(){ 199 if ($this->capture) $this->doc .= DOKU_LF; 200 } 201 202 function listo_close(){ 203 if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; 204 } 205 206 function listitem_open($level){ 207 if ($this->capture) $this->doc .= str_repeat(DOKU_TAB, $level).'* '; 208 } 209 210 function listitem_close(){ 211 if ($this->capture) $this->doc .= DOKU_LF; 212 } 213 214 function listcontent_open(){} 215 function listcontent_close(){} 216 217 function unformatted($text){ 218 if ($this->capture) $this->doc .= $text; 219 } 220 221 function php($text){} 222 223 function phpblock($text){} 224 225 function html($text){} 226 227 function htmlblock($text){} 228 229 function preformatted($text){ 230 if ($this->capture) $this->doc .= $text; 231 } 232 233 function file($text, $lang = null, $file = null){ 234 if ($this->capture){ 235 $this->doc .= DOKU_LF.$text; 236 if (strlen($this->doc) > 250) $this->capture = false; 237 else $this->doc .= DOKU_LF; 238 } 239 } 240 241 function quote_open(){ 242 if ($this->capture) $this->doc .= DOKU_LF.DOKU_TAB.'"'; 243 } 244 245 function quote_close(){ 246 if ($this->capture){ 247 $this->doc .= '"'; 248 if (strlen($this->doc) > 250) $this->capture = false; 249 else $this->doc .= DOKU_LF; 250 } 251 } 252 253 function code($text, $language = NULL, $file = null){ 254 if ($this->capture){ 255 $this->doc .= DOKU_LF.$text; 256 if (strlen($this->doc) > 250) $this->capture = false; 257 else $this->doc .= DOKU_LF; 258 } 259 } 260 261 function acronym($acronym){ 262 if ($this->capture) $this->doc .= $acronym; 263 } 264 265 function smiley($smiley){ 266 if ($this->capture) $this->doc .= $smiley; 267 } 268 269 function entity($entity){ 270 if ($this->capture) $this->doc .= $entity; 271 } 272 273 function multiplyentity($x, $y){ 274 if ($this->capture) $this->doc .= $x.'×'.$y; 275 } 276 277 function singlequoteopening(){ 278 global $lang; 279 if ($this->capture) $this->doc .= $lang['singlequoteopening']; 280 } 281 282 function singlequoteclosing(){ 283 global $lang; 284 if ($this->capture) $this->doc .= $lang['singlequoteclosing']; 285 } 286 287 function apostrophe() { 288 global $lang; 289 if ($this->capture) $this->doc .= $lang['apostrophe']; 290 } 291 292 function doublequoteopening(){ 293 global $lang; 294 if ($this->capture) $this->doc .= $lang['doublequoteopening']; 295 } 296 297 function doublequoteclosing(){ 298 global $lang; 299 if ($this->capture) $this->doc .= $lang['doublequoteclosing']; 300 } 301 302 function camelcaselink($link) { 303 $this->internallink($link, $link); 304 } 305 306 function locallink($hash, $name = NULL){} 307 308 /** 309 * keep track of internal links in $this->meta['relation']['references'] 310 */ 311 function internallink($id, $name = NULL){ 312 global $ID; 313 314 if(is_array($name)) 315 $this->_firstimage($name['src']); 316 317 $default = $this->_simpleTitle($id); 318 319 // first resolve and clean up the $id 320 resolve_pageid(getNS($ID), $id, $exists); 321 list($page, $hash) = explode('#', $id, 2); 322 323 // set metadata 324 $this->meta['relation']['references'][$page] = $exists; 325 // $data = array('relation' => array('isreferencedby' => array($ID => true))); 326 // p_set_metadata($id, $data); 327 328 // add link title to summary 329 if ($this->capture){ 330 $name = $this->_getLinkTitle($name, $default, $id); 331 $this->doc .= $name; 332 } 333 } 334 335 function externallink($url, $name = NULL){ 336 if(is_array($name)) 337 $this->_firstimage($name['src']); 338 339 if ($this->capture){ 340 $this->doc .= $this->_getLinkTitle($name, '<' . $url . '>'); 341 } 342 } 343 344 function interwikilink($match, $name = NULL, $wikiName, $wikiUri){ 345 if(is_array($name)) 346 $this->_firstimage($name['src']); 347 348 if ($this->capture){ 349 list($wikiUri, $hash) = explode('#', $wikiUri, 2); 350 $name = $this->_getLinkTitle($name, $wikiUri); 351 $this->doc .= $name; 352 } 353 } 354 355 function windowssharelink($url, $name = NULL){ 356 if(is_array($name)) 357 $this->_firstimage($name['src']); 358 359 if ($this->capture){ 360 if ($name) $this->doc .= $name; 361 else $this->doc .= '<'.$url.'>'; 362 } 363 } 364 365 function emaillink($address, $name = NULL){ 366 if(is_array($name)) 367 $this->_firstimage($name['src']); 368 369 if ($this->capture){ 370 if ($name) $this->doc .= $name; 371 else $this->doc .= '<'.$address.'>'; 372 } 373 } 374 375 function internalmedia($src, $title=NULL, $align=NULL, $width=NULL, 376 $height=NULL, $cache=NULL, $linking=NULL){ 377 if ($this->capture && $title) $this->doc .= '['.$title.']'; 378 $this->_firstimage($src); 379 } 380 381 function externalmedia($src, $title=NULL, $align=NULL, $width=NULL, 382 $height=NULL, $cache=NULL, $linking=NULL){ 383 if ($this->capture && $title) $this->doc .= '['.$title.']'; 384 $this->_firstimage($src); 385 } 386 387 function rss($url,$params) { 388 $this->meta['relation']['haspart'][$url] = true; 389 390 $this->meta['date']['valid']['age'] = 391 isset($this->meta['date']['valid']['age']) ? 392 min($this->meta['date']['valid']['age'],$params['refresh']) : 393 $params['refresh']; 394 } 395 396 function table_open($maxcols = NULL, $numrows = NULL){} 397 function table_close(){} 398 399 function tablerow_open(){} 400 function tablerow_close(){} 401 402 function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1){} 403 function tableheader_close(){} 404 405 function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1){} 406 function tablecell_close(){} 407 408 //---------------------------------------------------------- 409 // Utils 410 411 /** 412 * Removes any Namespace from the given name but keeps 413 * casing and special chars 414 * 415 * @author Andreas Gohr <andi@splitbrain.org> 416 */ 417 function _simpleTitle($name){ 418 global $conf; 419 420 if(is_array($name)) return ''; 421 422 if($conf['useslash']){ 423 $nssep = '[:;/]'; 424 }else{ 425 $nssep = '[:;]'; 426 } 427 $name = preg_replace('!.*'.$nssep.'!','',$name); 428 //if there is a hash we use the anchor name only 429 $name = preg_replace('!.*#!','',$name); 430 return $name; 431 } 432 433 /** 434 * Creates a linkid from a headline 435 * 436 * @param string $title The headline title 437 * @param boolean $create Create a new unique ID? 438 * @author Andreas Gohr <andi@splitbrain.org> 439 */ 440 function _headerToLink($title, $create=false) { 441 if($create){ 442 return sectionID($title,$this->headers); 443 }else{ 444 $check = false; 445 return sectionID($title,$check); 446 } 447 } 448 449 /** 450 * Construct a title and handle images in titles 451 * 452 * @author Harry Fuecks <hfuecks@gmail.com> 453 */ 454 function _getLinkTitle($title, $default, $id=NULL) { 455 global $conf; 456 457 $isImage = false; 458 if (is_null($title)){ 459 if (useHeading('content') && $id){ 460 $heading = p_get_first_heading($id,false); 461 if ($heading) return $heading; 462 } 463 return $default; 464 } else if (is_string($title)){ 465 return $title; 466 } else if (is_array($title)){ 467 if($title['title']) return '['.$title['title'].']'; 468 } 469 } 470 471 function _firstimage($src){ 472 if($this->firstimage) return; 473 global $ID; 474 475 list($src,$hash) = explode('#',$src,2); 476 if(!preg_match('/^https?:\/\//i',$src)){ 477 resolve_mediaid(getNS($ID),$src, $exists); 478 } 479 if(preg_match('/.(jpe?g|gif|png)$/i',$src)){ 480 $this->firstimage = $src; 481 } 482 } 483} 484 485//Setup VIM: ex: et ts=4 : 486