Completed
Push — actionrefactor ( 6e4bf0 )
by Andreas
04:36
created

template.php ➔ tpl_content_core()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
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
function tpl_content_core() {
91
    $router = \dokuwiki\ActionRouter::getInstance();
92
    $router->getAction()->tplContent();
93
    return true; // FIXME when is this false? do we need to catch an exception?
94
}
95
96
/**
97
 * Default Action of TPL_ACT_RENDER
98
 *
99
 * @return bool
100
 */
101
function XXX_tpl_content_core() {
102
    global $ACT;
103
    global $TEXT;
104
    global $PRE;
105
    global $SUF;
106
    global $SUM;
107
    global $IDX;
108
    global $INPUT;
109
110
    switch($ACT) {
111
        case 'show':
112
            html_show();
113
            break;
114
        /** @noinspection PhpMissingBreakStatementInspection */
115
        case 'locked':
116
            html_locked();
117
        case 'edit':
118
        case 'recover':
119
            html_edit();
120
            break;
121
        case 'preview':
122
            html_edit();
123
            html_show($TEXT);
124
            break;
125
        case 'draft':
126
            html_draft();
127
            break;
128
        case 'search':
129
            html_search();
130
            break;
131
        case 'revisions':
132
            html_revisions($INPUT->int('first'));
133
            break;
134
        case 'diff':
135
            html_diff();
136
            break;
137
        case 'recent':
138
            $show_changes = $INPUT->str('show_changes');
139
            if (empty($show_changes)) {
140
                $show_changes = get_doku_pref('show_changes', $show_changes);
141
            }
142
            html_recent($INPUT->extract('first')->int('first'), $show_changes);
143
            break;
144
        case 'index':
145
            html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
146
            break;
147
        case 'backlink':
148
            html_backlinks();
149
            break;
150
        case 'conflict':
151
            html_conflict(con($PRE, $TEXT, $SUF), $SUM);
152
            html_diff(con($PRE, $TEXT, $SUF), false);
153
            break;
154
        case 'login':
155
            html_login();
156
            break;
157
        case 'register':
158
            html_register();
159
            break;
160
        case 'resendpwd':
161
            html_resendpwd();
162
            break;
163
        case 'denied':
164
            html_denied();
165
            break;
166
        case 'profile' :
167
            html_updateprofile();
168
            break;
169
        case 'admin':
170
            tpl_admin();
171
            break;
172
        case 'subscribe':
173
            tpl_subscribe();
174
            break;
175
        case 'media':
176
            tpl_media();
177
            break;
178
        default:
179
            $evt = new Doku_Event('TPL_ACT_UNKNOWN', $ACT);
180
            if($evt->advise_before()) {
181
                msg("Failed to handle command: ".hsc($ACT), -1);
182
            }
183
            $evt->advise_after();
184
            unset($evt);
185
            return false;
186
    }
187
    return true;
188
}
189
190
/**
191
 * Places the TOC where the function is called
192
 *
193
 * If you use this you most probably want to call tpl_content with
194
 * a false argument
195
 *
196
 * @author Andreas Gohr <[email protected]>
197
 *
198
 * @param bool $return Should the TOC be returned instead to be printed?
199
 * @return string
200
 */
201
function tpl_toc($return = false) {
202
    global $TOC;
203
    global $ACT;
204
    global $ID;
205
    global $REV;
206
    global $INFO;
207
    global $conf;
208
    global $INPUT;
209
    $toc = array();
210
211
    if(is_array($TOC)) {
212
        // if a TOC was prepared in global scope, always use it
213
        $toc = $TOC;
214
    } elseif(($ACT == 'show' || substr($ACT, 0, 6) == 'export') && !$REV && $INFO['exists']) {
215
        // get TOC from metadata, render if neccessary
216
        $meta = p_get_metadata($ID, '', METADATA_RENDER_USING_CACHE);
217
        if(isset($meta['internal']['toc'])) {
218
            $tocok = $meta['internal']['toc'];
219
        } else {
220
            $tocok = true;
221
        }
222
        $toc = isset($meta['description']['tableofcontents']) ? $meta['description']['tableofcontents'] : null;
223
        if(!$tocok || !is_array($toc) || !$conf['tocminheads'] || count($toc) < $conf['tocminheads']) {
224
            $toc = array();
225
        }
226
    } elseif($ACT == 'admin') {
227
        // try to load admin plugin TOC
228
        /** @var $plugin DokuWiki_Admin_Plugin */
229
        if ($plugin = plugin_getRequestAdminPlugin()) {
230
            $toc = $plugin->getTOC();
231
            $TOC = $toc; // avoid later rebuild
232
        }
233
    }
234
235
    trigger_event('TPL_TOC_RENDER', $toc, null, false);
236
    $html = html_TOC($toc);
237
    if($return) return $html;
238
    echo $html;
239
    return '';
240
}
241
242
/**
243
 * Handle the admin page contents
244
 *
245
 * @author Andreas Gohr <[email protected]>
246
 *
247
 * @return bool
248
 */
