1<?php 2/** 3 * HTML output functions 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9use dokuwiki\Action\Denied; 10use dokuwiki\Action\Locked; 11use dokuwiki\ChangeLog\PageChangeLog; 12use dokuwiki\Extension\AuthPlugin; 13use dokuwiki\Extension\Event; 14use dokuwiki\Ui\Backlinks; 15use dokuwiki\Ui\Editor; 16use dokuwiki\Ui\Index; 17use dokuwiki\Ui\Login; 18use dokuwiki\Ui\PageConflict; 19use dokuwiki\Ui\PageDiff; 20use dokuwiki\Ui\PageDraft; 21use dokuwiki\Ui\PageRevisions; 22use dokuwiki\Ui\PageView; 23use dokuwiki\Ui\Recent; 24use dokuwiki\Ui\UserProfile; 25use dokuwiki\Ui\UserRegister; 26use dokuwiki\Ui\UserResendPwd; 27use dokuwiki\Utf8\Clean; 28 29if (!defined('SEC_EDIT_PATTERN')) { 30 define('SEC_EDIT_PATTERN', '#<!-- EDIT({.*?}) -->#'); 31} 32 33 34/** 35 * Convenience function to quickly build a wikilink 36 * 37 * @author Andreas Gohr <andi@splitbrain.org> 38 * @param string $id id of the target page 39 * @param string $name the name of the link, i.e. the text that is displayed 40 * @param string|array $search search string(s) that shall be highlighted in the target page 41 * @return string the HTML code of the link 42 */ 43function html_wikilink($id, $name = null, $search = '') { 44 /** @var Doku_Renderer_xhtml $xhtml_renderer */ 45 static $xhtml_renderer = null; 46 if (is_null($xhtml_renderer)) { 47 $xhtml_renderer = p_get_renderer('xhtml'); 48 } 49 50 return $xhtml_renderer->internallink($id,$name,$search,true,'navigation'); 51} 52 53/** 54 * The loginform 55 * 56 * @author Andreas Gohr <andi@splitbrain.org> 57 * 58 * @param bool $svg Whether to show svg icons in the register and resendpwd links or not 59 * @deprecated 2020-07-18 60 */ 61function html_login($svg = false) { 62 dbg_deprecated(Login::class .'::show()'); 63 (new dokuwiki\Ui\Login($svg))->show(); 64} 65 66 67/** 68 * Denied page content 69 * 70 * @deprecated 2020-07-18 not called anymore, see inc/Action/Denied::tplContent() 71 */ 72function html_denied() { 73 dbg_deprecated(Denied::class .'::showBanner()'); 74 (new dokuwiki\Action\Denied())->showBanner(); 75} 76 77/** 78 * inserts section edit buttons if wanted or removes the markers 79 * 80 * @author Andreas Gohr <andi@splitbrain.org> 81 * 82 * @param string $text 83 * @param bool $show show section edit buttons? 84 * @return string 85 */ 86function html_secedit($text, $show = true) { 87 global $INFO; 88 89 if ((isset($INFO) && !$INFO['writable']) || !$show || (isset($INFO) && $INFO['rev'])) { 90 return preg_replace(SEC_EDIT_PATTERN,'',$text); 91 } 92 93 return preg_replace_callback(SEC_EDIT_PATTERN, 94 'html_secedit_button', $text); 95} 96 97/** 98 * prepares section edit button data for event triggering 99 * used as a callback in html_secedit 100 * 101 * @author Andreas Gohr <andi@splitbrain.org> 102 * 103 * @param array $matches matches with regexp 104 * @return string 105 * @triggers HTML_SECEDIT_BUTTON 106 */ 107function html_secedit_button($matches){ 108 $json = htmlspecialchars_decode($matches[1], ENT_QUOTES); 109 $data = json_decode($json, true); 110 if ($data == NULL) { 111 return ''; 112 } 113 $data ['target'] = strtolower($data['target']); 114 $data ['hid'] = strtolower($data['hid']); 115 116 return Event::createAndTrigger('HTML_SECEDIT_BUTTON', $data, 117 'html_secedit_get_button'); 118} 119 120/** 121 * prints a section editing button 122 * used as default action form HTML_SECEDIT_BUTTON 123 * 124 * @author Adrian Lang <lang@cosmocode.de> 125 * 126 * @param array $data name, section id and target 127 * @return string html 128 */ 129function html_secedit_get_button($data) { 130 global $ID; 131 global $INFO; 132 133 if (!isset($data['name']) || $data['name'] === '') return ''; 134 135 $name = $data['name']; 136 unset($data['name']); 137 138 $secid = $data['secid']; 139 unset($data['secid']); 140 141 $params = array_merge( 142 array('do' => 'edit', 'rev' => $INFO['lastmod'], 'summary' => '['.$name.'] '), 143 $data 144 ); 145 146 $html = '<div class="secedit editbutton_'.$data['target'] .' editbutton_'.$secid .'">'; 147 $html.= html_btn('secedit', $ID, '', $params, 'post', $name); 148 $html.= '</div>'; 149 return $html; 150} 151 152/** 153 * Just the back to top button (in its own form) 154 * 155 * @author Andreas Gohr <andi@splitbrain.org> 156 * 157 * @return string html 158 */ 159function html_topbtn() { 160 global $lang; 161 162 return '<a class="nolink" href="#dokuwiki__top">' 163 .'<button class="button" onclick="window.scrollTo(0, 0)" title="'. $lang['btn_top'] .'">' 164 . $lang['btn_top'] 165 .'</button></a>'; 166} 167 168/** 169 * Displays a button (using its own form) 170 * If tooltip exists, the access key tooltip is replaced. 171 * 172 * @author Andreas Gohr <andi@splitbrain.org> 173 * 174 * @param string $name 175 * @param string $id 176 * @param string $akey access key 177 * @param string[] $params key-value pairs added as hidden inputs 178 * @param string $method 179 * @param string $tooltip 180 * @param bool|string $label label text, false: lookup btn_$name in localization 181 * @param string $svg (optional) svg code, inserted into the button 182 * @return string 183 */ 184function html_btn($name, $id, $akey, $params, $method = 'get', $tooltip = '', $label = false, $svg = null) { 185 global $conf; 186 global $lang; 187 188 if (!$label) 189 $label = $lang['btn_'.$name]; 190 191 //filter id (without urlencoding) 192 $id = idfilter($id,false); 193 194 //make nice URLs even for buttons 195 if ($conf['userewrite'] == 2) { 196 $script = DOKU_BASE.DOKU_SCRIPT.'/'.$id; 197 } elseif ($conf['userewrite']) { 198 $script = DOKU_BASE.$id; 199 } else { 200 $script = DOKU_BASE.DOKU_SCRIPT; 201 $params['id'] = $id; 202 } 203 204 $html = '<form class="button btn_'.$name.'" method="'.$method.'" action="'.$script.'"><div class="no">'; 205 206 if (is_array($params)) { 207 foreach ($params as $key => $val) { 208 $html .= '<input type="hidden" name="'.$key.'" value="'.hsc($val).'" />'; 209 } 210 } 211 212 $tip = empty($tooltip) ? hsc($label) : hsc($tooltip); 213 214 $html .= '<button type="submit" '; 215 if ($akey) { 216 $tip .= ' ['.strtoupper($akey).']'; 217 $html .= 'accesskey="'.$akey.'" '; 218 } 219 $html .= 'title="'.$tip.'">'; 220 if ($svg) { 221 $html .= '<span>'. hsc($label) .'</span>'. inlineSVG($svg); 222 } else { 223 $html .= hsc($label); 224 } 225 $html .= '</button>'; 226 $html .= '</div></form>'; 227 228 return $html; 229} 230/** 231 * show a revision warning 232 * 233 * @author Szymon Olewniczak <dokuwiki@imz.re> 234 * @deprecated 2020-07-18 235 */ 236function html_showrev() { 237 dbg_deprecated(PageView::class .'::showrev()'); 238} 239 240/** 241 * Show a wiki page 242 * 243 * @author Andreas Gohr <andi@splitbrain.org> 244 * 245 * @param null|string $txt wiki text or null for showing $ID 246 * @deprecated 2020-07-18 247 */ 248function html_show($txt=null) { 249 dbg_deprecated(PageView::class .'::show()'); 250 (new dokuwiki\Ui\PageView($txt))->show(); 251} 252 253/** 254 * ask the user about how to handle an exisiting draft 255 * 256 * @author Andreas Gohr <andi@splitbrain.org> 257 * @deprecated 2020-07-18 258 */ 259function html_draft() { 260 dbg_deprecated(PageDraft::class .'::show()'); 261 (new dokuwiki\Ui\PageDraft)->show(); 262} 263 264/** 265 * Highlights searchqueries in HTML code 266 * 267 * @author Andreas Gohr <andi@splitbrain.org> 268 * @author Harry Fuecks <hfuecks@gmail.com> 269 * 270 * @param string $html 271 * @param array|string $phrases 272 * @return string html 273 */ 274function html_hilight($html, $phrases) { 275 $phrases = (array) $phrases; 276 $phrases = array_map('preg_quote_cb', $phrases); 277 $phrases = array_map('ft_snippet_re_preprocess', $phrases); 278 $phrases = array_filter($phrases); 279 $regex = join('|',$phrases); 280 281 if ($regex === '') return $html; 282 if (!Clean::isUtf8($regex)) return $html; 283 284 return @preg_replace_callback("/((<[^>]*)|$regex)/ui", function ($match) { 285 $hlight = unslash($match[0]); 286 if (!isset($match[2])) { 287 $hlight = '<span class="search_hit">'.$hlight.'</span>'; 288 } 289 return $hlight; 290 }, $html); 291} 292 293/** 294 * Display error on locked pages 295 * 296 * @author Andreas Gohr <andi@splitbrain.org> 297 * @deprecated 2020-07-18 not called anymore, see inc/Action/Locked::tplContent() 298 */ 299function html_locked() { 300 dbg_deprecated(Locked::class .'::showBanner()'); 301 (new dokuwiki\Action\Locked())->showBanner(); 302} 303 304/** 305 * list old revisions 306 * 307 * @author Andreas Gohr <andi@splitbrain.org> 308 * @author Ben Coburn <btcoburn@silicodon.net> 309 * @author Kate Arzamastseva <pshns@ukr.net> 310 * 311 * @param int $first skip the first n changelog lines 312 * @param string $media_id id of media, or empty for current page 313 * @deprecated 2020-07-18 314 */ 315function html_revisions($first = 0, $media_id = '') { 316 dbg_deprecated(PageRevisions::class .'::show()'); 317 if ($media_id) { 318 (new dokuwiki\Ui\MediaRevisions($media_id))->show($first); 319 } else { 320 global $INFO; 321 (new dokuwiki\Ui\PageRevisions($INFO['id']))->show($first); 322 } 323} 324 325/** 326 * display recent changes 327 * 328 * @author Andreas Gohr <andi@splitbrain.org> 329 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 330 * @author Ben Coburn <btcoburn@silicodon.net> 331 * @author Kate Arzamastseva <pshns@ukr.net> 332 * 333 * @param int $first 334 * @param string $show_changes 335 * @deprecated 2020-07-18 336 */ 337function html_recent($first = 0, $show_changes = 'both') { 338 dbg_deprecated(Recent::class .'::show()'); 339 (new dokuwiki\Ui\Recent($first, $show_changes))->show(); 340} 341 342/** 343 * Display page index 344 * 345 * @author Andreas Gohr <andi@splitbrain.org> 346 * 347 * @param string $ns 348 * @deprecated 2020-07-18 349 */ 350function html_index($ns) { 351 dbg_deprecated(Index::class .'::show()'); 352 (new dokuwiki\Ui\Index($ns))->show(); 353} 354 355/** 356 * Index tree item formatter for html_buildlist() 357 * 358 * User function for html_buildlist() 359 * 360 * @author Andreas Gohr <andi@splitbrain.org> 361 * 362 * @param array $item 363 * @return string 364 * @deprecated 2020-07-18 365 */ 366function html_list_index($item) { 367 dbg_deprecated(Index::class .'::formatListItem()'); 368 return (new dokuwiki\Ui\Index)->formatListItem($item); 369} 370 371/** 372 * Index list item formatter for html_buildlist() 373 * 374 * This user function is used in html_buildlist to build the 375 * <li> tags for namespaces when displaying the page index 376 * it gives different classes to opened or closed "folders" 377 * 378 * @author Andreas Gohr <andi@splitbrain.org> 379 * 380 * @param array $item 381 * @return string html 382 * @deprecated 2020-07-18 383 */ 384function html_li_index($item) { 385 dbg_deprecated(Index::class .'::tagListItem()'); 386 return (new dokuwiki\Ui\Index)->tagListItem($item); 387} 388 389/** 390 * Default list item formatter for html_buildlist() 391 * 392 * @author Andreas Gohr <andi@splitbrain.org> 393 * 394 * @param array $item 395 * @return string html 396 * @deprecated 2020-07-18 397 */ 398function html_li_default($item){ 399 return '<li class="level'.$item['level'].'">'; 400} 401 402/** 403 * Build an unordered list 404 * 405 * Build an unordered list from the given $data array 406 * Each item in the array has to have a 'level' property 407 * the item itself gets printed by the given $func user 408 * function. The second and optional function is used to 409 * print the <li> tag. Both user function need to accept 410 * a single item. 411 * 412 * Both user functions can be given as array to point to 413 * a member of an object. 414 * 415 * @author Andreas Gohr <andi@splitbrain.org> 416 * 417 * @param array $data array with item arrays 418 * @param string $class class of ul wrapper 419 * @param callable $func callback to print an list item 420 * @param callable $lifunc (optional) callback to the opening li tag 421 * @param bool $forcewrapper (optional) Trigger building a wrapper ul if the first level is 422 * 0 (we have a root object) or 1 (just the root content) 423 * @return string html of an unordered list 424 */ 425function html_buildlist($data, $class, $func, $lifunc = null, $forcewrapper = false) { 426 if (count($data) === 0) { 427 return ''; 428 } 429 430 $firstElement = reset($data); 431 $start_level = $firstElement['level']; 432 $level = $start_level; 433 $html = ''; 434 $open = 0; 435 436 // set callback function to build the <li> tag, formerly defined as html_li_default() 437 if (!is_callable($lifunc)) { 438 $lifunc = function ($item) { 439 return '<li class="level'.$item['level'].'">'; 440 }; 441 } 442 443 foreach ($data as $item) { 444 if ($item['level'] > $level) { 445 //open new list 446 for ($i = 0; $i < ($item['level'] - $level); $i++) { 447 if ($i) $html .= '<li class="clear">'; 448 $html .= "\n".'<ul class="'.$class.'">'."\n"; 449 $open++; 450 } 451 $level = $item['level']; 452 453 } elseif ($item['level'] < $level) { 454 //close last item 455 $html .= '</li>'."\n"; 456 while ($level > $item['level'] && $open > 0 ) { 457 //close higher lists 458 $html .= '</ul>'."\n".'</li>'."\n"; 459 $level--; 460 $open--; 461 } 462 } elseif ($html !== '') { 463 //close previous item 464 $html .= '</li>'."\n"; 465 } 466 467 //print item 468 $html .= call_user_func($lifunc, $item); 469 $html .= '<div class="li">'; 470 471 $html .= call_user_func($func, $item); 472 $html .= '</div>'; 473 } 474 475 //close remaining items and lists 476 $html .= '</li>'."\n"; 477 while ($open-- > 0) { 478 $html .= '</ul></li>'."\n"; 479 } 480 481 if ($forcewrapper || $start_level < 2) { 482 // Trigger building a wrapper ul if the first level is 483 // 0 (we have a root object) or 1 (just the root content) 484 $html = "\n".'<ul class="'.$class.'">'."\n".$html.'</ul>'."\n"; 485 } 486 487 return $html; 488} 489 490/** 491 * display backlinks 492 * 493 * @author Andreas Gohr <andi@splitbrain.org> 494 * @author Michael Klier <chi@chimeric.de> 495 * @deprecated 2020-07-18 496 */ 497function html_backlinks() { 498 dbg_deprecated(Backlinks::class .'::show()'); 499 (new dokuwiki\Ui\Backlinks)->show(); 500} 501 502/** 503 * Get header of diff HTML 504 * 505 * @param string $l_rev Left revisions 506 * @param string $r_rev Right revision 507 * @param string $id Page id, if null $ID is used 508 * @param bool $media If it is for media files 509 * @param bool $inline Return the header on a single line 510 * @return string[] HTML snippets for diff header 511 * @deprecated 2020-07-18 512 */ 513function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = false) { 514 dbg_deprecated('see '. PageDiff::class .'::buildDiffHead()'); 515 return ['', '', '', '']; 516} 517 518/** 519 * Show diff 520 * between current page version and provided $text 521 * or between the revisions provided via GET or POST 522 * 523 * @author Andreas Gohr <andi@splitbrain.org> 524 * @param string $text when non-empty: compare with this text with most current version 525 * @param bool $intro display the intro text 526 * @param string $type type of the diff (inline or sidebyside) 527 * @deprecated 2020-07-18 528 */ 529function html_diff($text = '', $intro = true, $type = null) { 530 dbg_deprecated(PageDiff::class .'::show()'); 531 global $INFO; 532 (new dokuwiki\Ui\PageDiff($INFO['id']))->compareWith($text)->preference([ 533 'showIntro' => $intro, 534 'difftype' => $type, 535 ])->show(); 536} 537 538/** 539 * Create html for revision navigation 540 * 541 * @param PageChangeLog $pagelog changelog object of current page 542 * @param string $type inline vs sidebyside 543 * @param int $l_rev left revision timestamp 544 * @param int $r_rev right revision timestamp 545 * @return string[] html of left and right navigation elements 546 * @deprecated 2020-07-18 547 */ 548function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) { 549 dbg_deprecated('see '. PageDiff::class .'::buildRevisionsNavigation()'); 550 return ['', '']; 551} 552 553/** 554 * Create html link to a diff defined by two revisions 555 * 556 * @param string $difftype display type 557 * @param string $linktype 558 * @param int $lrev oldest revision 559 * @param int $rrev newest revision or null for diff with current revision 560 * @return string html of link to a diff 561 * @deprecated 2020-07-18 562 */ 563function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null) { 564 dbg_deprecated('see '. PageDiff::class .'::diffViewlink()'); 565 return ''; 566} 567 568/** 569 * Insert soft breaks in diff html 570 * 571 * @param string $diffhtml 572 * @return string 573 * @deprecated 2020-07-18 574 */ 575function html_insert_softbreaks($diffhtml) { 576 dbg_deprecated(PageDiff::class .'::insertSoftbreaks()'); 577 return (new dokuwiki\Ui\PageDiff)->insertSoftbreaks($diffhtml); 578} 579 580/** 581 * show warning on conflict detection 582 * 583 * @author Andreas Gohr <andi@splitbrain.org> 584 * 585 * @param string $text 586 * @param string $summary 587 * @deprecated 2020-07-18 588 */ 589function html_conflict($text, $summary) { 590 dbg_deprecated(PageConflict::class .'::show()'); 591 (new dokuwiki\Ui\PageConflict($text, $summary))->show(); 592} 593 594/** 595 * Prints the global message array 596 * 597 * @author Andreas Gohr <andi@splitbrain.org> 598 */ 599function html_msgarea() { 600 global $MSG, $MSG_shown; 601 /** @var array $MSG */ 602 // store if the global $MSG has already been shown and thus HTML output has been started 603 $MSG_shown = true; 604 605 if (!isset($MSG)) return; 606 607 $shown = array(); 608 foreach ($MSG as $msg) { 609 $hash = md5($msg['msg']); 610 if (isset($shown[$hash])) continue; // skip double messages 611 if (info_msg_allowed($msg)) { 612 print '<div class="'.$msg['lvl'].'">'; 613 print $msg['msg']; 614 print '</div>'; 615 } 616 $shown[$hash] = 1; 617 } 618 619 unset($GLOBALS['MSG']); 620} 621 622/** 623 * Prints the registration form 624 * 625 * @author Andreas Gohr <andi@splitbrain.org> 626 * @deprecated 2020-07-18 627 */ 628function html_register() { 629 dbg_deprecated(UserRegister::class .'::show()'); 630 (new dokuwiki\Ui\UserRegister)->show(); 631} 632 633/** 634 * Print the update profile form 635 * 636 * @author Christopher Smith <chris@jalakai.co.uk> 637 * @author Andreas Gohr <andi@splitbrain.org> 638 * @deprecated 2020-07-18 639 */ 640function html_updateprofile() { 641 dbg_deprecated(UserProfile::class .'::show()'); 642 (new dokuwiki\Ui\UserProfile)->show(); 643} 644 645/** 646 * Preprocess edit form data 647 * 648 * @author Andreas Gohr <andi@splitbrain.org> 649 * 650 * @deprecated 2020-07-18 651 */ 652function html_edit() { 653 dbg_deprecated(Editor::class .'::show()'); 654 (new dokuwiki\Ui\Editor)->show(); 655} 656 657/** 658 * Display the default edit form 659 * 660 * Is the default action for HTML_EDIT_FORMSELECTION. 661 * 662 * @param array $param 663 * @deprecated 2020-07-18 664 */ 665function html_edit_form($param) { 666 dbg_deprecated(Editor::class .'::addTextarea()'); 667 (new dokuwiki\Ui\Editor)->addTextarea($param); 668} 669 670/** 671 * prints some debug info 672 * 673 * @author Andreas Gohr <andi@splitbrain.org> 674 */ 675function html_debug() { 676 global $conf; 677 global $lang; 678 /** @var AuthPlugin $auth */ 679 global $auth; 680 global $INFO; 681 682 //remove sensitive data 683 $cnf = $conf; 684 debug_guard($cnf); 685 $nfo = $INFO; 686 debug_guard($nfo); 687 $ses = $_SESSION; 688 debug_guard($ses); 689 690 print '<html><body>'; 691 692 print '<p>When reporting bugs please send all the following '; 693 print 'output as a mail to andi@splitbrain.org '; 694 print 'The best way to do this is to save this page in your browser</p>'; 695 696 print '<b>$INFO:</b><pre>'; 697 print_r($nfo); 698 print '</pre>'; 699 700 print '<b>$_SERVER:</b><pre>'; 701 print_r($_SERVER); 702 print '</pre>'; 703 704 print '<b>$conf:</b><pre>'; 705 print_r($cnf); 706 print '</pre>'; 707 708 print '<b>DOKU_BASE:</b><pre>'; 709 print DOKU_BASE; 710 print '</pre>'; 711 712 print '<b>abs DOKU_BASE:</b><pre>'; 713 print DOKU_URL; 714 print '</pre>'; 715 716 print '<b>rel DOKU_BASE:</b><pre>'; 717 print dirname($_SERVER['PHP_SELF']).'/'; 718 print '</pre>'; 719 720 print '<b>PHP Version:</b><pre>'; 721 print phpversion(); 722 print '</pre>'; 723 724 print '<b>locale:</b><pre>'; 725 print setlocale(LC_ALL,0); 726 print '</pre>'; 727 728 print '<b>encoding:</b><pre>'; 729 print $lang['encoding']; 730 print '</pre>'; 731 732 if ($auth) { 733 print '<b>Auth backend capabilities:</b><pre>'; 734 foreach ($auth->getCapabilities() as $cando) { 735 print ' '.str_pad($cando,16) .' => '. (int)$auth->canDo($cando) . DOKU_LF; 736 } 737 print '</pre>'; 738 } 739 740 print '<b>$_SESSION:</b><pre>'; 741 print_r($ses); 742 print '</pre>'; 743 744 print '<b>Environment:</b><pre>'; 745 print_r($_ENV); 746 print '</pre>'; 747 748 print '<b>PHP settings:</b><pre>'; 749 $inis = ini_get_all(); 750 print_r($inis); 751 print '</pre>'; 752 753 if (function_exists('apache_get_version')) { 754 $apache = array(); 755 $apache['version'] = apache_get_version(); 756 757 if (function_exists('apache_get_modules')) { 758 $apache['modules'] = apache_get_modules(); 759 } 760 print '<b>Apache</b><pre>'; 761 print_r($apache); 762 print '</pre>'; 763 } 764 765 print '</body></html>'; 766} 767 768/** 769 * Form to request a new password for an existing account 770 * 771 * @author Benoit Chesneau <benoit@bchesneau.info> 772 * @author Andreas Gohr <gohr@cosmocode.de> 773 * @deprecated 2020-07-18 774 */ 775function html_resendpwd() { 776 dbg_deprecated(UserResendPwd::class .'::show()'); 777 (new dokuwiki\Ui\UserResendPwd)->show(); 778} 779 780/** 781 * Return the TOC rendered to XHTML 782 * 783 * @author Andreas Gohr <andi@splitbrain.org> 784 * 785 * @param array $toc 786 * @return string html 787 */ 788function html_TOC($toc) { 789 if (!count($toc)) return ''; 790 global $lang; 791 $out = '<!-- TOC START -->'.DOKU_LF; 792 $out .= '<div id="dw__toc" class="dw__toc">'.DOKU_LF; 793 $out .= '<h3 class="toggle">'; 794 $out .= $lang['toc']; 795 $out .= '</h3>'.DOKU_LF; 796 $out .= '<div>'.DOKU_LF; 797 $out .= html_buildlist($toc, 'toc', 'html_list_toc', null, true); 798 $out .= '</div>'.DOKU_LF.'</div>'.DOKU_LF; 799 $out .= '<!-- TOC END -->'.DOKU_LF; 800 return $out; 801} 802 803/** 804 * Callback for html_buildlist 805 * 806 * @param array $item 807 * @return string html 808 */ 809function html_list_toc($item) { 810 if (isset($item['hid'])){ 811 $link = '#'.$item['hid']; 812 } else { 813 $link = $item['link']; 814 } 815 816 return '<a href="'.$link.'">'.hsc($item['title']).'</a>'; 817} 818 819/** 820 * Helper function to build TOC items 821 * 822 * Returns an array ready to be added to a TOC array 823 * 824 * @param string $link - where to link (if $hash set to '#' it's a local anchor) 825 * @param string $text - what to display in the TOC 826 * @param int $level - nesting level 827 * @param string $hash - is prepended to the given $link, set blank if you want full links 828 * @return array the toc item 829 */ 830function html_mktocitem($link, $text, $level, $hash='#') { 831 return array( 832 'link' => $hash.$link, 833 'title' => $text, 834 'type' => 'ul', 835 'level' => $level 836 ); 837} 838 839/** 840 * Output a Doku_Form object. 841 * Triggers an event with the form name: HTML_{$name}FORM_OUTPUT 842 * 843 * @author Tom N Harris <tnharris@whoopdedo.org> 844 * 845 * @param string $name The name of the form 846 * @param Doku_Form $form The form 847 * @return void 848 * @deprecated 2020-07-18 849 */ 850function html_form($name, $form) { 851 dbg_deprecated('use dokuwiki\Form\Form instead of Doku_Form'); 852 // Safety check in case the caller forgets. 853 $form->endFieldset(); 854 Event::createAndTrigger('HTML_'.strtoupper($name).'FORM_OUTPUT', $form, 'html_form_output', false); 855} 856 857/** 858 * Form print function. 859 * Just calls printForm() on the form object. 860 * 861 * @param Doku_Form $form The form 862 * @return void 863 * @deprecated 2020-07-18 864 */ 865function html_form_output($form) { 866 dbg_deprecated('use dokuwiki\Form\Form::toHTML()'); 867 $form->printForm(); 868} 869 870/** 871 * Embed a flash object in HTML 872 * 873 * This will create the needed HTML to embed a flash movie in a cross browser 874 * compatble way using valid XHTML 875 * 876 * The parameters $params, $flashvars and $atts need to be associative arrays. 877 * No escaping needs to be done for them. The alternative content *has* to be 878 * escaped because it is used as is. If no alternative content is given 879 * $lang['noflash'] is used. 880 * 881 * @author Andreas Gohr <andi@splitbrain.org> 882 * @link http://latrine.dgx.cz/how-to-correctly-insert-a-flash-into-xhtml 883 * 884 * @param string $swf - the SWF movie to embed 885 * @param int $width - width of the flash movie in pixels 886 * @param int $height - height of the flash movie in pixels 887 * @param array $params - additional parameters (<param>) 888 * @param array $flashvars - parameters to be passed in the flashvar parameter 889 * @param array $atts - additional attributes for the <object> tag 890 * @param string $alt - alternative content (is NOT automatically escaped!) 891 * @return string - the XHTML markup 892 */ 893function html_flashobject($swf,$width,$height,$params=null,$flashvars=null,$atts=null,$alt=''){ 894 global $lang; 895 896 $out = ''; 897 898 // prepare the object attributes 899 if(is_null($atts)) $atts = array(); 900 $atts['width'] = (int) $width; 901 $atts['height'] = (int) $height; 902 if(!$atts['width']) $atts['width'] = 425; 903 if(!$atts['height']) $atts['height'] = 350; 904 905 // add object attributes for standard compliant browsers 906 $std = $atts; 907 $std['type'] = 'application/x-shockwave-flash'; 908 $std['data'] = $swf; 909 910 // add object attributes for IE 911 $ie = $atts; 912 $ie['classid'] = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; 913 914 // open object (with conditional comments) 915 $out .= '<!--[if !IE]> -->'.NL; 916 $out .= '<object '.buildAttributes($std).'>'.NL; 917 $out .= '<!-- <![endif]-->'.NL; 918 $out .= '<!--[if IE]>'.NL; 919 $out .= '<object '.buildAttributes($ie).'>'.NL; 920 $out .= ' <param name="movie" value="'.hsc($swf).'" />'.NL; 921 $out .= '<!--><!-- -->'.NL; 922 923 // print params 924 if(is_array($params)) foreach($params as $key => $val){ 925 $out .= ' <param name="'.hsc($key).'" value="'.hsc($val).'" />'.NL; 926 } 927 928 // add flashvars 929 if(is_array($flashvars)){ 930 $out .= ' <param name="FlashVars" value="'.buildURLparams($flashvars).'" />'.NL; 931 } 932 933 // alternative content 934 if($alt){ 935 $out .= $alt.NL; 936 }else{ 937 $out .= $lang['noflash'].NL; 938 } 939 940 // finish 941 $out .= '</object>'.NL; 942 $out .= '<!-- <![endif]-->'.NL; 943 944 return $out; 945} 946 947/** 948 * Prints HTML code for the given tab structure 949 * 950 * @param array $tabs tab structure 951 * @param string $current_tab the current tab id 952 * @return void 953 */ 954function html_tabs($tabs, $current_tab = null) { 955 echo '<ul class="tabs">'.NL; 956 957 foreach ($tabs as $id => $tab) { 958 html_tab($tab['href'], $tab['caption'], $id === $current_tab); 959 } 960 961 echo '</ul>'.NL; 962} 963 964/** 965 * Prints a single tab 966 * 967 * @author Kate Arzamastseva <pshns@ukr.net> 968 * @author Adrian Lang <mail@adrianlang.de> 969 * 970 * @param string $href - tab href 971 * @param string $caption - tab caption 972 * @param boolean $selected - is tab selected 973 * @return void 974 */ 975 976function html_tab($href, $caption, $selected = false) { 977 $tab = '<li>'; 978 if ($selected) { 979 $tab .= '<strong>'; 980 } else { 981 $tab .= '<a href="' . hsc($href) . '">'; 982 } 983 $tab .= hsc($caption) 984 . '</' . ($selected ? 'strong' : 'a') . '>' 985 . '</li>'.NL; 986 echo $tab; 987} 988 989/** 990 * Display size change 991 * 992 * @param int $sizechange - size of change in Bytes 993 * @param Doku_Form $form - (optional) form to add elements to 994 * @return void|string 995 */ 996function html_sizechange($sizechange, $form = null) { 997 if (isset($sizechange)) { 998 $class = 'sizechange'; 999 $value = filesize_h(abs($sizechange)); 1000 if ($sizechange > 0) { 1001 $class .= ' positive'; 1002 $value = '+' . $value; 1003 } elseif ($sizechange < 0) { 1004 $class .= ' negative'; 1005 $value = '-' . $value; 1006 } else { 1007 $value = '±' . $value; 1008 } 1009 if (!isset($form)) { 1010 return '<span class="'.$class.'">'.$value.'</span>'; 1011 } else { // Doku_Form 1012 $form->addElement(form_makeOpenTag('span', array('class' => $class))); 1013 $form->addElement($value); 1014 $form->addElement(form_makeCloseTag('span')); 1015 } 1016 } 1017} 1018