Completed
Pull Request — authpdo (#1572)
by
unknown
04:27
created

template.php ➔ tpl_metaheaders()   F

Complexity

Conditions 24
Paths 5544

Size

Total Lines 138
Code Lines 88

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 24
eloc 88
nc 5544
nop 1
dl 0
loc 138
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
702
                return false;
703
            }
704
            $id        = $parent;
705
            $params    = array('do' => '');
706
            $accesskey = 'b';
707
            break;
708
        case 'img_backto':
709
            $params = array();
710
            $accesskey = 'b';
711
            $replacement = $ID;
712
            break;
713
        case 'login':
714
            $params['sectok'] = getSecurityToken();
715
            if($INPUT->server->has('REMOTE_USER')) {
716
                if(!actionOK('logout')) {
717
                    return false;
718
                }
719
                $params['do'] = 'logout';
720
                $type         = 'logout';
721
            }
722
            break;
723
        case 'register':
724
            if($INPUT->server->str('REMOTE_USER')) {
725
                return false;
726
            }
727
            break;
728
        case 'resendpwd':
729
            if($INPUT->server->str('REMOTE_USER')) {
730
                return false;
731
            }
732
            break;
733
        case 'admin':
734
            if(!$INFO['ismanager']) {
735
                return false;
736
            }
737
            break;
738
        case 'revert':
739
            if(!$INFO['ismanager'] || !$REV || !$INFO['writable']) {
740
                return false;
741
            }
742
            $params['rev']    = $REV;
743
            $params['sectok'] = getSecurityToken();
744
            break;
745
        case 'subscribe':
746
            if(!$INPUT->server->str('REMOTE_USER')) {
747
                return false;
748
            }
749
            break;
750
        case 'backlink':
751
            break;
752
        case 'profile':
753
            if(!$INPUT->server->has('REMOTE_USER')) {
754
                return false;
755
            }
756
            break;
757
        case 'media':
758
            $params['ns'] = getNS($ID);
759
            break;
760
        case 'mediaManager':
761
            // View image in media manager
762
            global $IMG;
763
            $imgNS = getNS($IMG);
764
            $authNS = auth_quickaclcheck("$imgNS:*");
765
            if ($authNS < AUTH_UPLOAD) {
766
                return false;
767
            }
768
            $params = array(
769
                'ns' => $imgNS,
770
                'image' => $IMG,
771
                'do' => 'media'
772
            );
773
            //$type = 'media';
774
            break;
775
        default:
776
            //unknown type
777
            $unknown = true;
778
    }
779
780
    $data = compact('accesskey', 'type', 'id', 'method', 'params', 'nofollow', 'replacement');
781
782
    $evt = new Doku_Event('TPL_ACTION_GET', $data);
783
    if($evt->advise_before()) {
784
        //handle unknown types
785
        if($unknown) {
786
            $data = '[unknown %s type]';
787
        }
788
    }
789
    $evt->advise_after();
790
    unset($evt);
791
792
    return $data;
793
}
794
795
/**
796
 * Wrapper around tpl_button() and tpl_actionlink()
797
 *
798
 * @author Anika Henke <[email protected]>
799
 *
800
 * @param string        $type action command
801
 * @param bool          $link link or form button?
802
 * @param string|bool   $wrapper HTML element wrapper
803
 * @param bool          $return return or print
804
 * @param string        $pre prefix for links
805
 * @param string        $suf suffix for links
806
 * @param string        $inner inner HTML for links
807
 * @return bool|string
808
 */
809
function tpl_action($type, $link = false, $wrapper = false, $return = false, $pre = '', $suf = '', $inner = '') {
810
    $out = '';
811
    if($link) {
812
        $out .= tpl_actionlink($type, $pre, $suf, $inner, true);
813
    } else {
814
        $out .= tpl_button($type, true);
815
    }
816
    if($out && $wrapper) $out = "<$wrapper>$out</$wrapper>";
817
818
    if($return) return $out;
819
    print $out;
820
    return $out ? true : false;
821
}
822
823
/**
824
 * Print the search form
825
 *
826
 * If the first parameter is given a div with the ID 'qsearch_out' will
827
 * be added which instructs the ajax pagequicksearch to kick in and place
828
 * its output into this div. The second parameter controls the propritary
829
 * attribute autocomplete. If set to false this attribute will be set with an
830
 * value of "off" to instruct the browser to disable it's own built in
831
 * autocompletion feature (MSIE and Firefox)
832
 *
833
 * @author Andreas Gohr <[email protected]>
834
 *
835
 * @param bool $ajax
836
 * @param bool $autocomplete
837
 * @return bool
838
 */
839
function tpl_searchform($ajax = true, $autocomplete = true) {
840
    global $lang;
841
    global $ACT;
842
    global $QUERY;
843
844
    // don't print the search form if search action has been disabled
845
    if(!actionOK('search')) return false;
846
847
    print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get" role="search"><div class="no">';
848
    print '<input type="hidden" name="do" value="search" />';
849
    print '<input type="text" ';
850
    if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" ';
851
    print 'placeholder="'.$lang['btn_search'].'" ';
852
    if(!$autocomplete) print 'autocomplete="off" ';
853
    print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]" />';
854
    print '<button type="submit" title="'.$lang['btn_search'].'">'.$lang['btn_search'].'</button>';
855
    if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
856
    print '</div></form>';
857
    return true;
858
}
859
860
/**
861
 * Print the breadcrumbs trace
862
 *
863
 * @author Andreas Gohr <[email protected]>
864
 *
865
 * @param string $sep Separator between entries
866
 * @return bool
867
 */