249
function tpl_admin() {
250
    global $INFO;
251
    global $TOC;
252
    global $INPUT;
253
254
    $plugin = null;
255
    $class  = $INPUT->str('page');
256
    if(!empty($class)) {
257
        $pluginlist = plugin_list('admin');
258
259
        if(in_array($class, $pluginlist)) {
260
            // attempt to load the plugin
261
            /** @var $plugin DokuWiki_Admin_Plugin */
262
            $plugin = plugin_load('admin', $class);
263
        }
264
    }
265
266
    if($plugin !== null) {
267
        if(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet
268
        if($INFO['prependTOC']) tpl_toc();
269
        $plugin->html();
270
    } else {
271
        $admin = new dokuwiki\Ui\Admin();
272
        $admin->show();
273
    }
274
    return true;
275
}
276
277
/**
278
 * Print the correct HTML meta headers
279
 *
280
 * This has to go into the head section of your template.
281
 *
282
 * @author Andreas Gohr <[email protected]>
283
 *
284
 * @triggers TPL_METAHEADER_OUTPUT
285
 * @param  bool $alt Should feeds and alternative format links be added?
286
 * @return bool
287
 */
288
function tpl_metaheaders($alt = true) {
289
    global $ID;
290
    global $REV;
291
    global $INFO;
292
    global $JSINFO;
293
    global $ACT;
294
    global $QUERY;
295
    global $lang;
296
    global $conf;
297
    global $updateVersion;
298
    /** @var Input $INPUT */
299
    global $INPUT;
300
301
    // prepare the head array
302
    $head = array();
303
304
    // prepare seed for js and css
305
    $tseed   = $updateVersion;
306
    $depends = getConfigFiles('main');
307
    $depends[] = DOKU_CONF."tpl/".$conf['template']."/style.ini";
308
    foreach($depends as $f) $tseed .= @filemtime($f);
309
    $tseed   = md5($tseed);
310
311
    // the usual stuff
312
    $head['meta'][] = array('name'=> 'generator', 'content'=> 'DokuWiki');
313
    if(actionOK('search')) {
314
        $head['link'][] = array(
315
            'rel' => 'search', 'type'=> 'application/opensearchdescription+xml',
316
            'href'=> DOKU_BASE.'lib/exe/opensearch.php', 'title'=> $conf['title']
317
        );
318
    }
319
320
    $head['link'][] = array('rel'=> 'start', 'href'=> DOKU_BASE);
321
    if(actionOK('index')) {
322
        $head['link'][] = array(
323
            'rel'  => 'contents', 'href'=> wl($ID, 'do=index', false, '&'),
324
            'title'=> $lang['btn_index']
325
        );
326
    }
327
328
    if($alt) {
329
        if(actionOK('rss')) {
330
            $head['link'][] = array(
331
                'rel'  => 'alternate', 'type'=> 'application/rss+xml',
332
                'title'=> $lang['btn_recent'], 'href'=> DOKU_BASE.'feed.php'
333
            );
334
            $head['link'][] = array(
335
                'rel'  => 'alternate', 'type'=> 'application/rss+xml',
336
                'title'=> $lang['currentns'],
337
                'href' => DOKU_BASE.'feed.php?mode=list&ns='.$INFO['namespace']
338
            );
339
        }
340
        if(($ACT == 'show' || $ACT == 'search') && $INFO['writable']) {
341
            $head['link'][] = array(
342
                'rel'  => 'edit',
343
                'title'=> $lang['btn_edit'],
344
                'href' => wl($ID, 'do=edit', false, '&')
345
            );
346
        }
347
348
        if(actionOK('rss') && $ACT == 'search') {
349
            $head['link'][] = array(
350
                'rel'  => 'alternate', 'type'=> 'application/rss+xml',
351
                'title'=> $lang['searchresult'],
352
                'href' => DOKU_BASE.'feed.php?mode=search&q='.$QUERY
353
            );
354
        }
355
356
        if(actionOK('export_xhtml')) {
357
            $head['link'][] = array(
358
                'rel' => 'alternate', 'type'=> 'text/html', 'title'=> $lang['plainhtml'],
359
                'href'=> exportlink($ID, 'xhtml', '', false, '&')
360
            );
361
        }
362
363
        if(actionOK('export_raw')) {
364
            $head['link'][] = array(
365
                'rel' => 'alternate', 'type'=> 'text/plain', 'title'=> $lang['wikimarkup'],
366
                'href'=> exportlink($ID, 'raw', '', false, '&')
367
            );
368
        }
369
    }
370
371
    // setup robot tags apropriate for different modes
372
    if(($ACT == 'show' || $ACT == 'export_xhtml') && !$REV) {
373
        if($INFO['exists']) {
374
            //delay indexing:
375
            if((time() - $INFO['lastmod']) >= $conf['indexdelay']) {
376
                $head['meta'][] = array('name'=> 'robots', 'content'=> 'index,follow');
377
            } else {
378
                $head['meta'][] = array('name'=> 'robots', 'content'=> 'noindex,nofollow');
379
            }
380
            $canonicalUrl = wl($ID, '', true, '&');
381
            if ($ID == $conf['start']) {
382
                $canonicalUrl = DOKU_URL;
383
            }
384
            $head['link'][] = array('rel'=> 'canonical', 'href'=> $canonicalUrl);
385
        } else {
386
            $head['meta'][] = array('name'=> 'robots', 'content'=> 'noindex,follow');
387
        }
388
    } elseif(defined('DOKU_MEDIADETAIL')) {
389
        $head['meta'][] = array('name'=> 'robots', 'content'=> 'index,follow');
390
    } else {
391
        $head['meta'][] = array('name'=> 'robots', 'content'=> 'noindex,nofollow');
392
    }
393
394
    // set metadata
395
    if($ACT == 'show' || $ACT == 'export_xhtml') {
396
        // keywords (explicit or implicit)
397
        if(!empty($INFO['meta']['subject'])) {
398
            $head['meta'][] = array('name'=> 'keywords', 'content'=> join(',', $INFO['meta']['subject']));
399
        } else {
400
            $head['meta'][] = array('name'=> 'keywords', 'content'=> str_replace(':', ',', $ID));
401
        }
402
    }
403
404
    // load stylesheets
405
    $head['link'][] = array(
406
        'rel' => 'stylesheet', 'type'=> 'text/css',
407
        'href'=> DOKU_BASE.'lib/exe/css.php?t='.rawurlencode($conf['template']).'&tseed='.$tseed
408
    );
409
410
    // make $INFO and other vars available to JavaScripts
411
    $json   = new JSON();
412
    $script = "var NS='".$INFO['namespace']."';";
413
    if($conf['useacl'] && $INPUT->server->str('REMOTE_USER')) {
414
        $script .= "var SIG='".toolbar_signature()."';";
415
    }
416
    $script .= 'var JSINFO = '.$json->encode($JSINFO).';';
417
    $head['script'][] = array('type'=> 'text/javascript', '_data'=> $script);
418
419
    // load jquery
420
    $jquery = getCdnUrls();
421
    foreach($jquery as $src) {
422
        $head['script'][] = array(
423
            'type' => 'text/javascript', 'charset' => 'utf-8', '_data' => '', 'src' => $src
424
        );
425
    }
426
427
    // load our javascript dispatcher
428
    $head['script'][] = array(
429
        'type'=> 'text/javascript', 'charset'=> 'utf-8', '_data'=> '',
430
        'src' => DOKU_BASE.'lib/exe/js.php'.'?t='.rawurlencode($conf['template']).'&tseed='.$tseed
431
    );
432
433
    // trigger event here
434
    trigger_event('TPL_METAHEADER_OUTPUT', $head, '_tpl_metaheaders_action', true);
435
    return true;
436
}
437
438
/**
439
 * prints the array build by tpl_metaheaders
440
 *
441
 * $data is an array of different header tags. Each tag can have multiple
442
 * instances. Attributes are given as key value pairs. Values will be HTML
443
 * encoded automatically so they should be provided as is in the $data array.
444
 *
445
 * For tags having a body attribute specify the body data in the special
446
 * attribute '_data'. This field will NOT BE ESCAPED automatically.
447
 *
448
 * @author Andreas Gohr <[email protected]>
449
 *
450
 * @param array $data
451
 */
452
function _tpl_metaheaders_action($data) {
453
    foreach($data as $tag => $inst) {
454
        if($tag == 'script') {
455
            echo "<!--[if gte IE 9]><!-->\n"; // no scripts for old IE
456
        }
457
        foreach($inst as $attr) {
458
            echo '<', $tag, ' ', buildAttributes($attr);
459
            if(isset($attr['_data']) || $tag == 'script') {
460
                if($tag == 'script' && $attr['_data'])
461
                    $attr['_data'] = "/*<![CDATA[*/".
462
                        $attr['_data'].
463
                        "\n/*!]]>*/";
464
465
                echo '>', $attr['_data'], '</', $tag, '>';
466
            } else {
467
                echo '/>';
468
            }
469
            echo "\n";
470
        }
471
        if($tag == 'script') {
472
            echo "<!--<![endif]-->\n";
473
        }
474
    }
475
}
476
477
/**
478
 * Print a link
479
 *
480
 * Just builds a link.
481
 *
482
 * @author Andreas Gohr <[email protected]>
483
 *
484
 * @param string $url
485
 * @param string $name
486
 * @param string $more
487
 * @param bool $return if true return the link html, otherwise print
488
 * @return bool|string html of the link, or true if printed
489
 */
490
function tpl_link($url, $name, $more = '', $return = false) {
491
    $out = '<a href="'.$url.'" ';
492
    if($more) $out .= ' '.$more;
493
    $out .= ">$name</a>";
494
    if($return) return $out;
495
    print $out;
496
    return true;
497
}
498
499
/**
500
 * Prints a link to a WikiPage
501
 *
502
 * Wrapper around html_wikilink
503
 *
504
 * @author Andreas Gohr <[email protected]>
505
 *
506
 * @param string      $id   page id
507
 * @param string|null $name the name of the link
508
 * @return bool true
509
 */
510
function tpl_pagelink($id, $name = null) {
511
    print '<bdi>'.html_wikilink($id, $name).'</bdi>';
512
    return true;
513
}
514
515
/**
516
 * get the parent page
517
 *
518
 * Tries to find out which page is parent.
519
 * returns false if none is available
520
 *
521
 * @author Andreas Gohr <[email protected]>
522
 *
523
 * @param string $id page id
524
 * @return false|string
525
 */
526
function tpl_getparent($id) {
527
    $parent = getNS($id).':';
528
    resolve_pageid('', $parent, $exists);
529
    if($parent == $id) {
530
        $pos    = strrpos(getNS($id), ':');
531
        $parent = substr($parent, 0, $pos).':';
532
        resolve_pageid('', $parent, $exists);
533
        if($parent == $id) return false;
534
    }
535
    return $parent;
536
}
537
538
/**
539
 * Print one of the buttons
540
 *
541
 * @author Adrian Lang <[email protected]>
542
 * @see    tpl_get_action
543
 *
544
 * @param string $type
545
 * @param bool $return
546
 * @return bool|string html, or false if no data, true if printed
547
 */
548
function tpl_button($type, $return = false) {
549
    $data = tpl_get_action($type);
550
    if($data === false) {
551
        return false;
552
    } elseif(!is_array($data)) {
553
        $out = sprintf($data, 'button');
554
    } else {
555
        /**
556
         * @var string $accesskey
557
         * @var string $id
558
         * @var string $method
559
         * @var array  $params
560
         */
561
        extract($data);
562
        if($id === '#dokuwiki__top') {
563
            $out = html_topbtn();
564
        } else {
565
            $out = html_btn($type, $id, $accesskey, $params, $method);
566
        }
567
    }
568
    if($return) return $out;
569
    echo $out;
570
    return true;
571
}
572
573
/**
574
 * Like the action buttons but links
575
 *
576
 * @author Adrian Lang <[email protected]>
577
 * @see    tpl_get_action
578
 *
579
 * @param string $type    action command
580
 * @param string $pre     prefix of link
581
 * @param string $suf     suffix of link
582
 * @param string $inner   innerHML of link
583
 * @param bool   $return  if true it returns html, otherwise prints
584
 * @return bool|string html or false if no data, true if printed
585
 */
586
function tpl_actionlink($type, $pre = '', $suf = '', $inner = '', $return = false) {
587
    global $lang;
588
    $data = tpl_get_action($type);
589
    if($data === false) {
590
        return false;
591
    } elseif(!is_array($data)) {
592
        $out = sprintf($data, 'link');
593
    } else {
594
        /**
595
         * @var string $accesskey
596
         * @var string $id
597
         * @var string $method
598
         * @var bool   $nofollow
599
         * @var array  $params
600
         * @var string $replacement
601
         */
602
        extract($data);
603
        if(strpos($id, '#') === 0) {
604
            $linktarget = $id;
605
        } else {
606
            $linktarget = wl($id, $params);
607
        }
608
        $caption = $lang['btn_'.$type];
609
        if(strpos($caption, '%s')){
610
            $caption = sprintf($caption, $replacement);
611
        }
612
        $akey    = $addTitle = '';
613
        if($accesskey) {
614
            $akey     = 'accesskey="'.$accesskey.'" ';
615
            $addTitle = ' ['.strtoupper($accesskey).']';
616
        }
617
        $rel = $nofollow ? 'rel="nofollow" ' : '';
618
        $out = tpl_link(
619
            $linktarget, $pre.(($inner) ? $inner : $caption).$suf,
620
            'class="action '.$type.'" '.
621
                $akey.$rel.
622
                'title="'.hsc($caption).$addTitle.'"', true
623
        );
624
    }
625
    if($return) return $out;
626
    echo $out;
627
    return true;
628
}
629
630
/**
631
 * Check the actions and get data for buttons and links
632
 *
633
 * Available actions are
634
 *
635
 *  edit        - edit/create/show/draft
636
 *  history     - old revisions
637
 *  recent      - recent changes
638
 *  login       - login/logout - if ACL enabled
639
 *  profile     - user profile (if logged in)
640
 *  index       - The index
641
 *  admin       - admin page - if enough rights
642
 *  top         - back to top
643
 *  back        - back to parent - if available
644
 *  backlink    - links to the list of backlinks
645
 *  subscribe/subscription- subscribe/unsubscribe
646
 *
647
 * @author Andreas Gohr <[email protected]>
648
 * @author Matthias Grimm <[email protected]>
649
 * @author Adrian Lang <[email protected]>
650
 *
651
 * @param string $type
652
 * @return array|bool|string
653
 */
654
function tpl_get_action($type) {
655
    global $ID;
656
    global $INFO;
657
    global $REV;
658
    global $ACT;
659
    global $conf;
660
    /** @var Input $INPUT */
661
    global $INPUT;
662
663
    // check disabled actions and fix the badly named ones
664
    if($type == 'history') $type = 'revisions';
665
    if ($type == 'subscription') $type = 'subscribe';
666
    if(!actionOK($type)) return false;
667
668
    $accesskey   = null;
669
    $id          = $ID;
670
    $method      = 'get';
671
    $params      = array('do' => $type);
672
    $nofollow    = true;
673
    $replacement = '';
674
675
    $unknown = false;
676
    switch($type) {
677
        case 'edit':
678
            // most complicated type - we need to decide on current action
679
            if($ACT == 'show' || $ACT == 'search') {
680
                $method = 'post';
681
                if($INFO['writable']) {
682
                    $accesskey = 'e';
683
                    if(!empty($INFO['draft'])) {
684
                        $type         = 'draft';
685
                        $params['do'] = 'draft';
686
                    } else {
687
                        $params['rev'] = $REV;
688
                        if(!$INFO['exists']) {
689
                            $type = 'create';
690
                        }
691
                    }
692
                } else {
693
                    if(!actionOK('source')) return false; //pseudo action
694
                    $params['rev'] = $REV;
695
                    $type          = 'source';
696
                    $accesskey     = 'v';
697
                }
698
            } else {
699
                $params    = array('do' => '');
700
                $type      = 'show';
701
                $accesskey = 'v';
702
            }
703
            break;
704
        case 'revisions':
705
            $type      = 'revs';
706
            $accesskey = 'o';
707
            break;
708
        case 'recent':
709
            $accesskey = 'r';
710
            break;
711
        case 'index':
712
            $accesskey = 'x';
713
            // allow searchbots to get to the sitemap from the homepage (when dokuwiki isn't providing a sitemap.xml)
714
            if ($conf['start'] == $ID && !$conf['sitemap']) {
715
                $nofollow = false;
716
            }
717
            break;
718
        case 'top':
719
            $accesskey = 't';
720
            $params    = array('do' => '');
721
            $id        = '#dokuwiki__top';
722
            break;
723
        case 'back':
724
            $parent = tpl_getparent($ID);
725
            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...
726
                return false;
727
            }
728
            $id        = $parent;
729
            $params    = array('do' => '');
730
            $accesskey = 'b';
731
            break;
732
        case 'img_backto':
733
            $params = array();
734
            $accesskey = 'b';
735
            $replacement = $ID;
736
            break;
737
        case 'login':
738
            $params['sectok'] = getSecurityToken();
739
            if($INPUT->server->has('REMOTE_USER')) {
740
                if(!actionOK('logout')) {
741
                    return false;
742
                }
743
                $params['do'] = 'logout';
744
                $type         = 'logout';
745
            }
746
            break;
747
        case 'register':
748
            if($INPUT->server->str('REMOTE_USER')) {
749
                return false;
750
            }
751
            break;
752
        case 'resendpwd':
753
            if($INPUT->server->str('REMOTE_USER')) {
754
                return false;
755
            }
756
            break;
757
        case 'admin':
758
            if(!$INFO['ismanager']) {
759
                return false;
760
            }
761
            break;
762
        case 'revert':
763
            if(!$INFO['ismanager'] || !$REV || !$INFO['writable']) {
764
                return false;
765
            }
766
            $params['rev']    = $REV;
767
            $params['sectok'] = getSecurityToken();
768
            break;
769
        case 'subscribe':
770
            if(!$INPUT->server->str('REMOTE_USER')) {
771
                return false;
772
            }
773
            break;
774
        case 'backlink':
775
            break;
776
        case 'profile':
777
            if(!$INPUT->server->has('REMOTE_USER')) {
778
                return false;
779
            }
780
            break;
781
        case 'media':
782
            $params['ns'] = getNS($ID);
783
            break;
784
        case 'mediaManager':
785
            // View image in media manager
786
            global $IMG;
787
            $imgNS = getNS($IMG);
788
            $authNS = auth_quickaclcheck("$imgNS:*");
789
            if ($authNS < AUTH_UPLOAD) {
790
                return false;
791
            }
792
            $params = array(
793
                'ns' => $imgNS,
794
                'image' => $IMG,
795
                'do' => 'media'
796
            );
797
            //$type = 'media';
798
            break;
799
        default:
800
            //unknown type
801
            $unknown = true;
802
    }
803
804
    $data = compact('accesskey', 'type', 'id', 'method', 'params', 'nofollow', 'replacement');
805
806
    $evt = new Doku_Event('TPL_ACTION_GET', $data);
807
    if($evt->advise_before()) {
808
        //handle unknown types
809
        if($unknown) {
810
            $data = '[unknown %s type]';
811
        }
812
    }
813
    $evt->advise_after();
814
    unset($evt);
815
816
    return $data;
817
}
818
819
/**
820
 * Wrapper around tpl_button() and tpl_actionlink()
821
 *
822
 * @author Anika Henke <[email protected]>
823
 *
824
 * @param string        $type action command
825
 * @param bool          $link link or form button?
826
 * @param string|bool   $wrapper HTML element wrapper
827
 * @param bool          $return return or print
828
 * @param string        $pre prefix for links
829
 * @param string        $suf suffix for links
830
 * @param string        $inner inner HTML for links
831
 * @return bool|string
832
 */
