[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Renderer output base class 4 * 5 * @author Harry Fuecks <hfuecks@gmail.com> 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9 use dokuwiki\Extension\Plugin; 10 use dokuwiki\Extension\SyntaxPlugin; 11 12 /** 13 * Allowed chars in $language for code highlighting 14 * @see GeSHi::set_language() 15 */ 16 define('PREG_PATTERN_VALID_LANGUAGE', '#[^a-zA-Z0-9\-_]#'); 17 18 /** 19 * An empty renderer, produces no output 20 * 21 * Inherits from dokuwiki\Plugin\DokuWiki_Plugin for giving additional functions to render plugins 22 * 23 * The renderer transforms the syntax instructions created by the parser and handler into the 24 * desired output format. For each instruction a corresponding method defined in this class will 25 * be called. That method needs to produce the desired output for the instruction and add it to the 26 * $doc field. When all instructions are processed, the $doc field contents will be cached by 27 * DokuWiki and sent to the user. 28 */ 29 abstract class Doku_Renderer extends Plugin { 30 /** @var array Settings, control the behavior of the renderer */ 31 public $info = array( 32 'cache' => true, // may the rendered result cached? 33 'toc' => true, // render the TOC? 34 ); 35 36 /** @var array contains the smiley configuration, set in p_render() */ 37 public $smileys = array(); 38 /** @var array contains the entity configuration, set in p_render() */ 39 public $entities = array(); 40 /** @var array contains the acronym configuration, set in p_render() */ 41 public $acronyms = array(); 42 /** @var array contains the interwiki configuration, set in p_render() */ 43 public $interwiki = array(); 44 45 /** @var array the list of headers used to create unique link ids */ 46 protected $headers = array(); 47 48 /** 49 * @var string the rendered document, this will be cached after the renderer ran through 50 */ 51 public $doc = ''; 52 53 /** 54 * clean out any per-use values 55 * 56 * This is called before each use of the renderer object and should be used to 57 * completely reset the state of the renderer to be reused for a new document 58 */ 59 public function reset(){ 60 $this->headers = array(); 61 $this->doc = ''; 62 $this->info['cache'] = true; 63 $this->info['toc'] = true; 64 } 65 66 /** 67 * Allow the plugin to prevent DokuWiki from reusing an instance 68 * 69 * Since most renderer plugins fail to implement Doku_Renderer::reset() we default 70 * to reinstantiating the renderer here 71 * 72 * @return bool false if the plugin has to be instantiated 73 */ 74 public function isSingleton() { 75 return false; 76 } 77 78 /** 79 * Returns the format produced by this renderer. 80 * 81 * Has to be overidden by sub classes 82 * 83 * @return string 84 */ 85 abstract public function getFormat(); 86 87 /** 88 * Disable caching of this renderer's output 89 */ 90 public function nocache() { 91 $this->info['cache'] = false; 92 } 93 94 /** 95 * Disable TOC generation for this renderer's output 96 * 97 * This might not be used for certain sub renderer 98 */ 99 public function notoc() { 100 $this->info['toc'] = false; 101 } 102 103 /** 104 * Handle plugin rendering 105 * 106 * Most likely this needs NOT to be overwritten by sub classes 107 * 108 * @param string $name Plugin name 109 * @param mixed $data custom data set by handler 110 * @param string $state matched state if any 111 * @param string $match raw matched syntax 112 */ 113 public function plugin($name, $data, $state = '', $match = '') { 114 /** @var SyntaxPlugin $plugin */ 115 $plugin = plugin_load('syntax', $name); 116 if($plugin != null) { 117 $plugin->render($this->getFormat(), $this, $data); 118 } 119 } 120 121 /** 122 * handle nested render instructions 123 * this method (and nest_close method) should not be overloaded in actual renderer output classes 124 * 125 * @param array $instructions 126 */ 127 public function nest($instructions) { 128 foreach($instructions as $instruction) { 129 // execute the callback against ourself 130 if(method_exists($this, $instruction[0])) { 131 call_user_func_array(array($this, $instruction[0]), $instruction[1] ? $instruction[1] : array()); 132 } 133 } 134 } 135 136 /** 137 * dummy closing instruction issued by Doku_Handler_Nest 138 * 139 * normally the syntax mode should override this instruction when instantiating Doku_Handler_Nest - 140 * however plugins will not be able to - as their instructions require data. 141 */ 142 public function nest_close() { 143 } 144 145 #region Syntax modes - sub classes will need to implement them to fill $doc 146 147 /** 148 * Initialize the document 149 */ 150 public function document_start() { 151 } 152 153 /** 154 * Finalize the document 155 */ 156 public function document_end() { 157 } 158 159 /** 160 * Render the Table of Contents 161 * 162 * @return string 163 */ 164 public function render_TOC() { 165 return ''; 166 } 167 168 /** 169 * Add an item to the TOC 170 * 171 * @param string $id the hash link 172 * @param string $text the text to display 173 * @param int $level the nesting level 174 */ 175 public function toc_additem($id, $text, $level) { 176 } 177 178 /** 179 * Render a heading 180 * 181 * @param string $text the text to display 182 * @param int $level header level 183 * @param int $pos byte position in the original source 184 */ 185 public function header($text, $level, $pos) { 186 } 187 188 /** 189 * Open a new section 190 * 191 * @param int $level section level (as determined by the previous header) 192 */ 193 public function section_open($level) { 194 } 195 196 /** 197 * Close the current section 198 */ 199 public function section_close() { 200 } 201 202 /** 203 * Render plain text data 204 * 205 * @param string $text 206 */ 207 public function cdata($text) { 208 } 209 210 /** 211 * Open a paragraph 212 */ 213 public function p_open() { 214 } 215 216 /** 217 * Close a paragraph 218 */ 219 public function p_close() { 220 } 221 222 /** 223 * Create a line break 224 */ 225 public function linebreak() { 226 } 227 228 /** 229 * Create a horizontal line 230 */ 231 public function hr() { 232 } 233 234 /** 235 * Start strong (bold) formatting 236 */ 237 public function strong_open() { 238 } 239 240 /** 241 * Stop strong (bold) formatting 242 */ 243 public function strong_close() { 244 } 245 246 /** 247 * Start emphasis (italics) formatting 248 */ 249 public function emphasis_open() { 250 } 251 252 /** 253 * Stop emphasis (italics) formatting 254 */ 255 public function emphasis_close() { 256 } 257 258 /** 259 * Start underline formatting 260 */ 261 public function underline_open() { 262 } 263 264 /** 265 * Stop underline formatting 266 */ 267 public function underline_close() { 268 } 269 270 /** 271 * Start monospace formatting 272 */ 273 public function monospace_open() { 274 } 275 276 /** 277 * Stop monospace formatting 278 */ 279 public function monospace_close() { 280 } 281 282 /** 283 * Start a subscript 284 */ 285 public function subscript_open() { 286 } 287 288 /** 289 * Stop a subscript 290 */ 291 public function subscript_close() { 292 } 293 294 /** 295 * Start a superscript 296 */ 297 public function superscript_open() { 298 } 299 300 /** 301 * Stop a superscript 302 */ 303 public function superscript_close() { 304 } 305 306 /** 307 * Start deleted (strike-through) formatting 308 */ 309 public function deleted_open() { 310 } 311 312 /** 313 * Stop deleted (strike-through) formatting 314 */ 315 public function deleted_close() { 316 } 317 318 /** 319 * Start a footnote 320 */ 321 public function footnote_open() { 322 } 323 324 /** 325 * Stop a footnote 326 */ 327 public function footnote_close() { 328 } 329 330 /** 331 * Open an unordered list 332 */ 333 public function listu_open() { 334 } 335 336 /** 337 * Close an unordered list 338 */ 339 public function listu_close() { 340 } 341 342 /** 343 * Open an ordered list 344 */ 345 public function listo_open() { 346 } 347 348 /** 349 * Close an ordered list 350 */ 351 public function listo_close() { 352 } 353 354 /** 355 * Open a list item 356 * 357 * @param int $level the nesting level 358 * @param bool $node true when a node; false when a leaf 359 */ 360 public function listitem_open($level,$node=false) { 361 } 362 363 /** 364 * Close a list item 365 */ 366 public function listitem_close() { 367 } 368 369 /** 370 * Start the content of a list item 371 */ 372 public function listcontent_open() { 373 } 374 375 /** 376 * Stop the content of a list item 377 */ 378 public function listcontent_close() { 379 } 380 381 /** 382 * Output unformatted $text 383 * 384 * Defaults to $this->cdata() 385 * 386 * @param string $text 387 */ 388 public function unformatted($text) { 389 $this->cdata($text); 390 } 391 392 /** 393 * Output inline PHP code 394 * 395 * If $conf['phpok'] is true this should evaluate the given code and append the result 396 * to $doc 397 * 398 * @param string $text The PHP code 399 */ 400 public function php($text) { 401 } 402 403 /** 404 * Output block level PHP code 405 * 406 * If $conf['phpok'] is true this should evaluate the given code and append the result 407 * to $doc 408 * 409 * @param string $text The PHP code 410 */ 411 public function phpblock($text) { 412 } 413 414 /** 415 * Output raw inline HTML 416 * 417 * If $conf['htmlok'] is true this should add the code as is to $doc 418 * 419 * @param string $text The HTML 420 */ 421 public function html($text) { 422 } 423 424 /** 425 * Output raw block-level HTML 426 * 427 * If $conf['htmlok'] is true this should add the code as is to $doc 428 * 429 * @param string $text The HTML 430 */ 431 public function htmlblock($text) { 432 } 433 434 /** 435 * Output preformatted text 436 * 437 * @param string $text 438 */ 439 public function preformatted($text) { 440 } 441 442 /** 443 * Start a block quote 444 */ 445 public function quote_open() { 446 } 447 448 /** 449 * Stop a block quote 450 */ 451 public function quote_close() { 452 } 453 454 /** 455 * Display text as file content, optionally syntax highlighted 456 * 457 * @param string $text text to show 458 * @param string $lang programming language to use for syntax highlighting 459 * @param string $file file path label 460 */ 461 public function file($text, $lang = null, $file = null) { 462 } 463 464 /** 465 * Display text as code content, optionally syntax highlighted 466 * 467 * @param string $text text to show 468 * @param string $lang programming language to use for syntax highlighting 469 * @param string $file file path label 470 */ 471 public function code($text, $lang = null, $file = null) { 472 } 473 474 /** 475 * Format an acronym 476 * 477 * Uses $this->acronyms 478 * 479 * @param string $acronym 480 */ 481 public function acronym($acronym) { 482 } 483 484 /** 485 * Format a smiley 486 * 487 * Uses $this->smiley 488 * 489 * @param string $smiley 490 */ 491 public function smiley($smiley) { 492 } 493 494 /** 495 * Format an entity 496 * 497 * Entities are basically small text replacements 498 * 499 * Uses $this->entities 500 * 501 * @param string $entity 502 */ 503 public function entity($entity) { 504 } 505 506 /** 507 * Typographically format a multiply sign 508 * 509 * Example: ($x=640, $y=480) should result in "640×480" 510 * 511 * @param string|int $x first value 512 * @param string|int $y second value 513 */ 514 public function multiplyentity($x, $y) { 515 } 516 517 /** 518 * Render an opening single quote char (language specific) 519 */ 520 public function singlequoteopening() { 521 } 522 523 /** 524 * Render a closing single quote char (language specific) 525 */ 526 public function singlequoteclosing() { 527 } 528 529 /** 530 * Render an apostrophe char (language specific) 531 */ 532 public function apostrophe() { 533 } 534 535 /** 536 * Render an opening double quote char (language specific) 537 */ 538 public function doublequoteopening() { 539 } 540 541 /** 542 * Render an closinging double quote char (language specific) 543 */ 544 public function doublequoteclosing() { 545 } 546 547 /** 548 * Render a CamelCase link 549 * 550 * @param string $link The link name 551 * @see http://en.wikipedia.org/wiki/CamelCase 552 */ 553 public function camelcaselink($link) { 554 } 555 556 /** 557 * Render a page local link 558 * 559 * @param string $hash hash link identifier 560 * @param string $name name for the link 561 */ 562 public function locallink($hash, $name = null) { 563 } 564 565 /** 566 * Render a wiki internal link 567 * 568 * @param string $link page ID to link to. eg. 'wiki:syntax' 569 * @param string|array $title name for the link, array for media file 570 */ 571 public function internallink($link, $title = null) { 572 } 573 574 /** 575 * Render an external link 576 * 577 * @param string $link full URL with scheme 578 * @param string|array $title name for the link, array for media file 579 */ 580 public function externallink($link, $title = null) { 581 } 582 583 /** 584 * Render the output of an RSS feed 585 * 586 * @param string $url URL of the feed 587 * @param array $params Finetuning of the output 588 */ 589 public function rss($url, $params) { 590 } 591 592 /** 593 * Render an interwiki link 594 * 595 * You may want to use $this->_resolveInterWiki() here 596 * 597 * @param string $link original link - probably not much use 598 * @param string|array $title name for the link, array for media file 599 * @param string $wikiName indentifier (shortcut) for the remote wiki 600 * @param string $wikiUri the fragment parsed from the original link 601 */ 602 public function interwikilink($link, $title, $wikiName, $wikiUri) { 603 } 604 605 /** 606 * Link to file on users OS 607 * 608 * @param string $link the link 609 * @param string|array $title name for the link, array for media file 610 */ 611 public function filelink($link, $title = null) { 612 } 613 614 /** 615 * Link to windows share 616 * 617 * @param string $link the link 618 * @param string|array $title name for the link, array for media file 619 */ 620 public function windowssharelink($link, $title = null) { 621 } 622 623 /** 624 * Render a linked E-Mail Address 625 * 626 * Should honor $conf['mailguard'] setting 627 * 628 * @param string $address Email-Address 629 * @param string|array $name name for the link, array for media file 630 */ 631 public function emaillink($address, $name = null) { 632 } 633 634 /** 635 * Render an internal media file 636 * 637 * @param string $src media ID 638 * @param string $title descriptive text 639 * @param string $align left|center|right 640 * @param int $width width of media in pixel 641 * @param int $height height of media in pixel 642 * @param string $cache cache|recache|nocache 643 * @param string $linking linkonly|detail|nolink 644 */ 645 public function internalmedia($src, $title = null, $align = null, $width = null, 646 $height = null, $cache = null, $linking = null) { 647 } 648 649 /** 650 * Render an external media file 651 * 652 * @param string $src full media URL 653 * @param string $title descriptive text 654 * @param string $align left|center|right 655 * @param int $width width of media in pixel 656 * @param int $height height of media in pixel 657 * @param string $cache cache|recache|nocache 658 * @param string $linking linkonly|detail|nolink 659 */ 660 public function externalmedia($src, $title = null, $align = null, $width = null, 661 $height = null, $cache = null, $linking = null) { 662 } 663 664 /** 665 * Render a link to an internal media file 666 * 667 * @param string $src media ID 668 * @param string $title descriptive text 669 * @param string $align left|center|right 670 * @param int $width width of media in pixel 671 * @param int $height height of media in pixel 672 * @param string $cache cache|recache|nocache 673 */ 674 public function internalmedialink($src, $title = null, $align = null, 675 $width = null, $height = null, $cache = null) { 676 } 677 678 /** 679 * Render a link to an external media file 680 * 681 * @param string $src media ID 682 * @param string $title descriptive text 683 * @param string $align left|center|right 684 * @param int $width width of media in pixel 685 * @param int $height height of media in pixel 686 * @param string $cache cache|recache|nocache 687 */ 688 public function externalmedialink($src, $title = null, $align = null, 689 $width = null, $height = null, $cache = null) { 690 } 691 692 /** 693 * Start a table 694 * 695 * @param int $maxcols maximum number of columns 696 * @param int $numrows NOT IMPLEMENTED 697 * @param int $pos byte position in the original source 698 */ 699 public function table_open($maxcols = null, $numrows = null, $pos = null) { 700 } 701 702 /** 703 * Close a table 704 * 705 * @param int $pos byte position in the original source 706 */ 707 public function table_close($pos = null) { 708 } 709 710 /** 711 * Open a table header 712 */ 713 public function tablethead_open() { 714 } 715 716 /** 717 * Close a table header 718 */ 719 public function tablethead_close() { 720 } 721 722 /** 723 * Open a table body 724 */ 725 public function tabletbody_open() { 726 } 727 728 /** 729 * Close a table body 730 */ 731 public function tabletbody_close() { 732 } 733 734 /** 735 * Open a table footer 736 */ 737 public function tabletfoot_open() { 738 } 739 740 /** 741 * Close a table footer 742 */ 743 public function tabletfoot_close() { 744 } 745 746 /** 747 * Open a table row 748 */ 749 public function tablerow_open() { 750 } 751 752 /** 753 * Close a table row 754 */ 755 public function tablerow_close() { 756 } 757 758 /** 759 * Open a table header cell 760 * 761 * @param int $colspan 762 * @param string $align left|center|right 763 * @param int $rowspan 764 */ 765 public function tableheader_open($colspan = 1, $align = null, $rowspan = 1) { 766 } 767 768 /** 769 * Close a table header cell 770 */ 771 public function tableheader_close() { 772 } 773 774 /** 775 * Open a table cell 776 * 777 * @param int $colspan 778 * @param string $align left|center|right 779 * @param int $rowspan 780 */ 781 public function tablecell_open($colspan = 1, $align = null, $rowspan = 1) { 782 } 783 784 /** 785 * Close a table cell 786 */ 787 public function tablecell_close() { 788 } 789 790 #endregion 791 792 #region util functions, you probably won't need to reimplement them 793 794 /** 795 * Creates a linkid from a headline 796 * 797 * @author Andreas Gohr <andi@splitbrain.org> 798 * @param string $title The headline title 799 * @param boolean $create Create a new unique ID? 800 * @return string 801 */ 802 public function _headerToLink($title, $create = false) { 803 if($create) { 804 return sectionID($title, $this->headers); 805 } else { 806 $check = false; 807 return sectionID($title, $check); 808 } 809 } 810 811 /** 812 * Removes any Namespace from the given name but keeps 813 * casing and special chars 814 * 815 * @author Andreas Gohr <andi@splitbrain.org> 816 * 817 * @param string $name 818 * @return string 819 */ 820 public function _simpleTitle($name) { 821 global $conf; 822 823 //if there is a hash we use the ancor name only 824 @list($name, $hash) = explode('#', $name, 2); 825 if($hash) return $hash; 826 827 if($conf['useslash']) { 828 $name = strtr($name, ';/', ';:'); 829 } else { 830 $name = strtr($name, ';', ':'); 831 } 832 833 return noNSorNS($name); 834 } 835 836 /** 837 * Resolve an interwikilink 838 * 839 * @param string $shortcut identifier for the interwiki link 840 * @param string $reference fragment that refers the content 841 * @param null|bool $exists reference which returns if an internal page exists 842 * @return string interwikilink 843 */ 844 public function _resolveInterWiki(&$shortcut, $reference, &$exists = null) { 845 //get interwiki URL 846 if(isset($this->interwiki[$shortcut])) { 847 $url = $this->interwiki[$shortcut]; 848 }elseif(isset($this->interwiki['default'])) { 849 $shortcut = 'default'; 850 $url = $this->interwiki[$shortcut]; 851 }else{ 852 // not parsable interwiki outputs '' to make sure string manipluation works 853 $shortcut = ''; 854 $url = ''; 855 } 856 857 //split into hash and url part 858 $hash = strrchr($reference, '#'); 859 if($hash) { 860 $reference = substr($reference, 0, -strlen($hash)); 861 $hash = substr($hash, 1); 862 } 863 864 //replace placeholder 865 if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#', $url)) { 866 //use placeholders 867 $url = str_replace('{URL}', rawurlencode($reference), $url); 868 //wiki names will be cleaned next, otherwise urlencode unsafe chars 869 $url = str_replace('{NAME}', ($url[0] === ':') ? $reference : 870 preg_replace_callback('/[[\\\\\]^`{|}#%]/', function($match) { 871 return rawurlencode($match[0]); 872 }, $reference), $url); 873 $parsed = parse_url($reference); 874 if (empty($parsed['scheme'])) $parsed['scheme'] = ''; 875 if (empty($parsed['host'])) $parsed['host'] = ''; 876 if (empty($parsed['port'])) $parsed['port'] = 80; 877 if (empty($parsed['path'])) $parsed['path'] = ''; 878 if (empty($parsed['query'])) $parsed['query'] = ''; 879 $url = strtr($url,[ 880 '{SCHEME}' => $parsed['scheme'], 881 '{HOST}' => $parsed['host'], 882 '{PORT}' => $parsed['port'], 883 '{PATH}' => $parsed['path'], 884 '{QUERY}' => $parsed['query'] , 885 ]); 886 } else if($url != '') { 887 // make sure when no url is defined, we keep it null 888 // default 889 $url = $url.rawurlencode($reference); 890 } 891 //handle as wiki links 892 if($url && $url[0] === ':') { 893 $urlparam = null; 894 $id = $url; 895 if (strpos($url, '?') !== false) { 896 list($id, $urlparam) = explode('?', $url, 2); 897 } 898 $url = wl(cleanID($id), $urlparam); 899 $exists = page_exists($id); 900 } 901 if($hash) $url .= '#'.rawurlencode($hash); 902 903 return $url; 904 } 905 906 #endregion 907 } 908 909 910 //Setup VIM: ex: et ts=4 :
title
Description
Body
title
Description
Body
title
Description
Body
title
Body