868
function tpl_breadcrumbs($sep = '•') {
869
    global $lang;
870
    global $conf;
871
872
    //check if enabled
873
    if(!$conf['breadcrumbs']) return false;
874
875
    $crumbs = breadcrumbs(); //setup crumb trace
876
877
    $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
878
879
    //render crumbs, highlight the last one
880
    print '<span class="bchead">'.$lang['breadcrumb'].'</span>';
881
    $last = count($crumbs);
882
    $i    = 0;
883
    foreach($crumbs as $id => $name) {
884
        $i++;
885
        echo $crumbs_sep;
886
        if($i == $last) print '<span class="curid">';
887
        print '<bdi>';
888
        tpl_link(wl($id), hsc($name), 'class="breadcrumbs" title="'.$id.'"');
889
        print '</bdi>';
890
        if($i == $last) print '</span>';
891
    }
892
    return true;
893
}
894
895
/**
896
 * Hierarchical breadcrumbs
897
 *
898
 * This code was suggested as replacement for the usual breadcrumbs.
899
 * It only makes sense with a deep site structure.
900
 *
901
 * @author Andreas Gohr <[email protected]>
902
 * @author Nigel McNie <[email protected]>
903
 * @author Sean Coates <[email protected]>
904
 * @author <[email protected]>
905
 * @todo   May behave strangely in RTL languages
906
 *
907
 * @param string $sep Separator between entries
908
 * @return bool
909
 */
910
function tpl_youarehere($sep = ' » ') {
911
    global $conf;
912
    global $ID;
913
    global $lang;
914
915
    // check if enabled
916
    if(!$conf['youarehere']) return false;
917
918
    $parts = explode(':', $ID);
919
    $count = count($parts);
920
921
    echo '<span class="bchead">'.$lang['youarehere'].' </span>';
922
923
    // always print the startpage
924
    echo '<span class="home">';
925
    tpl_pagelink(':'.$conf['start']);
926
    echo '</span>';
927
928
    // print intermediate namespace links
929
    $part = '';
930
    for($i = 0; $i < $count - 1; $i++) {
931
        $part .= $parts[$i].':';
932
        $page = $part;
933
        if($page == $conf['start']) continue; // Skip startpage
934
935
        // output
936
        echo $sep;
937
        tpl_pagelink($page);
938
    }
939
940
    // print current page, skipping start page, skipping for namespace index
941
    resolve_pageid('', $page, $exists);
942
    if(isset($page) && $page == $part.$parts[$i]) return true;
943
    $page = $part.$parts[$i];
944
    if($page == $conf['start']) return true;
945
    echo $sep;
946
    tpl_pagelink($page);
947
    return true;
948
}
949
950
/**
951
 * Print info if the user is logged in
952
 * and show full name in that case
953
 *
954
 * Could be enhanced with a profile link in future?
955
 *
956
 * @author Andreas Gohr <[email protected]>
957
 *
958
 * @return bool
959
 */
960
function tpl_userinfo() {
961
    global $lang;
962
    /** @var Input $INPUT */
963
    global $INPUT;
964
965
    if($INPUT->server->str('REMOTE_USER')) {
966
        print $lang['loggedinas'].' '.userlink();
967
        return true;
968
    }
969
    return false;
970
}
971
972
/**
973
 * Print some info about the current page
974
 *
975
 * @author Andreas Gohr <[email protected]>
976
 *
977
 * @param bool $ret return content instead of printing it
978
 * @return bool|string
979
 */
980
function tpl_pageinfo($ret = false) {
981
    global $conf;
982
    global $lang;
983
    global $INFO;
984
    global $ID;
985
986
    // return if we are not allowed to view the page
987
    if(!auth_quickaclcheck($ID)) {
988
        return false;
989
    }
990
991
    // prepare date and path
992
    $fn = $INFO['filepath'];
993
    if(!$conf['fullpath']) {
994
        if($INFO['rev']) {
995
            $fn = str_replace(fullpath($conf['olddir']).'/', '', $fn);
996
        } else {
997
            $fn = str_replace(fullpath($conf['datadir']).'/', '', $fn);
998
        }
999
    }
1000
    $fn   = utf8_decodeFN($fn);
1001
    $date = dformat($INFO['lastmod']);
1002
1003
    // print it
1004
    if($INFO['exists']) {
1005
        $out = '';
1006
        $out .= '<bdi>'.$fn.'</bdi>';
1007
        $out .= ' · ';
1008
        $out .= $lang['lastmod'];
1009
        $out .= ' ';
1010
        $out .= $date;
1011
        if($INFO['editor']) {
1012
            $out .= ' '.$lang['by'].' ';
1013
            $out .= '<bdi>'.editorinfo($INFO['editor']).'</bdi>';
1014
        } else {
1015
            $out .= ' ('.$lang['external_edit'].')';
1016
        }
1017
        if($INFO['locked']) {
1018
            $out .= ' · ';
1019
            $out .= $lang['lockedby'];
1020
            $out .= ' ';
1021
            $out .= '<bdi>'.editorinfo($INFO['locked']).'</bdi>';
1022
        }
1023
        if($ret) {
1024
            return $out;
1025
        } else {
1026
            echo $out;
1027
            return true;
1028
        }
1029
    }
1030
    return false;
1031
}
1032
1033
/**
1034
 * Prints or returns the name of the given page (current one if none given).
1035
 *
1036
 * If useheading is enabled this will use the first headline else
1037
 * the given ID is used.
1038
 *
1039
 * @author Andreas Gohr <[email protected]>
1040
 *
1041
 * @param string $id page id
1042
 * @param bool   $ret return content instead of printing
1043
 * @return bool|string
1044
 */