833
function tpl_action($type, $link = false, $wrapper = false, $return = false, $pre = '', $suf = '', $inner = '') {
834
    $out = '';
835
    if($link) {
836
        $out .= tpl_actionlink($type, $pre, $suf, $inner, true);
837
    } else {
838
        $out .= tpl_button($type, true);
839
    }
840
    if($out && $wrapper) $out = "<$wrapper>$out</$wrapper>";
841
842
    if($return) return $out;
843
    print $out;
844
    return $out ? true : false;
845
}
846
847
/**
848
 * Print the search form
849
 *
850
 * If the first parameter is given a div with the ID 'qsearch_out' will
851
 * be added which instructs the ajax pagequicksearch to kick in and place
852
 * its output into this div. The second parameter controls the propritary
853
 * attribute autocomplete. If set to false this attribute will be set with an
854
 * value of "off" to instruct the browser to disable it's own built in
855
 * autocompletion feature (MSIE and Firefox)
856
 *
857
 * @author Andreas Gohr <[email protected]>
858
 *
859
 * @param bool $ajax
860
 * @param bool $autocomplete
861
 * @return bool
862
 */
863
function tpl_searchform($ajax = true, $autocomplete = true) {
864
    global $lang;
865
    global $ACT;
866
    global $QUERY;
867
868
    // don't print the search form if search action has been disabled
869
    if(!actionOK('search')) return false;
870
871
    print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get" role="search"><div class="no">';
872
    print '<input type="hidden" name="do" value="search" />';
873
    print '<input type="text" ';
874
    if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" ';
875
    print 'placeholder="'.$lang['btn_search'].'" ';
876
    if(!$autocomplete) print 'autocomplete="off" ';
877
    print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]" />';
