xref: /dokuwiki/inc/template.php (revision aa84c75bde8809d9ed957b0e49977b296ba14e26)
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',realpath(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 * Also enables gzip compression if configured.
16 *
17 * @author Andreas Gohr <andi@splitbrain.org>
18 */
19function template($tpl){
20  global $conf;
21
22  if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl))
23    return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl;
24
25  return DOKU_INC.'lib/tpl/default/'.$tpl;
26}
27
28/**
29 * Print the content
30 *
31 * This function is used for printing all the usual content
32 * (defined by the global $ACT var) by calling the appropriate
33 * outputfunction(s) from html.php
34 *
35 * Everything that doesn't use the main template file isn't
36 * handled by this function. ACL stuff is not done here either.
37 *
38 * @author Andreas Gohr <andi@splitbrain.org>
39 */
40function tpl_content() {
41  global $ACT;
42
43  ob_start();
44
45  trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core');
46
47  $html_output = ob_get_clean();
48
49  trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln');
50}
51
52function 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      $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
92      html_recent($first);
93      break;
94    case 'index':
95      html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
96      break;
97    case 'backlink':
98      html_backlinks();
99      break;
100    case 'conflict':
101      html_conflict(con($PRE,$TEXT,$SUF),$SUM);
102      html_diff(con($PRE,$TEXT,$SUF),false);
103      break;
104    case 'locked':
105      html_locked();
106      break;
107    case 'login':
108      html_login();
109      break;
110    case 'register':
111      html_register();
112      break;
113    case 'resendpwd':
114      html_resendpwd();
115      break;
116    case 'denied':
117      print p_locale_xhtml('denied');
118      break;
119    case 'profile' :
120      html_updateprofile();
121      break;
122    case 'admin':
123      tpl_admin();
124      break;
125    default:
126      $evt = new Doku_Event('TPL_ACT_UNKNOWN',$ACT);
127      if ($evt->advise_before())
128        msg("Failed to handle command: ".hsc($ACT),-1);
129      $evt->advise_after();
130      unset($evt);
131  }
132}
133
134/**
135 * Handle the admin page contents
136 *
137 * @author Andreas Gohr <andi@splitbrain.org>
138 */
139function tpl_admin(){
140
141    $plugin = NULL;
142    if ($_REQUEST['page']) {
143        $pluginlist = plugin_list('admin');
144
145        if (in_array($_REQUEST['page'], $pluginlist)) {
146
147          // attempt to load the plugin
148          $plugin =& plugin_load('admin',$_REQUEST['page']);
149        }
150    }
151
152    if ($plugin !== NULL)
153        $plugin->html();
154    else
155        html_admin();
156}
157
158/**
159 * Print the correct HTML meta headers
160 *
161 * This has to go into the head section of your template.
162 *
163 * @param  boolean $alt Should feeds and alternative format links be added?
164 * @author Andreas Gohr <andi@splitbrain.org>
165 */
166function tpl_metaheaders($alt=true){
167  global $ID;
168  global $REV;
169  global $INFO;
170  global $ACT;
171  global $lang;
172  global $conf;
173  $it=2;
174
175  // the usual stuff
176  ptln('<meta name="generator" content="DokuWiki '.getVersion().'" />',$it);
177  ptln('<link rel="start" href="'.DOKU_BASE.'" />',$it);
178  ptln('<link rel="contents" href="'.wl($ID,'do=index').'" title="'.$lang['index'].'" />',$it);
179
180  if($alt){
181    ptln('<link rel="alternate" type="application/rss+xml" title="Recent Changes" href="'.DOKU_BASE.'feed.php" />',$it);
182    ptln('<link rel="alternate" type="application/rss+xml" title="Current Namespace" href="'.DOKU_BASE.'feed.php?mode=list&amp;ns='.$INFO['namespace'].'" />',$it);
183    ptln('<link rel="alternate" type="text/html" title="Plain HTML" href="'.exportlink($ID, 'xhtml').'" />',$it);
184    ptln('<link rel="alternate" type="text/plain" title="Wiki Markup" href="'.exportlink($ID, 'raw').'" />',$it);
185  }
186
187  // setup robot tags apropriate for different modes
188  if( ($ACT=='show' || $ACT=='export_xhtml') && !$REV){
189    if($INFO['exists']){
190      ptln('<meta name="date" content="'.date('Y-m-d\TH:i:sO',$INFO['lastmod']).'" />',$it);
191      //delay indexing:
192      if((time() - $INFO['lastmod']) >= $conf['indexdelay']){
193        ptln('<meta name="robots" content="index,follow" />',$it);
194      }else{
195        ptln('<meta name="robots" content="noindex,nofollow" />',$it);
196      }
197    }else{
198      ptln('<meta name="robots" content="noindex,follow" />',$it);
199    }
200  }elseif(defined('DOKU_MEDIADETAIL')){
201    ptln('<meta name="robots" content="index,follow" />',$it);
202  }else{
203    ptln('<meta name="robots" content="noindex,nofollow" />',$it);
204  }
205
206  // load stylesheets
207  ptln('<link rel="stylesheet" media="screen" type="text/css" href="'.DOKU_BASE.'lib/exe/css.php" />',$it);
208  ptln('<link rel="stylesheet" media="print" type="text/css" href="'.DOKU_BASE.'lib/exe/css.php?print=1" />',$it);
209
210  // load javascript
211  $js_edit  = ($ACT=='edit' || $ACT=='preview' || $ACT=='recover') ? 1 : 0;
212  $js_write = ($INFO['writable']) ? 1 : 0;
213  if(defined('DOKU_MEDIAMANAGER')){
214    $js_edit  = 1;
215    $js_write = 0;
216  }
217  if(($js_edit && $js_write) || defined('DOKU_MEDIAMANAGER')){
218    ptln('<script type="text/javascript" charset="utf-8">',$it);
219    ptln("NS='".$INFO['namespace']."';",$it+2);
220    if($conf['useacl'] && $_SERVER['REMOTE_USER']){
221      require_once(DOKU_INC.'inc/toolbar.php');
222      ptln("SIG='".toolbar_signature()."';",$it+2);
223    }
224    ptln('</script>',$it);
225  }
226  ptln('<script type="text/javascript" charset="utf-8" src="'.
227       DOKU_BASE.'lib/exe/js.php?edit='.$js_edit.'&amp;write='.$js_write.'"></script>',$it);
228}
229
230/**
231 * Print a link
232 *
233 * Just builds a link.
234 *
235 * @author Andreas Gohr <andi@splitbrain.org>
236 */
237function tpl_link($url,$name,$more=''){
238  print '<a href="'.$url.'" ';
239  if ($more) print ' '.$more;
240  print ">$name</a>";
241}
242
243/**
244 * Prints a link to a WikiPage
245 *
246 * Wrapper around html_wikilink
247 *
248 * @author Andreas Gohr <andi@splitbrain.org>
249 */
250function tpl_pagelink($id,$name=NULL){
251  print html_wikilink($id,$name);
252}
253
254/**
255 * get the parent page
256 *
257 * Tries to find out which page is parent.
258 * returns false if none is available
259 *
260 * @author Andreas Gohr <andi@splitbrain.org>
261 */
262function tpl_getparent($id){
263  global $conf;
264  $parent = getNS($id).':';
265  resolve_pageid('',$parent,$exists);
266  if($parent == $id) {
267    $pos = strrpos (getNS($id),':');
268    $parent = substr($parent,0,$pos).':';
269    resolve_pageid('',$parent,$exists);
270    if($parent == $id) return false;
271  }
272  return $parent;
273}
274
275/**
276 * Print one of the buttons
277 *
278 * Available Buttons are
279 *
280 *  edit        - edit/create/show/draft button
281 *  history     - old revisions
282 *  recent      - recent changes
283 *  login       - login/logout button - if ACL enabled
284 *  index       - The index
285 *  admin       - admin page - if enough rights
286 *  top         - a back to top button
287 *  back        - a back to parent button - if available
288 *  backtomedia - returns to the mediafile upload dialog
289 *                after references have been displayed
290 *  backlink    - links to the list of backlinks
291 *
292 * @author Andreas Gohr <andi@splitbrain.org>
293 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
294 */
295function tpl_button($type){
296  global $ACT;
297  global $ID;
298  global $REV;
299  global $NS;
300  global $INFO;
301  global $conf;
302  global $auth;
303
304  // check disabled actions and fix the badly named ones
305  $ctype = $type;
306  if($type == 'history') $ctype='revisions';
307  if(!actionOK($ctype)) return;
308
309  switch($type){
310    case 'edit':
311      #most complicated type - we need to decide on current action
312      if($ACT == 'show' || $ACT == 'search'){
313        if($INFO['writable']){
314          if($INFO['draft']){
315            echo html_btn('draft',$ID,'e',array('do' => 'draft'),'post');
316          }else{
317            if($INFO['exists']){
318              echo html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
319            }else{
320              echo html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
321            }
322          }
323        }else{
324          if(!actionOK('source')) return false; //pseudo action
325          echo html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post');
326        }
327      }else{
328          echo html_btn('show',$ID,'v',array('do' => 'show'));
329      }
330      break;
331    case 'history':
332      print html_btn('revs',$ID,'o',array('do' => 'revisions'));
333      break;
334    case 'recent':
335      print html_btn('recent','','r',array('do' => 'recent'));
336      break;
337    case 'index':
338      print html_btn('index',$ID,'x',array('do' => 'index'));
339      break;
340    case 'back':
341      if ($parent = tpl_getparent($ID)) {
342        print html_btn('back',$parent,'b',array('do' => 'show'));
343      }
344      break;
345    case 'top':
346      print html_topbtn();
347      break;
348    case 'login':
349      if($conf['useacl']){
350        if($_SERVER['REMOTE_USER']){
351          print html_btn('logout',$ID,'',array('do' => 'logout',));
352        }else{
353          print html_btn('login',$ID,'',array('do' => 'login'));
354        }
355      }
356      break;
357    case 'admin':
358      if($INFO['perm'] == AUTH_ADMIN)
359        print html_btn('admin',$ID,'',array('do' => 'admin'));
360      break;
361    case 'backtomedia':
362      print html_backtomedia_button(array('ns' => $NS),'b');
363      break;
364    case 'subscription':
365      if($conf['useacl'] && $ACT == 'show' && $conf['subscribers'] == 1){
366        if($_SERVER['REMOTE_USER']){
367          if($INFO['subscribed']){
368            print html_btn('unsubscribe',$ID,'',array('do' => 'unsubscribe',));
369          } else {
370            print html_btn('subscribe',$ID,'',array('do' => 'subscribe',));
371          }
372        }
373      }
374      break;
375    case 'backlink':
376      print html_btn('backlink',$ID,'',array('do' => 'backlink'));
377      break;
378    case 'profile':
379      if($conf['useacl'] && $_SERVER['REMOTE_USER'] &&
380         $auth->canDo('Profile') && ($ACT!='profile')){
381        print html_btn('profile',$ID,'',array('do' => 'profile'));
382      }
383      break;
384    default:
385      print '[unknown button type]';
386  }
387}
388
389/**
390 * Like the action buttons but links
391 *
392 * Available links are
393 *
394 *  edit    - edit/create/show button
395 *  history - old revisions
396 *  recent  - recent changes
397 *  login   - login/logout button - if ACL enabled
398 *  index   - The index
399 *  admin   - admin page - if enough rights
400 *  top     - a back to top button
401 *  back    - a back to parent button - if available
402 * backlink - links to the list of backlinks
403 *
404 * @author Andreas Gohr <andi@splitbrain.org>
405 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
406 * @see    tpl_button
407 */
408function tpl_actionlink($type,$pre='',$suf=''){
409  global $ID;
410  global $INFO;
411  global $REV;
412  global $ACT;
413  global $conf;
414  global $lang;
415  global $auth;
416
417  // check disabled actions and fix the badly named ones
418  $ctype = $type;
419  if($type == 'history') $ctype='revisions';
420  if(!actionOK($ctype)) return;
421
422  switch($type){
423    case 'edit':
424      #most complicated type - we need to decide on current action
425      if($ACT == 'show' || $ACT == 'search'){
426        if($INFO['writable']){
427          if($INFO['exists']){
428            tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
429                     $pre.$lang['btn_edit'].$suf,
430                     'class="action edit" accesskey="e" rel="nofollow"');
431          }else{
432            tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
433                     $pre.$lang['btn_create'].$suf,
434                     'class="action create" accesskey="e" rel="nofollow"');
435          }
436        }else{
437          if(!actionOK('source')) return false; //pseudo action
438          tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
439                   $pre.$lang['btn_source'].$suf,
440                   'class="action source" accesskey="v" rel="nofollow"');
441        }
442      }else{
443          tpl_link(wl($ID,'do=show'),
444                   $pre.$lang['btn_show'].$suf,
445                   'class="action show" accesskey="v" rel="nofollow"');
446      }
447      return true;
448    case 'history':
449      tpl_link(wl($ID,'do=revisions'),$pre.$lang['btn_revs'].$suf,'class="action revisions" accesskey="o"');
450      return true;
451    case 'recent':
452      tpl_link(wl($ID,'do=recent'),$pre.$lang['btn_recent'].$suf,'class="action recent" accesskey="r"');
453      return true;
454    case 'index':
455      tpl_link(wl($ID,'do=index'),$pre.$lang['btn_index'].$suf,'class="action index" accesskey="x"');
456      return true;
457    case 'top':
458      print '<a href="#dokuwiki__top" class="action top" accesskey="x">'.$pre.$lang['btn_top'].$suf.'</a>';
459      return true;
460    case 'back':
461      if ($ID = tpl_getparent($ID)) {
462        tpl_link(wl($ID,'do=show'),$pre.$lang['btn_back'].$suf,'class="action back" accesskey="b"');
463        return true;
464      }
465      return false;
466    case 'login':
467      if($conf['useacl']){
468        if($_SERVER['REMOTE_USER']){
469          tpl_link(wl($ID,'do=logout'),$pre.$lang['btn_logout'].$suf,'class="action logout"');
470        }else{
471          tpl_link(wl($ID,'do=login'),$pre.$lang['btn_login'].$suf,'class="action logout"');
472        }
473        return true;
474      }
475      return false;
476    case 'admin':
477      if($INFO['perm'] == AUTH_ADMIN){
478        tpl_link(wl($ID,'do=admin'),$pre.$lang['btn_admin'].$suf,'class="action admin"');
479        return true;
480      }
481      return false;
482   case 'subscribe':
483   case 'subscription':
484      if($conf['useacl'] && $ACT == 'show' && $conf['subscribers'] == 1){
485        if($_SERVER['REMOTE_USER']){
486          if($INFO['subscribed']) {
487            tpl_link(wl($ID,'do=unsubscribe'),$pre.$lang['btn_unsubscribe'].$suf,'class="action unsubscribe"');
488          } else {
489            tpl_link(wl($ID,'do=subscribe'),$pre.$lang['btn_subscribe'].$suf,'class="action subscribe"');
490          }
491          return true;
492        }
493      }
494      return false;
495    case 'backlink':
496      tpl_link(wl($ID,'do=backlink'),$pre.$lang['btn_backlink'].$suf, 'class="action backlink"');
497      return true;
498    case 'profile':
499      if($conf['useacl'] && $_SERVER['REMOTE_USER'] &&
500         $auth->canDo('Profile') && ($ACT!='profile')){
501        tpl_link(wl($ID,'do=profile'),$pre.$lang['btn_profile'].$suf, 'class="action profile"');
502        return true;
503      }
504      return false;
505    default:
506      print '[unknown link type]';
507      return true;
508  }
509}
510
511/**
512 * Print the search form
513 *
514 * If the first parameter is given a div with the ID 'qsearch_out' will
515 * be added which instructs the ajax pagequicksearch to kick in and place
516 * its output into this div. The second parameter controls the propritary
517 * attribute autocomplete. If set to false this attribute will be set with an
518 * value of "off" to instruct the browser to disable it's own built in
519 * autocompletion feature (MSIE and Firefox)
520 *
521 * @author Andreas Gohr <andi@splitbrain.org>
522 */
523function tpl_searchform($ajax=true,$autocomplete=true){
524  global $lang;
525  global $ACT;
526
527  print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search"><div class="no">';
528  print '<input type="hidden" name="do" value="search" />';
529  print '<input type="text" ';
530  if($ACT == 'search') print 'value="'.htmlspecialchars($_REQUEST['id']).'" ';
531  if(!$autocomplete) print 'autocomplete="off" ';
532  print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[ALT+F]" />';
533  print '<input type="submit" value="'.$lang['btn_search'].'" class="button" title="'.$lang['btn_search'].'" />';
534  if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
535  print '</div></form>';
536}
537
538/**
539 * Print the breadcrumbs trace
540 *
541 * @author Andreas Gohr <andi@splitbrain.org>
542 */
543function tpl_breadcrumbs(){
544  global $lang;
545  global $conf;
546
547  //check if enabled
548  if(!$conf['breadcrumbs']) return;
549
550  $crumbs = breadcrumbs(); //setup crumb trace
551
552  //reverse crumborder in right-to-left mode
553  if($lang['direction'] == 'rtl') $crumbs = array_reverse($crumbs,true);
554
555  //render crumbs, highlight the last one
556  print $lang['breadcrumb'].':';
557  $last = count($crumbs);
558  $i = 0;
559  foreach ($crumbs as $id => $name){
560    $i++;
561    print ' <span class="bcsep">&raquo;</span> ';
562    if ($i == $last) print '<span class="curid">';
563    tpl_link(wl($id),$name,'class="breadcrumbs" title="'.$id.'"');
564    if ($i == $last) print '</span>';
565  }
566}
567
568/**
569 * Hierarchical breadcrumbs
570 *
571 * This code was suggested as replacement for the usual breadcrumbs.
572 * It only makes sense with a deep site structure.
573 *
574 * @author Andreas Gohr <andi@splitbrain.org>
575 * @author Nigel McNie <oracle.shinoda@gmail.com>
576 * @author Sean Coates <sean@caedmon.net>
577 * @link   http://wiki.splitbrain.org/wiki:tipsandtricks:hierarchicalbreadcrumbs
578 * @todo   May behave strangely in RTL languages
579 */
580function tpl_youarehere($sep=' &raquo; '){
581  global $conf;
582  global $ID;
583  global $lang;
584
585  // check if enabled
586  if(!$conf['youarehere']) return;
587
588  $parts = explode(':', $ID);
589  $count = count($parts);
590
591  echo $lang['youarehere'].': ';
592
593  // always print the startpage
594  $title = p_get_first_heading($conf['start']);
595  if(!$title) $title = $conf['start'];
596  tpl_link(wl($conf['start']),$title,'title="'.$conf['start'].'"');
597
598  // print intermediate namespace links
599  $part = '';
600  for($i=0; $i<$count - 1; $i++){
601    $part .= $parts[$i].':';
602    $page = $part;
603    resolve_pageid('',$page,$exists);
604    if ($page == $conf['start']) continue; // Skip startpage
605
606    // output
607    echo $sep;
608    if($exists){
609      $title = p_get_first_heading($page);
610      if(!$title) $title = $parts[$i];
611      tpl_link(wl($page),$title,'title="'.$page.'"');
612    }else{
613      tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2"');
614    }
615  }
616
617  // print current page, skipping start page, skipping for namespace index
618  if(isset($page) && $page==$part.$parts[$i]) return;
619  $page = $part.$parts[$i];
620  if($page == $conf['start']) return;
621  echo $sep;
622  if(file_exists(wikiFN($page))){
623    $title = p_get_first_heading($page);
624    if(!$title) $title = $parts[$i];
625    tpl_link(wl($page),$title,'title="'.$page.'"');
626  }else{
627    tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2"');
628  }
629}
630
631/**
632 * Print info if the user is logged in
633 * and show full name in that case
634 *
635 * Could be enhanced with a profile link in future?
636 *
637 * @author Andreas Gohr <andi@splitbrain.org>
638 */
639function tpl_userinfo(){
640  global $lang;
641  global $INFO;
642  if($_SERVER['REMOTE_USER'])
643    print $lang['loggedinas'].': '.$INFO['userinfo']['name'];
644}
645
646/**
647 * Print some info about the current page
648 *
649 * @author Andreas Gohr <andi@splitbrain.org>
650 */
651function tpl_pageinfo(){
652  global $conf;
653  global $lang;
654  global $INFO;
655  global $REV;
656
657  // prepare date and path
658  $fn = $INFO['filepath'];
659  if(!$conf['fullpath']){
660    if($REV){
661      $fn = str_replace(realpath($conf['olddir']).DIRECTORY_SEPARATOR,'',$fn);
662    }else{
663      $fn = str_replace(realpath($conf['datadir']).DIRECTORY_SEPARATOR,'',$fn);
664    }
665  }
666  $fn = utf8_decodeFN($fn);
667  $date = date($conf['dformat'],$INFO['lastmod']);
668
669  // print it
670  if($INFO['exists']){
671    print $fn;
672    print ' &middot; ';
673    print $lang['lastmod'];
674    print ': ';
675    print $date;
676    if($INFO['editor']){
677      print ' '.$lang['by'].' ';
678      print $INFO['editor'];
679    }
680    if($INFO['locked']){
681      print ' &middot; ';
682      print $lang['lockedby'];
683      print ': ';
684      print $INFO['locked'];
685    }
686  }
687}
688
689/**
690 * Prints or returns the name of the given page (current one if none given).
691 *
692 * If useheading is enabled this will use the first headline else
693 * the given ID is used.
694 *
695 * @author Andreas Gohr <andi@splitbrain.org>
696 */
697function tpl_pagetitle($id=null, $ret=false){
698  global $conf;
699  if(is_null($id)){
700    global $ID;
701    $id = $ID;
702  }
703
704  $name = $id;
705  if ($conf['useheading']) {
706    $title = p_get_first_heading($id);
707    if ($title) $name = $title;
708  }
709
710  if ($ret) {
711      return hsc($name);
712  } else {
713      print hsc($name);
714  }
715}
716
717/**
718 * Returns the requested EXIF/IPTC tag from the current image
719 *
720 * If $tags is an array all given tags are tried until a
721 * value is found. If no value is found $alt is returned.
722 *
723 * Which texts are known is defined in the functions _exifTagNames
724 * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
725 * to the names of the latter one)
726 *
727 * Only allowed in: detail.php
728 *
729 * @author Andreas Gohr <andi@splitbrain.org>
730 */
731function tpl_img_getTag($tags,$alt='',$src=null){
732  // Init Exif Reader
733  global $SRC;
734
735  if(is_null($src)) $src = $SRC;
736
737  static $meta = null;
738  if(is_null($meta)) $meta = new JpegMeta($src);
739  if($meta === false) return $alt;
740  $info = $meta->getField($tags);
741  if($info == false) return $alt;
742  return $info;
743}
744
745/**
746 * Prints the image with a link to the full sized version
747 *
748 * Only allowed in: detail.php
749 */
750function tpl_img($maxwidth=0,$maxheight=0){
751  global $IMG;
752  $w = tpl_img_getTag('File.Width');
753  $h = tpl_img_getTag('File.Height');
754
755  //resize to given max values
756  $ratio = 1;
757  if($w >= $h){
758    if($maxwidth && $w >= $maxwidth){
759      $ratio = $maxwidth/$w;
760    }elseif($maxheight && $h > $maxheight){
761      $ratio = $maxheight/$h;
762    }
763  }else{
764    if($maxheight && $h >= $maxheight){
765      $ratio = $maxheight/$h;
766    }elseif($maxwidth && $w > $maxwidth){
767      $ratio = $maxwidth/$w;
768    }
769  }
770  if($ratio){
771    $w = floor($ratio*$w);
772    $h = floor($ratio*$h);
773  }
774
775  //prepare URLs
776  $url=ml($IMG,array('cache'=>$_REQUEST['cache']));
777  $src=ml($IMG,array('cache'=>$_REQUEST['cache'],'w'=>$w,'h'=>$h));
778
779  //prepare attributes
780  $alt=tpl_img_getTag('Simple.Title');
781  $p = array();
782  if($w) $p['width']  = $w;
783  if($h) $p['height'] = $h;
784         $p['class']  = 'img_detail';
785  if($alt){
786    $p['alt']   = $alt;
787    $p['title'] = $alt;
788  }else{
789    $p['alt'] = '';
790  }
791  $p = buildAttributes($p);
792
793  print '<a href="'.$url.'">';
794  print '<img src="'.$src.'" '.$p.'/>';
795  print '</a>';
796}
797
798/**
799 * This function inserts a 1x1 pixel gif which in reality
800 * is the inexer function.
801 *
802 * Should be called somewhere at the very end of the main.php
803 * template
804 */
805function tpl_indexerWebBug(){
806  global $ID;
807  global $INFO;
808  if(!$INFO['exists']) return;
809
810  if(isHiddenPage($ID)) return; //no need to index hidden pages
811
812  $p = array();
813  $p['src']    = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
814                 '&'.time();
815  $p['width']  = 1;
816  $p['height'] = 1;
817  $p['alt']    = '';
818  $att = buildAttributes($p);
819  print "<img $att />";
820}
821
822// configuration methods
823/**
824 * tpl_getConf($id)
825 *
826 * use this function to access template configuration variables
827 */
828function tpl_getConf($id){
829  global $conf;
830  global $tpl_configloaded;
831
832  $tpl = $conf['template'];
833
834  if (!$tpl_configloaded){
835    $tconf = tpl_loadConfig();
836    if ($tconf !== false){
837      foreach ($tconf as $key => $value){
838        if (isset($conf['tpl'][$tpl][$key])) continue;
839        $conf['tpl'][$tpl][$key] = $value;
840      }
841      $tpl_configloaded = true;
842    }
843  }
844
845  return $conf['tpl'][$tpl][$id];
846}
847
848/**
849 * tpl_loadConfig()
850 * reads all template configuration variables
851 * this function is automatically called by tpl_getConf()
852 */
853function tpl_loadConfig(){
854
855  $file = DOKU_TPLINC.'/conf/default.php';
856  $conf = array();
857
858  if (!@file_exists($file)) return false;
859
860  // load default config file
861  include($file);
862
863  return $conf;
864}
865
866/**
867 * prints the "main content" in the mediamanger popup
868 *
869 * Depending on the user's actions this may be a list of
870 * files in a namespace, the meta editing dialog or
871 * a message of referencing pages
872 *
873 * Only allowed in mediamanager.php
874 *
875 * @author Andreas Gohr <andi@splitbrain.org>
876 */
877function tpl_mediaContent(){
878  global $IMG;
879  global $AUTH;
880  global $INUSE;
881  global $NS;
882  global $JUMPTO;
883
884  ptln('<div id="media__content">');
885  if($_REQUEST['edit']){
886    media_metaform($IMG,$AUTH);
887  }elseif(is_array($INUSE)){
888    media_filesinuse($INUSE,$IMG);
889  }else{
890    media_filelist($NS,$AUTH,$JUMPTO);
891  }
892  ptln('</div>');
893}
894
895/**
896 * prints the namespace tree in the mediamanger popup
897 *
898 * Only allowed in mediamanager.php
899 *
900 * @author Andreas Gohr <andi@splitbrain.org>
901 */
902function tpl_mediaTree(){
903  global $NS;
904
905  ptln('<div id="media__tree">');
906  media_nstree($NS);
907  ptln('</div>');
908}
909
910//Setup VIM: ex: et ts=2 enc=utf-8 :
911