1045
function tpl_pagetitle($id = null, $ret = false) {
1046
    global $ACT, $INPUT, $conf, $lang;
1047
1048
    if(is_null($id)) {
1049
        global $ID;
1050
        $id = $ID;
1051
    }
1052
1053
    $name = $id;
1054
    if(useHeading('navigation')) {
1055
        $first_heading = p_get_first_heading($id);
1056
        if($first_heading) $name = $first_heading;
0 ignored issues
show
Bug Best Practice introduced by
The expression $first_heading of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1057
    }
1058
1059
    // default page title is the page name, modify with the current action
1060
    switch ($ACT) {
1061
        // admin functions
1062
        case 'admin' :
1063
            $page_title = $lang['btn_admin'];
1064
            // try to get the plugin name
1065
            /** @var $plugin DokuWiki_Admin_Plugin */
1066
            if ($plugin = plugin_getRequestAdminPlugin()){
1067
                $plugin_title = $plugin->getMenuText($conf['lang']);
1068
                $page_title = $plugin_title ? $plugin_title : $plugin->getPluginName();
1069
            }
1070
            break;
1071
1072
        // user functions
1073
        case 'login' :
1074
        case 'profile' :
1075
        case 'register' :
1076
        case 'resendpwd' :
1077
            $page_title = $lang['btn_'.$ACT];
1078
            break;
1079
1080
         // wiki functions
1081
        case 'search' :
1082
        case 'index' :
1083
            $page_title = $lang['btn_'.$ACT];
1084
            break;
1085
1086
        // page functions
1087
        case 'edit' :
1088
            $page_title = "✎ ".$name;
1089
            break;
1090
1091
        case 'revisions' :
1092
            $page_title = $name . ' - ' . $lang['btn_revs'];
1093
            break;
1094
1095
        case 'backlink' :
1096
        case 'recent' :
1097
        case 'subscribe' :
1098
            $page_title = $name . ' - ' . $lang['btn_'.$ACT];
1099
            break;
1100
1101
        default : // SHOW and anything else not included
1102
            $page_title = $name;
1103
    }
1104
1105
    if($ret) {
1106
        return hsc($page_title);
1107
    } else {
1108
        print hsc($page_title);
1109
        return true;
1110
    }
1111
}
1112
1113
/**
1114
 * Returns the requested EXIF/IPTC tag from the current image
1115
 *
1116
 * If $tags is an array all given tags are tried until a
1117
 * value is found. If no value is found $alt is returned.
1118
 *
1119
 * Which texts are known is defined in the functions _exifTagNames
1120
 * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
1121
 * to the names of the latter one)
1122
 *
1123
 * Only allowed in: detail.php
1124
 *
1125
 * @author Andreas Gohr <[email protected]>
1126
 *
1127
 * @param array|string $tags tag or array of tags to try
1128
 * @param string       $alt  alternative output if no data was found
1129
 * @param null|string  $src  the image src, uses global $SRC if not given
1130
 * @return string
1131
 */
1132
function tpl_img_getTag($tags, $alt = '', $src = null) {
1133
    // Init Exif Reader
1134
    global $SRC;
1135
1136
    if(is_null($src)) $src = $SRC;
1137
1138
    static $meta = null;
1139
    if(is_null($meta)) $meta = new JpegMeta($src);
1140
    if($meta === false) return $alt;
1141
    $info = cleanText($meta->getField($tags));
1142
    if($info == false) return $alt;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $info of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
1143
    return $info;
1144
}
1145
1146
/**
1147
 * Returns a description list of the metatags of the current image
1148
 *
1149
 * @return string html of description list
1150
 */
1151
function tpl_img_meta() {
1152
    global $lang;
1153
1154
    $tags = tpl_get_img_meta();
1155
1156
    echo '<dl>';
1157
    foreach($tags as $tag) {
1158
        $label = $lang[$tag['langkey']];
1159
        if(!$label) $label = $tag['langkey'] . ':';
1160
1161
        echo '<dt>'.$label.'</dt><dd>';
1162
        if ($tag['type'] == 'date') {
1163
            echo dformat($tag['value']);
1164
        } else {
1165
            echo hsc($tag['value']);
1166
        }
1167
        echo '</dd>';
1168
    }
1169
    echo '</dl>';
1170
}
1171
1172
/**
1173
 * Returns metadata as configured in mediameta config file, ready for creating html
1174
 *
1175
 * @return array with arrays containing the entries:
1176
 *   - string langkey  key to lookup in the $lang var, if not found printed as is
1177
 *   - string type     type of value
1178
 *   - string value    tag value (unescaped)
1179
 */
1180
function tpl_get_img_meta() {
1181
1182
    $config_files = getConfigFiles('mediameta');
1183
    foreach ($config_files as $config_file) {
1184
        if(file_exists($config_file)) {
1185
            include($config_file);
1186
        }
1187
    }
1188
    /** @var array $fields the included array with metadata */
1189
1190
    $tags = array();
1191
    foreach($fields as $tag){
0 ignored issues
show
Bug introduced by
The variable $fields does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1192
        $t = array();
1193
        if (!empty($tag[0])) {
1194
            $t = array($tag[0]);
1195
        }
1196
        if(is_array($tag[3])) {
1197
            $t = array_merge($t,$tag[3]);
1198
        }
1199
        $value = tpl_img_getTag($t);
1200
        if ($value) {
1201
            $tags[] = array('langkey' => $tag[1], 'type' => $tag[2], 'value' => $value);
1202
        }
1203
    }
1204
    return $tags;
1205
}
1206
1207
/**
1208
 * Prints the image with a link to the full sized version
1209
 *
1210
 * Only allowed in: detail.php
1211
 *
1212
 * @triggers TPL_IMG_DISPLAY
1213
 * @param $maxwidth  int - maximal width of the image
1214
 * @param $maxheight int - maximal height of the image
1215
 * @param $link bool     - link to the orginal size?
1216
 * @param $params array  - additional image attributes
1217
 * @return bool Result of TPL_IMG_DISPLAY
1218
 */
1219
function tpl_img($maxwidth = 0, $maxheight = 0, $link = true, $params = null) {
1220
    global $IMG;
1221
    /** @var Input $INPUT */
1222
    global $INPUT;
1223
    global $REV;
1224
    $w = tpl_img_getTag('File.Width');
1225
    $h = tpl_img_getTag('File.Height');
1226
1227
    //resize to given max values
1228
    $ratio = 1;
1229
    if($w >= $h) {
1230
        if($maxwidth && $w >= $maxwidth) {
1231
            $ratio = $maxwidth / $w;
1232
        } elseif($maxheight && $h > $maxheight) {
1233
            $ratio = $maxheight / $h;
1234
        }
1235
    } else {
1236
        if($maxheight && $h >= $maxheight) {
1237
            $ratio = $maxheight / $h;
1238
        } elseif($maxwidth && $w > $maxwidth) {
1239
            $ratio = $maxwidth / $w;
1240
        }
1241
    }
1242
    if($ratio) {
1243
        $w = floor($ratio * $w);
1244
        $h = floor($ratio * $h);
1245
    }
1246
1247
    //prepare URLs
1248
    $url = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV), true, '&');