878
    print '<button type="submit" title="'.$lang['btn_search'].'">'.$lang['btn_search'].'</button>';
879
    if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
880
    print '</div></form>';
881
    return true;
882
}
883
884
/**
885
 * Print the breadcrumbs trace
886
 *
887
 * @author Andreas Gohr <[email protected]>
888
 *
889
 * @param string $sep Separator between entries
890
 * @return bool
891
 */
892
function tpl_breadcrumbs($sep = '•') {
893
    global $lang;
894
    global $conf;
895
896
    //check if enabled
897
    if(!$conf['breadcrumbs']) return false;
898
899
    $crumbs = breadcrumbs(); //setup crumb trace
900
901
    $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
902
903
    //render crumbs, highlight the last one
904
    print '<span class="bchead">'.$lang['breadcrumb'].'</span>';
905
    $last = count($crumbs);
906
    $i    = 0;
907
    foreach($crumbs as $id => $name) {
908
        $i++;
909
        echo $crumbs_sep;
910
        if($i == $last) print '<span class="curid">';
911
        print '<bdi>';
912
        tpl_link(wl($id), hsc($name), 'class="breadcrumbs" title="'.$id.'"');
913
        print '</bdi>';
914
        if($i == $last) print '</span>';
915
    }
916
    return true;
917
}
918
919
/**
920
 * Hierarchical breadcrumbs
921
 *
922
 * This code was suggested as replacement for the usual breadcrumbs.
923
 * It only makes sense with a deep site structure.
924
 *
925
 * @author Andreas Gohr <[email protected]>
926
 * @author Nigel McNie <[email protected]>
927
 * @author Sean Coates <[email protected]>
928
 * @author <[email protected]>
929
 * @todo   May behave strangely in RTL languages
930
 *
931
 * @param string $sep Separator between entries
932
 * @return bool
933
 */
934
function tpl_youarehere($sep = ' » ') {
935
    global $conf;
936
    global $ID;
937
    global $lang;
938
939
    // check if enabled
940
    if(!$conf['youarehere']) return false;
941
942
    $parts = explode(':', $ID);
943
    $count = count($parts);
944
945
    echo '<span class="bchead">'.$lang['youarehere'].' </span>';
946
947
    // always print the startpage
948
    echo '<span class="home">';
949
    tpl_pagelink(':'.$conf['start']);
950
    echo '</span>';
951
952
    // print intermediate namespace links
953
    $part = '';
954
    for($i = 0; $i < $count - 1; $i++) {
955
        $part .= $parts[$i].':';
956
        $page = $part;
957
        if($page == $conf['start']) continue; // Skip startpage
958
959
        // output
960
        echo $sep;
961
        tpl_pagelink($page);
962
    }
963
964
    // print current page, skipping start page, skipping for namespace index
965
    resolve_pageid('', $page, $exists);
966
    if(isset($page) && $page == $part.$parts[$i]) return true;
967
    $page = $part.$parts[$i];
968
    if($page == $conf['start']) return true;
969
    echo $sep;
970
    tpl_pagelink($page);
971
    return true;
972
}
973
974
/**
975
 * Print info if the user is logged in
976
 * and show full name in that case
977
 *
978
 * Could be enhanced with a profile link in future?
979
 *
980
 * @author Andreas Gohr <[email protected]>
981
 *
982
 * @return bool
983
 */
984
function tpl_userinfo() {
985
    global $lang;
986
    /** @var Input $INPUT */
987
    global $INPUT;
988
989
    if($INPUT->server->str('REMOTE_USER')) {
990
        print $lang['loggedinas'].' '.userlink();
991
        return true;
992
    }
993
    return false;
994
}
995
996
/**
997
 * Print some info about the current page
998
 *
999
 * @author Andreas Gohr <[email protected]>
1000
 *
1001
 * @param bool $ret return content instead of printing it
1002
 * @return bool|string
1003
 */
1004
function tpl_pageinfo($ret = false) {
1005
    global $conf;
1006
    global $lang;
1007
    global $INFO;
1008
    global $ID;
1009
1010
    // return if we are not allowed to view the page
1011
    if(!auth_quickaclcheck($ID)) {
1012
        return false;
1013
    }
1014
1015
    // prepare date and path
1016
    $fn = $INFO['filepath'];
1017
    if(!$conf['fullpath']) {
1018
        if($INFO['rev']) {
1019
            $fn = str_replace($conf['olddir'].'/', '', $fn);
1020
        } else {
1021
            $fn = str_replace($conf['datadir'].'/', '', $fn);
1022
        }
1023
    }
1024
    $fn   = utf8_decodeFN($fn);
1025
    $date = dformat($INFO['lastmod']);
1026
1027
    // print it
1028
    if($INFO['exists']) {
1029
        $out = '';
1030
        $out .= '<bdi>'.$fn.'</bdi>';
1031
        $out .= ' · ';
1032
        $out .= $lang['lastmod'];
1033
        $out .= ' ';
1034
        $out .= $date;
1035
        if($INFO['editor']) {
1036
            $out .= ' '.$lang['by'].' ';
1037
            $out .= '<bdi>'.editorinfo($INFO['editor']).'</bdi>';
1038
        } else {
1039
            $out .= ' ('.$lang['external_edit'].')';
1040
        }
1041
        if($INFO['locked']) {
1042
            $out .= ' · ';
1043
            $out .= $lang['lockedby'];
1044
            $out .= ' ';
1045
            $out .= '<bdi>'.editorinfo($INFO['locked']).'</bdi>';
1046
        }
1047
        if($ret) {
1048
            return $out;
1049
        } else {
1050
            echo $out;
1051
            return true;
1052
        }
1053
    }
1054
    return false;
1055
}
1056
1057
/**
1058
 * Prints or returns the name of the given page (current one if none given).
1059
 *
1060
 * If useheading is enabled this will use the first headline else
1061
 * the given ID is used.
1062
 *
1063
 * @author Andreas Gohr <[email protected]>
1064
 *
1065
 * @param string $id page id
1066
 * @param bool   $ret return content instead of printing
1067
 * @return bool|string
1068
 */
1069
function tpl_pagetitle($id = null, $ret = false) {
1070
    global $ACT, $INPUT, $conf, $lang;
1071
1072
    if(is_null($id)) {
1073
        global $ID;
1074
        $id = $ID;
1075
    }
1076
1077
    $name = $id;
1078
    if(useHeading('navigation')) {
1079
        $first_heading = p_get_first_heading($id);
1080
        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...
1081
    }
1082
1083
    // default page title is the page name, modify with the current action
1084
    switch ($ACT) {
1085
        // admin functions
1086
        case 'admin' :
1087
            $page_title = $lang['btn_admin'];
1088
            // try to get the plugin name
1089
            /** @var $plugin DokuWiki_Admin_Plugin */
1090
            if ($plugin = plugin_getRequestAdminPlugin()){
1091
                $plugin_title = $plugin->getMenuText($conf['lang']);
1092
                $page_title = $plugin_title ? $plugin_title : $plugin->getPluginName();
1093
            }
1094
            break;
1095
1096
        // user functions
1097
        case 'login' :
1098
        case 'profile' :
1099
        case 'register' :
1100
        case 'resendpwd' :
1101
            $page_title = $lang['btn_'.$ACT];
1102
            break;
1103
1104
         // wiki functions
1105
        case 'search' :
1106
        case 'index' :
1107
            $page_title = $lang['btn_'.$ACT];
1108
            break;
1109
1110
        // page functions
1111
        case 'edit' :
1112
            $page_title = "✎ ".$name;
1113
            break;
1114
1115
        case 'revisions' :
1116
            $page_title = $name . ' - ' . $lang['btn_revs'];
1117
            break;
1118
1119
        case 'backlink' :
1120
        case 'recent' :
1121
        case 'subscribe' :
1122
            $page_title = $name . ' - ' . $lang['btn_'.$ACT];
1123
            break;
1124
1125
        default : // SHOW and anything else not included
1126
            $page_title = $name;
1127
    }
1128
1129
    if($ret) {
1130
        return hsc($page_title);
1131
    } else {
1132
        print hsc($page_title);
1133
        return true;
1134
    }
1135
}
1136
1137
/**
1138
 * Returns the requested EXIF/IPTC tag from the current image
1139
 *
1140
 * If $tags is an array all given tags are tried until a
1141
 * value is found. If no value is found $alt is returned.
1142
 *
1143
 * Which texts are known is defined in the functions _exifTagNames
1144
 * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
1145
 * to the names of the latter one)
1146
 *
1147
 * Only allowed in: detail.php
1148
 *
1149
 * @author Andreas Gohr <[email protected]>
1150
 *
1151
 * @param array|string $tags tag or array of tags to try
1152
 * @param string       $alt  alternative output if no data was found
1153
 * @param null|string  $src  the image src, uses global $SRC if not given
1154
 * @return string
1155
 */
