[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> html.php (source)

   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  
   9  use dokuwiki\Action\Denied;
  10  use dokuwiki\Action\Locked;
  11  use dokuwiki\ChangeLog\PageChangeLog;
  12  use dokuwiki\Extension\AuthPlugin;
  13  use dokuwiki\Extension\Event;
  14  use dokuwiki\Ui\Backlinks;
  15  use dokuwiki\Ui\Editor;
  16  use dokuwiki\Ui\Index;
  17  use dokuwiki\Ui\Login;
  18  use dokuwiki\Ui\PageConflict;
  19  use dokuwiki\Ui\PageDiff;
  20  use dokuwiki\Ui\PageDraft;
  21  use dokuwiki\Ui\PageRevisions;
  22  use dokuwiki\Ui\PageView;
  23  use dokuwiki\Ui\Recent;
  24  use dokuwiki\Ui\UserProfile;
  25  use dokuwiki\Ui\UserRegister;
  26  use dokuwiki\Ui\UserResendPwd;
  27  use dokuwiki\Utf8\Clean;
  28  
  29  if (!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   */
  43  function 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   */
  61  function 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   */
  72  function 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   */
  86  function 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   */
 107  function 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   */
 129  function 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   */
 159  function 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   */
 184  function 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   */
 236  function 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   */
 248  function 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   */
 259  function 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   */
 274  function 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   */
 299  function 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   */
 315  function 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   */
 337  function 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   */
 350  function 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   */
 366  function 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   */
 384  function 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   */
 398  function 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   */
 425  function 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   */
 497  function 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   */
 513  function 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   */
 529  function 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   */
 548  function 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   */
 563  function 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   */
 575  function 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   */
 589  function 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   */
 599  function 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   */
 628  function 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   */
 640  function 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   */
 652  function 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   */
 665  function 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   */
 675  function 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   */
 775  function 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   */
 788  function 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   */
 809  function 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   */
 830  function 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   */
 850  function 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   */
 865  function 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   */
 893  function 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   */
 954  function 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  
 976  function 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   */
 996  function 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  }