1249
    $src = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV, 'w'=> $w, 'h'=> $h), true, '&');
1250
1251
    //prepare attributes
1252
    $alt = tpl_img_getTag('Simple.Title');
1253
    if(is_null($params)) {
1254
        $p = array();
1255
    } else {
1256
        $p = $params;
1257
    }
1258
    if($w) $p['width'] = $w;
1259
    if($h) $p['height'] = $h;
1260
    $p['class'] = 'img_detail';
1261
    if($alt) {
1262
        $p['alt']   = $alt;
1263
        $p['title'] = $alt;
1264
    } else {
1265
        $p['alt'] = '';
1266
    }
1267
    $p['src'] = $src;
1268
1269
    $data = array('url'=> ($link ? $url : null), 'params'=> $p);
1270
    return trigger_event('TPL_IMG_DISPLAY', $data, '_tpl_img_action', true);
1271
}
1272
1273
/**
1274
 * Default action for TPL_IMG_DISPLAY
1275
 *
1276
 * @param array $data
1277
 * @return bool
1278
 */
1279
function _tpl_img_action($data) {
1280
    global $lang;
1281
    $p = buildAttributes($data['params']);
1282
1283
    if($data['url']) print '<a href="'.hsc($data['url']).'" title="'.$lang['mediaview'].'">';
1284
    print '<img '.$p.'/>';
1285
    if($data['url']) print '</a>';
1286
    return true;
1287
}
1288
1289
/**
1290
 * This function inserts a small gif which in reality is the indexer function.
1291
 *
1292
 * Should be called somewhere at the very end of the main.php
1293
 * template
1294
 *
1295
 * @return bool
1296
 */
1297
function tpl_indexerWebBug() {
1298
    global $ID;
1299
1300
    $p           = array();
1301
    $p['src']    = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
1302
        '&'.time();
1303
    $p['width']  = 2; //no more 1x1 px image because we live in times of ad blockers...
1304
    $p['height'] = 1;
1305
    $p['alt']    = '';
1306
    $att         = buildAttributes($p);
1307
    print "<img $att />";
1308
    return true;
1309
}
1310
1311
/**
1312
 * tpl_getConf($id)
1313
 *
1314
 * use this function to access template configuration variables
1315
 *
1316
 * @param string $id      name of the value to access
1317
 * @param mixed  $notset  what to return if the setting is not available
1318
 * @return mixed
1319
 */
1320
function tpl_getConf($id, $notset=false) {
1321
    global $conf;
1322
    static $tpl_configloaded = false;
1323
1324
    $tpl = $conf['template'];
1325
1326
    if(!$tpl_configloaded) {
1327
        $tconf = tpl_loadConfig();
1328
        if($tconf !== false) {
1329
            foreach($tconf as $key => $value) {
1330
                if(isset($conf['tpl'][$tpl][$key])) continue;
1331
                $conf['tpl'][$tpl][$key] = $value;
1332
            }
1333
            $tpl_configloaded = true;
1334
        }
1335
    }
1336
1337
    if(isset($conf['tpl'][$tpl][$id])){
1338
        return $conf['tpl'][$tpl][$id];
1339
    }
1340
1341
    return $notset;
1342
}
1343
1344
/**
1345
 * tpl_loadConfig()
1346
 *
1347
 * reads all template configuration variables
1348
 * this function is automatically called by tpl_getConf()
1349
 *
1350
 * @return array
1351
 */
1352
function tpl_loadConfig() {
1353
1354
    $file = tpl_incdir().'/conf/default.php';
1355
    $conf = array();
1356
1357
    if(!file_exists($file)) return false;
1358
1359
    // load default config file
1360
    include($file);
1361
1362
    return $conf;
1363
}
1364
1365
// language methods
1366
/**
1367
 * tpl_getLang($id)
1368
 *
1369
 * use this function to access template language variables
1370
 *
1371
 * @param string $id key of language string
1372
 * @return string
1373
 */
