[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> template.php (source)

   1  <?php
   2  /**
   3   * DokuWiki template functions
   4   *
   5   * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   6   * @author     Andreas Gohr <andi@splitbrain.org>
   7   */
   8  
   9    if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/');
  10    require_once(DOKU_CONF.'dokuwiki.php');
  11  
  12  /**
  13   * Returns the path to the given template, uses
  14   * default one if the custom version doesn't exist.
  15   *
  16   * @author Andreas Gohr <andi@splitbrain.org>
  17   */
  18  function template($tpl){
  19    global $conf;
  20  
  21    if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl))
  22      return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl;
  23  
  24    return DOKU_INC.'lib/tpl/default/'.$tpl;
  25  }
  26  
  27  /**
  28   * Print the content
  29   *
  30   * This function is used for printing all the usual content
  31   * (defined by the global $ACT var) by calling the appropriate
  32   * outputfunction(s) from html.php
  33   *
  34   * Everything that doesn't use the main template file isn't
  35   * handled by this function. ACL stuff is not done here either.
  36   *
  37   * @author Andreas Gohr <andi@splitbrain.org>
  38   */
  39  function tpl_content($prependTOC=true) {
  40      global $ACT;
  41      global $INFO;
  42      $INFO['prependTOC'] = $prependTOC;
  43  
  44      ob_start();
  45      trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core');
  46      $html_output = ob_get_clean();
  47      trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln');
  48  
  49      return !empty($html_output);
  50  }
  51  
  52  function tpl_content_core(){
  53    global $ACT;
  54    global $TEXT;
  55    global $PRE;
  56    global $SUF;
  57    global $SUM;
  58    global $IDX;
  59  
  60    switch($ACT){
  61      case 'show':
  62        html_show();
  63        break;
  64      case 'preview':
  65        html_edit($TEXT);
  66        html_show($TEXT);
  67        break;
  68      case 'recover':
  69        html_edit($TEXT);
  70        break;
  71      case 'edit':
  72        html_edit();
  73        break;
  74      case 'draft':
  75        html_draft();
  76        break;
  77      case 'wordblock':
  78        html_edit($TEXT,'wordblock');
  79        break;
  80      case 'search':
  81        html_search();
  82        break;
  83      case 'revisions':
  84        $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  85        html_revisions($first);
  86        break;
  87      case 'diff':
  88        html_diff();
  89        break;
  90      case 'recent':
  91        if (is_array($_REQUEST['first'])) {
  92          $_REQUEST['first'] = array_keys($_REQUEST['first']);
  93          $_REQUEST['first'] = $_REQUEST['first'][0];
  94        }
  95        $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  96        html_recent($first);
  97        break;
  98      case 'index':
  99        html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
 100        break;
 101      case 'backlink':
 102        html_backlinks();
 103        break;
 104      case 'conflict':
 105        html_conflict(con($PRE,$TEXT,$SUF),$SUM);
 106        html_diff(con($PRE,$TEXT,$SUF),false);
 107        break;
 108      case 'locked':
 109        html_locked();
 110        html_edit();
 111        break;
 112      case 'login':
 113        html_login();
 114        break;
 115      case 'register':
 116        html_register();
 117        break;
 118      case 'resendpwd':
 119        html_resendpwd();
 120        break;
 121      case 'denied':
 122        print p_locale_xhtml('denied');
 123        break;
 124      case 'profile' :
 125        html_updateprofile();
 126        break;
 127      case 'admin':
 128        tpl_admin();
 129        break;
 130      default:
 131        $evt = new Doku_Event('TPL_ACT_UNKNOWN',$ACT);
 132        if ($evt->advise_before())
 133          msg("Failed to handle command: ".hsc($ACT),-1);
 134        $evt->advise_after();
 135        unset($evt);
 136        return false;
 137    }
 138    return true;
 139  }
 140  
 141  /**
 142   * Places the TOC where the function is called
 143   *
 144   * If you use this you most probably want to call tpl_content with
 145   * a false argument
 146   *
 147   * @author Andreas Gohr <andi@splitbrain.org>
 148   */
 149  function tpl_toc($return=false){
 150      global $TOC;
 151      global $ACT;
 152      global $ID;
 153      global $REV;
 154      global $INFO;
 155      $toc = array();
 156  
 157      if(is_array($TOC)){
 158          // if a TOC was prepared in global scope, always use it
 159          $toc = $TOC;
 160      }elseif(($ACT == 'show' || substr($ACT,0,6) == 'export') && !$REV && $INFO['exists']){
 161          // get TOC from metadata, render if neccessary
 162          $meta = p_get_metadata($ID, false, true);
 163          if(isset($meta['internal']['toc'])){
 164              $tocok = $meta['internal']['toc'];
 165          }else{
 166              $tocok = true;
 167          }
 168          $toc   = $meta['description']['tableofcontents'];
 169          if(!$tocok || !is_array($toc) || count($toc) < 3){
 170              $toc = array();
 171          }
 172      }elseif($ACT == 'admin'){
 173          // try to load admin plugin TOC FIXME: duplicates code from tpl_admin
 174          $plugin = null;
 175          if (!empty($_REQUEST['page'])) {
 176              $pluginlist = plugin_list('admin');
 177              if (in_array($_REQUEST['page'], $pluginlist)) {
 178                  // attempt to load the plugin
 179                  $plugin =& plugin_load('admin',$_REQUEST['page']);
 180              }
 181          }
 182          if ( ($plugin !== null) &&
 183               (!$plugin->forAdminOnly() || $INFO['isadmin']) ){
 184              $toc = $plugin->getTOC();
 185              $TOC = $toc; // avoid later rebuild
 186          }
 187      }
 188  
 189      trigger_event('TPL_TOC_RENDER', $toc, NULL, false);
 190      $html = html_TOC($toc);
 191      if($return) return $html;
 192      echo $html;
 193  }
 194  
 195  /**
 196   * Handle the admin page contents
 197   *
 198   * @author Andreas Gohr <andi@splitbrain.org>
 199   */
 200  function tpl_admin(){
 201      global $INFO;
 202      global $TOC;
 203  
 204      $plugin = null;
 205      if (!empty($_REQUEST['page'])) {
 206          $pluginlist = plugin_list('admin');
 207  
 208          if (in_array($_REQUEST['page'], $pluginlist)) {
 209  
 210            // attempt to load the plugin
 211            $plugin =& plugin_load('admin',$_REQUEST['page']);
 212          }
 213      }
 214  
 215      if ($plugin !== null){
 216          if($plugin->forAdminOnly() && !$INFO['isadmin']){
 217              msg('For admins only',-1);
 218              html_admin();
 219          }else{
 220              if(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet
 221              if($INFO['prependTOC']) tpl_toc();
 222              $plugin->html();
 223          }
 224      }else{
 225          html_admin();
 226      }
 227      return true;
 228  }
 229  
 230  /**
 231   * Print the correct HTML meta headers
 232   *
 233   * This has to go into the head section of your template.
 234   *
 235   * @triggers TPL_METAHEADER_OUTPUT
 236   * @param  boolean $alt Should feeds and alternative format links be added?
 237   * @author Andreas Gohr <andi@splitbrain.org>
 238   */
 239  function tpl_metaheaders($alt=true){
 240    global $ID;
 241    global $REV;
 242    global $INFO;
 243    global $ACT;
 244    global $QUERY;
 245    global $lang;
 246    global $conf;
 247    $it=2;
 248  
 249    // prepare the head array
 250    $head = array();
 251  
 252  
 253    // the usual stuff
 254    $head['meta'][] = array( 'name'=>'generator', 'content'=>'DokuWiki '.getVersion() );
 255    $head['link'][] = array( 'rel'=>'search', 'type'=>'application/opensearchdescription+xml',
 256                             'href'=>DOKU_BASE.'lib/exe/opensearch.php', 'title'=>$conf['title'] );
 257    $head['link'][] = array( 'rel'=>'start', 'href'=>DOKU_BASE );
 258    if(actionOK('index')){
 259      $head['link'][] = array( 'rel'=>'contents', 'href'=> wl($ID,'do=index',false,'&'),
 260                             'title'=>$lang['btn_index'] );
 261    }
 262  
 263    if($alt){
 264      $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
 265                               'title'=>'Recent Changes', 'href'=>DOKU_BASE.'feed.php');
 266      $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
 267                               'title'=>'Current Namespace',
 268                               'href'=>DOKU_BASE.'feed.php?mode=list&ns='.$INFO['namespace']);
 269      if(($ACT == 'show' || $ACT == 'search') && $INFO['writable']){
 270          $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/wiki',
 271                                   'title'=>$lang['btn_edit'],
 272                                   'href'=> wl($ID,'do=edit',false,'&'));
 273      }
 274  
 275      if($ACT == 'search'){
 276        $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
 277                                 'title'=>'Search Result',
 278                                 'href'=>DOKU_BASE.'feed.php?mode=search&q='.$QUERY);
 279      }
 280  
 281      if(actionOK('export_xhtml')){
 282        $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/html', 'title'=>'Plain HTML',
 283                                 'href'=>exportlink($ID, 'xhtml', '', false, '&'));
 284      }
 285  
 286      if(actionOK('export_raw')){
 287        $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/plain', 'title'=>'Wiki Markup',
 288                                 'href'=>exportlink($ID, 'raw', '', false, '&'));
 289      }
 290    }
 291  
 292    // setup robot tags apropriate for different modes
 293    if( ($ACT=='show' || $ACT=='export_xhtml') && !$REV){
 294      if($INFO['exists']){
 295        //delay indexing:
 296        if((time() - $INFO['lastmod']) >= $conf['indexdelay']){
 297          $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
 298        }else{
 299          $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
 300        }
 301      }else{
 302        $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,follow');
 303      }
 304    }elseif(defined('DOKU_MEDIADETAIL')){
 305      $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
 306    }else{
 307      $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
 308    }
 309  
 310    // set metadata
 311    if($ACT == 'show' || $ACT=='export_xhtml'){
 312      // date of modification
 313      if($REV){
 314        $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$REV));
 315      }else{
 316        $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$INFO['lastmod']));
 317      }
 318  
 319      // keywords (explicit or implicit)
 320      if(!empty($INFO['meta']['subject'])){
 321        $head['meta'][] = array( 'name'=>'keywords', 'content'=>join(',',$INFO['meta']['subject']));
 322      }else{
 323        $head['meta'][] = array( 'name'=>'keywords', 'content'=>str_replace(':',',',$ID));
 324      }
 325    }
 326  
 327    // load stylesheets
 328    $head['link'][] = array('rel'=>'stylesheet', 'media'=>'all', 'type'=>'text/css',
 329                            'href'=>DOKU_BASE.'lib/exe/css.php?s=all&t='.$conf['template']);
 330    $head['link'][] = array('rel'=>'stylesheet', 'media'=>'screen', 'type'=>'text/css',
 331                            'href'=>DOKU_BASE.'lib/exe/css.php?t='.$conf['template']);
 332    $head['link'][] = array('rel'=>'stylesheet', 'media'=>'print', 'type'=>'text/css',
 333                            'href'=>DOKU_BASE.'lib/exe/css.php?s=print&t='.$conf['template']);
 334  
 335    // load javascript
 336    $js_edit  = ($ACT=='edit' || $ACT=='preview' || $ACT=='recover' || $ACT=='wordblock' ) ? 1 : 0;
 337    $js_write = ($INFO['writable']) ? 1 : 0;
 338    if(defined('DOKU_MEDIAMANAGER')){
 339      $js_edit  = 1;
 340      $js_write = 0;
 341    }
 342    if(($js_edit && $js_write) || defined('DOKU_MEDIAMANAGER')){
 343      $script = "NS='".$INFO['namespace']."';";
 344      if($conf['useacl'] && $_SERVER['REMOTE_USER']){
 345        require_once (DOKU_INC.'inc/toolbar.php');
 346        $script .= "SIG='".toolbar_signature()."';";
 347      }
 348      $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8',
 349                                 '_data'=> $script);
 350    }
 351    $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8', '_data'=>'',
 352                               'src'=>DOKU_BASE.'lib/exe/js.php?edit='.$js_edit.'&write='.$js_write);
 353  
 354    // trigger event here
 355    trigger_event('TPL_METAHEADER_OUTPUT',$head,'_tpl_metaheaders_action',true);
 356    return true;
 357  }
 358  
 359  /**
 360   * prints the array build by tpl_metaheaders
 361   *
 362   * $data is an array of different header tags. Each tag can have multiple
 363   * instances. Attributes are given as key value pairs. Values will be HTML
 364   * encoded automatically so they should be provided as is in the $data array.
 365   *
 366   * For tags having a body attribute specify the the body data in the special
 367   * attribute '_data'. This field will NOT BE ESCAPED automatically.
 368   *
 369   * @author Andreas Gohr <andi@splitbrain.org>
 370   */
 371  function _tpl_metaheaders_action($data){
 372    foreach($data as $tag => $inst){
 373      foreach($inst as $attr){
 374        echo '<',$tag,' ',buildAttributes($attr);
 375        if(isset($attr['_data'])){
 376            if($tag == 'script' && $attr['_data'])
 377              $attr['_data'] = "<!--//--><![CDATA[//><!--\n".
 378                               $attr['_data'].
 379                               "\n//--><!]]>";
 380  
 381            echo '>',$attr['_data'],'</',$tag,'>';
 382        }else{
 383          echo '/>';
 384        }
 385        echo "\n";
 386      }
 387    }
 388  }
 389  
 390  /**
 391   * Print a link
 392   *
 393   * Just builds a link.
 394   *
 395   * @author Andreas Gohr <andi@splitbrain.org>
 396   */
 397  function tpl_link($url,$name,$more=''){
 398    print '<a href="'.$url.'" ';
 399    if ($more) print ' '.$more;
 400    print ">$name</a>";
 401    return true;
 402  }
 403  
 404  /**
 405   * Prints a link to a WikiPage
 406   *
 407   * Wrapper around html_wikilink
 408   *
 409   * @author Andreas Gohr <andi@splitbrain.org>
 410   */
 411  function tpl_pagelink($id,$name=NULL){
 412    print html_wikilink($id,$name);
 413    return true;
 414  }
 415  
 416  /**
 417   * get the parent page
 418   *
 419   * Tries to find out which page is parent.
 420   * returns false if none is available
 421   *
 422   * @author Andreas Gohr <andi@splitbrain.org>
 423   */
 424  function tpl_getparent($id){
 425    global $conf;
 426    $parent = getNS($id).':';
 427    resolve_pageid('',$parent,$exists);
 428    if($parent == $id) {
 429      $pos = strrpos (getNS($id),':');
 430      $parent = substr($parent,0,$pos).':';
 431      resolve_pageid('',$parent,$exists);
 432      if($parent == $id) return false;
 433    }
 434    return $parent;
 435  }
 436  
 437  /**
 438   * Print one of the buttons
 439   *
 440   * Available Buttons are
 441   *
 442   *  edit        - edit/create/show/draft button
 443   *  history     - old revisions
 444   *  recent      - recent changes
 445   *  login       - login/logout button - if ACL enabled
 446   *  profile     - user profile button (if logged in)
 447   *  index       - The index
 448   *  admin       - admin page - if enough rights
 449   *  top         - a back to top button
 450   *  back        - a back to parent button - if available
 451   *  backlink    - links to the list of backlinks
 452   *  subscription- subscribe/unsubscribe button
 453   *
 454   * @author Andreas Gohr <andi@splitbrain.org>
 455   * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
 456   */
 457  function tpl_button($type){
 458    global $ACT;
 459    global $ID;
 460    global $REV;
 461    global $NS;
 462    global $INFO;
 463    global $conf;
 464    global $auth;
 465  
 466    // check disabled actions and fix the badly named ones
 467    $ctype = $type;
 468    if($type == 'history') $ctype='revisions';
 469    if(!actionOK($ctype)) return false;
 470  
 471    switch($type){
 472      case 'edit':
 473        #most complicated type - we need to decide on current action
 474        if($ACT == 'show' || $ACT == 'search'){
 475          if($INFO['writable']){
 476            if(!empty($INFO['draft'])){
 477              echo html_btn('draft',$ID,'e',array('do' => 'draft'),'post');
 478            }else{
 479              if($INFO['exists']){
 480                echo html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
 481              }else{
 482                echo html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
 483              }
 484            }
 485          }else{
 486            if(!actionOK('source')) return false; //pseudo action
 487            echo html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post');
 488          }
 489        }else{
 490            echo html_btn('show',$ID,'v',array('do' => 'show'));
 491        }
 492        return true;
 493      case 'history':
 494        if(!actionOK('revisions'))
 495          return false;
 496        print html_btn('revs',$ID,'o',array('do' => 'revisions'));
 497        return true;
 498      case 'recent':
 499        if(!actionOK('recent'))
 500          return false;
 501        print html_btn('recent',$ID,'r',array('do' => 'recent'));
 502        return true;
 503      case 'index':
 504        if(!actionOK('index'))
 505          return false;
 506        print html_btn('index',$ID,'x',array('do' => 'index'));
 507        return true;
 508      case 'back':
 509        if ($parent = tpl_getparent($ID)) {
 510          print html_btn('back',$parent,'b',array('do' => 'show'));
 511          return true;
 512        }
 513        return false;
 514      case 'top':
 515        print html_topbtn();
 516        return true;
 517      case 'login':
 518        if($conf['useacl'] && $auth){
 519          if($_SERVER['REMOTE_USER']){
 520            print html_btn('logout',$ID,'',array('do' => 'logout', 'sectok' => getSecurityToken()));
 521          }else{
 522            print html_btn('login',$ID,'',array('do' => 'login', 'sectok' => getSecurityToken()));
 523          }
 524          return true;
 525        }
 526        return false;
 527      case 'admin':
 528        if($INFO['ismanager']){
 529          print html_btn('admin',$ID,'',array('do' => 'admin'));
 530          return true;
 531        }
 532        return false;
 533      case 'subscribe':
 534      case 'subscription':
 535        if($conf['useacl'] && $auth && $ACT == 'show' && $conf['subscribers'] == 1){
 536          if($_SERVER['REMOTE_USER']){
 537            if($INFO['subscribed']){
 538              if(!actionOK('unsubscribe'))
 539                return false;
 540              print html_btn('unsubscribe',$ID,'',array('do' => 'unsubscribe',));
 541            } else {
 542              if(!actionOK('subscribe'))
 543                return false;
 544              print html_btn('subscribe',$ID,'',array('do' => 'subscribe',));
 545            }
 546            if($type == 'subscribe') return true;
 547          }
 548        }
 549        if($type == 'subscribe') return false;
 550        // fall through for backward compatibility
 551      case 'subscribens':
 552        if($conf['useacl'] && $auth && $ACT == 'show' && $conf['subscribers'] == 1){
 553          if($_SERVER['REMOTE_USER']){
 554            if($INFO['subscribedns']){
 555              if(!actionOK('unsubscribens'))
 556                return false;
 557              print html_btn('unsubscribens',$ID,'',array('do' => 'unsubscribens',));
 558            } else {
 559              if(!actionOK('subscribens'))
 560                return false;
 561              print html_btn('subscribens',$ID,'',array('do' => 'subscribens',));
 562            }
 563            return true;
 564          }
 565        }
 566        return false;
 567      case 'backlink':
 568        if(!actionOK('backlink'))
 569          return false;
 570        print html_btn('backlink',$ID,'',array('do' => 'backlink'));
 571        return true;
 572      case 'profile':
 573        if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $auth &&
 574           $auth->canDo('Profile') && ($ACT!='profile')){
 575          print html_btn('profile',$ID,'',array('do' => 'profile'));
 576          return true;
 577        }
 578        return false;
 579      default:
 580        print '[unknown button type]';
 581        return true;
 582    }
 583  }
 584  
 585  /**
 586   * Like the action buttons but links
 587   *
 588   * Available links are
 589   *
 590   *  edit    - edit/create/show link
 591   *  history - old revisions
 592   *  recent  - recent changes
 593   *  login   - login/logout link - if ACL enabled
 594   *  profile - user profile link (if logged in)
 595   *  index   - The index
 596   *  admin   - admin page - if enough rights
 597   *  top     - a back to top link
 598   *  back    - a back to parent link - if available
 599   *  backlink - links to the list of backlinks
 600   *  subscribe/subscription - subscribe/unsubscribe link
 601   *
 602   * @author Andreas Gohr <andi@splitbrain.org>
 603   * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
 604   * @see    tpl_button
 605   */
 606  function tpl_actionlink($type,$pre='',$suf='',$inner=''){
 607    global $ID;
 608    global $INFO;
 609    global $REV;
 610    global $ACT;
 611    global $conf;
 612    global $lang;
 613    global $auth;
 614  
 615    // check disabled actions and fix the badly named ones
 616    $ctype = $type;
 617    if($type == 'history') $ctype='revisions';
 618    if(!actionOK($ctype)) return false;
 619  
 620    switch($type){
 621      case 'edit':
 622        #most complicated type - we need to decide on current action
 623        if($ACT == 'show' || $ACT == 'search'){
 624          if($INFO['writable']){
 625            if(!empty($INFO['draft'])) {
 626              tpl_link(wl($ID,'do=draft'),
 627                         $pre.(($inner)?$inner:$lang['btn_draft']).$suf,
 628                         'class="action edit" accesskey="e" rel="nofollow"');
 629            } else {
 630              if($INFO['exis