Creating repository for dokuwiki modifications for sudaraka.org
[sudaraka-org:dokuwiki-mods.git] / inc / template.php
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')) die('meh.');
10
11 /**
12  * Returns the path to the given template, uses
13  * default one if the custom version doesn't exist.
14  *
15  * @author Andreas Gohr <andi@splitbrain.org>
16  */
17 function template($tpl){
18     global $conf;
19
20     if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl))
21         return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl;
22
23     return DOKU_INC.'lib/tpl/default/'.$tpl;
24 }
25
26 /**
27  * Print the content
28  *
29  * This function is used for printing all the usual content
30  * (defined by the global $ACT var) by calling the appropriate
31  * outputfunction(s) from html.php
32  *
33  * Everything that doesn't use the main template file isn't
34  * handled by this function. ACL stuff is not done here either.
35  *
36  * @author Andreas Gohr <andi@splitbrain.org>
37  */
38 function tpl_content($prependTOC=true) {
39     global $ACT;
40     global $INFO;
41     $INFO['prependTOC'] = $prependTOC;
42
43     ob_start();
44     trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core');
45     $html_output = ob_get_clean();
46     trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln');
47
48     return !empty($html_output);
49 }
50
51 function tpl_content_core(){
52     global $ACT;
53     global $TEXT;
54     global $PRE;
55     global $SUF;
56     global $SUM;
57     global $IDX;
58
59     switch($ACT){
60         case 'show':
61             html_show();
62             break;
63         case 'locked':
64             html_locked();
65         case 'edit':
66         case 'recover':
67             html_edit();
68             break;
69         case 'preview':
70             html_edit();
71             html_show($TEXT);
72             break;
73         case 'draft':
74             html_draft();
75             break;
76         case 'search':
77             html_search();
78             break;
79         case 'revisions':
80             $first = isset($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
81             html_revisions($first);
82             break;
83         case 'diff':
84             html_diff();
85             break;
86         case 'recent':
87             if (is_array($_REQUEST['first'])) {
88                 $_REQUEST['first'] = array_keys($_REQUEST['first']);
89                 $_REQUEST['first'] = $_REQUEST['first'][0];
90             }
91             $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
92             $show_changes = $_REQUEST['show_changes'];
93             html_recent($first, $show_changes);
94             break;
95         case 'index':
96             html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
97             break;
98         case 'backlink':
99             html_backlinks();
100             break;
101         case 'conflict':
102             html_conflict(con($PRE,$TEXT,$SUF),$SUM);
103             html_diff(con($PRE,$TEXT,$SUF),false);
104             break;
105         case 'login':
106             html_login();
107             break;
108         case 'register':
109             html_register();
110             break;
111         case 'resendpwd':
112             html_resendpwd();
113             break;
114         case 'denied':
115             print p_locale_xhtml('denied');
116             break;
117         case 'profile' :
118             html_updateprofile();
119             break;
120         case 'admin':
121             tpl_admin();
122             break;
123         case 'subscribe':
124             tpl_subscribe();
125             break;
126         case 'media':
127             tpl_media();
128             break;
129         default:
130             $evt = new Doku_Event('TPL_ACT_UNKNOWN',$ACT);
131             if ($evt->advise_before())
132                 msg("Failed to handle command: ".hsc($ACT),-1);
133             $evt->advise_after();
134             unset($evt);
135             return false;
136     }
137     return true;
138 }
139
140 /**
141  * Places the TOC where the function is called
142  *
143  * If you use this you most probably want to call tpl_content with
144  * a false argument
145  *
146  * @author Andreas Gohr <andi@splitbrain.org>
147  */
148 function tpl_toc($return=false){
149     global $TOC;
150     global $ACT;
151     global $ID;
152     global $REV;
153     global $INFO;
154     global $conf;
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, METADATA_RENDER_USING_CACHE);
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) || !$conf['tocminheads'] || count($toc) < $conf['tocminheads']){
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(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet
217         if($INFO['prependTOC']) tpl_toc();
218         $plugin->html();
219     }else{
220         html_admin();
221     }
222     return true;
223 }
224
225 /**
226  * Print the correct HTML meta headers
227  *
228  * This has to go into the head section of your template.
229  *
230  * @triggers TPL_METAHEADER_OUTPUT
231  * @param  boolean $alt Should feeds and alternative format links be added?
232  * @author Andreas Gohr <andi@splitbrain.org>
233  */
234 function tpl_metaheaders($alt=true){
235     global $ID;
236     global $REV;
237     global $INFO;
238     global $JSINFO;
239     global $ACT;
240     global $QUERY;
241     global $lang;
242     global $conf;
243     $it=2;
244
245     // prepare the head array
246     $head = array();
247
248     // prepare seed for js and css
249     $tseed = 0;
250     $depends = getConfigFiles('main');
251     foreach($depends as $f) {
252         $time = @filemtime($f);
253         if($time > $tseed) $tseed = $time;
254     }
255
256     // the usual stuff
257     $head['meta'][] = array( 'name'=>'generator', 'content'=>'DokuWiki');
258     $head['link'][] = array( 'rel'=>'search', 'type'=>'application/opensearchdescription+xml',
259             'href'=>DOKU_BASE.'lib/exe/opensearch.php', 'title'=>$conf['title'] );
260     $head['link'][] = array( 'rel'=>'start', 'href'=>DOKU_BASE );
261     if(actionOK('index')){
262         $head['link'][] = array( 'rel'=>'contents', 'href'=> wl($ID,'do=index',false,'&'),
263                 'title'=>$lang['btn_index'] );
264     }
265
266     if($alt){
267         $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
268                 'title'=>'Recent Changes', 'href'=>DOKU_BASE.'feed.php');
269         $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
270                 'title'=>'Current Namespace',
271                 'href'=>DOKU_BASE.'feed.php?mode=list&ns='.$INFO['namespace']);
272         if(($ACT == 'show' || $ACT == 'search') && $INFO['writable']){
273             $head['link'][] = array( 'rel'=>'edit',
274                     'title'=>$lang['btn_edit'],
275                     'href'=> wl($ID,'do=edit',false,'&'));
276         }
277
278         if($ACT == 'search'){
279             $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
280                     'title'=>'Search Result',
281                     'href'=>DOKU_BASE.'feed.php?mode=search&q='.$QUERY);
282         }
283
284         if(actionOK('export_xhtml')){
285             $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/html', 'title'=>'Plain HTML',
286                     'href'=>exportlink($ID, 'xhtml', '', false, '&'));
287         }
288
289         if(actionOK('export_raw')){
290             $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/plain', 'title'=>'Wiki Markup',
291                     'href'=>exportlink($ID, 'raw', '', false, '&'));
292         }
293     }
294
295     // setup robot tags apropriate for different modes
296     if( ($ACT=='show' || $ACT=='export_xhtml') && !$REV){
297         if($INFO['exists']){
298             //delay indexing:
299             if((time() - $INFO['lastmod']) >= $conf['indexdelay']){
300                 $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
301             }else{
302                 $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
303             }
304             $head['link'][] = array( 'rel'=>'canonical', 'href'=>wl($ID,'',true,'&') );
305         }else{
306             $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,follow');
307         }
308     }elseif(defined('DOKU_MEDIADETAIL')){
309         $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
310     }else{
311         $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
312     }
313
314     // set metadata
315     if($ACT == 'show' || $ACT=='export_xhtml'){
316         // date of modification
317         if($REV){
318             $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$REV));
319         }else{
320             $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$INFO['lastmod']));
321         }
322
323         // keywords (explicit or implicit)
324         if(!empty($INFO['meta']['subject'])){
325             $head['meta'][] = array( 'name'=>'keywords', 'content'=>join(',',$INFO['meta']['subject']));
326         }else{
327             $head['meta'][] = array( 'name'=>'keywords', 'content'=>str_replace(':',',',$ID));
328         }
329     }
330
331     // load stylesheets
332     $head['link'][] = array('rel'=>'stylesheet', 'media'=>'screen', 'type'=>'text/css',
333             'href'=>DOKU_BASE.'lib/exe/css.php?t='.$conf['template'].'&tseed='.$tseed);
334     $head['link'][] = array('rel'=>'stylesheet', 'media'=>'all', 'type'=>'text/css',
335             'href'=>DOKU_BASE.'lib/exe/css.php?s=all&t='.$conf['template'].'&tseed='.$tseed);
336     $head['link'][] = array('rel'=>'stylesheet', 'media'=>'print', 'type'=>'text/css',
337             'href'=>DOKU_BASE.'lib/exe/css.php?s=print&t='.$conf['template'].'&tseed='.$tseed);
338
339     // make $INFO and other vars available to JavaScripts
340     $json = new JSON();
341     $script = "var NS='".$INFO['namespace']."';";
342     if($conf['useacl'] && $_SERVER['REMOTE_USER']){
343         $script .= "var SIG='".toolbar_signature()."';";
344     }
345     $script .= 'var JSINFO = '.$json->encode($JSINFO).';';
346     $head['script'][] = array( 'type'=>'text/javascript', '_data'=> $script);
347
348     // load external javascript
349     $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8', '_data'=>'',
350             'src'=>DOKU_BASE.'lib/exe/js.php'.'?tseed='.$tseed);
351
352     // trigger event here
353     trigger_event('TPL_METAHEADER_OUTPUT',$head,'_tpl_metaheaders_action',true);
354     return true;
355 }
356
357 /**
358  * prints the array build by tpl_metaheaders
359  *
360  * $data is an array of different header tags. Each tag can have multiple
361  * instances. Attributes are given as key value pairs. Values will be HTML
362  * encoded automatically so they should be provided as is in the $data array.
363  *
364  * For tags having a body attribute specify the the body data in the special
365  * attribute '_data'. This field will NOT BE ESCAPED automatically.
366  *
367  * @author Andreas Gohr <andi@splitbrain.org>
368  */
369 function _tpl_metaheaders_action($data){
370     foreach($data as $tag => $inst){
371         foreach($inst as $attr){
372             echo '<',$tag,' ',buildAttributes($attr);
373             if(isset($attr['_data']) || $tag == 'script'){
374                 if($tag == 'script' && $attr['_data'])
375                     $attr['_data'] = "<!--//--><![CDATA[//><!--\n".
376                         $attr['_data'].
377                         "\n//--><!]]>";
378
379                 echo '>',$attr['_data'],'</',$tag,'>';
380             }else{
381                 echo '/>';
382             }
383             echo "\n";
384         }
385     }
386 }
387
388 /**
389  * Print a link
390  *
391  * Just builds a link.
392  *
393  * @author Andreas Gohr <andi@splitbrain.org>
394  */
395 function tpl_link($url,$name,$more='',$return=false){
396     $out = '<a href="'.$url.'" ';
397     if ($more) $out .= ' '.$more;
398     $out .= ">$name</a>";
399     if ($return) return $out;
400     print $out;
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  * @author Adrian Lang <mail@adrianlang.de>
441  * @see    tpl_get_action
442  */
443 function tpl_button($type,$return=false){
444     $data = tpl_get_action($type);
445     if ($data === false) {
446         return false;
447     } elseif (!is_array($data)) {
448         $out = sprintf($data, 'button');
449     } else {
450         extract($data);
451         if ($id === '#dokuwiki__top') {
452             $out = html_topbtn();
453         } else {
454             $out = html_btn($type, $id, $accesskey, $params, $method);
455         }
456     }
457     if ($return) return $out;
458     echo $out;
459     return true;
460 }
461
462 /**
463  * Like the action buttons but links
464  *
465  * @author Adrian Lang <mail@adrianlang.de>
466  * @see    tpl_get_action
467  */
468 function tpl_actionlink($type,$pre='',$suf='',$inner='',$return=false){
469     global $lang;
470     $data = tpl_get_action($type);
471     if ($data === false) {
472         return false;
473     } elseif (!is_array($data)) {
474         $out = sprintf($data, 'link');
475     } else {
476         extract($data);
477         if (strpos($id, '#') === 0) {
478             $linktarget = $id;
479         } else {
480             $linktarget = wl($id, $params);
481         }
482         $caption = $lang['btn_' . $type];
483         $akey = $addTitle = '';
484         if($accesskey){
485             $akey = 'accesskey="'.$accesskey.'" ';
486             $addTitle = ' ['.strtoupper($accesskey).']';
487         }
488         $out = tpl_link($linktarget, $pre.(($inner)?$inner:$caption).$suf,
489                         'class="action ' . $type . '" ' .
490                         $akey . 'rel="nofollow" ' .
491                         'title="' . hsc($caption).$addTitle . '"', 1);
492     }
493     if ($return) return $out;
494     echo $out;
495     return true;
496 }
497
498 /**
499  * Check the actions and get data for buttons and links
500  *
501  * Available actions are
502  *
503  *  edit        - edit/create/show/draft
504  *  history     - old revisions
505  *  recent      - recent changes
506  *  login       - login/logout - if ACL enabled
507  *  profile     - user profile (if logged in)
508  *  index       - The index
509  *  admin       - admin page - if enough rights
510  *  top         - back to top
511  *  back        - back to parent - if available
512  *  backlink    - links to the list of backlinks
513  *  subscribe/subscription- subscribe/unsubscribe
514  *
515  * @author Andreas Gohr <andi@splitbrain.org>
516  * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
517  * @author Adrian Lang <mail@adrianlang.de>
518  */
519 function tpl_get_action($type) {
520     global $ID;
521     global $INFO;
522     global $REV;
523     global $ACT;
524     global $conf;
525     global $auth;
526
527     // check disabled actions and fix the badly named ones
528     if($type == 'history') $type='revisions';
529     if(!actionOK($type)) return false;
530
531     $accesskey = null;
532     $id        = $ID;
533     $method    = 'get';
534     $params    = array('do' => $type);
535     switch($type){
536         case 'edit':
537             // most complicated type - we need to decide on current action
538             if($ACT == 'show' || $ACT == 'search'){
539                 $method = 'post';
540                 if($INFO['writable']){
541                     $accesskey = 'e';
542                     if(!empty($INFO['draft'])) {
543                         $type = 'draft';
544                         $params['do'] = 'draft';
545                     } else {
546                         $params['rev'] = $REV;
547                         if(!$INFO['exists']){
548                             $type   = 'create';
549                         }
550                     }
551                 }else{
552                     if(!actionOK('source')) return false; //pseudo action
553                     $params['rev'] = $REV;
554                     $type = 'source';
555                     $accesskey = 'v';
556                 }
557             }else{
558                 $params = '';
559                 $type = 'show';
560                 $accesskey = 'v';
561             }
562             break;
563         case 'revisions':
564             $type = 'revs';
565             $accesskey = 'o';
566             break;
567         case 'recent':
568             $accesskey = 'r';
569             break;
570         case 'index':
571             $accesskey = 'x';
572             break;
573         case 'top':
574             $accesskey = 'x';
575             $params = '';
576             $id = '#dokuwiki__top';
577             break;
578         case 'back':
579             $parent = tpl_getparent($ID);
580             if (!$parent) {
581                 return false;
582             }
583             $id = $parent;
584             $params = '';
585             $accesskey = 'b';
586             break;
587         case 'login':
588             $params['sectok'] = getSecurityToken();
589             if(isset($_SERVER['REMOTE_USER'])){
590                 if (!actionOK('logout')) {
591                     return false;
592                 }
593                 $params['do'] = 'logout';
594                 $type = 'logout';
595             }
596             break;
597         case 'register':
598             if($_SERVER['REMOTE_USER']){
599                 return false;
600             }
601             break;
602         case 'resendpwd':
603             if($_SERVER['REMOTE_USER']){
604                 return false;
605             }
606             break;
607         case 'admin':
608             if(!$INFO['ismanager']){
609                 return false;
610             }
611             break;
612         case 'revert':
613             if(!$INFO['ismanager'] || !$REV || !$INFO['writable']) {
614                 return false;
615             }
616             $params['rev'] = $REV;
617             $params['sectok'] = getSecurityToken();
618             break;
619         case 'subscription':
620             $type = 'subscribe';
621             $params['do'] = 'subscribe';
622         case 'subscribe':
623             if(!$_SERVER['REMOTE_USER']){
624                 return false;
625             }
626             break;
627         case 'backlink':
628             break;
629         case 'profile':
630             if(!isset($_SERVER['REMOTE_USER'])){
631                 return false;
632             }
633             break;
634         case 'media':
635             break;
636         default:
637             return '[unknown %s type]';
638             break;
639     }
640     return compact('accesskey', 'type', 'id', 'method', 'params');
641 }
642
643 /**
644  * Wrapper around tpl_button() and tpl_actionlink()
645  *
646  * @author Anika Henke <anika@selfthinker.org>
647  */
648 function tpl_action($type,$link=0,$wrapper=false,$return=false,$pre='',$suf='',$inner='') {
649     $out = '';
650     if ($link) $out .= tpl_actionlink($type,$pre,$suf,$inner,1);
651     else $out .= tpl_button($type,1);
652     if ($out && $wrapper) $out = "<$wrapper>$out</$wrapper>";
653
654     if ($return) return $out;
655     print $out;
656     return $out ? true : false;
657 }
658
659 /**
660  * Print the search form
661  *
662  * If the first parameter is given a div with the ID 'qsearch_out' will
663  * be added which instructs the ajax pagequicksearch to kick in and place
664  * its output into this div. The second parameter controls the propritary
665  * attribute autocomplete. If set to false this attribute will be set with an
666  * value of "off" to instruct the browser to disable it's own built in
667  * autocompletion feature (MSIE and Firefox)
668  *
669  * @author Andreas Gohr <andi@splitbrain.org>
670  */
671 function tpl_searchform($ajax=true,$autocomplete=true){
672     global $lang;
673     global $ACT;
674     global $QUERY;
675
676     // don't print the search form if search action has been disabled
677     if (!actionOk('search')) return false;
678
679     print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get"><div class="no">';
680     print '<input type="hidden" name="do" value="search" />';
681     print '<input type="text" ';
682     if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" ';
683     if(!$autocomplete) print 'autocomplete="off" ';
684     print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]" />';
685     print '<input type="submit" value="'.$lang['btn_search'].'" class="button" title="'.$lang['btn_search'].'" />';
686     if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
687     print '</div></form>';
688     return true;
689 }
690
691 /**
692  * Print the breadcrumbs trace
693  *
694  * @author Andreas Gohr <andi@splitbrain.org>
695  */
696 function tpl_breadcrumbs($sep='&bull;'){
697     global $lang;
698     global $conf;
699
700     //check if enabled
701     if(!$conf['breadcrumbs']) return false;
702
703     $crumbs = breadcrumbs(); //setup crumb trace
704
705     //reverse crumborder in right-to-left mode, add RLM character to fix heb/eng display mixups
706     if($lang['direction'] == 'rtl') {
707         $crumbs = array_reverse($crumbs,true);
708         $crumbs_sep = ' &#8207;<span class="bcsep">'.$sep.'</span>&#8207; ';
709     } else {
710         $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
711     }
712
713     //render crumbs, highlight the last one
714     print '<span class="bchead">'.$lang['breadcrumb'].':</span>';
715     $last = count($crumbs);
716     $i = 0;
717     foreach ($crumbs as $id => $name){
718         $i++;
719         echo $crumbs_sep;
720         if ($i == $last) print '<span class="curid">';
721         tpl_link(wl($id),hsc($name),'class="breadcrumbs" title="'.$id.'"');
722         if ($i == $last) print '</span>';
723     }
724     return true;
725 }
726
727 /**
728  * Hierarchical breadcrumbs
729  *
730  * This code was suggested as replacement for the usual breadcrumbs.
731  * It only makes sense with a deep site structure.
732  *
733  * @author Andreas Gohr <andi@splitbrain.org>
734  * @author Nigel McNie <oracle.shinoda@gmail.com>
735  * @author Sean Coates <sean@caedmon.net>
736  * @author <fredrik@averpil.com>
737  * @todo   May behave strangely in RTL languages
738  */
739 function tpl_youarehere($sep=' &raquo; '){
740     global $conf;
741     global $ID;
742     global $lang;
743
744     // check if enabled
745     if(!$conf['youarehere']) return false;
746
747     $parts = explode(':', $ID);
748     $count = count($parts);
749
750     echo '<span class="bchead">'.$lang['youarehere'].': </span>';
751
752     // always print the startpage
753     tpl_pagelink(':'.$conf['start']);
754
755     // print intermediate namespace links
756     $part = '';
757     for($i=0; $i<$count - 1; $i++){
758         $part .= $parts[$i].':';
759         $page = $part;
760         if ($page == $conf['start']) continue; // Skip startpage
761
762         // output
763         echo $sep;
764         tpl_pagelink($page);
765     }
766
767     // print current page, skipping start page, skipping for namespace index
768     resolve_pageid('',$page,$exists);
769     if(isset($page) && $page==$part.$parts[$i]) return;
770     $page = $part.$parts[$i];
771     if($page == $conf['start']) return;
772     echo $sep;
773     tpl_pagelink($page);
774     return true;
775 }
776
777 /**
778  * Print info if the user is logged in
779  * and show full name in that case
780  *
781  * Could be enhanced with a profile link in future?
782  *
783  * @author Andreas Gohr <andi@splitbrain.org>
784  */
785 function tpl_userinfo(){
786     global $lang;
787     global $INFO;
788     if(isset($_SERVER['REMOTE_USER'])){
789         print $lang['loggedinas'].': '.hsc($INFO['userinfo']['name']).' ('.hsc($_SERVER['REMOTE_USER']).')';
790         return true;
791     }
792     return false;
793 }
794
795 /**
796  * Print some info about the current page
797  *
798  * @author Andreas Gohr <andi@splitbrain.org>
799  */
800 function tpl_pageinfo($ret=false){
801     global $conf;
802     global $lang;
803     global $INFO;
804     global $ID;
805
806     // return if we are not allowed to view the page
807     if (!auth_quickaclcheck($ID)) { return false; }
808
809     // prepare date and path
810     $fn = $INFO['filepath'];
811     if(!$conf['fullpath']){
812         if($INFO['rev']){
813             $fn = str_replace(fullpath($conf['olddir']).'/','',$fn);
814         }else{
815             $fn = str_replace(fullpath($conf['datadir']).'/','',$fn);
816         }
817     }
818     $fn = utf8_decodeFN($fn);
819     $date = dformat($INFO['lastmod']);
820
821     // print it
822     if($INFO['exists']){
823         $out = '';
824         $out .= $fn;
825         $out .= ' &middot; ';
826         $out .= $lang['lastmod'];
827         $out .= ': ';
828         $out .= $date;
829         if($INFO['editor']){
830             $out .= ' '.$lang['by'].' ';
831             $out .= editorinfo($INFO['editor']);
832         }else{
833             $out .= ' ('.$lang['external_edit'].')';
834         }
835         if($INFO['locked']){
836             $out .= ' &middot; ';
837             $out .= $lang['lockedby'];
838             $out .= ': ';
839             $out .= editorinfo($INFO['locked']);
840         }
841         if($ret){
842             return $out;
843         }else{
844             echo $out;
845             return true;
846         }
847     }
848     return false;
849 }
850
851 /**
852  * Prints or returns the name of the given page (current one if none given).
853  *
854  * If useheading is enabled this will use the first headline else
855  * the given ID is used.
856  *
857  * @author Andreas Gohr <andi@splitbrain.org>
858  */
859 function tpl_pagetitle($id=null, $ret=false){
860     global $conf;
861     if(is_null($id)){
862         global $ID;
863         $id = $ID;
864     }
865
866     $name = $id;
867     if (useHeading('navigation')) {
868         $title = p_get_first_heading($id);
869         if ($title) $name = $title;
870     }
871
872     if ($ret) {
873         return hsc($name);
874     } else {
875         print hsc($name);
876         return true;
877     }
878 }
879
880 /**
881  * Returns the requested EXIF/IPTC tag from the current image
882  *
883  * If $tags is an array all given tags are tried until a
884  * value is found. If no value is found $alt is returned.
885  *
886  * Which texts are known is defined in the functions _exifTagNames
887  * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
888  * to the names of the latter one)
889  *
890  * Only allowed in: detail.php
891  *
892  * @author Andreas Gohr <andi@splitbrain.org>
893  */
894 function tpl_img_getTag($tags,$alt='',$src=null){
895     // Init Exif Reader
896     global $SRC;
897
898     if(is_null($src)) $src = $SRC;
899
900     static $meta = null;
901     if(is_null($meta)) $meta = new JpegMeta($src);
902     if($meta === false) return $alt;
903     $info = $meta->getField($tags);
904     if($info == false) return $alt;
905     return $info;
906 }
907
908 /**
909  * Prints the image with a link to the full sized version
910  *
911  * Only allowed in: detail.php
912  *
913  * @param $maxwidth  int - maximal width of the image
914  * @param $maxheight int - maximal height of the image
915  * @param $link bool     - link to the orginal size?
916  * @param $params array  - additional image attributes
917  */
918 function tpl_img($maxwidth=0,$maxheight=0,$link=true,$params=null){
919     global $IMG;
920     $w = tpl_img_getTag('File.Width');
921     $h = tpl_img_getTag('File.Height');
922
923     //resize to given max values
924     $ratio = 1;
925     if($w >= $h){
926         if($maxwidth && $w >= $maxwidth){
927             $ratio = $maxwidth/$w;
928         }elseif($maxheight && $h > $maxheight){
929             $ratio = $maxheight/$h;
930         }
931     }else{
932         if($maxheight && $h >= $maxheight){
933             $ratio = $maxheight/$h;
934         }elseif($maxwidth && $w > $maxwidth){
935             $ratio = $maxwidth/$w;
936         }
937     }
938     if($ratio){
939         $w = floor($ratio*$w);
940         $h = floor($ratio*$h);
941     }
942
943     //prepare URLs
944     $url=ml($IMG,array('cache'=>$_REQUEST['cache']),true,'&');
945     $src=ml($IMG,array('cache'=>$_REQUEST['cache'],'w'=>$w,'h'=>$h),true,'&');
946
947     //prepare attributes
948     $alt=tpl_img_getTag('Simple.Title');
949     if(is_null($params)){
950         $p = array();
951     }else{
952         $p = $params;
953     }
954     if($w) $p['width']  = $w;
955     if($h) $p['height'] = $h;
956     $p['class']  = 'img_detail';
957     if($alt){
958         $p['alt']   = $alt;
959         $p['title'] = $alt;
960     }else{
961         $p['alt'] = '';
962     }
963     $p['src'] = $src;
964
965     $data = array('url'=>($link?$url:null), 'params'=>$p);
966     return trigger_event('TPL_IMG_DISPLAY',$data,'_tpl_img_action',true);
967 }
968
969 /**
970  * Default action for TPL_IMG_DISPLAY
971  */
972 function _tpl_img_action($data, $param=NULL) {
973     global $lang;
974     $p = buildAttributes($data['params']);
975
976     if($data['url']) print '<a href="'.hsc($data['url']).'" title="'.$lang['mediaview'].'">';
977     print '<img '.$p.'/>';
978     if($data['url']) print '</a>';
979     return true;
980 }
981
982 /**
983  * This function inserts a small gif which in reality is the indexer function.
984  *
985  * Should be called somewhere at the very end of the main.php
986  * template
987  */
988 function tpl_indexerWebBug(){
989     global $ID;
990     global $INFO;
991     if(!$INFO['exists']) return false;
992
993     $p = array();
994     $p['src']    = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
995         '&'.time();
996     $p['width']  = 2; //no more 1x1 px image because we live in times of ad blockers...
997     $p['height'] = 1;
998     $p['alt']    = '';
999     $att = buildAttributes($p);
1000     print "<img $att />";
1001     return true;
1002 }
1003
1004 // configuration methods
1005 /**
1006  * tpl_getConf($id)
1007  *
1008  * use this function to access template configuration variables
1009  */
1010 function tpl_getConf($id){
1011     global $conf;
1012     static $tpl_configloaded = false;
1013
1014     $tpl = $conf['template'];
1015
1016     if (!$tpl_configloaded){
1017         $tconf = tpl_loadConfig();
1018         if ($tconf !== false){
1019             foreach ($tconf as $key => $value){
1020                 if (isset($conf['tpl'][$tpl][$key])) continue;
1021                 $conf['tpl'][$tpl][$key] = $value;
1022             }
1023             $tpl_configloaded = true;
1024         }
1025     }
1026
1027     return $conf['tpl'][$tpl][$id];
1028 }
1029
1030 /**
1031  * tpl_loadConfig()
1032  * reads all template configuration variables
1033  * this function is automatically called by tpl_getConf()
1034  */
1035 function tpl_loadConfig(){
1036
1037     $file = DOKU_TPLINC.'/conf/default.php';
1038     $conf = array();
1039
1040     if (!@file_exists($file)) return false;
1041
1042     // load default config file
1043     include($file);
1044
1045     return $conf;
1046 }
1047
1048 // language methods
1049 /**
1050  * tpl_getLang($id)
1051  *
1052  * use this function to access template language variables
1053  */
1054 function tpl_getLang($id){
1055     static $lang = array();
1056
1057     if (count($lang) === 0){
1058         $path = DOKU_TPLINC.'lang/';
1059
1060         $lang = array();
1061
1062         global $conf;            // definitely don't invoke "global $lang"
1063         // don't include once
1064         @include($path.'en/lang.php');
1065         if ($conf['lang'] != 'en') @include($path.$conf['lang'].'/lang.php');
1066     }
1067
1068     return $lang[$id];
1069 }
1070
1071 /**
1072  * prints the "main content" in the mediamanger popup
1073  *
1074  * Depending on the user's actions this may be a list of
1075  * files in a namespace, the meta editing dialog or
1076  * a message of referencing pages
1077  *
1078  * Only allowed in mediamanager.php
1079  *
1080  * @triggers MEDIAMANAGER_CONTENT_OUTPUT
1081  * @param bool $fromajax - set true when calling this function via ajax
1082  * @author Andreas Gohr <andi@splitbrain.org>
1083  */
1084 function tpl_mediaContent($fromajax=false){
1085     global $IMG;
1086     global $AUTH;
1087     global $INUSE;
1088     global $NS;
1089     global $JUMPTO;
1090
1091     if(is_array($_REQUEST['do'])){
1092         $do = array_shift(array_keys($_REQUEST['do']));
1093     }else{
1094         $do = $_REQUEST['do'];
1095     }
1096     if(in_array($do,array('save','cancel'))) $do = '';
1097
1098     if(!$do){
1099         if($_REQUEST['edit']){
1100             $do = 'metaform';
1101         }elseif(is_array($INUSE)){
1102             $do = 'filesinuse';
1103         }else{
1104             $do = 'filelist';
1105         }
1106     }
1107
1108     // output the content pane, wrapped in an event.
1109     if(!$fromajax) ptln('<div id="media__content">');
1110     $data = array( 'do' => $do);
1111     $evt = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data);
1112     if ($evt->advise_before()) {
1113         $do = $data['do'];
1114         if($do == 'filesinuse'){
1115             media_filesinuse($INUSE,$IMG);
1116         }elseif($do == 'filelist'){
1117             media_filelist($NS,$AUTH,$JUMPTO);
1118         }elseif($do == 'searchlist'){
1119             media_searchlist($_REQUEST['q'],$NS,$AUTH);
1120         }else{
1121             msg('Unknown action '.hsc($do),-1);
1122         }
1123     }
1124     $evt->advise_after();
1125     unset($evt);
1126     if(!$fromajax) ptln('</div>');
1127
1128 }
1129
1130 /**
1131  * Prints the central column in full-screen media manager
1132  * Depending on the opened tab this may be a list of
1133  * files in a namespace, upload form or search form
1134  *
1135  * @author Kate Arzamastseva <pshns@ukr.net>
1136  */
1137 function tpl_mediaFileList(){
1138     global $AUTH;
1139     global $NS;
1140     global $JUMPTO;
1141     global $lang;
1142
1143     $opened_tab = $_REQUEST['tab_files'];
1144     if (!$opened_tab || !in_array($opened_tab, array('files', 'upload', 'search'))) $opened_tab = 'files';
1145     if ($_REQUEST['mediado'] == 'update') $opened_tab = 'upload';
1146
1147     echo '<h2 class="a11y">' . $lang['mediaselect'] . '</h2>'.NL;
1148
1149     media_tabs_files($opened_tab);
1150
1151     echo '<div class="panelHeader">'.NL;
1152     echo '<h3>';
1153     $tabTitle = ($NS) ? $NS : '['.$lang['mediaroot'].']';
1154     printf($lang['media_' . $opened_tab], '<strong>'.hsc($tabTitle).'</strong>');
1155     echo '</h3>'.NL;
1156     if ($opened_tab === 'search' || $opened_tab === 'files') {
1157         media_tab_files_options();
1158     }
1159     echo '</div>'.NL;
1160
1161     echo '<div class="panelContent">'.NL;
1162     if ($opened_tab == 'files') {
1163         media_tab_files($NS,$AUTH,$JUMPTO);
1164     } elseif ($opened_tab == 'upload') {
1165         media_tab_upload($NS,$AUTH,$JUMPTO);
1166     } elseif ($opened_tab == 'search') {
1167         media_tab_search($NS,$AUTH);
1168     }
1169     echo '</div>'.NL;
1170 }
1171
1172 /**
1173  * Prints the third column in full-screen media manager
1174  * Depending on the opened tab this may be details of the
1175  * selected file, the meta editing dialog or
1176  * list of file revisions
1177  *
1178  * @author Kate Arzamastseva <pshns@ukr.net>
1179  */
1180 function tpl_mediaFileDetails($image, $rev){
1181     global $AUTH, $NS, $conf, $DEL, $lang;
1182
1183     $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes')) && $conf['mediarevisions']);
1184     if (!$image || (!file_exists(mediaFN($image)) && !$removed) || $DEL) return '';
1185     if ($rev && !file_exists(mediaFN($image, $rev))) $rev = false;
1186     if (isset($NS) && getNS($image) != $NS) return '';
1187     $do = $_REQUEST['mediado'];
1188
1189     $opened_tab = $_REQUEST['tab_details'];
1190
1191     $tab_array = array('view');
1192     list($ext, $mime) = mimetype($image);
1193     if ($mime == 'image/jpeg') {
1194         $tab_array[] = 'edit';
1195     }
1196     if ($conf['mediarevisions']) {
1197         $tab_array[] = 'history';
1198     }
1199
1200     if (!$opened_tab || !in_array($opened_tab, $tab_array)) $opened_tab = 'view';
1201     if ($_REQUEST['edit']) $opened_tab = 'edit';
1202     if ($do == 'restore') $opened_tab = 'view';
1203
1204     media_tabs_details($image, $opened_tab);
1205
1206     echo '<div class="panelHeader"><h3>';
1207     list($ext,$mime,$dl) = mimetype($image,false);
1208     $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
1209     $class = 'select mediafile mf_'.$class;
1210     $tabTitle = '<strong class="'.$class.'">'.$image.'</strong>';
1211     if ($opened_tab === 'view' && $rev) {
1212         printf($lang['media_viewold'], $tabTitle, dformat($rev));
1213     } else {
1214         printf($lang['media_' . $opened_tab], $tabTitle);
1215     }
1216
1217     echo '</h3></div>'.NL;
1218
1219     echo '<div class="panelContent">'.NL;
1220
1221     if ($opened_tab == 'view') {
1222         media_tab_view($image, $NS, $AUTH, $rev);
1223
1224     } elseif ($opened_tab == 'edit' && !$removed) {
1225         media_tab_edit($image, $NS, $AUTH);
1226
1227     } elseif ($opened_tab == 'history' && $conf['mediarevisions']) {
1228         media_tab_history($image,$NS,$AUTH);
1229     }
1230
1231     echo '</div>'.NL;
1232 }
1233
1234 /**
1235  * prints the namespace tree in the mediamanger popup
1236  *
1237  * Only allowed in mediamanager.php
1238  *
1239  * @author Andreas Gohr <andi@splitbrain.org>
1240  */
1241 function tpl_mediaTree(){
1242     global $NS;
1243     ptln('<div id="media__tree">');
1244     media_nstree($NS);
1245     ptln('</div>');
1246 }
1247
1248
1249 /**
1250  * Print a dropdown menu with all DokuWiki actions
1251  *
1252  * Note: this will not use any pretty URLs
1253  *
1254  * @author Andreas Gohr <andi@splitbrain.org>
1255  */
1256 function tpl_actiondropdown($empty='',$button='&gt;'){
1257     global $ID;
1258     global $INFO;
1259     global $REV;
1260     global $ACT;
1261     global $conf;
1262     global $lang;
1263     global $auth;
1264
1265     echo '<form action="' . DOKU_SCRIPT . '" method="post" accept-charset="utf-8">';
1266     echo '<input type="hidden" name="id" value="'.$ID.'" />';
1267     if($REV) echo '<input type="hidden" name="rev" value="'.$REV.'" />';
1268     echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />';
1269
1270     echo '<select name="do" class="edit quickselect">';
1271     echo '<option value="">'.$empty.'</option>';
1272
1273     echo '<optgroup label=" &mdash; ">';
1274         $act = tpl_get_action('edit');
1275         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1276
1277         $act = tpl_get_action('revisions');
1278         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1279
1280         $act = tpl_get_action('revert');
1281         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1282
1283         $act = tpl_get_action('backlink');
1284         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1285     echo '</optgroup>';
1286
1287     echo '<optgroup label=" &mdash; ">';
1288         $act = tpl_get_action('recent');
1289         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1290
1291         $act = tpl_get_action('index');
1292         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1293     echo '</optgroup>';
1294
1295     echo '<optgroup label=" &mdash; ">';
1296         $act = tpl_get_action('login');
1297         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1298
1299         $act = tpl_get_action('profile');
1300         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1301
1302         $act = tpl_get_action('subscribe');
1303         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1304
1305         $act = tpl_get_action('admin');
1306         if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1307     echo '</optgroup>';
1308
1309     echo '</select>';
1310     echo '<input type="submit" value="'.$button.'" />';
1311     echo '</form>';
1312 }
1313
1314 /**
1315  * Print a informational line about the used license
1316  *
1317  * @author Andreas Gohr <andi@splitbrain.org>
1318  * @param  string $img    - print image? (|button|badge)
1319  * @param  bool   $return - when true don't print, but return HTML
1320  */
1321 function tpl_license($img='badge',$imgonly=false,$return=false){
1322     global $license;
1323     global $conf;
1324     global $lang;
1325     if(!$conf['license']) return '';
1326     if(!is_array($license[$conf['license']])) return '';
1327     $lic = $license[$conf['license']];
1328
1329     $out  = '<div class="license">';
1330     if($img){
1331         $src = license_img($img);
1332         if($src){
1333             $out .= '<a href="'.$lic['url'].'" rel="license"';
1334             if($conf['target']['extern']) $out .= ' target="'.$conf['target']['extern'].'"';
1335             $out .= '><img src="'.DOKU_BASE.$src.'" class="medialeft lic'.$img.'" alt="'.$lic['name'].'" /></a> ';
1336         }
1337     }
1338     if(!$imgonly) {
1339         $out .= $lang['license'];
1340         $out .= ' <a href="'.$lic['url'].'" rel="license" class="urlextern"';
1341         if($conf['target']['extern']) $out .= ' target="'.$conf['target']['extern'].'"';
1342         $out .= '>'.$lic['name'].'</a>';
1343     }
1344     $out .= '</div>';
1345
1346     if($return) return $out;
1347     echo $out;
1348 }
1349
1350
1351 /**
1352  * Includes the rendered XHTML of a given page
1353  *
1354  * This function is useful to populate sidebars or similar features in a
1355  * template
1356  */
1357 function tpl_include_page($pageid,$print=true){
1358     global $ID;
1359     global $TOC;
1360     $oldid  = $ID;
1361     $oldtoc = $TOC;
1362     $html = p_wiki_xhtml($pageid,'',false);
1363     $ID  = $oldid;
1364     $TOC = $oldtoc;
1365
1366     if(!$print) return $html;
1367     echo $html;
1368 }
1369
1370 /**
1371  * Display the subscribe form
1372  *
1373  * @author Adrian Lang <lang@cosmocode.de>
1374  */
1375 function tpl_subscribe() {
1376     global $INFO;
1377     global $ID;
1378     global $lang;
1379     global $conf;
1380     $stime_days = $conf['subscribe_time']/60/60/24;
1381
1382     echo p_locale_xhtml('subscr_form');
1383     echo '<h2>' . $lang['subscr_m_current_header'] . '</h2>';
1384     echo '<div class="level2">';
1385     if ($INFO['subscribed'] === false) {
1386         echo '<p>' . $lang['subscr_m_not_subscribed'] . '</p>';
1387     } else {
1388         echo '<ul>';
1389         foreach($INFO['subscribed'] as $sub) {
1390             echo '<li><div class="li">';
1391             if ($sub['target'] !== $ID) {
1392                 echo '<code class="ns">'.hsc(prettyprint_id($sub['target'])).'</code>';
1393             } else {
1394                 echo '<code class="page">'.hsc(prettyprint_id($sub['target'])).'</code>';
1395             }
1396             $sstl = sprintf($lang['subscr_style_'.$sub['style']], $stime_days);
1397             if(!$sstl) $sstl = hsc($sub['style']);
1398             echo ' ('.$sstl.') ';
1399
1400             echo '<a href="' . wl($ID,
1401                                   array('do'=>'subscribe',
1402                                         'sub_target'=>$sub['target'],
1403                                         'sub_style'=>$sub['style'],
1404                                         'sub_action'=>'unsubscribe',
1405                                         'sectok' => getSecurityToken())) .
1406                  '" class="unsubscribe">'.$lang['subscr_m_unsubscribe'] .
1407                  '</a></div></li>';
1408         }
1409         echo '</ul>';
1410     }
1411     echo '</div>';
1412
1413     // Add new subscription form
1414     echo '<h2>' . $lang['subscr_m_new_header'] . '</h2>';
1415     echo '<div class="level2">';
1416     $ns = getNS($ID).':';
1417     $targets = array(
1418             $ID => '<code class="page">'.prettyprint_id($ID).'</code>',
1419             $ns => '<code class="ns">'.prettyprint_id($ns).'</code>',
1420             );
1421     $styles = array(
1422             'every'  => $lang['subscr_style_every'],
1423             'digest' => sprintf($lang['subscr_style_digest'], $stime_days),
1424             'list' => sprintf($lang['subscr_style_list'], $stime_days),
1425             );
1426
1427     $form = new Doku_Form(array('id' => 'subscribe__form'));
1428     $form->startFieldset($lang['subscr_m_subscribe']);
1429     $form->addRadioSet('sub_target', $targets);
1430     $form->startFieldset($lang['subscr_m_receive']);
1431     $form->addRadioSet('sub_style', $styles);
1432     $form->addHidden('sub_action', 'subscribe');
1433     $form->addHidden('do', 'subscribe');
1434     $form->addHidden('id', $ID);
1435     $form->endFieldset();
1436     $form->addElement(form_makeButton('submit', 'subscribe', $lang['subscr_m_subscribe']));
1437     html_form('SUBSCRIBE', $form);
1438     echo '</div>';
1439 }
1440
1441 /**
1442  * Tries to send already created content right to the browser
1443  *
1444  * Wraps around ob_flush() and flush()
1445  *
1446  * @author Andreas Gohr <andi@splitbrain.org>
1447  */
1448 function tpl_flush(){
1449     ob_flush();
1450     flush();
1451 }
1452
1453
1454 /**
1455  * Returns icon from data/media root directory if it exists, otherwise
1456  * the one in the template's image directory.
1457  *
1458  * @param  bool $abs        - if to use absolute URL
1459  * @param  string $fileName - file name of icon
1460  * @author Anika Henke <anika@selfthinker.org>
1461  */
1462 function tpl_getFavicon($abs=false, $fileName='favicon.ico') {
1463     if (file_exists(mediaFN($fileName))) {
1464         return ml($fileName, '', true, '', $abs);
1465     }
1466
1467     if($abs) {
1468         return DOKU_URL.substr(DOKU_TPL.'images/'.$fileName, strlen(DOKU_REL));
1469     }
1470     return DOKU_TPL.'images/'.$fileName;
1471 }
1472
1473 /**
1474  * Returns <link> tag for various icon types (favicon|mobile|generic)
1475  *
1476  * @param  array $types - list of icon types to display (favicon|mobile|generic)
1477  * @author Anika Henke <anika@selfthinker.org>
1478  */
1479 function tpl_favicon($types=array('favicon')) {
1480
1481     $return = '';
1482
1483     foreach ($types as $type) {
1484         switch($type) {
1485             case 'favicon':
1486                 $return .= '<link rel="shortcut icon" href="'.tpl_getFavicon().'" />'.NL;
1487                 break;
1488             case 'mobile':
1489                 $return .= '<link rel="apple-touch-icon" href="'.tpl_getFavicon(false, 'apple-touch-icon.png').'" />'.NL;
1490                 break;
1491             case 'generic':
1492                 // ideal world solution, which doesn't work in any browser yet
1493                 $return .= '<link rel="icon" href="'.tpl_getFavicon(false, 'icon.svg').'" type="image/svg+xml" />'.NL;
1494                 break;
1495         }
1496     }
1497
1498     return $return;
1499 }
1500
1501 /**
1502  * Prints full-screen media manager
1503  *
1504  * @author Kate Arzamastseva <pshns@ukr.net>
1505  */
1506 function tpl_media() {
1507     global $DEL, $NS, $IMG, $AUTH, $JUMPTO, $REV, $lang, $fullscreen, $conf;
1508     $fullscreen = true;
1509     require_once DOKU_INC.'lib/exe/mediamanager.php';
1510
1511     if ($_REQUEST['image']) $image = cleanID($_REQUEST['image']);
1512     if (isset($IMG)) $image = $IMG;
1513     if (isset($JUMPTO)) $image = $JUMPTO;
1514     if (isset($REV) && !$JUMPTO) $rev = $REV;
1515
1516     echo '<div id="mediamanager__page">'.NL;
1517     echo '<h1>'.$lang['btn_media'].'</h1>'.NL;
1518     html_msgarea();
1519
1520     echo '<div class="panel namespaces">'.NL;
1521     echo '<h2>'.$lang['namespaces'].'</h2>'.NL;
1522     echo '<div class="panelHeader">';
1523     echo $lang['media_namespaces'];
1524     echo '</div>'.NL;
1525
1526     echo '<div class="panelContent" id="media__tree">'.NL;
1527     media_nstree($NS);
1528     echo '</div>'.NL;
1529     echo '</div>'.NL;
1530
1531     echo '<div class="panel filelist">'.NL;
1532     tpl_mediaFileList();
1533     echo '</div>'.NL;
1534
1535     echo '<div class="panel file">'.NL;
1536     echo '<h2 class="a11y">'.$lang['media_file'].'</h2>'.NL;
1537     tpl_mediaFileDetails($image, $rev);
1538     echo '</div>'.NL;
1539
1540     echo '</div>'.NL;
1541 }
1542
1543 //Setup VIM: ex: et ts=4 :
1544