1374
function tpl_getLang($id) {
1375
    static $lang = array();
1376
1377
    if(count($lang) === 0) {
1378
        global $conf, $config_cascade; // definitely don't invoke "global $lang"
1379
1380
        $path = tpl_incdir() . 'lang/';
1381
1382
        $lang = array();
1383
1384
        // don't include once
1385
        @include($path . 'en/lang.php');
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1386
        foreach($config_cascade['lang']['template'] as $config_file) {
1387
            if(file_exists($config_file . $conf['template'] . '/en/lang.php')) {
1388
                include($config_file . $conf['template'] . '/en/lang.php');
1389
            }
1390
        }
1391
1392
        if($conf['lang'] != 'en') {
1393
            @include($path . $conf['lang'] . '/lang.php');
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1394
            foreach($config_cascade['lang']['template'] as $config_file) {
1395
                if(file_exists($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php')) {
1396
                    include($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php');
1397
                }
1398
            }
1399
        }
1400
    }
1401
    return $lang[$id];
1402
}
1403
1404
/**
1405
 * Retrieve a language dependent file and pass to xhtml renderer for display
1406
 * template equivalent of p_locale_xhtml()
1407
 *
1408
 * @param   string $id id of language dependent wiki page
1409
 * @return  string     parsed contents of the wiki page in xhtml format
1410
 */
1411
function tpl_locale_xhtml($id) {
1412
    return p_cached_output(tpl_localeFN($id));
1413
}
1414
1415
/**
1416
 * Prepends appropriate path for a language dependent filename
1417
 *
1418
 * @param string $id id of localized text
1419
 * @return string wiki text
1420
 */
1421
function tpl_localeFN($id) {
1422
    $path = tpl_incdir().'lang/';
1423
    global $conf;
1424
    $file = DOKU_CONF.'template_lang/'.$conf['template'].'/'.$conf['lang'].'/'.$id.'.txt';
1425
    if (!file_exists($file)){
1426
        $file = $path.$conf['lang'].'/'.$id.'.txt';
1427
        if(!file_exists($file)){
1428
            //fall back to english
1429
            $file = $path.'en/'.$id.'.txt';
1430
        }
1431
    }
1432
    return $file;
1433
}
1434
1435
/**
1436
 * prints the "main content" in the mediamanger popup
1437
 *
1438
 * Depending on the user's actions this may be a list of
1439
 * files in a namespace, the meta editing dialog or
1440
 * a message of referencing pages
1441
 *
1442
 * Only allowed in mediamanager.php
1443
 *
1444
 * @triggers MEDIAMANAGER_CONTENT_OUTPUT
1445
 * @param bool $fromajax - set true when calling this function via ajax
1446
 * @param string $sort
1447
 *
1448
 * @author Andreas Gohr <[email protected]>
1449
 */
1450
function tpl_mediaContent($fromajax = false, $sort='natural') {
1451
    global $IMG;
1452
    global $AUTH;
1453
    global $INUSE;
1454
    global $NS;
1455
    global $JUMPTO;
1456
    /** @var Input $INPUT */
1457
    global $INPUT;
1458
1459
    $do = $INPUT->extract('do')->str('do');
1460
    if(in_array($do, array('save', 'cancel'))) $do = '';
1461
1462
    if(!$do) {
1463
        if($INPUT->bool('edit')) {
1464
            $do = 'metaform';
1465
        } elseif(is_array($INUSE)) {
1466
            $do = 'filesinuse';
1467
        } else {
1468
            $do = 'filelist';
1469
        }
1470
    }
1471
1472
    // output the content pane, wrapped in an event.
1473
    if(!$fromajax) ptln('<div id="media__content">');
1474
    $data = array('do' => $do);
1475
    $evt  = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data);
1476
    if($evt->advise_before()) {
1477
        $do = $data['do'];
1478
        if($do == 'filesinuse') {
1479
            media_filesinuse($INUSE, $IMG);
1480
        } elseif($do == 'filelist') {
1481
            media_filelist($NS, $AUTH, $JUMPTO,false,$sort);
1482
        } elseif($do == 'searchlist') {
1483
            media_searchlist($INPUT->str('q'), $NS, $AUTH);
1484
        } else {
1485
            msg('Unknown action '.hsc($do), -1);
1486
        }
1487
    }
1488
    $evt->advise_after();
1489
    unset($evt);
1490
    if(!$fromajax) ptln('</div>');
1491
1492
}
1493
1494
/**
1495
 * Prints the central column in full-screen media manager
1496
 * Depending on the opened tab this may be a list of
1497
 * files in a namespace, upload form or search form
1498
 *
1499
 * @author Kate Arzamastseva <[email protected]>
1500
 */
1501
function tpl_mediaFileList() {
1502
    global $AUTH;
1503
    global $NS;
1504
    global $JUMPTO;
1505
    global $lang;
1506
    /** @var Input $INPUT */
1507
    global $INPUT;
1508
1509
    $opened_tab = $INPUT->str('tab_files');
1510
    if(!$opened_tab || !in_array($opened_tab, array('files', 'upload', 'search'))) $opened_tab = 'files';
1511
    if($INPUT->str('mediado') == 'update') $opened_tab = 'upload';
1512
1513
    echo '<h2 class="a11y">'.$lang['mediaselect'].'</h2>'.NL;
1514
1515
    media_tabs_files($opened_tab);
1516
1517
    echo '<div class="panelHeader">'.NL;
1518
    echo '<h3>';
1519
    $tabTitle = ($NS) ? $NS : '['.$lang['mediaroot'].']';
1520
    printf($lang['media_'.$opened_tab], '<strong>'.hsc($tabTitle).'</strong>');
1521
    echo '</h3>'.NL;
1522
    if($opened_tab === 'search' || $opened_tab === 'files') {
1523
        media_tab_files_options();
1524
    }
1525
    echo '</div>'.NL;
1526
1527
    echo '<div class="panelContent">'.NL;
1528
    if($opened_tab == 'files') {
1529
        media_tab_files($NS, $AUTH, $JUMPTO);
1530
    } elseif($opened_tab == 'upload') {
1531
        media_tab_upload($NS, $AUTH, $JUMPTO);
1532
    } elseif($opened_tab == 'search') {
1533
        media_tab_search($NS, $AUTH);
1534
    }
1535
    echo '</div>'.NL;
1536
}
1537
1538
/**
1539
 * Prints the third column in full-screen media manager
1540
 * Depending on the opened tab this may be details of the
1541
 * selected file, the meta editing dialog or
1542
 * list of file revisions
1543
 *
1544
 * @author Kate Arzamastseva <[email protected]>
1545
 */
1546
function tpl_mediaFileDetails($image, $rev) {
1547
    global $conf, $DEL, $lang;
1548
    /** @var Input $INPUT */
1549
    global $INPUT;
1550
1551
    $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes')) && $conf['mediarevisions']);
1552
    if(!$image || (!file_exists(mediaFN($image)) && !$removed) || $DEL) return;
1553
    if($rev && !file_exists(mediaFN($image, $rev))) $rev = false;
1554
    $ns = getNS($image);
1555
    $do = $INPUT->str('mediado');
1556
1557
    $opened_tab = $INPUT->str('tab_details');
1558
1559
    $tab_array = array('view');
1560
    list(, $mime) = mimetype($image);
1561
    if($mime == 'image/jpeg') {
1562
        $tab_array[] = 'edit';
1563
    }
1564
    if($conf['mediarevisions']) {
1565
        $tab_array[] = 'history';
1566
    }
1567
1568
    if(!$opened_tab || !in_array($opened_tab, $tab_array)) $opened_tab = 'view';
1569
    if($INPUT->bool('edit')) $opened_tab = 'edit';
1570
    if($do == 'restore') $opened_tab = 'view';
1571
1572
    media_tabs_details($image, $opened_tab);
1573
1574
    echo '<div class="panelHeader"><h3>';
1575
    list($ext) = mimetype($image, false);
1576
    $class    = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
1577
    $class    = 'select mediafile mf_'.$class;
1578
    $tabTitle = '<strong><a href="'.ml($image).'" class="'.$class.'" title="'.$lang['mediaview'].'">'.$image.'</a>'.'</strong>';
1579
    if($opened_tab === 'view' && $rev) {
1580
        printf($lang['media_viewold'], $tabTitle, dformat($rev));
1581
    } else {
1582
        printf($lang['media_'.$opened_tab], $tabTitle);
1583
    }
1584
1585
    echo '</h3></div>'.NL;
1586
1587
    echo '<div class="panelContent">'.NL;
1588
1589
    if($opened_tab == 'view') {
1590
        media_tab_view($image, $ns, null, $rev);
0 ignored issues
show
Security Bug introduced by
It seems like $ns defined by getNS($image) on line 1554 can also be of type false; however, media_tab_view() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1591
1592
    } elseif($opened_tab == 'edit' && !$removed) {
1593
        media_tab_edit($image, $ns);
0 ignored issues
show
Security Bug introduced by
It seems like $ns defined by getNS($image) on line 1554 can also be of type false; however, media_tab_edit() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1594
1595
    } elseif($opened_tab == 'history' && $conf['mediarevisions']) {
1596
        media_tab_history($image, $ns);
0 ignored issues
show
Security Bug introduced by
It seems like $ns defined by getNS($image) on line 1554 can also be of type false; however, media_tab_history() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1597
    }
1598
1599
    echo '</div>'.NL;
1600
}
1601
1602
/**
1603
 * prints the namespace tree in the mediamanger popup
1604
 *
1605
 * Only allowed in mediamanager.php
1606
 *
1607
 * @author Andreas Gohr <[email protected]>
1608
 */
1609
function tpl_mediaTree() {
1610
    global $NS;
1611
    ptln('<div id="media__tree">');
1612
    media_nstree($NS);
1613
    ptln('</div>');
1614
}
1615
1616
/**
1617
 * Print a dropdown menu with all DokuWiki actions
1618
 *
1619
 * Note: this will not use any pretty URLs
1620
 *
1621
 * @author Andreas Gohr <[email protected]>
1622
 *
1623
 * @param string $empty empty option label
1624
 * @param string $button submit button label
1625
 */
1626
function tpl_actiondropdown($empty = '', $button = '&gt;') {
1627
    global $ID;
1628
    global $REV;
1629
    global $lang;
1630
    /** @var Input $INPUT */
1631
    global $INPUT;
1632
1633
    $action_structure = array(
1634
        'page_tools' => array('edit', 'revert', 'revisions', 'backlink', 'subscribe'),
1635
        'site_tools' => array('recent', 'media', 'index'),
1636
        'user_tools' => array('login', 'register', 'profile', 'admin'),
1637
    );
1638
1639
    echo '<form action="'.script().'" method="get" accept-charset="utf-8">';
1640
    echo '<div class="no">';
1641
    echo '<input type="hidden" name="id" value="'.$ID.'" />';
1642
    if($REV) echo '<input type="hidden" name="rev" value="'.$REV.'" />';
1643
    if ($INPUT->server->str('REMOTE_USER')) {
1644
        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />';
1645
    }
1646
1647
    echo '<select name="do" class="edit quickselect" title="'.$lang['tools'].'">';
1648
    echo '<option value="">'.$empty.'</option>';
1649
1650
    foreach($action_structure as $tools => $actions) {
1651
        echo '<optgroup label="'.$lang[$tools].'">';
1652
        foreach($actions as $action) {
1653
            $act = tpl_get_action($action);
1654
            if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1655
        }
1656
        echo '</optgroup>';
1657
    }
1658
1659
    echo '</select>';
1660
    echo '<button type="submit">'.$button.'</button>';
1661
    echo '</div>';
1662
    echo '</form>';
1663
}
1664
1665
/**
1666
 * Print a informational line about the used license
1667
 *
1668
 * @author Andreas Gohr <[email protected]>
1669
 * @param  string $img     print image? (|button|badge)
1670
 * @param  bool   $imgonly skip the textual description?
1671
 * @param  bool   $return  when true don't print, but return HTML
1672
 * @param  bool   $wrap    wrap in div with class="license"?
1673
 * @return string
1674
 */
1675
function tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap = true) {
1676
    global $license;
1677
    global $conf;
1678
    global $lang;
1679
    if(!$conf['license']) return '';
1680
    if(!is_array($license[$conf['license']])) return '';
1681
    $lic    = $license[$conf['license']];
1682
    $target = ($conf['target']['extern']) ? ' target="'.$conf['target']['extern'].'"' : '';
1683
1684
    $out = '';
1685
    if($wrap) $out .= '<div class="license">';
1686
    if($img) {
1687
        $src = license_img($img);
1688
        if($src) {
1689
            $out .= '<a href="'.$lic['url'].'" rel="license"'.$target;
1690
            $out .= '><img src="'.DOKU_BASE.$src.'" alt="'.$lic['name'].'" /></a>';
1691
            if(!$imgonly) $out .= ' ';
1692
        }
1693
    }
1694
    if(!$imgonly) {
1695
        $out .= $lang['license'].' ';
1696
        $out .= '<bdi><a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
1697
        $out .= '>'.$lic['name'].'</a></bdi>';
1698
    }
1699
    if($wrap) $out .= '</div>';
1700
1701
    if($return) return $out;
1702
    echo $out;
1703
    return '';
1704
}
1705
1706
/**
1707
 * Includes the rendered HTML of a given page
1708
 *
1709
 * This function is useful to populate sidebars or similar features in a
1710
 * template
1711
 *
1712
 * @param string $pageid
1713
 * @param bool $print
1714
 * @param bool $propagate
1715
 * @return bool|null|string
1716
 */