1156
function tpl_img_getTag($tags, $alt = '', $src = null) {
1157
    // Init Exif Reader
1158
    global $SRC;
1159
1160
    if(is_null($src)) $src = $SRC;
1161
1162
    static $meta = null;
1163
    if(is_null($meta)) $meta = new JpegMeta($src);
1164
    if($meta === false) return $alt;
1165
    $info = cleanText($meta->getField($tags));
1166
    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...
1167
    return $info;
1168
}
1169
1170
/**
1171
 * Returns a description list of the metatags of the current image
1172
 *
1173
 * @return string html of description list
1174
 */
1175
function tpl_img_meta() {
1176
    global $lang;
1177
1178
    $tags = tpl_get_img_meta();
1179
1180
    echo '<dl>';
1181
    foreach($tags as $tag) {
1182
        $label = $lang[$tag['langkey']];
1183
        if(!$label) $label = $tag['langkey'] . ':';
1184
1185
        echo '<dt>'.$label.'</dt><dd>';
1186
        if ($tag['type'] == 'date') {
1187
            echo dformat($tag['value']);
1188
        } else {
1189
            echo hsc($tag['value']);
1190
        }
1191
        echo '</dd>';
1192
    }
1193
    echo '</dl>';
1194
}
1195
1196
/**
1197
 * Returns metadata as configured in mediameta config file, ready for creating html
1198
 *
1199
 * @return array with arrays containing the entries:
1200
 *   - string langkey  key to lookup in the $lang var, if not found printed as is
1201
 *   - string type     type of value
1202
 *   - string value    tag value (unescaped)
1203
 */
1204
function tpl_get_img_meta() {
1205
1206
    $config_files = getConfigFiles('mediameta');
1207
    foreach ($config_files as $config_file) {
1208
        if(file_exists($config_file)) {
1209
            include($config_file);
1210
        }
1211
    }
1212
    /** @var array $fields the included array with metadata */
1213
1214
    $tags = array();
1215
    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...
1216
        $t = array();
1217
        if (!empty($tag[0])) {
1218
            $t = array($tag[0]);
1219
        }
1220
        if(is_array($tag[3])) {
1221
            $t = array_merge($t,$tag[3]);
1222
        }
1223
        $value = tpl_img_getTag($t);
1224
        if ($value) {
1225
            $tags[] = array('langkey' => $tag[1], 'type' => $tag[2], 'value' => $value);
1226
        }
1227
    }
1228
    return $tags;
1229
}
1230
1231
/**
1232
 * Prints the image with a link to the full sized version
1233
 *
1234
 * Only allowed in: detail.php
1235
 *
1236
 * @triggers TPL_IMG_DISPLAY
1237
 * @param $maxwidth  int - maximal width of the image
1238
 * @param $maxheight int - maximal height of the image
1239
 * @param $link bool     - link to the orginal size?
1240
 * @param $params array  - additional image attributes
1241
 * @return bool Result of TPL_IMG_DISPLAY
1242
 */
1243
function tpl_img($maxwidth = 0, $maxheight = 0, $link = true, $params = null) {
1244
    global $IMG;
1245
    /** @var Input $INPUT */
1246
    global $INPUT;
1247
    global $REV;
1248
    $w = (int) tpl_img_getTag('File.Width');
1249
    $h = (int) tpl_img_getTag('File.Height');
1250
1251
    //resize to given max values
1252
    $ratio = 1;
1253
    if($w >= $h) {
1254
        if($maxwidth && $w >= $maxwidth) {
1255
            $ratio = $maxwidth / $w;
1256
        } elseif($maxheight && $h > $maxheight) {
1257
            $ratio = $maxheight / $h;
1258
        }
1259
    } else {
1260
        if($maxheight && $h >= $maxheight) {
1261
            $ratio = $maxheight / $h;
1262
        } elseif($maxwidth && $w > $maxwidth) {
1263
            $ratio = $maxwidth / $w;
1264
        }
1265
    }
1266
    if($ratio) {
1267
        $w = floor($ratio * $w);
1268
        $h = floor($ratio * $h);
1269
    }
1270
1271
    //prepare URLs
1272
    $url = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV), true, '&');
1273
    $src = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV, 'w'=> $w, 'h'=> $h), true, '&');
1274
1275
    //prepare attributes
1276
    $alt = tpl_img_getTag('Simple.Title');
1277
    if(is_null($params)) {
1278
        $p = array();
1279
    } else {
1280
        $p = $params;
1281
    }
1282
    if($w) $p['width'] = $w;
1283
    if($h) $p['height'] = $h;
1284
    $p['class'] = 'img_detail';
1285
    if($alt) {
1286
        $p['alt']   = $alt;
1287
        $p['title'] = $alt;
1288
    } else {
1289
        $p['alt'] = '';
1290
    }
1291
    $p['src'] = $src;
1292
1293
    $data = array('url'=> ($link ? $url : null), 'params'=> $p);
1294
    return trigger_event('TPL_IMG_DISPLAY', $data, '_tpl_img_action', true);
1295
}
1296
1297
/**
1298
 * Default action for TPL_IMG_DISPLAY
1299
 *
1300
 * @param array $data
1301
 * @return bool
1302
 */
1303
function _tpl_img_action($data) {
1304
    global $lang;
1305
    $p = buildAttributes($data['params']);
1306
1307
    if($data['url']) print '<a href="'.hsc($data['url']).'" title="'.$lang['mediaview'].'">';
1308
    print '<img '.$p.'/>';
1309
    if($data['url']) print '</a>';
1310
    return true;
1311
}
1312
1313
/**
1314
 * This function inserts a small gif which in reality is the indexer function.
1315
 *
1316
 * Should be called somewhere at the very end of the main.php
1317
 * template
1318
 *
1319
 * @return bool
1320
 */
1321
function tpl_indexerWebBug() {
1322
    global $ID;
1323
1324
    $p           = array();
1325
    $p['src']    = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
1326
        '&'.time();
1327
    $p['width']  = 2; //no more 1x1 px image because we live in times of ad blockers...
1328
    $p['height'] = 1;
1329
    $p['alt']    = '';
1330
    $att         = buildAttributes($p);
1331
    print "<img $att />";
1332
    return true;
1333
}
1334
1335
/**
1336
 * tpl_getConf($id)
1337
 *
1338
 * use this function to access template configuration variables
1339
 *
1340
 * @param string $id      name of the value to access
1341
 * @param mixed  $notset  what to return if the setting is not available
1342
 * @return mixed
1343
 */
1344
function tpl_getConf($id, $notset=false) {
1345
    global $conf;
1346
    static $tpl_configloaded = false;
1347
1348
    $tpl = $conf['template'];
1349
1350
    if(!$tpl_configloaded) {
1351
        $tconf = tpl_loadConfig();
1352
        if($tconf !== false) {
1353
            foreach($tconf as $key => $value) {
1354
                if(isset($conf['tpl'][$tpl][$key])) continue;
1355
                $conf['tpl'][$tpl][$key] = $value;
1356
            }
1357
            $tpl_configloaded = true;
1358
        }
1359
    }
1360
1361
    if(isset($conf['tpl'][$tpl][$id])){
1362
        return $conf['tpl'][$tpl][$id];
1363
    }
1364
1365
    return $notset;
1366
}
1367
1368
/**
1369
 * tpl_loadConfig()
1370
 *
1371
 * reads all template configuration variables
1372
 * this function is automatically called by tpl_getConf()
1373
 *
1374
 * @return array
1375
 */
1376
function tpl_loadConfig() {
1377
1378
    $file = tpl_incdir().'/conf/default.php';
1379
    $conf = array();
1380
1381
    if(!file_exists($file)) return false;
1382
1383
    // load default config file
1384
    include($file);
1385
1386
    return $conf;
1387
}
1388
1389
// language methods
1390
/**
1391
 * tpl_getLang($id)
1392
 *
1393
 * use this function to access template language variables
1394
 *
1395
 * @param string $id key of language string
1396
 * @return string
1397
 */