1717
function tpl_include_page($pageid, $print = true, $propagate = false) {
1718
    if (!$pageid) return false;
1719
    if ($propagate) $pageid = page_findnearest($pageid);
1720
1721
    global $TOC;
1722
    $oldtoc = $TOC;
1723
    $html   = p_wiki_xhtml($pageid, '', false);
0 ignored issues
show
Security Bug introduced by
It seems like $pageid defined by page_findnearest($pageid) on line 1719 can also be of type false; however, p_wiki_xhtml() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1724
    $TOC    = $oldtoc;
1725
1726
    if(!$print) return $html;
1727
    echo $html;
1728
    return $html;
1729
}
1730
1731
/**
1732
 * Display the subscribe form
1733
 *
1734
 * @author Adrian Lang <[email protected]>
1735
 */
1736
function tpl_subscribe() {
1737
    global $INFO;
1738
    global $ID;
1739
    global $lang;
1740
    global $conf;
1741
    $stime_days = $conf['subscribe_time'] / 60 / 60 / 24;
1742
1743
    echo p_locale_xhtml('subscr_form');
1744
    echo '<h2>'.$lang['subscr_m_current_header'].'</h2>';
1745
    echo '<div class="level2">';
1746
    if($INFO['subscribed'] === false) {
1747
        echo '<p>'.$lang['subscr_m_not_subscribed'].'</p>';
1748
    } else {
1749
        echo '<ul>';
1750
        foreach($INFO['subscribed'] as $sub) {
1751
            echo '<li><div class="li">';
1752
            if($sub['target'] !== $ID) {
1753
                echo '<code class="ns">'.hsc(prettyprint_id($sub['target'])).'</code>';
1754
            } else {
1755
                echo '<code class="page">'.hsc(prettyprint_id($sub['target'])).'</code>';
1756
            }
1757
            $sstl = sprintf($lang['subscr_style_'.$sub['style']], $stime_days);
1758
            if(!$sstl) $sstl = hsc($sub['style']);
1759
            echo ' ('.$sstl.') ';
1760
1761
            echo '<a href="'.wl(
1762
                $ID,
1763
                array(
1764
                     'do'        => 'subscribe',
1765
                     'sub_target'=> $sub['target'],
1766
                     'sub_style' => $sub['style'],
1767
                     'sub_action'=> 'unsubscribe',
1768
                     'sectok'    => getSecurityToken()
1769
                )
1770
            ).
1771
                '" class="unsubscribe">'.$lang['subscr_m_unsubscribe'].
1772
                '</a></div></li>';
1773
        }
1774
        echo '</ul>';
1775
    }
1776
    echo '</div>';
1777
1778
    // Add new subscription form
1779
    echo '<h2>'.$lang['subscr_m_new_header'].'</h2>';
1780
    echo '<div class="level2">';
1781
    $ns      = getNS($ID).':';
1782
    $targets = array(
1783
        $ID => '<code class="page">'.prettyprint_id($ID).'</code>',
1784
        $ns => '<code class="ns">'.prettyprint_id($ns).'</code>',
1785
    );
1786
    $styles  = array(
1787
        'every'  => $lang['subscr_style_every'],
1788
        'digest' => sprintf($lang['subscr_style_digest'], $stime_days),
1789
        'list'   => sprintf($lang['subscr_style_list'], $stime_days),
1790
    );
1791
1792
    $form = new Doku_Form(array('id' => 'subscribe__form'));
1793
    $form->startFieldset($lang['subscr_m_subscribe']);
1794
    $form->addRadioSet('sub_target', $targets);
1795
    $form->startFieldset($lang['subscr_m_receive']);
1796
    $form->addRadioSet('sub_style', $styles);
1797
    $form->addHidden('sub_action', 'subscribe');
1798
    $form->addHidden('do', 'subscribe');
1799
    $form->addHidden('id', $ID);
1800
    $form->endFieldset();
1801
    $form->addElement(form_makeButton('submit', 'subscribe', $lang['subscr_m_subscribe']));
1802
    html_form('SUBSCRIBE', $form);
1803
    echo '</div>';
1804
}
1805
1806
/**
1807
 * Tries to send already created content right to the browser
1808
 *
1809
 * Wraps around ob_flush() and flush()
1810
 *
1811
 * @author Andreas Gohr <[email protected]>
1812
 */