1398
function tpl_getLang($id) {
1399
    static $lang = array();
1400
1401
    if(count($lang) === 0) {
1402
        global $conf, $config_cascade; // definitely don't invoke "global $lang"
1403
1404
        $path = tpl_incdir() . 'lang/';
1405
1406
        $lang = array();
1407
1408
        // don't include once
1409
        @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...
1410
        foreach($config_cascade['lang']['template'] as $config_file) {
1411
            if(file_exists($config_file . $conf['template'] . '/en/lang.php')) {
1412
                include($config_file . $conf['template'] . '/en/lang.php');
1413
            }
1414
        }
1415
1416
        if($conf['lang'] != 'en') {
1417
            @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...
1418
            foreach($config_cascade['lang']['template'] as $config_file) {
1419
                if(file_exists($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php')) {
1420
                    include($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php');
1421
                }
1422
            }
1423
        }
1424
    }
1425
    return $lang[$id];
1426
}
1427
1428
/**
1429
 * Retrieve a language dependent file and pass to xhtml renderer for display
1430
 * template equivalent of p_locale_xhtml()
1431
 *
1432
 * @param   string $id id of language dependent wiki page
1433
 * @return  string     parsed contents of the wiki page in xhtml format
1434
 */
1435
function tpl_locale_xhtml($id) {
1436
    return p_cached_output(tpl_localeFN($id));
1437
}
1438
1439
/**
1440
 * Prepends appropriate path for a language dependent filename
1441
 *
1442
 * @param string $id id of localized text
1443
 * @return string wiki text
1444
 */
1445
function tpl_localeFN($id) {
1446
    $path = tpl_incdir().'lang/';
1447
    global $conf;
1448
    $file = DOKU_CONF.'template_lang/'.$conf['template'].'/'.$conf['lang'].'/'.$id.'.txt';
1449
    if (!file_exists($file)){
1450
        $file = $path.$conf['lang'].'/'.$id.'.txt';
1451
        if(!file_exists($file)){
1452
            //fall back to english
1453
            $file = $path.'en/'.$id.'.txt';
1454
        }
1455
    }
1456
    return $file;
1457
}
1458
1459
/**
1460
 * prints the "main content" in the mediamanager popup
1461
 *
1462
 * Depending on the user's actions this may be a list of
1463
 * files in a namespace, the meta editing dialog or
1464
 * a message of referencing pages
1465
 *
1466
 * Only allowed in mediamanager.php
1467
 *
1468
 * @triggers MEDIAMANAGER_CONTENT_OUTPUT
1469
 * @param bool $fromajax - set true when calling this function via ajax
1470
 * @param string $sort
1471
 *
1472
 * @author Andreas Gohr <[email protected]>
1473
 */
1474
function tpl_mediaContent($fromajax = false, $sort='natural') {
1475
    global $IMG;
1476
    global $AUTH;
1477
    global $INUSE;
1478
    global $NS;
1479
    global $JUMPTO;
1480
    /** @var Input $INPUT */
1481
    global $INPUT;
1482
1483
    $do = $INPUT->extract('do')->str('do');
1484
    if(in_array($do, array('save', 'cancel'))) $do = '';
1485
1486
    if(!$do) {
1487
        if($INPUT->bool('edit')) {
1488
            $do = 'metaform';
1489
        } elseif(is_array($INUSE)) {
1490
            $do = 'filesinuse';
1491
        } else {
1492
            $do = 'filelist';
1493
        }
1494
    }
1495
1496
    // output the content pane, wrapped in an event.
1497
    if(!$fromajax) ptln('<div id="media__content">');
1498
    $data = array('do' => $do);
1499
    $evt  = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data);
1500
    if($evt->advise_before()) {
1501
        $do = $data['do'];
1502
        if($do == 'filesinuse') {
1503
            media_filesinuse($INUSE, $IMG);
1504
        } elseif($do == 'filelist') {
1505
            media_filelist($NS, $AUTH, $JUMPTO,false,$sort);
1506
        } elseif($do == 'searchlist') {
1507
            media_searchlist($INPUT->str('q'), $NS, $AUTH);
1508
        } else {
1509
            msg('Unknown action '.hsc($do), -1);
1510
        }
1511
    }
1512
    $evt->advise_after();
1513
    unset($evt);
1514
    if(!$fromajax) ptln('</div>');
1515
1516
}
1517
1518
/**
1519
 * Prints the central column in full-screen media manager
1520
 * Depending on the opened tab this may be a list of
1521
 * files in a namespace, upload form or search form
1522
 *
1523
 * @author Kate Arzamastseva <[email protected]>
1524
 */
1525
function tpl_mediaFileList() {
1526
    global $AUTH;
1527
    global $NS;
1528
    global $JUMPTO;
1529
    global $lang;
1530
    /** @var Input $INPUT */
1531
    global $INPUT;
1532
1533
    $opened_tab = $INPUT->str('tab_files');
1534
    if(!$opened_tab || !in_array($opened_tab, array('files', 'upload', 'search'))) $opened_tab = 'files';
1535
    if($INPUT->str('mediado') == 'update') $opened_tab = 'upload';
1536
1537
    echo '<h2 class="a11y">'.$lang['mediaselect'].'</h2>'.NL;
1538
1539
    media_tabs_files($opened_tab);
1540
1541
    echo '<div class="panelHeader">'.NL;
1542
    echo '<h3>';
1543
    $tabTitle = ($NS) ? $NS : '['.$lang['mediaroot'].']';
1544
    printf($lang['media_'.$opened_tab], '<strong>'.hsc($tabTitle).'</strong>');
1545
    echo '</h3>'.NL;
1546
    if($opened_tab === 'search' || $opened_tab === 'files') {
1547
        media_tab_files_options();
1548
    }
1549
    echo '</div>'.NL;
1550
1551
    echo '<div class="panelContent">'.NL;
1552
    if($opened_tab == 'files') {
1553
        media_tab_files($NS, $AUTH, $JUMPTO);
1554
    } elseif($opened_tab == 'upload') {
1555
        media_tab_upload($NS, $AUTH, $JUMPTO);
1556
    } elseif($opened_tab == 'search') {
1557
        media_tab_search($NS, $AUTH);
1558
    }
1559
    echo '</div>'.NL;
1560
}
1561
1562
/**
1563
 * Prints the third column in full-screen media manager
1564
 * Depending on the opened tab this may be details of the
1565
 * selected file, the meta editing dialog or
1566
 * list of file revisions
1567
 *
1568
 * @author Kate Arzamastseva <[email protected]>
1569
 *
1570
 * @param string $image
1571
 * @param boolean $rev
1572
 */
1573
function tpl_mediaFileDetails($image, $rev) {
1574
    global $conf, $DEL, $lang;
1575
    /** @var Input $INPUT */
1576
    global $INPUT;
1577
1578
    $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes')) && $conf['mediarevisions']);
1579
    if(!$image || (!file_exists(mediaFN($image)) && !$removed) || $DEL) return;
1580
    if($rev && !file_exists(mediaFN($image, $rev))) $rev = false;
0 ignored issues
show
Documentation introduced by
$rev is of type boolean, but the function expects a string|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1581
    $ns = getNS($image);
1582
    $do = $INPUT->str('mediado');
1583
1584
    $opened_tab = $INPUT->str('tab_details');
1585
1586
    $tab_array = array('view');
1587
    list(, $mime) = mimetype($image);
1588
    if($mime == 'image/jpeg') {
1589
        $tab_array[] = 'edit';
1590
    }
1591
    if($conf['mediarevisions']) {
1592
        $tab_array[] = 'history';
1593
    }
1594
1595
    if(!$opened_tab || !in_array($opened_tab, $tab_array)) $opened_tab = 'view';
1596
    if($INPUT->bool('edit')) $opened_tab = 'edit';
1597
    if($do == 'restore') $opened_tab = 'view';
1598
1599
    media_tabs_details($image, $opened_tab);
1600
1601
    echo '<div class="panelHeader"><h3>';
1602
    list($ext) = mimetype($image, false);
1603
    $class    = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
1604
    $class    = 'select mediafile mf_'.$class;
1605
    $tabTitle = '<strong><a href="'.ml($image).'" class="'.$class.'" title="'.$lang['mediaview'].'">'.$image.'</a>'.'</strong>';
1606
    if($opened_tab === 'view' && $rev) {
1607
        printf($lang['media_viewold'], $tabTitle, dformat($rev));
0 ignored issues
show
Documentation introduced by
$rev is of type boolean, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1608
    } else {
1609
        printf($lang['media_'.$opened_tab], $tabTitle);
1610
    }
1611
1612
    echo '</h3></div>'.NL;
1613
1614
    echo '<div class="panelContent">'.NL;
1615
1616
    if($opened_tab == 'view') {
1617
        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 1581 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...
Documentation introduced by
$rev is of type boolean, but the function expects a string|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1618
1619
    } elseif($opened_tab == 'edit' && !$removed) {
1620
        media_tab_edit($image, $ns);
0 ignored issues
show
Security Bug introduced by
It seems like $ns defined by getNS($image) on line 1581 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...
1621
1622
    } elseif($opened_tab == 'history' && $conf['mediarevisions']) {
1623
        media_tab_history($image, $ns);
0 ignored issues
show
Security Bug introduced by
It seems like $ns defined by getNS($image) on line 1581 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...
1624
    }
1625
1626
    echo '</div>'.NL;
1627
}
1628
1629
/**
1630
 * prints the namespace tree in the mediamanager popup
1631
 *
1632
 * Only allowed in mediamanager.php
1633
 *
1634
 * @author Andreas Gohr <[email protected]>
1635
 */
1636
function tpl_mediaTree() {
1637
    global $NS;
1638
    ptln('<div id="media__tree">');
1639
    media_nstree($NS);
1640
    ptln('</div>');
1641
}
1642
1643
/**
1644
 * Print a dropdown menu with all DokuWiki actions
1645
 *
1646
 * Note: this will not use any pretty URLs
1647
 *
1648
 * @author Andreas Gohr <[email protected]>
1649
 *
1650
 * @param string $empty empty option label
1651
 * @param string $button submit button label
1652
 */
1653
function tpl_actiondropdown($empty = '', $button = '&gt;') {
1654
    global $ID;
1655
    global $REV;
1656
    global $lang;
1657
    /** @var Input $INPUT */
1658
    global $INPUT;
1659
1660
    $action_structure = array(
1661
        'page_tools' => array('edit', 'revert', 'revisions', 'backlink', 'subscribe'),
1662
        'site_tools' => array('recent', 'media', 'index'),
1663
        'user_tools' => array('login', 'register', 'profile', 'admin'),
1664
    );
1665
1666
    echo '<form action="'.script().'" method="get" accept-charset="utf-8">';
1667
    echo '<div class="no">';
1668
    echo '<input type="hidden" name="id" value="'.$ID.'" />';
1669
    if($REV) echo '<input type="hidden" name="rev" value="'.$REV.'" />';
1670
    if ($INPUT->server->str('REMOTE_USER')) {
1671
        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />';
1672
    }
1673
1674
    echo '<select name="do" class="edit quickselect" title="'.$lang['tools'].'">';
1675
    echo '<option value="">'.$empty.'</option>';
1676
1677
    foreach($action_structure as $tools => $actions) {
1678
        echo '<optgroup label="'.$lang[$tools].'">';
1679
        foreach($actions as $action) {
1680
            $act = tpl_get_action($action);
1681
            if($act) echo '<option value="'.$act['params']['do'].'">'.$lang['btn_'.$act['type']].'</option>';
1682
        }
1683
        echo '</optgroup>';
1684
    }
1685
1686
    echo '</select>';
1687
    echo '<button type="submit">'.$button.'</button>';
1688
    echo '</div>';
1689
    echo '</form>';
1690
}
1691
1692
/**
1693
 * Print a informational line about the used license
1694
 *
1695
 * @author Andreas Gohr <[email protected]>
1696
 * @param  string $img     print image? (|button|badge)
1697
 * @param  bool   $imgonly skip the textual description?
1698
 * @param  bool   $return  when true don't print, but return HTML
1699
 * @param  bool   $wrap    wrap in div with class="license"?
1700
 * @return string
1701
 */
1702
function tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap = true) {
1703
    global $license;
1704
    global $conf;
1705
    global $lang;
1706
    if(!$conf['license']) return '';
1707
    if(!is_array($license[$conf['license']])) return '';
1708
    $lic    = $license[$conf['license']];
1709
    $target = ($conf['target']['extern']) ? ' target="'.$conf['target']['extern'].'"' : '';
1710
1711
    $out = '';
1712
    if($wrap) $out .= '<div class="license">';
1713
    if($img) {
1714
        $src = license_img($img);
1715
        if($src) {
1716
            $out .= '<a href="'.$lic['url'].'" rel="license"'.$target;
1717
            $out .= '><img src="'.DOKU_BASE.$src.'" alt="'.$lic['name'].'" /></a>';
1718
            if(!$imgonly) $out .= ' ';
1719
        }
1720
    }
1721
    if(!$imgonly) {
1722
        $out .= $lang['license'].' ';
1723
        $out .= '<bdi><a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
1724
        $out .= '>'.$lic['name'].'</a></bdi>';
1725
    }
1726
    if($wrap) $out .= '</div>';
1727
1728
    if($return) return $out;
1729
    echo $out;
1730
    return '';
1731
}
1732
1733
/**
1734
 * Includes the rendered HTML of a given page
1735
 *
1736
 * This function is useful to populate sidebars or similar features in a
1737
 * template
1738
 *
1739
 * @param string $pageid The page name you want to include
1740
 * @param bool $print Should the content be printed or returned only
1741
 * @param bool $propagate Search higher namespaces, too?
1742
 * @param bool $useacl Include the page only if the ACLs check out?
1743
 * @return bool|null|string
1744
 */