1813
function tpl_flush() {
1814
    ob_flush();
1815
    flush();
1816
}
1817
1818
/**
1819
 * Tries to find a ressource file in the given locations.
1820
 *
1821
 * If a given location starts with a colon it is assumed to be a media
1822
 * file, otherwise it is assumed to be relative to the current template
1823
 *
1824
 * @param  string[] $search       locations to look at
1825
 * @param  bool     $abs           if to use absolute URL
1826
 * @param  array   &$imginfo   filled with getimagesize()
1827
 * @return string
1828
 *
1829
 * @author Andreas  Gohr <[email protected]>
1830
 */
1831
function tpl_getMediaFile($search, $abs = false, &$imginfo = null) {
1832
    $img     = '';
1833
    $file    = '';
1834
    $ismedia = false;
1835
    // loop through candidates until a match was found:
1836
    foreach($search as $img) {
1837
        if(substr($img, 0, 1) == ':') {
1838
            $file    = mediaFN($img);
1839
            $ismedia = true;
1840
        } else {
1841
            $file    = tpl_incdir().$img;
1842
            $ismedia = false;
1843
        }
1844
1845
        if(file_exists($file)) break;
1846
    }
1847
1848
    // fetch image data if requested
1849
    if(!is_null($imginfo)) {
1850
        $imginfo = getimagesize($file);
1851
    }
1852
1853
    // build URL
1854
    if($ismedia) {
1855
        $url = ml($img, '', true, '', $abs);
1856
    } else {
1857
        $url = tpl_basedir().$img;
1858
        if($abs) $url = DOKU_URL.substr($url, strlen(DOKU_REL));
1859
    }
1860
1861
    return $url;
1862
}
1863
1864
/**
1865
 * PHP include a file
1866
 *
1867
 * either from the conf directory if it exists, otherwise use
1868
 * file in the template's root directory.
1869
 *
1870
 * The function honours config cascade settings and looks for the given
1871
 * file next to the ´main´ config files, in the order protected, local,
1872
 * default.
1873
 *
1874
 * Note: no escaping or sanity checking is done here. Never pass user input
1875
 * to this function!
1876
 *
1877
 * @author Anika Henke <[email protected]>
1878
 * @author Andreas Gohr <[email protected]>
1879
 *
1880
 * @param string $file
1881
 */