1745
function tpl_include_page($pageid, $print = true, $propagate = false, $useacl = true) {
1746
    if($propagate) {
1747
        $pageid = page_findnearest($pageid, $useacl);
1748
    } elseif($useacl && auth_quickaclcheck($pageid) == AUTH_NONE) {
1749
        return false;
1750
    }
1751
    if(!$pageid) return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression $pageid 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...
1752
1753
    global $TOC;
1754
    $oldtoc = $TOC;
1755
    $html   = p_wiki_xhtml($pageid, '', false);
1756
    $TOC    = $oldtoc;
1757
1758
    if($print) echo $html;
1759
    return $html;
1760
}
1761
1762
/**
1763
 * Display the subscribe form
1764
 *
1765
 * @author Adrian Lang <[email protected]>
1766
 */
1767
function tpl_subscribe() {
1768
    global $INFO;
1769
    global $ID;
1770
    global $lang;
1771
    global $conf;
1772
    $stime_days = $conf['subscribe_time'] / 60 / 60 / 24;
1773
1774
    echo p_locale_xhtml('subscr_form');
1775
    echo '<h2>'.$lang['subscr_m_current_header'].'</h2>';
1776
    echo '<div class="level2">';
1777
    if($INFO['subscribed'] === false) {
1778
        echo '<p>'.$lang['subscr_m_not_subscribed'].'</p>';
1779
    } else {
1780
        echo '<ul>';
1781
        foreach($INFO['subscribed'] as $sub) {
1782
            echo '<li><div class="li">';
1783
            if($sub['target'] !== $ID) {
1784
                echo '<code class="ns">'.hsc(prettyprint_id($sub['target'])).'</code>';
1785
            } else {
1786
                echo '<code class="page">'.hsc(prettyprint_id($sub['target'])).'</code>';
1787
            }
1788
            $sstl = sprintf($lang['subscr_style_'.$sub['style']], $stime_days);
1789
            if(!$sstl) $sstl = hsc($sub['style']);
1790
            echo ' ('.$sstl.') ';
1791
1792
            echo '<a href="'.wl(
1793
                $ID,
1794
                array(
1795
                     'do'        => 'subscribe',
1796
                     'sub_target'=> $sub['target'],
1797
                     'sub_style' => $sub['style'],
1798
                     'sub_action'=> 'unsubscribe',
1799
                     'sectok'    => getSecurityToken()
1800
                )
1801
            ).
1802
                '" class="unsubscribe">'.$lang['subscr_m_unsubscribe'].
1803
                '</a></div></li>';
1804
        }
1805
        echo '</ul>';
1806
    }
1807
    echo '</div>';
1808
1809
    // Add new subscription form
1810
    echo '<h2>'.$lang['subscr_m_new_header'].'</h2>';
1811
    echo '<div class="level2">';
1812
    $ns      = getNS($ID).':';
1813
    $targets = array(
1814
        $ID => '<code class="page">'.prettyprint_id($ID).'</code>',
1815
        $ns => '<code class="ns">'.prettyprint_id($ns).'</code>',
1816
    );
1817
    $styles  = array(
1818
        'every'  => $lang['subscr_style_every'],
1819
        'digest' => sprintf($lang['subscr_style_digest'], $stime_days),
1820
        'list'   => sprintf($lang['subscr_style_list'], $stime_days),
1821
    );
1822
1823
    $form = new Doku_Form(array('id' => 'subscribe__form'));
1824
    $form->startFieldset($lang['subscr_m_subscribe']);
1825
    $form->addRadioSet('sub_target', $targets);
1826
    $form->startFieldset($lang['subscr_m_receive']);
1827
    $form->addRadioSet('sub_style', $styles);
1828
    $form->addHidden('sub_action', 'subscribe');
1829
    $form->addHidden('do', 'subscribe');
1830
    $form->addHidden('id', $ID);
1831
    $form->endFieldset();
1832
    $form->addElement(form_makeButton('submit', 'subscribe', $lang['subscr_m_subscribe']));
1833
    html_form('SUBSCRIBE', $form);
1834
    echo '</div>';
1835
}
1836
1837
/**
1838
 * Tries to send already created content right to the browser
1839
 *
1840
 * Wraps around ob_flush() and flush()
1841
 *
1842
 * @author Andreas Gohr <[email protected]>
1843
 */