1882
function tpl_includeFile($file) {
1883
    global $config_cascade;
1884
    foreach(array('protected', 'local', 'default') as $config_group) {
1885
        if(empty($config_cascade['main'][$config_group])) continue;
1886
        foreach($config_cascade['main'][$config_group] as $conf_file) {
1887
            $dir = dirname($conf_file);
1888
            if(file_exists("$dir/$file")) {
1889
                include("$dir/$file");
1890
                return;
1891
            }
1892
        }
1893
    }
1894
1895
    // still here? try the template dir
1896
    $file = tpl_incdir().$file;
1897
    if(file_exists($file)) {
1898
        include($file);
1899
    }
1900
}
1901
1902
/**
1903
 * Returns <link> tag for various icon types (favicon|mobile|generic)
1904
 *
1905
 * @author Anika Henke <[email protected]>
1906
 *
1907
 * @param  array $types - list of icon types to display (favicon|mobile|generic)
1908
 * @return string
1909
 */
1910
function tpl_favicon($types = array('favicon')) {
1911
1912
    $return = '';
1913
1914
    foreach($types as $type) {
1915
        switch($type) {
1916
            case 'favicon':
1917
                $look = array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico');
1918
                $return .= '<link rel="shortcut icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1919
                break;
1920
            case 'mobile':
1921
                $look = array(':wiki:apple-touch-icon.png', ':apple-touch-icon.png', 'images/apple-touch-icon.png');
1922
                $return .= '<link rel="apple-touch-icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1923
                break;
1924
            case 'generic':
1925
                // ideal world solution, which doesn't work in any browser yet
1926
                $look = array(':wiki:favicon.svg', ':favicon.svg', 'images/favicon.svg');
1927
                $return .= '<link rel="icon" href="'.tpl_getMediaFile($look).'" type="image/svg+xml" />'.NL;
1928
                break;
1929
        }
1930
    }
1931
1932
    return $return;
1933
}
1934
1935
/**
1936
 * Prints full-screen media manager
1937
 *
1938
 * @author Kate Arzamastseva <[email protected]>
1939
 */
1940
function tpl_media() {
1941
    global $NS, $IMG, $JUMPTO, $REV, $lang, $fullscreen, $INPUT;
1942
    $fullscreen = true;
1943
    require_once DOKU_INC.'lib/exe/mediamanager.php';
1944
1945
    $rev   = '';
1946
    $image = cleanID($INPUT->str('image'));
1947
    if(isset($IMG)) $image = $IMG;
1948
    if(isset($JUMPTO)) $image = $JUMPTO;
1949
    if(isset($REV) && !$JUMPTO) $rev = $REV;
1950
1951
    echo '<div id="mediamanager__page">'.NL;
1952
    echo '<h1>'.$lang['btn_media'].'</h1>'.NL;
1953
    html_msgarea();
1954
1955
    echo '<div class="panel namespaces">'.NL;
1956
    echo '<h2>'.$lang['namespaces'].'</h2>'.NL;
1957
    echo '<div class="panelHeader">';
1958
    echo $lang['media_namespaces'];
1959
    echo '</div>'.NL;
1960
1961
    echo '<div class="panelContent" id="media__tree">'.NL;
1962
    media_nstree($NS);
1963
    echo '</div>'.NL;
1964
    echo '</div>'.NL;
1965
1966
    echo '<div class="panel filelist">'.NL;
1967
    tpl_mediaFileList();
1968
    echo '</div>'.NL;
1969
1970
    echo '<div class="panel file">'.NL;
1971
    echo '<h2 class="a11y">'.$lang['media_file'].'</h2>'.NL;
1972
    tpl_mediaFileDetails($image, $rev);
1973
    echo '</div>'.NL;
1974
1975
    echo '</div>'.NL;
1976
}
1977
1978
/**
1979
 * Return useful layout classes
1980
 *
1981
 * @author Anika Henke <[email protected]>
1982
 *
1983
 * @return string
1984
 */
1985
function tpl_classes() {
1986
    global $ACT, $conf, $ID, $INFO;
1987
    /** @var Input $INPUT */
1988
    global $INPUT;
1989
1990
    $classes = array(
1991
        'dokuwiki',
1992
        'mode_'.$ACT,
1993
        'tpl_'.$conf['template'],
1994
        $INPUT->server->bool('REMOTE_USER') ? 'loggedIn' : '',
1995
        $INFO['exists'] ? '' : 'notFound',
1996
        ($ID == $conf['start']) ? 'home' : '',
1997
    );
1998
    return join(' ', $classes);
1999
}
2000
2001
/**
2002
 * Create event for tools menues
2003
 *
2004
 * @author Anika Henke <[email protected]>
2005
 * @param string $toolsname name of menu
2006
 * @param array $items
2007
 * @param string $view e.g. 'main', 'detail', ...
2008
 */
2009
function tpl_toolsevent($toolsname, $items, $view = 'main') {
2010
    $data = array(
2011
        'view' => $view,
2012
        'items' => $items
2013
    );
2014
2015
    $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY';
2016
    $evt = new Doku_Event($hook, $data);
2017
    if($evt->advise_before()) {
2018
        foreach($evt->data['items'] as $k => $html) echo $html;
2019
    }
2020
    $evt->advise_after();
2021
}
2022
2023
//Setup VIM: ex: et ts=4 :
2024
2025