1844
function tpl_flush() {
1845
    ob_flush();
1846
    flush();
1847
}
1848
1849
/**
1850
 * Tries to find a ressource file in the given locations.
1851
 *
1852
 * If a given location starts with a colon it is assumed to be a media
1853
 * file, otherwise it is assumed to be relative to the current template
1854
 *
1855
 * @param  string[] $search       locations to look at
1856
 * @param  bool     $abs           if to use absolute URL
1857
 * @param  array   &$imginfo   filled with getimagesize()
1858
 * @return string
1859
 *
1860
 * @author Andreas  Gohr <[email protected]>
1861
 */
1862
function tpl_getMediaFile($search, $abs = false, &$imginfo = null) {
1863
    $img     = '';
1864
    $file    = '';
1865
    $ismedia = false;
1866
    // loop through candidates until a match was found:
1867
    foreach($search as $img) {
1868
        if(substr($img, 0, 1) == ':') {
1869
            $file    = mediaFN($img);
1870
            $ismedia = true;
1871
        } else {
1872
            $file    = tpl_incdir().$img;
1873
            $ismedia = false;
1874
        }
1875
1876
        if(file_exists($file)) break;
1877
    }
1878
1879
    // fetch image data if requested
1880
    if(!is_null($imginfo)) {
1881
        $imginfo = getimagesize($file);
1882
    }
1883
1884
    // build URL
1885
    if($ismedia) {
1886
        $url = ml($img, '', true, '', $abs);
1887
    } else {
1888
        $url = tpl_basedir().$img;
1889
        if($abs) $url = DOKU_URL.substr($url, strlen(DOKU_REL));
1890
    }
1891
1892
    return $url;
1893
}
1894
1895
/**
1896
 * PHP include a file
1897
 *
1898
 * either from the conf directory if it exists, otherwise use
1899
 * file in the template's root directory.
1900
 *
1901
 * The function honours config cascade settings and looks for the given
1902
 * file next to the ´main´ config files, in the order protected, local,
1903
 * default.
1904
 *
1905
 * Note: no escaping or sanity checking is done here. Never pass user input
1906
 * to this function!
1907
 *
1908
 * @author Anika Henke <[email protected]>
1909
 * @author Andreas Gohr <[email protected]>
1910
 *
1911
 * @param string $file
1912
 */
1913
function tpl_includeFile($file) {
1914
    global $config_cascade;
1915
    foreach(array('protected', 'local', 'default') as $config_group) {
1916
        if(empty($config_cascade['main'][$config_group])) continue;
1917
        foreach($config_cascade['main'][$config_group] as $conf_file) {
1918
            $dir = dirname($conf_file);
1919
            if(file_exists("$dir/$file")) {
1920
                include("$dir/$file");
1921
                return;
1922
            }
1923
        }
1924
    }
1925
1926
    // still here? try the template dir
1927
    $file = tpl_incdir().$file;
1928
    if(file_exists($file)) {
1929
        include($file);
1930
    }
1931
}
1932
1933
/**
1934
 * Returns <link> tag for various icon types (favicon|mobile|generic)
1935
 *
1936
 * @author Anika Henke <[email protected]>
1937
 *
1938
 * @param  array $types - list of icon types to display (favicon|mobile|generic)
1939
 * @return string
1940
 */
1941
function tpl_favicon($types = array('favicon')) {
1942
1943
    $return = '';
1944
1945
    foreach($types as $type) {
1946
        switch($type) {
1947
            case 'favicon':
1948
                $look = array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico');
1949
                $return .= '<link rel="shortcut icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1950
                break;
1951
            case 'mobile':
1952
                $look = array(':wiki:apple-touch-icon.png', ':apple-touch-icon.png', 'images/apple-touch-icon.png');
1953
                $return .= '<link rel="apple-touch-icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1954
                break;
1955
            case 'generic':
1956
                // ideal world solution, which doesn't work in any browser yet
1957
                $look = array(':wiki:favicon.svg', ':favicon.svg', 'images/favicon.svg');
1958
                $return .= '<link rel="icon" href="'.tpl_getMediaFile($look).'" type="image/svg+xml" />'.NL;
1959
                break;
1960
        }
1961
    }
1962
1963
    return $return;
1964
}
1965
1966
/**
1967
 * Prints full-screen media manager
1968
 *
1969
 * @author Kate Arzamastseva <[email protected]>
1970
 */
1971
function tpl_media() {
1972
    global $NS, $IMG, $JUMPTO, $REV, $lang, $fullscreen, $INPUT;
1973
    $fullscreen = true;
1974
    require_once DOKU_INC.'lib/exe/mediamanager.php';
1975
1976
    $rev   = '';
1977
    $image = cleanID($INPUT->str('image'));
1978
    if(isset($IMG)) $image = $IMG;
1979
    if(isset($JUMPTO)) $image = $JUMPTO;
1980
    if(isset($REV) && !$JUMPTO) $rev = $REV;
1981
1982
    echo '<div id="mediamanager__page">'.NL;
1983
    echo '<h1>'.$lang['btn_media'].'</h1>'.NL;
1984
    html_msgarea();
1985
1986
    echo '<div class="panel namespaces">'.NL;
1987
    echo '<h2>'.$lang['namespaces'].'</h2>'.NL;
1988
    echo '<div class="panelHeader">';
1989
    echo $lang['media_namespaces'];
1990
    echo '</div>'.NL;
1991
1992
    echo '<div class="panelContent" id="media__tree">'.NL;
1993
    media_nstree($NS);
1994
    echo '</div>'.NL;
1995
    echo '</div>'.NL;
1996
1997
    echo '<div class="panel filelist">'.NL;
1998
    tpl_mediaFileList();
1999
    echo '</div>'.NL;
2000
2001
    echo '<div class="panel file">'.NL;
2002
    echo '<h2 class="a11y">'.$lang['media_file'].'</h2>'.NL;
2003
    tpl_mediaFileDetails($image, $rev);
2004
    echo '</div>'.NL;
2005
2006
    echo '</div>'.NL;
2007
}
2008
2009
/**
2010
 * Return useful layout classes
2011
 *
2012
 * @author Anika Henke <[email protected]>
2013
 *
2014
 * @return string
2015
 */
2016
function tpl_classes() {
2017
    global $ACT, $conf, $ID, $INFO;
2018
    /** @var Input $INPUT */
2019
    global $INPUT;
2020
2021
    $classes = array(
2022
        'dokuwiki',
2023
        'mode_'.$ACT,
2024
        'tpl_'.$conf['template'],
2025
        $INPUT->server->bool('REMOTE_USER') ? 'loggedIn' : '',
2026
        $INFO['exists'] ? '' : 'notFound',
2027
        ($ID == $conf['start']) ? 'home' : '',
2028
    );
2029
    return join(' ', $classes);
2030
}
2031
2032
/**
2033
 * Create event for tools menues
2034
 *
2035
 * @author Anika Henke <[email protected]>
2036
 * @param string $toolsname name of menu
2037
 * @param array $items
2038
 * @param string $view e.g. 'main', 'detail', ...
2039
 */
2040
function tpl_toolsevent($toolsname, $items, $view = 'main') {
2041
    $data = array(
2042
        'view' => $view,
2043
        'items' => $items
2044
    );
2045
2046
    $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY';
2047
    $evt = new Doku_Event($hook, $data);
2048
    if($evt->advise_before()) {
2049
        foreach($evt->data['items'] as $k => $html) echo $html;
2050
    }
2051
    $evt->advise_after();
2052
}
2053
2054
//Setup VIM: ex: et ts=4 :
2055
2056