xref: /dokuwiki/inc/template.php (revision 24870174d2ee45460ba6bcfe5f5a0ae94715efd7)
16b13307fSandi<?php
26b13307fSandi/**
36b13307fSandi * DokuWiki template functions
46b13307fSandi *
56b13307fSandi * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
66b13307fSandi * @author     Andreas Gohr <andi@splitbrain.org>
76b13307fSandi */
8*24870174SAndreas Gohruse dokuwiki\ActionRouter;
9*24870174SAndreas Gohruse dokuwiki\Action\Exception\FatalException;
10*24870174SAndreas Gohruse dokuwiki\Extension\PluginInterface;
11*24870174SAndreas Gohruse dokuwiki\Ui\Admin;
12*24870174SAndreas Gohruse dokuwiki\StyleUtils;
13*24870174SAndreas Gohruse dokuwiki\Menu\Item\AbstractItem;
14*24870174SAndreas Gohruse dokuwiki\Form\Form;
15*24870174SAndreas Gohruse dokuwiki\Menu\MobileMenu;
16*24870174SAndreas Gohruse dokuwiki\Ui\Subscribe;
17e1d9dcc8SAndreas Gohruse dokuwiki\Extension\AdminPlugin;
18e1d9dcc8SAndreas Gohruse dokuwiki\Extension\Event;
192cd6cc0aSAndreas Gohruse dokuwiki\File\PageResolver;
20e1d9dcc8SAndreas Gohr
216b13307fSandi/**
22ac7a515fSAndreas Gohr * Access a template file
23ac7a515fSAndreas Gohr *
24ac7a515fSAndreas Gohr * Returns the path to the given file inside the current template, uses
25ac7a515fSAndreas Gohr * default template if the custom version doesn't exist.
265a892029SAndreas Gohr *
275a892029SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
28ac7a515fSAndreas Gohr * @param string $file
29ac7a515fSAndreas Gohr * @return string
305a892029SAndreas Gohr */
31ac7a515fSAndreas Gohrfunction template($file) {
325a892029SAndreas Gohr    global $conf;
335a892029SAndreas Gohr
34ac7a515fSAndreas Gohr    if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$file))
35ac7a515fSAndreas Gohr        return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$file;
365a892029SAndreas Gohr
37ac7a515fSAndreas Gohr    return DOKU_INC.'lib/tpl/dokuwiki/'.$file;
385a892029SAndreas Gohr}
395a892029SAndreas Gohr
40c4766956SAndreas Gohr/**
41c4766956SAndreas Gohr * Convenience function to access template dir from local FS
42c4766956SAndreas Gohr *
43c4766956SAndreas Gohr * This replaces the deprecated DOKU_TPLINC constant
44c4766956SAndreas Gohr *
45c4766956SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
46afb2c082SAndreas Gohr * @param string $tpl The template to use, default to current one
47ac7a515fSAndreas Gohr * @return string
48c4766956SAndreas Gohr */
49afb2c082SAndreas Gohrfunction tpl_incdir($tpl='') {
5075b14482SAndreas Gohr    global $conf;
51afb2c082SAndreas Gohr    if(!$tpl) $tpl = $conf['template'];
52afb2c082SAndreas Gohr    return DOKU_INC.'lib/tpl/'.$tpl.'/';
53c4766956SAndreas Gohr}
54c4766956SAndreas Gohr
55c4766956SAndreas Gohr/**
56c4766956SAndreas Gohr * Convenience function to access template dir from web
57c4766956SAndreas Gohr *
58c4766956SAndreas Gohr * This replaces the deprecated DOKU_TPL constant
59c4766956SAndreas Gohr *
60c4766956SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
61afb2c082SAndreas Gohr * @param string $tpl The template to use, default to current one
62ac7a515fSAndreas Gohr * @return string
63c4766956SAndreas Gohr */
6499dca513SAndreas Gohrfunction tpl_basedir($tpl='') {
6575b14482SAndreas Gohr    global $conf;
66afb2c082SAndreas Gohr    if(!$tpl) $tpl = $conf['template'];
67dcd4911eSMichael Hamann    return DOKU_BASE.'lib/tpl/'.$tpl.'/';
68c4766956SAndreas Gohr}
69c4766956SAndreas Gohr
705a892029SAndreas Gohr/**
716b13307fSandi * Print the content
726b13307fSandi *
736b13307fSandi * This function is used for printing all the usual content
746b13307fSandi * (defined by the global $ACT var) by calling the appropriate
756b13307fSandi * outputfunction(s) from html.php
766b13307fSandi *
77ee4c4a1bSAndreas Gohr * Everything that doesn't use the main template file isn't
78ee4c4a1bSAndreas Gohr * handled by this function. ACL stuff is not done here either.
796b13307fSandi *
806b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
8142ea7f44SGerrit Uitslag *
82ac7a515fSAndreas Gohr * @triggers TPL_ACT_RENDER
83ac7a515fSAndreas Gohr * @triggers TPL_CONTENT_DISPLAY
84ac7a515fSAndreas Gohr * @param bool $prependTOC should the TOC be displayed here?
85ac7a515fSAndreas Gohr * @return bool true if any output
866b13307fSandi */
87b8595a66SAndreas Gohrfunction tpl_content($prependTOC = true) {
887ea0913cSchris    global $ACT;
89b8595a66SAndreas Gohr    global $INFO;
90b8595a66SAndreas Gohr    $INFO['prependTOC'] = $prependTOC;
917ea0913cSchris
927ea0913cSchris    ob_start();
93cbb44eabSAndreas Gohr    Event::createAndTrigger('TPL_ACT_RENDER', $ACT, 'tpl_content_core');
947ea0913cSchris    $html_output = ob_get_clean();
95cbb44eabSAndreas Gohr    Event::createAndTrigger('TPL_CONTENT_DISPLAY', $html_output, 'ptln');
9654e95700STom N Harris
9754e95700STom N Harris    return !empty($html_output);
987ea0913cSchris}
997ea0913cSchris
100ac7a515fSAndreas Gohr/**
101ac7a515fSAndreas Gohr * Default Action of TPL_ACT_RENDER
102ac7a515fSAndreas Gohr *
103ac7a515fSAndreas Gohr * @return bool
104ac7a515fSAndreas Gohr */
1057ea0913cSchrisfunction tpl_content_core() {
106*24870174SAndreas Gohr    $router = ActionRouter::getInstance();
107952acff9SAndreas Gohr    try {
108952acff9SAndreas Gohr        $router->getAction()->tplContent();
109*24870174SAndreas Gohr    } catch(FatalException $e) {
110952acff9SAndreas Gohr        // there was no content for the action
111952acff9SAndreas Gohr        msg(hsc($e->getMessage()), -1);
11254e95700STom N Harris        return false;
1136b13307fSandi    }
11454e95700STom N Harris    return true;
1156b13307fSandi}
1166b13307fSandi
117c19fe9c0Sandi/**
118b8595a66SAndreas Gohr * Places the TOC where the function is called
119b8595a66SAndreas Gohr *
120b8595a66SAndreas Gohr * If you use this you most probably want to call tpl_content with
121b8595a66SAndreas Gohr * a false argument
122b8595a66SAndreas Gohr *
123b8595a66SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
12442ea7f44SGerrit Uitslag *
125ac7a515fSAndreas Gohr * @param bool $return Should the TOC be returned instead to be printed?
126ac7a515fSAndreas Gohr * @return string
127b8595a66SAndreas Gohr */
128b8595a66SAndreas Gohrfunction tpl_toc($return = false) {
129b8595a66SAndreas Gohr    global $TOC;
130b8595a66SAndreas Gohr    global $ACT;
131b8595a66SAndreas Gohr    global $ID;
132b8595a66SAndreas Gohr    global $REV;
133b8595a66SAndreas Gohr    global $INFO;
134851f2e89SAnika Henke    global $conf;
135ac7a515fSAndreas Gohr    global $INPUT;
136*24870174SAndreas Gohr    $toc = [];
137b8595a66SAndreas Gohr
138b8595a66SAndreas Gohr    if(is_array($TOC)) {
139b8595a66SAndreas Gohr        // if a TOC was prepared in global scope, always use it
140b8595a66SAndreas Gohr        $toc = $TOC;
1413c86d7c9SAndreas Gohr    } elseif(($ACT == 'show' || substr($ACT, 0, 6) == 'export') && !$REV && $INFO['exists']) {
142b8595a66SAndreas Gohr        // get TOC from metadata, render if neccessary
143e0c26282SGerrit Uitslag        $meta = p_get_metadata($ID, '', METADATA_RENDER_USING_CACHE);
144b8595a66SAndreas Gohr        if(isset($meta['internal']['toc'])) {
145b8595a66SAndreas Gohr            $tocok = $meta['internal']['toc'];
146b8595a66SAndreas Gohr        } else {
1472bb0d541Schris            $tocok = true;
148b8595a66SAndreas Gohr        }
149*24870174SAndreas Gohr        $toc = $meta['description']['tableofcontents'] ?? null;
150851f2e89SAnika Henke        if(!$tocok || !is_array($toc) || !$conf['tocminheads'] || count($toc) < $conf['tocminheads']) {
151*24870174SAndreas Gohr            $toc = [];
152b8595a66SAndreas Gohr        }
153b8595a66SAndreas Gohr    } elseif($ACT == 'admin') {
154a61966c5SChristopher Smith        // try to load admin plugin TOC
155e1d9dcc8SAndreas Gohr        /** @var $plugin AdminPlugin */
156a61966c5SChristopher Smith        if ($plugin = plugin_getRequestAdminPlugin()) {
157b8595a66SAndreas Gohr            $toc = $plugin->getTOC();
158b8595a66SAndreas Gohr            $TOC = $toc; // avoid later rebuild
159b8595a66SAndreas Gohr        }
160b8595a66SAndreas Gohr    }
161b8595a66SAndreas Gohr
162cbb44eabSAndreas Gohr    Event::createAndTrigger('TPL_TOC_RENDER', $toc, null, false);
163b8595a66SAndreas Gohr    $html = html_TOC($toc);
164b8595a66SAndreas Gohr    if($return) return $html;
165b8595a66SAndreas Gohr    echo $html;
166ac7a515fSAndreas Gohr    return '';
167b8595a66SAndreas Gohr}
168b8595a66SAndreas Gohr
169b8595a66SAndreas Gohr/**
170c19fe9c0Sandi * Handle the admin page contents
171c19fe9c0Sandi *
172c19fe9c0Sandi * @author Andreas Gohr <andi@splitbrain.org>
17342ea7f44SGerrit Uitslag *
17442ea7f44SGerrit Uitslag * @return bool
175c19fe9c0Sandi */
176c19fe9c0Sandifunction tpl_admin() {
177f8cc712eSAndreas Gohr    global $INFO;
178b8595a66SAndreas Gohr    global $TOC;
179ac7a515fSAndreas Gohr    global $INPUT;
18011e2ce22Schris
181b8595a66SAndreas Gohr    $plugin = null;
182ac7a515fSAndreas Gohr    $class  = $INPUT->str('page');
183ac7a515fSAndreas Gohr    if(!empty($class)) {
18411e2ce22Schris        $pluginlist = plugin_list('admin');
18511e2ce22Schris
186ac7a515fSAndreas Gohr        if(in_array($class, $pluginlist)) {
18711e2ce22Schris            // attempt to load the plugin
188e1d9dcc8SAndreas Gohr            /** @var $plugin AdminPlugin */
189a04f2bd5SGerrit Uitslag            $plugin = plugin_load('admin', $class);
19011e2ce22Schris        }
19111e2ce22Schris    }
19211e2ce22Schris
193*24870174SAndreas Gohr    if($plugin instanceof PluginInterface) {
194b8595a66SAndreas Gohr        if(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet
195b8595a66SAndreas Gohr        if($INFO['prependTOC']) tpl_toc();
196f8cc712eSAndreas Gohr        $plugin->html();
197f8cc712eSAndreas Gohr    } else {
198*24870174SAndreas Gohr        $admin = new Admin();
1990470c28fSAndreas Gohr        $admin->show();
200f8cc712eSAndreas Gohr    }
20154e95700STom N Harris    return true;
202c19fe9c0Sandi}
2036b13307fSandi
2046b13307fSandi/**
2056b13307fSandi * Print the correct HTML meta headers
2066b13307fSandi *
2076b13307fSandi * This has to go into the head section of your template.
2086b13307fSandi *
2096b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
21042ea7f44SGerrit Uitslag *
211ac7a515fSAndreas Gohr * @triggers TPL_METAHEADER_OUTPUT
212ac7a515fSAndreas Gohr * @param  bool $alt Should feeds and alternative format links be added?
213ac7a515fSAndreas Gohr * @return bool
2146b13307fSandi */
215f96fa415SAndreas Gohrfunction tpl_metaheaders($alt = true) {
2166b13307fSandi    global $ID;
217d98d4540SBen Coburn    global $REV;
2186b13307fSandi    global $INFO;
21972e0dc37SAndreas Gohr    global $JSINFO;
2206b13307fSandi    global $ACT;
2214bb1b5aeSAndreas Gohr    global $QUERY;
2226b13307fSandi    global $lang;
223dc57ef04Sandi    global $conf;
2249c438d6cSMichael Hamann    global $updateVersion;
225585bf44eSChristopher Smith    /** @var Input $INPUT */
226585bf44eSChristopher Smith    global $INPUT;
2276b13307fSandi
2287bff22c0SAndreas Gohr    // prepare the head array
229*24870174SAndreas Gohr    $head = [];
2307bff22c0SAndreas Gohr
231202ac28bSMichael Klier    // prepare seed for js and css
232cd997f93SAndreas Gohr    $tseed   = $updateVersion;
233202ac28bSMichael Klier    $depends = getConfigFiles('main');
23484e76a7eSAndreas Gohr    $depends[] = DOKU_CONF."tpl/".$conf['template']."/style.ini";
235cd997f93SAndreas Gohr    foreach($depends as $f) $tseed .= @filemtime($f);
236cd997f93SAndreas Gohr    $tseed   = md5($tseed);
2377bff22c0SAndreas Gohr
2386b13307fSandi    // the usual stuff
239*24870174SAndreas Gohr    $head['meta'][] = ['name'=> 'generator', 'content'=> 'DokuWiki'];
24063cf4192Ssarehag    if(actionOK('search')) {
241*24870174SAndreas Gohr        $head['link'][] = [
242*24870174SAndreas Gohr            'rel' => 'search',
243*24870174SAndreas Gohr            'type'=> 'application/opensearchdescription+xml',
244*24870174SAndreas Gohr            'href'=> DOKU_BASE.'lib/exe/opensearch.php',
245*24870174SAndreas Gohr            'title'=> $conf['title']
246*24870174SAndreas Gohr        ];
24763cf4192Ssarehag    }
24863cf4192Ssarehag
249*24870174SAndreas Gohr    $head['link'][] = ['rel'=> 'start', 'href'=> DOKU_BASE];
2507aedde2eSGina Haeussge    if(actionOK('index')) {
251*24870174SAndreas Gohr        $head['link'][] = [
252*24870174SAndreas Gohr            'rel'  => 'contents',
253*24870174SAndreas Gohr            'href'=> wl($ID, 'do=index', false, '&'),
254ac7a515fSAndreas Gohr            'title'=> $lang['btn_index']
255*24870174SAndreas Gohr        ];
2567aedde2eSGina Haeussge    }
257f96fa415SAndreas Gohr
2585e0255e3SMichael Große    if (actionOK('manifest')) {
259*24870174SAndreas Gohr        $head['link'][] = [
260*24870174SAndreas Gohr            'rel'=> 'manifest',
261*24870174SAndreas Gohr            'href'=> DOKU_BASE.'lib/exe/manifest.php'
262*24870174SAndreas Gohr        ];
2635e0255e3SMichael Große    }
2645e0255e3SMichael Große
265*24870174SAndreas Gohr    $styleUtil = new StyleUtils();
2664593dbd2SAnna Dabrowska    $styleIni = $styleUtil->cssStyleini();
26740ca8540SMichael Große    $replacements = $styleIni['replacements'];
26840ca8540SMichael Große    if (!empty($replacements['__theme_color__'])) {
269*24870174SAndreas Gohr        $head['meta'][] = [
270*24870174SAndreas Gohr            'name' => 'theme-color',
271*24870174SAndreas Gohr            'content' => $replacements['__theme_color__']
272*24870174SAndreas Gohr        ];
27340ca8540SMichael Große    }
27440ca8540SMichael Große
275f96fa415SAndreas Gohr    if($alt) {
27654be1338SGerrit Uitslag        if(actionOK('rss')) {
277*24870174SAndreas Gohr            $head['link'][] = [
278*24870174SAndreas Gohr                'rel'  => 'alternate',
279*24870174SAndreas Gohr                'type'=> 'application/rss+xml',
280*24870174SAndreas Gohr                'title'=> $lang['btn_recent'],
281*24870174SAndreas Gohr                'href'=> DOKU_BASE.'feed.php'
282*24870174SAndreas Gohr            ];
283*24870174SAndreas Gohr            $head['link'][] = [
284*24870174SAndreas Gohr                'rel'  => 'alternate',
285*24870174SAndreas Gohr                'type'=> 'application/rss+xml',
286a1288caeSGerrit Uitslag                'title'=> $lang['currentns'],
287aac83cd4SPhy                'href' => DOKU_BASE.'feed.php?mode=list&ns='.(isset($INFO) ? $INFO['namespace'] : '')
288*24870174SAndreas Gohr            ];
28954be1338SGerrit Uitslag        }
290c35f3875SAndreas Gohr        if(($ACT == 'show' || $ACT == 'search') && $INFO['writable']) {
291*24870174SAndreas Gohr            $head['link'][] = [
292ac7a515fSAndreas Gohr                'rel'  => 'edit',
293715bdf1fSAndreas Gohr                'title'=> $lang['btn_edit'],
294ac7a515fSAndreas Gohr                'href' => wl($ID, 'do=edit', false, '&')
295*24870174SAndreas Gohr            ];
296c35f3875SAndreas Gohr        }
297c35f3875SAndreas Gohr
29854be1338SGerrit Uitslag        if(actionOK('rss') && $ACT == 'search') {
299*24870174SAndreas Gohr            $head['link'][] = [
300*24870174SAndreas Gohr                'rel'  => 'alternate',
301*24870174SAndreas Gohr                'type'=> 'application/rss+xml',
302a1288caeSGerrit Uitslag                'title'=> $lang['searchresult'],
303ac7a515fSAndreas Gohr                'href' => DOKU_BASE.'feed.php?mode=search&q='.$QUERY
304*24870174SAndreas Gohr            ];
3054bb1b5aeSAndreas Gohr        }
306bae36d94SAndreas Gohr
307bae36d94SAndreas Gohr        if(actionOK('export_xhtml')) {
308*24870174SAndreas Gohr            $head['link'][] = [
309*24870174SAndreas Gohr                'rel' => 'alternate',
310*24870174SAndreas Gohr                'type'=> 'text/html',
311*24870174SAndreas Gohr                'title'=> $lang['plainhtml'],
312ac7a515fSAndreas Gohr                'href'=> exportlink($ID, 'xhtml', '', false, '&')
313*24870174SAndreas Gohr            ];
314bae36d94SAndreas Gohr        }
315bae36d94SAndreas Gohr
316bae36d94SAndreas Gohr        if(actionOK('export_raw')) {
317*24870174SAndreas Gohr            $head['link'][] = [
318*24870174SAndreas Gohr                'rel' => 'alternate',
319*24870174SAndreas Gohr                'type'=> 'text/plain',
320*24870174SAndreas Gohr                'title'=> $lang['wikimarkup'],
321ac7a515fSAndreas Gohr                'href'=> exportlink($ID, 'raw', '', false, '&')
322*24870174SAndreas Gohr            ];
323f96fa415SAndreas Gohr        }
324bae36d94SAndreas Gohr    }
3256b13307fSandi
32663f13cadSDamien Regad    // setup robot tags appropriate for different modes
3274f2e0004STim Weber    if(($ACT == 'show' || $ACT == 'export_xhtml') && !$REV) {
3286b13307fSandi        if($INFO['exists']) {
3296b13307fSandi            //delay indexing:
330fb9fa88bSAndreas Gohr            if((time() - $INFO['lastmod']) >= $conf['indexdelay'] && !isHiddenPage($ID) ) {
331*24870174SAndreas Gohr                $head['meta'][] = ['name'=> 'robots', 'content'=> 'index,follow'];
3326b13307fSandi            } else {
333*24870174SAndreas Gohr                $head['meta'][] = ['name'=> 'robots', 'content'=> 'noindex,nofollow'];
3346b13307fSandi            }
33501f9be51SAnika Henke            $canonicalUrl = wl($ID, '', true, '&');
33601f9be51SAnika Henke            if ($ID == $conf['start']) {
33701f9be51SAnika Henke                $canonicalUrl = DOKU_URL;
33801f9be51SAnika Henke            }
339*24870174SAndreas Gohr            $head['link'][] = ['rel'=> 'canonical', 'href'=> $canonicalUrl];
3406b13307fSandi        } else {
341*24870174SAndreas Gohr            $head['meta'][] = ['name'=> 'robots', 'content'=> 'noindex,follow'];
3426b13307fSandi        }
3437a24876fSAndreas Gohr    } elseif(defined('DOKU_MEDIADETAIL')) {
344*24870174SAndreas Gohr        $head['meta'][] = ['name'=> 'robots', 'content'=> 'index,follow'];
3456b13307fSandi    } else {
346*24870174SAndreas Gohr        $head['meta'][] = ['name'=> 'robots', 'content'=> 'noindex,nofollow'];
3476b13307fSandi    }
3486b13307fSandi
349831800b8SAndreas Gohr    // set metadata
350831800b8SAndreas Gohr    if($ACT == 'show' || $ACT == 'export_xhtml') {
351831800b8SAndreas Gohr        // keywords (explicit or implicit)
352bb4866bdSchris        if(!empty($INFO['meta']['subject'])) {
353*24870174SAndreas Gohr            $head['meta'][] = ['name'=> 'keywords', 'content'=> implode(',', $INFO['meta']['subject'])];
354831800b8SAndreas Gohr        } else {
355*24870174SAndreas Gohr            $head['meta'][] = ['name'=> 'keywords', 'content'=> str_replace(':', ',', $ID)];
356831800b8SAndreas Gohr        }
357831800b8SAndreas Gohr    }
358831800b8SAndreas Gohr
35978a6aeb1SAndreas Gohr    // load stylesheets
360*24870174SAndreas Gohr    $head['link'][] = [
36159305168SPhy        'rel' => 'stylesheet',
362e283bd6cSAnika Henke        'href'=> DOKU_BASE.'lib/exe/css.php?t='.rawurlencode($conf['template']).'&tseed='.$tseed
363*24870174SAndreas Gohr    ];
364bad31ae9SAndreas Gohr
365aac83cd4SPhy    $script = "var NS='".(isset($INFO)?$INFO['namespace']:'')."';";
366585bf44eSChristopher Smith    if($conf['useacl'] && $INPUT->server->str('REMOTE_USER')) {
36798169a0fSAndreas Gohr        $script .= "var SIG=".toolbar_signature().";";
368c591aabeSAndreas Gohr    }
3690c39d46cSMichael Große    jsinfo();
370*24870174SAndreas Gohr    $script .= 'var JSINFO = ' . json_encode($JSINFO, JSON_THROW_ON_ERROR).';';
371*24870174SAndreas Gohr    $head['script'][] = ['_data'=> $script];
3728bbcb611SAndreas Gohr
37361537d47SAndreas Gohr    // load jquery
374fa078663SAndreas Gohr    $jquery = getCdnUrls();
375fa078663SAndreas Gohr    foreach($jquery as $src) {
376*24870174SAndreas Gohr        $head['script'][] = [
377fc6b11d2SMichael Große                '_data' => '',
378*24870174SAndreas Gohr                'src' => $src
379*24870174SAndreas Gohr            ] + ($conf['defer_js'] ? [ 'defer' => 'defer'] : []);
38061537d47SAndreas Gohr    }
38161537d47SAndreas Gohr
38261537d47SAndreas Gohr    // load our javascript dispatcher
383*24870174SAndreas Gohr    $head['script'][] = [
384de1dc35bSNicolas Friedli            '_data'=> '',
385*24870174SAndreas Gohr            'src' => DOKU_BASE.'lib/exe/js.php'.'?t='.rawurlencode($conf['template']).'&tseed='.$tseed
386*24870174SAndreas Gohr        ] + ($conf['defer_js'] ? [ 'defer' => 'defer'] : []);
3877bff22c0SAndreas Gohr
3887bff22c0SAndreas Gohr    // trigger event here
389cbb44eabSAndreas Gohr    Event::createAndTrigger('TPL_METAHEADER_OUTPUT', $head, '_tpl_metaheaders_action', true);
39054e95700STom N Harris    return true;
3917bff22c0SAndreas Gohr}
3927bff22c0SAndreas Gohr
3937bff22c0SAndreas Gohr/**
3947bff22c0SAndreas Gohr * prints the array build by tpl_metaheaders
3957bff22c0SAndreas Gohr *
3967bff22c0SAndreas Gohr * $data is an array of different header tags. Each tag can have multiple
3977bff22c0SAndreas Gohr * instances. Attributes are given as key value pairs. Values will be HTML
3987bff22c0SAndreas Gohr * encoded automatically so they should be provided as is in the $data array.
3997bff22c0SAndreas Gohr *
40042ea7f44SGerrit Uitslag * For tags having a body attribute specify the body data in the special
4011304d1dbSAndreas Gohr * attribute '_data'. This field will NOT BE ESCAPED automatically.
4027bff22c0SAndreas Gohr *
4037bff22c0SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
40442ea7f44SGerrit Uitslag *
40542ea7f44SGerrit Uitslag * @param array $data
4067bff22c0SAndreas Gohr */
4077bff22c0SAndreas Gohrfunction _tpl_metaheaders_action($data) {
4087bff22c0SAndreas Gohr    foreach($data as $tag => $inst) {
409427bf9a2SAndreas Gohr        if($tag == 'script') {
410427bf9a2SAndreas Gohr            echo "<!--[if gte IE 9]><!-->\n"; // no scripts for old IE
411427bf9a2SAndreas Gohr        }
4127bff22c0SAndreas Gohr        foreach($inst as $attr) {
4139b48e6a1SGerry Weißbach            if ( empty($attr) ) { continue; }
4147bff22c0SAndreas Gohr            echo '<', $tag, ' ', buildAttributes($attr);
41526afa874SMikhail I. Izmestev            if(isset($attr['_data']) || $tag == 'script') {
416740897dcSasivery                if($tag == 'script' && isset($attr['_data']))
41709f791c4SDominik Eckelmann                    $attr['_data'] = "/*<![CDATA[*/".
418e226efe1SAndreas Gohr                        $attr['_data'].
41909f791c4SDominik Eckelmann                        "\n/*!]]>*/";
420e226efe1SAndreas Gohr
421*24870174SAndreas Gohr                echo '>', $attr['_data'] ?? '', '</', $tag, '>';
4227bff22c0SAndreas Gohr            } else {
4237bff22c0SAndreas Gohr                echo '/>';
4247bff22c0SAndreas Gohr            }
4257bff22c0SAndreas Gohr            echo "\n";
4267bff22c0SAndreas Gohr        }
427427bf9a2SAndreas Gohr        if($tag == 'script') {
428427bf9a2SAndreas Gohr            echo "<!--<![endif]-->\n";
429427bf9a2SAndreas Gohr        }
4307bff22c0SAndreas Gohr    }
4316b13307fSandi}
4326b13307fSandi
4336b13307fSandi/**
4346b13307fSandi * Print a link
4356b13307fSandi *
4365e163278SAndreas Gohr * Just builds a link.
4376b13307fSandi *
4386b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
43942ea7f44SGerrit Uitslag *
44042ea7f44SGerrit Uitslag * @param string $url
44142ea7f44SGerrit Uitslag * @param string $name
44242ea7f44SGerrit Uitslag * @param string $more
44321d806cdSGerrit Uitslag * @param bool $return if true return the link html, otherwise print
44421d806cdSGerrit Uitslag * @return bool|string html of the link, or true if printed
4456b13307fSandi */
4461af98a77SAnika Henkefunction tpl_link($url, $name, $more = '', $return = false) {
44701f17825SAnika Henke    $out = '<a href="'.$url.'" ';
4481af98a77SAnika Henke    if($more) $out .= ' '.$more;
4491af98a77SAnika Henke    $out .= ">$name</a>";
4501af98a77SAnika Henke    if($return) return $out;
4511af98a77SAnika Henke    print $out;
45254e95700STom N Harris    return true;
4536b13307fSandi}
4546b13307fSandi
4556b13307fSandi/**
45655efc227SAndreas Gohr * Prints a link to a WikiPage
45755efc227SAndreas Gohr *
45855efc227SAndreas Gohr * Wrapper around html_wikilink
45955efc227SAndreas Gohr *
46055efc227SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
46142ea7f44SGerrit Uitslag *
46242ea7f44SGerrit Uitslag * @param string      $id   page id
46342ea7f44SGerrit Uitslag * @param string|null $name the name of the link
464fb008d31SIain Hallam * @param bool        $return
465fb008d31SIain Hallam * @return true|string
46655efc227SAndreas Gohr */
467c4a386f1SIain Hallamfunction tpl_pagelink($id, $name = null, $return = false) {
468c4a386f1SIain Hallam    $out = '<bdi>'.html_wikilink($id, $name).'</bdi>';
469c4a386f1SIain Hallam    if($return) return $out;
470c4a386f1SIain Hallam    print $out;
47154e95700STom N Harris    return true;
47255efc227SAndreas Gohr}
47355efc227SAndreas Gohr
47455efc227SAndreas Gohr/**
475a3ec5f4aSmatthiasgrimm * get the parent page
476a3ec5f4aSmatthiasgrimm *
477a3ec5f4aSmatthiasgrimm * Tries to find out which page is parent.
478a3ec5f4aSmatthiasgrimm * returns false if none is available
479a3ec5f4aSmatthiasgrimm *
480377f9e97SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
48142ea7f44SGerrit Uitslag *
48242ea7f44SGerrit Uitslag * @param string $id page id
48342ea7f44SGerrit Uitslag * @return false|string
484a3ec5f4aSmatthiasgrimm */
485377f9e97SAndreas Gohrfunction tpl_getparent($id) {
4868c6be208SAndreas Gohr    $resolver = new PageResolver('root');
4878c6be208SAndreas Gohr
488377f9e97SAndreas Gohr    $parent = getNS($id).':';
4898c6be208SAndreas Gohr    $parent = $resolver->resolveId($parent);
490a197105eSmatthiasgrimm    if($parent == $id) {
491a197105eSmatthiasgrimm        $pos    = strrpos(getNS($id), ':');
492a197105eSmatthiasgrimm        $parent = substr($parent, 0, $pos).':';
4938c6be208SAndreas Gohr        $parent = $resolver->resolveId($parent);
494377f9e97SAndreas Gohr        if($parent == $id) return false;
495a197105eSmatthiasgrimm    }
496377f9e97SAndreas Gohr    return $parent;
497a3ec5f4aSmatthiasgrimm}
498a3ec5f4aSmatthiasgrimm
499a3ec5f4aSmatthiasgrimm/**
5006b13307fSandi * Print one of the buttons
5016b13307fSandi *
502a453d131SAdrian Lang * @author Adrian Lang <mail@adrianlang.de>
503a453d131SAdrian Lang * @see    tpl_get_action
504e0c26282SGerrit Uitslag *
505e0c26282SGerrit Uitslag * @param string $type
506e0c26282SGerrit Uitslag * @param bool $return
507e0c26282SGerrit Uitslag * @return bool|string html, or false if no data, true if printed
508affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
5096b13307fSandi */
5101af98a77SAnika Henkefunction tpl_button($type, $return = false) {
511affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
512a453d131SAdrian Lang    $data = tpl_get_action($type);
513a453d131SAdrian Lang    if($data === false) {
514a453d131SAdrian Lang        return false;
515a453d131SAdrian Lang    } elseif(!is_array($data)) {
516a453d131SAdrian Lang        $out = sprintf($data, 'button');
517409d7af7SAndreas Gohr    } else {
518ac7a515fSAndreas Gohr        /**
519ac7a515fSAndreas Gohr         * @var string $accesskey
520ac7a515fSAndreas Gohr         * @var string $id
521ac7a515fSAndreas Gohr         * @var string $method
522ac7a515fSAndreas Gohr         * @var array  $params
523ac7a515fSAndreas Gohr         */
524a453d131SAdrian Lang        extract($data);
525a453d131SAdrian Lang        if($id === '#dokuwiki__top') {
526a453d131SAdrian Lang            $out = html_topbtn();
527409d7af7SAndreas Gohr        } else {
528a453d131SAdrian Lang            $out = html_btn($type, $id, $accesskey, $params, $method);
529409d7af7SAndreas Gohr        }
530409d7af7SAndreas Gohr    }
5311af98a77SAnika Henke    if($return) return $out;
532a453d131SAdrian Lang    echo $out;
533a453d131SAdrian Lang    return true;
5346b13307fSandi}
5356b13307fSandi
5366b13307fSandi/**
537ed630903Sandi * Like the action buttons but links
538ed630903Sandi *
539a453d131SAdrian Lang * @author Adrian Lang <mail@adrianlang.de>
540a453d131SAdrian Lang * @see    tpl_get_action
541e0c26282SGerrit Uitslag *
54242ea7f44SGerrit Uitslag * @param string $type    action command
543e0c26282SGerrit Uitslag * @param string $pre     prefix of link
544e0c26282SGerrit Uitslag * @param string $suf     suffix of link
545e0c26282SGerrit Uitslag * @param string $inner   innerHML of link
54621d806cdSGerrit Uitslag * @param bool   $return  if true it returns html, otherwise prints
547e0c26282SGerrit Uitslag * @return bool|string html or false if no data, true if printed
548affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
549a453d131SAdrian Lang */
550a453d131SAdrian Langfunction tpl_actionlink($type, $pre = '', $suf = '', $inner = '', $return = false) {
551affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
552a453d131SAdrian Lang    global $lang;
553a453d131SAdrian Lang    $data = tpl_get_action($type);
554a453d131SAdrian Lang    if($data === false) {
555a453d131SAdrian Lang        return false;
556a453d131SAdrian Lang    } elseif(!is_array($data)) {
557a453d131SAdrian Lang        $out = sprintf($data, 'link');
558a453d131SAdrian Lang    } else {
559ac7a515fSAndreas Gohr        /**
560ac7a515fSAndreas Gohr         * @var string $accesskey
561ac7a515fSAndreas Gohr         * @var string $id
562ac7a515fSAndreas Gohr         * @var string $method
563b1af9014SChristopher Smith         * @var bool   $nofollow
564ac7a515fSAndreas Gohr         * @var array  $params
565becfa414SGerrit Uitslag         * @var string $replacement
566ac7a515fSAndreas Gohr         */
567a453d131SAdrian Lang        extract($data);
568a453d131SAdrian Lang        if(strpos($id, '#') === 0) {
569a453d131SAdrian Lang            $linktarget = $id;
570a453d131SAdrian Lang        } else {
571a453d131SAdrian Lang            $linktarget = wl($id, $params);
572a453d131SAdrian Lang        }
573a453d131SAdrian Lang        $caption = $lang['btn_'.$type];
574becfa414SGerrit Uitslag        if(strpos($caption, '%s')){
575becfa414SGerrit Uitslag            $caption = sprintf($caption, $replacement);
576becfa414SGerrit Uitslag        }
577*24870174SAndreas Gohr        $akey = '';
578*24870174SAndreas Gohr        $addTitle = '';
579c7e90e3fSAnika Henke        if($accesskey) {
580c7e90e3fSAnika Henke            $akey     = 'accesskey="'.$accesskey.'" ';
581c7e90e3fSAnika Henke            $addTitle = ' ['.strtoupper($accesskey).']';
582c7e90e3fSAnika Henke        }
583b1af9014SChristopher Smith        $rel = $nofollow ? 'rel="nofollow" ' : '';
584ac7a515fSAndreas Gohr        $out = tpl_link(
585*24870174SAndreas Gohr            $linktarget, $pre.($inner ?: $caption).$suf,
586a453d131SAdrian Lang            'class="action '.$type.'" '.
587b1af9014SChristopher Smith                $akey.$rel.
588e0c26282SGerrit Uitslag                'title="'.hsc($caption).$addTitle.'"', true
589ac7a515fSAndreas Gohr        );
590a453d131SAdrian Lang    }
591a453d131SAdrian Lang    if($return) return $out;
592a453d131SAdrian Lang    echo $out;
593a453d131SAdrian Lang    return true;
594a453d131SAdrian Lang}
595a453d131SAdrian Lang
596a453d131SAdrian Lang/**
597a453d131SAdrian Lang * Check the actions and get data for buttons and links
598ed630903Sandi *
599ed630903Sandi * @author Andreas Gohr <andi@splitbrain.org>
600a3ec5f4aSmatthiasgrimm * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
601a453d131SAdrian Lang * @author Adrian Lang <mail@adrianlang.de>
602e0c26282SGerrit Uitslag *
603ac7a515fSAndreas Gohr * @param string $type
604ac7a515fSAndreas Gohr * @return array|bool|string
605affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
606ed630903Sandi */
607a453d131SAdrian Langfunction tpl_get_action($type) {
608affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
609a453d131SAdrian Lang    if($type == 'history') $type = 'revisions';
6104c4b65c8SMichael Hamann    if($type == 'subscription') $type = 'subscribe';
6114887c154SAndreas Gohr    if($type == 'img_backto') $type = 'imgBackto';
612409d7af7SAndreas Gohr
6134887c154SAndreas Gohr    $class = '\\dokuwiki\\Menu\\Item\\' . ucfirst($type);
6144887c154SAndreas Gohr    if(class_exists($class)) {
6154887c154SAndreas Gohr        try {
616*24870174SAndreas Gohr            /** @var AbstractItem $item */
6174887c154SAndreas Gohr            $item = new $class;
6184887c154SAndreas Gohr            $data = $item->getLegacyData();
6197b4365a7SGerrit Uitslag            $unknown = false;
6204887c154SAndreas Gohr        } catch(\RuntimeException $ignored) {
6214887c154SAndreas Gohr            return false;
622b8a111f5SMichael Klier        }
623ed630903Sandi    } else {
6244887c154SAndreas Gohr        global $ID;
625*24870174SAndreas Gohr        $data = [
6264887c154SAndreas Gohr            'accesskey' => null,
6274887c154SAndreas Gohr            'type' => $type,
6284887c154SAndreas Gohr            'id' => $ID,
6294887c154SAndreas Gohr            'method' => 'get',
630*24870174SAndreas Gohr            'params' => ['do' => $type],
6314887c154SAndreas Gohr            'nofollow' => true,
632*24870174SAndreas Gohr            'replacement' => ''
633*24870174SAndreas Gohr        ];
6347b4365a7SGerrit Uitslag        $unknown = true;
635ed630903Sandi    }
6367b4365a7SGerrit Uitslag
637e1d9dcc8SAndreas Gohr    $evt = new Event('TPL_ACTION_GET', $data);
6387b4365a7SGerrit Uitslag    if($evt->advise_before()) {
6397b4365a7SGerrit Uitslag        //handle unknown types
6407b4365a7SGerrit Uitslag        if($unknown) {
64138d2ca46SGerrit Uitslag            $data = '[unknown %s type]';
6427b4365a7SGerrit Uitslag        }
6437b4365a7SGerrit Uitslag    }
6447b4365a7SGerrit Uitslag    $evt->advise_after();
6457b4365a7SGerrit Uitslag    unset($evt);
6467b4365a7SGerrit Uitslag
6477b4365a7SGerrit Uitslag    return $data;
648ed630903Sandi}
649ed630903Sandi
650ed630903Sandi/**
65101f17825SAnika Henke * Wrapper around tpl_button() and tpl_actionlink()
65201f17825SAnika Henke *
65301f17825SAnika Henke * @author Anika Henke <anika@selfthinker.org>
65442ea7f44SGerrit Uitslag *
65542ea7f44SGerrit Uitslag * @param string        $type action command
656ac7a515fSAndreas Gohr * @param bool          $link link or form button?
657e0c26282SGerrit Uitslag * @param string|bool   $wrapper HTML element wrapper
658ac7a515fSAndreas Gohr * @param bool          $return return or print
659ac7a515fSAndreas Gohr * @param string        $pre prefix for links
660ac7a515fSAndreas Gohr * @param string        $suf suffix for links
661ac7a515fSAndreas Gohr * @param string        $inner inner HTML for links
662ac7a515fSAndreas Gohr * @return bool|string
663affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
66401f17825SAnika Henke */
665ac7a515fSAndreas Gohrfunction tpl_action($type, $link = false, $wrapper = false, $return = false, $pre = '', $suf = '', $inner = '') {
666affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
66701f17825SAnika Henke    $out = '';
668ac7a515fSAndreas Gohr    if($link) {
669e0c26282SGerrit Uitslag        $out .= tpl_actionlink($type, $pre, $suf, $inner, true);
670ac7a515fSAndreas Gohr    } else {
671e0c26282SGerrit Uitslag        $out .= tpl_button($type, true);
672ac7a515fSAndreas Gohr    }
67301f17825SAnika Henke    if($out && $wrapper) $out = "<$wrapper>$out</$wrapper>";
67401f17825SAnika Henke
67501f17825SAnika Henke    if($return) return $out;
67601f17825SAnika Henke    print $out;
677*24870174SAndreas Gohr    return (bool) $out;
67801f17825SAnika Henke}
67901f17825SAnika Henke
68001f17825SAnika Henke/**
6816b13307fSandi * Print the search form
6826b13307fSandi *
68372645b75SAndreas Gohr * If the first parameter is given a div with the ID 'qsearch_out' will
68472645b75SAndreas Gohr * be added which instructs the ajax pagequicksearch to kick in and place
68572645b75SAndreas Gohr * its output into this div. The second parameter controls the propritary
68672645b75SAndreas Gohr * attribute autocomplete. If set to false this attribute will be set with an
68772645b75SAndreas Gohr * value of "off" to instruct the browser to disable it's own built in
68872645b75SAndreas Gohr * autocompletion feature (MSIE and Firefox)
68972645b75SAndreas Gohr *
6906b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
69142ea7f44SGerrit Uitslag *
692ac7a515fSAndreas Gohr * @param bool $ajax
693ac7a515fSAndreas Gohr * @param bool $autocomplete
694ac7a515fSAndreas Gohr * @return bool
6956b13307fSandi */
69672645b75SAndreas Gohrfunction tpl_searchform($ajax = true, $autocomplete = true) {
6976b13307fSandi    global $lang;
698c1e3b7d9Smatthiasgrimm    global $ACT;
699ad4aaef7SAndreas Gohr    global $QUERY;
700cbcc2fa5SMichael Große    global $ID;
701c1e3b7d9Smatthiasgrimm
702670ff54eSchris    // don't print the search form if search action has been disabled
70364276bbcSarbrk1    if(!actionOK('search')) return false;
704670ff54eSchris
705*24870174SAndreas Gohr    $searchForm = new Form([
7063c7a3327SMichael Große        'action' => wl(),
7073c7a3327SMichael Große        'method' => 'get',
7083c7a3327SMichael Große        'role' => 'search',
7093c7a3327SMichael Große        'class' => 'search',
7103c7a3327SMichael Große        'id' => 'dw__search',
7117fa270bcSMichael Große    ], true);
7123eb2b869SMichael Große    $searchForm->addTagOpen('div')->addClass('no');
7133c7a3327SMichael Große    $searchForm->setHiddenField('do', 'search');
714d22b78c8SMichael Große    $searchForm->setHiddenField('id', $ID);
715d22b78c8SMichael Große    $searchForm->addTextInput('q')
7163c7a3327SMichael Große        ->addClass('edit')
7173c7a3327SMichael Große        ->attrs([
7183c7a3327SMichael Große            'title' => '[F]',
7193c7a3327SMichael Große            'accesskey' => 'f',
7203c7a3327SMichael Große            'placeholder' => $lang['btn_search'],
7213c7a3327SMichael Große            'autocomplete' => $autocomplete ? 'on' : 'off',
7223c7a3327SMichael Große        ])
7233c7a3327SMichael Große        ->id('qsearch__in')
7243c7a3327SMichael Große        ->val($ACT === 'search' ? $QUERY : '')
7253c7a3327SMichael Große        ->useInput(false)
7263c7a3327SMichael Große    ;
7273c7a3327SMichael Große    $searchForm->addButton('', $lang['btn_search'])->attrs([
7283c7a3327SMichael Große        'type' => 'submit',
7293c7a3327SMichael Große        'title' => $lang['btn_search'],
7303c7a3327SMichael Große    ]);
7313c7a3327SMichael Große    if ($ajax) {
7323c7a3327SMichael Große        $searchForm->addTagOpen('div')->id('qsearch__out')->addClass('ajax_qsearch JSpopup');
7333c7a3327SMichael Große        $searchForm->addTagClose('div');
7343c7a3327SMichael Große    }
7353eb2b869SMichael Große    $searchForm->addTagClose('div');
7363c7a3327SMichael Große
737c6977b3aSSatoshi Sahara    echo $searchForm->toHTML('QuickSearch');
7383c7a3327SMichael Große
73954e95700STom N Harris    return true;
7406b13307fSandi}
7416b13307fSandi
7426b13307fSandi/**
7436b13307fSandi * Print the breadcrumbs trace
7446b13307fSandi *
7456b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
74642ea7f44SGerrit Uitslag *
747ac7a515fSAndreas Gohr * @param string $sep Separator between entries
748c4a386f1SIain Hallam * @param bool   $return return or print
749c4a386f1SIain Hallam * @return bool|string
7506b13307fSandi */
751c4a386f1SIain Hallamfunction tpl_breadcrumbs($sep = null, $return = false) {
7526b13307fSandi    global $lang;
7536b13307fSandi    global $conf;
7546b13307fSandi
7556b13307fSandi    //check if enabled
756359fab8bSMichael Hamann    if(!$conf['breadcrumbs']) return false;
7576b13307fSandi
758c4a386f1SIain Hallam    //set default
759c4a386f1SIain Hallam    if(is_null($sep)) $sep = '•';
760c4a386f1SIain Hallam
761c4a386f1SIain Hallam    $out='';
762c4a386f1SIain Hallam
7636b13307fSandi    $crumbs = breadcrumbs(); //setup crumb trace
764265e3787Sandi
7652979a10bSKatriel Traum    $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
766265e3787Sandi
76740eb54bbSjan    //render crumbs, highlight the last one
768c4a386f1SIain Hallam    $out .= '<span class="bchead">'.$lang['breadcrumb'].'</span>';
76940eb54bbSjan    $last = count($crumbs);
77040eb54bbSjan    $i    = 0;
771a77f5846Sjan    foreach($crumbs as $id => $name) {
77240eb54bbSjan        $i++;
773c4a386f1SIain Hallam        $out .= $crumbs_sep;
774c4a386f1SIain Hallam        if($i == $last) $out .= '<span class="curid">';
775c4a386f1SIain Hallam        $out .= '<bdi>' . tpl_link(wl($id), hsc($name), 'class="breadcrumbs" title="'.$id.'"', true) .  '</bdi>';
776c4a386f1SIain Hallam        if($i == $last) $out .= '</span>';
7776b13307fSandi    }
778c4a386f1SIain Hallam    if($return) return $out;
779c4a386f1SIain Hallam    print $out;
780*24870174SAndreas Gohr    return (bool) $out;
7816b13307fSandi}
7826b13307fSandi
7836b13307fSandi/**
7841734437eSandi * Hierarchical breadcrumbs
7851734437eSandi *
78631e187f8SSean Coates * This code was suggested as replacement for the usual breadcrumbs.
7871734437eSandi * It only makes sense with a deep site structure.
7881734437eSandi *
7891734437eSandi * @author Andreas Gohr <andi@splitbrain.org>
7906bd812dfSNigel McNie * @author Nigel McNie <oracle.shinoda@gmail.com>
79131e187f8SSean Coates * @author Sean Coates <sean@caedmon.net>
792f46c9e83SAnika Henke * @author <fredrik@averpil.com>
79308d7a575SAndreas Gohr * @todo   May behave strangely in RTL languages
79442ea7f44SGerrit Uitslag *
795ac7a515fSAndreas Gohr * @param string $sep Separator between entries
796c4a386f1SIain Hallam * @param bool   $return return or print
797c4a386f1SIain Hallam * @return bool|string
7981734437eSandi */
799c4a386f1SIain Hallamfunction tpl_youarehere($sep = null, $return = false) {
8001734437eSandi    global $conf;
8011734437eSandi    global $ID;
8021734437eSandi    global $lang;
8031734437eSandi
80431e187f8SSean Coates    // check if enabled
80554e95700STom N Harris    if(!$conf['youarehere']) return false;
8061734437eSandi
807c4a386f1SIain Hallam    //set default
808c4a386f1SIain Hallam    if(is_null($sep)) $sep = ' » ';
809c4a386f1SIain Hallam
810c4a386f1SIain Hallam    $out = '';
811c4a386f1SIain Hallam
8121734437eSandi    $parts = explode(':', $ID);
813796bafb3SAndreas Gohr    $count = count($parts);
8141734437eSandi
815c4a386f1SIain Hallam    $out .= '<span class="bchead">'.$lang['youarehere'].' </span>';
8163940c519SMark
81708d7a575SAndreas Gohr    // always print the startpage
818c4a386f1SIain Hallam    $out .= '<span class="home">' . tpl_pagelink(':'.$conf['start'], null, true) . '</span>';
819796bafb3SAndreas Gohr
820796bafb3SAndreas Gohr    // print intermediate namespace links
821796bafb3SAndreas Gohr    $part = '';
822796bafb3SAndreas Gohr    for($i = 0; $i < $count - 1; $i++) {
823796bafb3SAndreas Gohr        $part .= $parts[$i].':';
824796bafb3SAndreas Gohr        $page = $part;
825796bafb3SAndreas Gohr        if($page == $conf['start']) continue; // Skip startpage
826796bafb3SAndreas Gohr
82708d7a575SAndreas Gohr        // output
828c4a386f1SIain Hallam        $out .= $sep . tpl_pagelink($page, null, true);
82931e187f8SSean Coates    }
8301734437eSandi
831796bafb3SAndreas Gohr    // print current page, skipping start page, skipping for namespace index
8328c6be208SAndreas Gohr    if (isset($page)) {
8338c6be208SAndreas Gohr        $page = (new PageResolver('root'))->resolveId($page);
8348c6be208SAndreas Gohr        if ($page == $part . $parts[$i]) {
835a8c33dedSMichael Große            if ($return) return $out;
836a8c33dedSMichael Große            print $out;
837a8c33dedSMichael Große            return true;
838a8c33dedSMichael Große        }
8398c6be208SAndreas Gohr    }
840796bafb3SAndreas Gohr    $page = $part.$parts[$i];
841a8c33dedSMichael Große    if($page == $conf['start']) {
842a8c33dedSMichael Große        if($return) return $out;
843a8c33dedSMichael Große        print $out;
844a8c33dedSMichael Große        return true;
845a8c33dedSMichael Große    }
846c4a386f1SIain Hallam    $out .= $sep;
847c4a386f1SIain Hallam    $out .= tpl_pagelink($page, null, true);
848c4a386f1SIain Hallam    if($return) return $out;
849c4a386f1SIain Hallam    print $out;
850*24870174SAndreas Gohr    return (bool) $out;
8511734437eSandi}
8521734437eSandi
8531734437eSandi/**
8546b13307fSandi * Print info if the user is logged in
855a2488c3cSMatthias Grimm * and show full name in that case
8566b13307fSandi *
8576b13307fSandi * Could be enhanced with a profile link in future?
8586b13307fSandi *
8596b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
86042ea7f44SGerrit Uitslag *
861ac7a515fSAndreas Gohr * @return bool
8626b13307fSandi */
8636b13307fSandifunction tpl_userinfo() {
8646b13307fSandi    global $lang;
865585bf44eSChristopher Smith    /** @var Input $INPUT */
866585bf44eSChristopher Smith    global $INPUT;
867585bf44eSChristopher Smith
868585bf44eSChristopher Smith    if($INPUT->server->str('REMOTE_USER')) {
869fde860beSGerrit Uitslag        print $lang['loggedinas'].' '.userlink();
87054e95700STom N Harris        return true;
87154e95700STom N Harris    }
87254e95700STom N Harris    return false;
8736b13307fSandi}
8746b13307fSandi
8756b13307fSandi/**
8766b13307fSandi * Print some info about the current page
8776b13307fSandi *
8786b13307fSandi * @author Andreas Gohr <andi@splitbrain.org>
87942ea7f44SGerrit Uitslag *
880ac7a515fSAndreas Gohr * @param bool $ret return content instead of printing it
881ac7a515fSAndreas Gohr * @return bool|string
8826b13307fSandi */
8834b0d3916SAndreas Gohrfunction tpl_pageinfo($ret = false) {
8846b13307fSandi    global $conf;
8856b13307fSandi    global $lang;
8866b13307fSandi    global $INFO;
887c6e92a3cSDavid Lorentsen    global $ID;
888c6e92a3cSDavid Lorentsen
889c6e92a3cSDavid Lorentsen    // return if we are not allowed to view the page
890ac7a515fSAndreas Gohr    if(!auth_quickaclcheck($ID)) {
891ac7a515fSAndreas Gohr        return false;
892ac7a515fSAndreas Gohr    }
8936b13307fSandi
8946b13307fSandi    // prepare date and path
8956b13307fSandi    $fn = $INFO['filepath'];
8966b13307fSandi    if(!$conf['fullpath']) {
897613bca54SAndreas Gohr        if($INFO['rev']) {
898c83f69baSSatoshi Sahara            $fn = str_replace($conf['olddir'].'/', '', $fn);
8996b13307fSandi        } else {
900c83f69baSSatoshi Sahara            $fn = str_replace($conf['datadir'].'/', '', $fn);
9016b13307fSandi        }
9026b13307fSandi    }
903bee6dc82Sandi    $fn   = utf8_decodeFN($fn);
904f2263577SAndreas Gohr    $date = dformat($INFO['lastmod']);
9056b13307fSandi
906faecdfdfSAndreas Gohr    // print it
907faecdfdfSAndreas Gohr    if($INFO['exists']) {
9084b0d3916SAndreas Gohr        $out = '';
909d317fb5dSAnika Henke        $out .= '<bdi>'.$fn.'</bdi>';
910e260f93bSAnika Henke        $out .= ' · ';
9114b0d3916SAndreas Gohr        $out .= $lang['lastmod'];
912fde860beSGerrit Uitslag        $out .= ' ';
9134b0d3916SAndreas Gohr        $out .= $date;
9146b13307fSandi        if($INFO['editor']) {
9154b0d3916SAndreas Gohr            $out .= ' '.$lang['by'].' ';
916d317fb5dSAnika Henke            $out .= '<bdi>'.editorinfo($INFO['editor']).'</bdi>';
9175aa52fafSBen Coburn        } else {
9184b0d3916SAndreas Gohr            $out .= ' ('.$lang['external_edit'].')';
9196b13307fSandi        }
9206b13307fSandi        if($INFO['locked']) {
921e260f93bSAnika Henke            $out .= ' · ';
9224b0d3916SAndreas Gohr            $out .= $lang['lockedby'];
923fde860beSGerrit Uitslag            $out .= ' ';
924d317fb5dSAnika Henke            $out .= '<bdi>'.editorinfo($INFO['locked']).'</bdi>';
9256b13307fSandi        }
9264b0d3916SAndreas Gohr        if($ret) {
9274b0d3916SAndreas Gohr            return $out;
9284b0d3916SAndreas Gohr        } else {
9294b0d3916SAndreas Gohr            echo $out;
93054e95700STom N Harris            return true;
9316b13307fSandi        }
9324b0d3916SAndreas Gohr    }
93354e95700STom N Harris    return false;
9346b13307fSandi}
9356b13307fSandi
936820fa24bSandi/**
937a6598f23SBen Coburn * Prints or returns the name of the given page (current one if none given).
93887c434ceSAndreas Gohr *
93987c434ceSAndreas Gohr * If useheading is enabled this will use the first headline else
940a6598f23SBen Coburn * the given ID is used.
94187c434ceSAndreas Gohr *
94287c434ceSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
94342ea7f44SGerrit Uitslag *
944ac7a515fSAndreas Gohr * @param string $id page id
945ac7a515fSAndreas Gohr * @param bool   $ret return content instead of printing
946ac7a515fSAndreas Gohr * @return bool|string
94787c434ceSAndreas Gohr */
948a6598f23SBen Coburnfunction tpl_pagetitle($id = null, $ret = false) {
949c248bda1SChristopher Smith    global $ACT, $INPUT, $conf, $lang;
950fffeeafeSChristopher Smith
95187c434ceSAndreas Gohr    if(is_null($id)) {
95287c434ceSAndreas Gohr        global $ID;
95387c434ceSAndreas Gohr        $id = $ID;
95487c434ceSAndreas Gohr    }
95587c434ceSAndreas Gohr
95687c434ceSAndreas Gohr    $name = $id;
957fe9ec250SChris Smith    if(useHeading('navigation')) {
958fffeeafeSChristopher Smith        $first_heading = p_get_first_heading($id);
959fffeeafeSChristopher Smith        if($first_heading) $name = $first_heading;
960fffeeafeSChristopher Smith    }
961fffeeafeSChristopher Smith
962fffeeafeSChristopher Smith    // default page title is the page name, modify with the current action
963fffeeafeSChristopher Smith    switch ($ACT) {
964fffeeafeSChristopher Smith        // admin functions
965fffeeafeSChristopher Smith        case 'admin' :
966fffeeafeSChristopher Smith            $page_title = $lang['btn_admin'];
967fffeeafeSChristopher Smith            // try to get the plugin name
968e1d9dcc8SAndreas Gohr            /** @var $plugin AdminPlugin */
969a61966c5SChristopher Smith            if ($plugin = plugin_getRequestAdminPlugin()){
970c248bda1SChristopher Smith                $plugin_title = $plugin->getMenuText($conf['lang']);
971*24870174SAndreas Gohr                $page_title = $plugin_title ?: $plugin->getPluginName();
972fffeeafeSChristopher Smith            }
973fffeeafeSChristopher Smith            break;
974fffeeafeSChristopher Smith
975fffeeafeSChristopher Smith        // user functions
976fffeeafeSChristopher Smith        case 'login' :
977fffeeafeSChristopher Smith        case 'profile' :
978fffeeafeSChristopher Smith        case 'register' :
979fffeeafeSChristopher Smith        case 'resendpwd' :
980fffeeafeSChristopher Smith            $page_title = $lang['btn_'.$ACT];
981fffeeafeSChristopher Smith            break;
982fffeeafeSChristopher Smith
983fffeeafeSChristopher Smith         // wiki functions
984fffeeafeSChristopher Smith        case 'search' :
985fffeeafeSChristopher Smith        case 'index' :
986fffeeafeSChristopher Smith            $page_title = $lang['btn_'.$ACT];
987fffeeafeSChristopher Smith            break;
988fffeeafeSChristopher Smith
989fffeeafeSChristopher Smith        // page functions
990fffeeafeSChristopher Smith        case 'edit' :
9912f19acc2Sbleistivt        case 'preview' :
992fffeeafeSChristopher Smith            $page_title = "✎ ".$name;
993fffeeafeSChristopher Smith            break;
994fffeeafeSChristopher Smith
995fffeeafeSChristopher Smith        case 'revisions' :
996fffeeafeSChristopher Smith            $page_title = $name . ' - ' . $lang['btn_revs'];
997fffeeafeSChristopher Smith            break;
998fffeeafeSChristopher Smith
999fffeeafeSChristopher Smith        case 'backlink' :
1000fffeeafeSChristopher Smith        case 'recent' :
1001fffeeafeSChristopher Smith        case 'subscribe' :
1002fffeeafeSChristopher Smith            $page_title = $name . ' - ' . $lang['btn_'.$ACT];
1003fffeeafeSChristopher Smith            break;
1004fffeeafeSChristopher Smith
1005fffeeafeSChristopher Smith        default : // SHOW and anything else not included
1006fffeeafeSChristopher Smith            $page_title = $name;
100787c434ceSAndreas Gohr    }
1008a6598f23SBen Coburn
1009a6598f23SBen Coburn    if($ret) {
1010fffeeafeSChristopher Smith        return hsc($page_title);
1011a6598f23SBen Coburn    } else {
1012fffeeafeSChristopher Smith        print hsc($page_title);
101354e95700STom N Harris        return true;
101487c434ceSAndreas Gohr    }
1015a6598f23SBen Coburn}
1016340756e4Sandi
101755efc227SAndreas Gohr/**
101855efc227SAndreas Gohr * Returns the requested EXIF/IPTC tag from the current image
101955efc227SAndreas Gohr *
102055efc227SAndreas Gohr * If $tags is an array all given tags are tried until a
102155efc227SAndreas Gohr * value is found. If no value is found $alt is returned.
102255efc227SAndreas Gohr *
102355efc227SAndreas Gohr * Which texts are known is defined in the functions _exifTagNames
102455efc227SAndreas Gohr * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
102555efc227SAndreas Gohr * to the names of the latter one)
102655efc227SAndreas Gohr *
10273df72098SAndreas Gohr * Only allowed in: detail.php
102855efc227SAndreas Gohr *
102955efc227SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
103042ea7f44SGerrit Uitslag *
103121d806cdSGerrit Uitslag * @param array|string $tags tag or array of tags to try
1032ac7a515fSAndreas Gohr * @param string       $alt  alternative output if no data was found
1033e0c26282SGerrit Uitslag * @param null|string  $src  the image src, uses global $SRC if not given
1034ac7a515fSAndreas Gohr * @return string
103555efc227SAndreas Gohr */
10363df72098SAndreas Gohrfunction tpl_img_getTag($tags, $alt = '', $src = null) {
103755efc227SAndreas Gohr    // Init Exif Reader
1038a46a7ce3Sasivery    global $SRC, $imgMeta;
10393df72098SAndreas Gohr
10403df72098SAndreas Gohr    if(is_null($src)) $src = $SRC;
10411eadd9e8SAndreas Gohr    if(is_null($src)) return $alt;
10423df72098SAndreas Gohr
1043a46a7ce3Sasivery    if(!isset($imgMeta) || $imgMeta === null) $imgMeta = new JpegMeta($src);
1044a46a7ce3Sasivery    if($imgMeta === false) return $alt;
1045a46a7ce3Sasivery    $info = cleanText($imgMeta->getField($tags));
104655efc227SAndreas Gohr    if($info == false) return $alt;
104755efc227SAndreas Gohr    return $info;
104855efc227SAndreas Gohr}
104955efc227SAndreas Gohr
1050a46a7ce3Sasivery
1051a46a7ce3Sasivery/**
1052a46a7ce3Sasivery * Garbage collects up the open JpegMeta object.
1053a46a7ce3Sasivery */
1054a46a7ce3Sasiveryfunction tpl_img_close(){
1055a46a7ce3Sasivery    global $imgMeta;
1056a46a7ce3Sasivery    $imgMeta = null;
1057a46a7ce3Sasivery}
1058a46a7ce3Sasivery
105955efc227SAndreas Gohr/**
1060becfa414SGerrit Uitslag * Returns a description list of the metatags of the current image
1061becfa414SGerrit Uitslag *
1062becfa414SGerrit Uitslag * @return string html of description list
1063becfa414SGerrit Uitslag */
1064becfa414SGerrit Uitslagfunction tpl_img_meta() {
1065becfa414SGerrit Uitslag    global $lang;
1066becfa414SGerrit Uitslag
1067becfa414SGerrit Uitslag    $tags = tpl_get_img_meta();
1068becfa414SGerrit Uitslag
1069becfa414SGerrit Uitslag    echo '<dl>';
1070becfa414SGerrit Uitslag    foreach($tags as $tag) {
1071becfa414SGerrit Uitslag        $label = $lang[$tag['langkey']];
1072fde860beSGerrit Uitslag        if(!$label) $label = $tag['langkey'] . ':';
1073becfa414SGerrit Uitslag
1074fde860beSGerrit Uitslag        echo '<dt>'.$label.'</dt><dd>';
1075becfa414SGerrit Uitslag        if ($tag['type'] == 'date') {
1076becfa414SGerrit Uitslag            echo dformat($tag['value']);
1077becfa414SGerrit Uitslag        } else {
1078becfa414SGerrit Uitslag            echo hsc($tag['value']);
1079becfa414SGerrit Uitslag        }
1080becfa414SGerrit Uitslag        echo '</dd>';
1081becfa414SGerrit Uitslag    }
1082becfa414SGerrit Uitslag    echo '</dl>';
1083becfa414SGerrit Uitslag}
1084becfa414SGerrit Uitslag
1085becfa414SGerrit Uitslag/**
1086becfa414SGerrit Uitslag * Returns metadata as configured in mediameta config file, ready for creating html
1087becfa414SGerrit Uitslag *
1088becfa414SGerrit Uitslag * @return array with arrays containing the entries:
1089becfa414SGerrit Uitslag *   - string langkey  key to lookup in the $lang var, if not found printed as is
1090becfa414SGerrit Uitslag *   - string type     type of value
1091becfa414SGerrit Uitslag *   - string value    tag value (unescaped)
1092becfa414SGerrit Uitslag */
1093becfa414SGerrit Uitslagfunction tpl_get_img_meta() {
1094becfa414SGerrit Uitslag
1095becfa414SGerrit Uitslag    $config_files = getConfigFiles('mediameta');
1096becfa414SGerrit Uitslag    foreach ($config_files as $config_file) {
109779e79377SAndreas Gohr        if(file_exists($config_file)) {
1098becfa414SGerrit Uitslag            include($config_file);
1099becfa414SGerrit Uitslag        }
1100becfa414SGerrit Uitslag    }
1101*24870174SAndreas Gohr    $tags = [];
1102becfa414SGerrit Uitslag    foreach($fields as $tag){
1103*24870174SAndreas Gohr        $t = [];
1104becfa414SGerrit Uitslag        if (!empty($tag[0])) {
1105*24870174SAndreas Gohr            $t = [$tag[0]];
1106becfa414SGerrit Uitslag        }
1107056bf31fSDamien Regad        if(isset($tag[3]) && is_array($tag[3])) {
1108becfa414SGerrit Uitslag            $t = array_merge($t,$tag[3]);
1109becfa414SGerrit Uitslag        }
1110becfa414SGerrit Uitslag        $value = tpl_img_getTag($t);
1111becfa414SGerrit Uitslag        if ($value) {
1112*24870174SAndreas Gohr            $tags[] = ['langkey' => $tag[1], 'type' => $tag[2], 'value' => $value];
1113becfa414SGerrit Uitslag        }
1114becfa414SGerrit Uitslag    }
1115becfa414SGerrit Uitslag    return $tags;
1116becfa414SGerrit Uitslag}
1117becfa414SGerrit Uitslag
1118becfa414SGerrit Uitslag/**
111955efc227SAndreas Gohr * Prints the image with a link to the full sized version
112055efc227SAndreas Gohr *
112155efc227SAndreas Gohr * Only allowed in: detail.php
1122a02d2933SAndreas Gohr *
1123ac7a515fSAndreas Gohr * @triggers TPL_IMG_DISPLAY
1124a02d2933SAndreas Gohr * @param $maxwidth  int - maximal width of the image
1125a02d2933SAndreas Gohr * @param $maxheight int - maximal height of the image
1126a02d2933SAndreas Gohr * @param $link bool     - link to the orginal size?
1127a02d2933SAndreas Gohr * @param $params array  - additional image attributes
112842ea7f44SGerrit Uitslag * @return bool Result of TPL_IMG_DISPLAY
112955efc227SAndreas Gohr */
1130a02d2933SAndreas Gohrfunction tpl_img($maxwidth = 0, $maxheight = 0, $link = true, $params = null) {
113155efc227SAndreas Gohr    global $IMG;
1132585bf44eSChristopher Smith    /** @var Input $INPUT */
1133ac7a515fSAndreas Gohr    global $INPUT;
11345c2eed9aSlisps    global $REV;
113565d3a5dbSAndreas Gohr    $w = (int) tpl_img_getTag('File.Width');
113665d3a5dbSAndreas Gohr    $h = (int) tpl_img_getTag('File.Height');
113755efc227SAndreas Gohr
113855efc227SAndreas Gohr    //resize to given max values
113923a34783SAndreas Gohr    $ratio = 1;
114023a34783SAndreas Gohr    if ($w >= $h) {
1141f8925855Sjoe.lapp        if($maxwidth && $w >= $maxwidth) {
114255efc227SAndreas Gohr            $ratio = $maxwidth / $w;
1143f8925855Sjoe.lapp        } elseif($maxheight && $h > $maxheight) {
114455efc227SAndreas Gohr            $ratio = $maxheight / $h;
114555efc227SAndreas Gohr        }
1146*24870174SAndreas Gohr    } elseif ($maxheight && $h >= $maxheight) {
114755efc227SAndreas Gohr        $ratio = $maxheight / $h;
1148f8925855Sjoe.lapp    } elseif($maxwidth && $w > $maxwidth) {
114955efc227SAndreas Gohr        $ratio = $maxwidth / $w;
115055efc227SAndreas Gohr    }
115155efc227SAndreas Gohr    if($ratio) {
115255efc227SAndreas Gohr        $w = floor($ratio * $w);
115355efc227SAndreas Gohr        $h = floor($ratio * $h);
115455efc227SAndreas Gohr    }
115555efc227SAndreas Gohr
11566de3759aSAndreas Gohr    //prepare URLs
1157*24870174SAndreas Gohr    $url = ml($IMG, ['cache'=> $INPUT->str('cache'), 'rev'=>$REV], true, '&');
1158*24870174SAndreas Gohr    $src = ml($IMG, ['cache'=> $INPUT->str('cache'), 'rev'=>$REV, 'w'=> $w, 'h'=> $h], true, '&');
115955efc227SAndreas Gohr
11602684e50aSAndreas Gohr    //prepare attributes
116155efc227SAndreas Gohr    $alt = tpl_img_getTag('Simple.Title');
1162a02d2933SAndreas Gohr    if(is_null($params)) {
1163*24870174SAndreas Gohr        $p = [];
1164a02d2933SAndreas Gohr    } else {
1165a02d2933SAndreas Gohr        $p = $params;
1166a02d2933SAndreas Gohr    }
11672684e50aSAndreas Gohr    if($w) $p['width'] = $w;
11682684e50aSAndreas Gohr    if($h) $p['height'] = $h;
11692684e50aSAndreas Gohr    $p['class'] = 'img_detail';
11702684e50aSAndreas Gohr    if($alt) {
11712684e50aSAndreas Gohr        $p['alt']   = $alt;
11722684e50aSAndreas Gohr        $p['title'] = $alt;
11732684e50aSAndreas Gohr    } else {
11742684e50aSAndreas Gohr        $p['alt'] = '';
11752684e50aSAndreas Gohr    }
1176a02d2933SAndreas Gohr    $p['src'] = $src;
117755efc227SAndreas Gohr
1178*24870174SAndreas Gohr    $data = ['url'=> ($link ? $url : null), 'params'=> $p];
1179cbb44eabSAndreas Gohr    return Event::createAndTrigger('TPL_IMG_DISPLAY', $data, '_tpl_img_action', true);
1180a02d2933SAndreas Gohr}
1181a02d2933SAndreas Gohr
1182a02d2933SAndreas Gohr/**
1183a02d2933SAndreas Gohr * Default action for TPL_IMG_DISPLAY
1184ac7a515fSAndreas Gohr *
1185ac7a515fSAndreas Gohr * @param array $data
1186ac7a515fSAndreas Gohr * @return bool
1187a02d2933SAndreas Gohr */
1188ac7a515fSAndreas Gohrfunction _tpl_img_action($data) {
118959f3611bSAnika Henke    global $lang;
1190a02d2933SAndreas Gohr    $p = buildAttributes($data['params']);
1191a02d2933SAndreas Gohr
119259f3611bSAnika Henke    if($data['url']) print '<a href="'.hsc($data['url']).'" title="'.$lang['mediaview'].'">';
1193a02d2933SAndreas Gohr    print '<img '.$p.'/>';
1194a02d2933SAndreas Gohr    if($data['url']) print '</a>';
119554e95700STom N Harris    return true;
119655efc227SAndreas Gohr}
119755efc227SAndreas Gohr
11987367b368SAndreas Gohr/**
1199881f2ee2SAndreas Haerter * This function inserts a small gif which in reality is the indexer function.
12007367b368SAndreas Gohr *
12017367b368SAndreas Gohr * Should be called somewhere at the very end of the main.php
12027367b368SAndreas Gohr * template
1203ac7a515fSAndreas Gohr *
1204ac7a515fSAndreas Gohr * @return bool
12057367b368SAndreas Gohr */
12067367b368SAndreas Gohrfunction tpl_indexerWebBug() {
12077367b368SAndreas Gohr    global $ID;
12081dad36f5SAndreas Gohr
1209*24870174SAndreas Gohr    $p           = [];
12104af80fe8SMichael Große    $p['src']    = DOKU_BASE.'lib/exe/taskrunner.php?id='.rawurlencode($ID).
1211e68c51baSAndreas Gohr        '&'.time();
1212881f2ee2SAndreas Haerter    $p['width']  = 2; //no more 1x1 px image because we live in times of ad blockers...
12137367b368SAndreas Gohr    $p['height'] = 1;
12147367b368SAndreas Gohr    $p['alt']    = '';
12157367b368SAndreas Gohr    $att         = buildAttributes($p);
12167367b368SAndreas Gohr    print "<img $att />";
121754e95700STom N Harris    return true;
12187367b368SAndreas Gohr}
12197367b368SAndreas Gohr
122078d4e784SEsther Brunner/**
122178d4e784SEsther Brunner * tpl_getConf($id)
122278d4e784SEsther Brunner *
122378d4e784SEsther Brunner * use this function to access template configuration variables
1224ac7a515fSAndreas Gohr *
122517448fb8SChristopher Smith * @param string $id      name of the value to access
122617448fb8SChristopher Smith * @param mixed  $notset  what to return if the setting is not available
122717448fb8SChristopher Smith * @return mixed
122878d4e784SEsther Brunner */
122917448fb8SChristopher Smithfunction tpl_getConf($id, $notset=false) {
123078d4e784SEsther Brunner    global $conf;
123117566ac6SAdrian Lang    static $tpl_configloaded = false;
123278d4e784SEsther Brunner
123378d4e784SEsther Brunner    $tpl = $conf['template'];
123478d4e784SEsther Brunner
123578d4e784SEsther Brunner    if(!$tpl_configloaded) {
123678d4e784SEsther Brunner        $tconf = tpl_loadConfig();
123778d4e784SEsther Brunner        if($tconf !== false) {
123878d4e784SEsther Brunner            foreach($tconf as $key => $value) {
123978d4e784SEsther Brunner                if(isset($conf['tpl'][$tpl][$key])) continue;
124078d4e784SEsther Brunner                $conf['tpl'][$tpl][$key] = $value;
124178d4e784SEsther Brunner            }
124278d4e784SEsther Brunner            $tpl_configloaded = true;
124378d4e784SEsther Brunner        }
124478d4e784SEsther Brunner    }
124578d4e784SEsther Brunner
1246*24870174SAndreas Gohr    return $conf['tpl'][$tpl][$id] ?? $notset;
124717448fb8SChristopher Smith}
124817448fb8SChristopher Smith
124978d4e784SEsther Brunner/**
125078d4e784SEsther Brunner * tpl_loadConfig()
1251ac7a515fSAndreas Gohr *
125278d4e784SEsther Brunner * reads all template configuration variables
125378d4e784SEsther Brunner * this function is automatically called by tpl_getConf()
1254ac7a515fSAndreas Gohr *
1255ac7a515fSAndreas Gohr * @return array
125678d4e784SEsther Brunner */
125778d4e784SEsther Brunnerfunction tpl_loadConfig() {
125878d4e784SEsther Brunner
1259c4766956SAndreas Gohr    $file = tpl_incdir().'/conf/default.php';
1260*24870174SAndreas Gohr    $conf = [];
126178d4e784SEsther Brunner
126279e79377SAndreas Gohr    if(!file_exists($file)) return false;
126378d4e784SEsther Brunner
126478d4e784SEsther Brunner    // load default config file
126578d4e784SEsther Brunner    include($file);
126678d4e784SEsther Brunner
126778d4e784SEsther Brunner    return $conf;
126878d4e784SEsther Brunner}
126978d4e784SEsther Brunner
127017566ac6SAdrian Lang// language methods
127117566ac6SAdrian Lang/**
127217566ac6SAdrian Lang * tpl_getLang($id)
127317566ac6SAdrian Lang *
127417566ac6SAdrian Lang * use this function to access template language variables
127542ea7f44SGerrit Uitslag *
127642ea7f44SGerrit Uitslag * @param string $id key of language string
127742ea7f44SGerrit Uitslag * @return string
127817566ac6SAdrian Lang */
127917566ac6SAdrian Langfunction tpl_getLang($id) {
1280*24870174SAndreas Gohr    static $lang = [];
128117566ac6SAdrian Lang
128217566ac6SAdrian Lang    if(count($lang) === 0) {
1283dd7a6159SGerrit Uitslag        global $conf, $config_cascade; // definitely don't invoke "global $lang"
1284dd7a6159SGerrit Uitslag
1285c4766956SAndreas Gohr        $path = tpl_incdir() . 'lang/';
128617566ac6SAdrian Lang
1287*24870174SAndreas Gohr        $lang = [];
128817566ac6SAdrian Lang
128917566ac6SAdrian Lang        // don't include once
129017566ac6SAdrian Lang        @include($path . 'en/lang.php');
1291dd7a6159SGerrit Uitslag        foreach($config_cascade['lang']['template'] as $config_file) {
129279e79377SAndreas Gohr            if(file_exists($config_file . $conf['template'] . '/en/lang.php')) {
1293dd7a6159SGerrit Uitslag                include($config_file . $conf['template'] . '/en/lang.php');
1294dd7a6159SGerrit Uitslag            }
129517566ac6SAdrian Lang        }
129617566ac6SAdrian Lang
1297dd7a6159SGerrit Uitslag        if($conf['lang'] != 'en') {
1298dd7a6159SGerrit Uitslag            @include($path . $conf['lang'] . '/lang.php');
1299dd7a6159SGerrit Uitslag            foreach($config_cascade['lang']['template'] as $config_file) {
130079e79377SAndreas Gohr                if(file_exists($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php')) {
1301dd7a6159SGerrit Uitslag                    include($config_file . $conf['template'] . '/' . $conf['lang'] . '/lang.php');
1302dd7a6159SGerrit Uitslag                }
1303dd7a6159SGerrit Uitslag            }
1304dd7a6159SGerrit Uitslag        }
130517566ac6SAdrian Lang    }
1306*24870174SAndreas Gohr    return $lang[$id] ?? '';
130717566ac6SAdrian Lang}
130817566ac6SAdrian Lang
13093df72098SAndreas Gohr/**
1310c5c17fdaSKlap-in * Retrieve a language dependent file and pass to xhtml renderer for display
1311e8ec13b9SKlap-in * template equivalent of p_locale_xhtml()
1312e8ec13b9SKlap-in *
1313e8ec13b9SKlap-in * @param   string $id id of language dependent wiki page
1314e8ec13b9SKlap-in * @return  string     parsed contents of the wiki page in xhtml format
1315e8ec13b9SKlap-in */
1316e8ec13b9SKlap-infunction tpl_locale_xhtml($id) {
1317c5c17fdaSKlap-in    return p_cached_output(tpl_localeFN($id));
1318e8ec13b9SKlap-in}
1319e8ec13b9SKlap-in
1320e8ec13b9SKlap-in/**
1321c5c17fdaSKlap-in * Prepends appropriate path for a language dependent filename
132242ea7f44SGerrit Uitslag *
132342ea7f44SGerrit Uitslag * @param string $id id of localized text
132442ea7f44SGerrit Uitslag * @return string wiki text
1325e8ec13b9SKlap-in */
1326c5c17fdaSKlap-infunction tpl_localeFN($id) {
1327e8ec13b9SKlap-in    $path = tpl_incdir().'lang/';
1328e8ec13b9SKlap-in    global $conf;
132938fb1fc7SGerrit Uitslag    $file = DOKU_CONF.'template_lang/'.$conf['template'].'/'.$conf['lang'].'/'.$id.'.txt';
133079e79377SAndreas Gohr    if (!file_exists($file)){
1331e8ec13b9SKlap-in        $file = $path.$conf['lang'].'/'.$id.'.txt';
133279e79377SAndreas Gohr        if(!file_exists($file)){
1333e8ec13b9SKlap-in            //fall back to english
1334e8ec13b9SKlap-in            $file = $path.'en/'.$id.'.txt';
1335e8ec13b9SKlap-in        }
1336e8ec13b9SKlap-in    }
1337e8ec13b9SKlap-in    return $file;
1338e8ec13b9SKlap-in}
1339e8ec13b9SKlap-in
1340e8ec13b9SKlap-in/**
13417abc270fSGerrit Uitslag * prints the "main content" in the mediamanager popup
13423df72098SAndreas Gohr *
13433df72098SAndreas Gohr * Depending on the user's actions this may be a list of
13443df72098SAndreas Gohr * files in a namespace, the meta editing dialog or
13453df72098SAndreas Gohr * a message of referencing pages
13463df72098SAndreas Gohr *
13473df72098SAndreas Gohr * Only allowed in mediamanager.php
13483df72098SAndreas Gohr *
1349c182313eSAndreas Gohr * @triggers MEDIAMANAGER_CONTENT_OUTPUT
1350c182313eSAndreas Gohr * @param bool $fromajax - set true when calling this function via ajax
135142ea7f44SGerrit Uitslag * @param string $sort
13528702de7fSGerrit Uitslag *
13533df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
13543df72098SAndreas Gohr */
135500e3e394SChristopher Smithfunction tpl_mediaContent($fromajax = false, $sort='natural') {
13563df72098SAndreas Gohr    global $IMG;
13573df72098SAndreas Gohr    global $AUTH;
13583df72098SAndreas Gohr    global $INUSE;
13593df72098SAndreas Gohr    global $NS;
13603df72098SAndreas Gohr    global $JUMPTO;
1361585bf44eSChristopher Smith    /** @var Input $INPUT */
1362ac7a515fSAndreas Gohr    global $INPUT;
13633df72098SAndreas Gohr
1364ac7a515fSAndreas Gohr    $do = $INPUT->extract('do')->str('do');
1365*24870174SAndreas Gohr    if(in_array($do, ['save', 'cancel'])) $do = '';
1366c182313eSAndreas Gohr
1367c182313eSAndreas Gohr    if(!$do) {
1368ac7a515fSAndreas Gohr        if($INPUT->bool('edit')) {
1369c182313eSAndreas Gohr            $do = 'metaform';
1370c182313eSAndreas Gohr        } elseif(is_array($INUSE)) {
1371c182313eSAndreas Gohr            $do = 'filesinuse';
1372c182313eSAndreas Gohr        } else {
1373c182313eSAndreas Gohr            $do = 'filelist';
1374c182313eSAndreas Gohr        }
1375c182313eSAndreas Gohr    }
1376c182313eSAndreas Gohr
1377c182313eSAndreas Gohr    // output the content pane, wrapped in an event.
1378c182313eSAndreas Gohr    if(!$fromajax) ptln('<div id="media__content">');
1379*24870174SAndreas Gohr    $data = ['do' => $do];
1380e1d9dcc8SAndreas Gohr    $evt  = new Event('MEDIAMANAGER_CONTENT_OUTPUT', $data);
1381c182313eSAndreas Gohr    if($evt->advise_before()) {
1382c182313eSAndreas Gohr        $do = $data['do'];
138330fd72fbSKate Arzamastseva        if($do == 'filesinuse') {
1384c182313eSAndreas Gohr            media_filesinuse($INUSE, $IMG);
1385c182313eSAndreas Gohr        } elseif($do == 'filelist') {
138600e3e394SChristopher Smith            media_filelist($NS, $AUTH, $JUMPTO,false,$sort);
1387c9f56829SAndreas Gohr        } elseif($do == 'searchlist') {
1388ac7a515fSAndreas Gohr            media_searchlist($INPUT->str('q'), $NS, $AUTH);
1389c182313eSAndreas Gohr        } else {
1390c182313eSAndreas Gohr            msg('Unknown action '.hsc($do), -1);
1391c182313eSAndreas Gohr        }
1392c182313eSAndreas Gohr    }
1393c182313eSAndreas Gohr    $evt->advise_after();
1394c182313eSAndreas Gohr    unset($evt);
1395c182313eSAndreas Gohr    if(!$fromajax) ptln('</div>');
1396c182313eSAndreas Gohr
13973df72098SAndreas Gohr}
13983df72098SAndreas Gohr
13993df72098SAndreas Gohr/**
1400d9162c6cSKate Arzamastseva * Prints the central column in full-screen media manager
1401d9162c6cSKate Arzamastseva * Depending on the opened tab this may be a list of
1402d9162c6cSKate Arzamastseva * files in a namespace, upload form or search form
1403d9162c6cSKate Arzamastseva *
1404d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1405d9162c6cSKate Arzamastseva */
1406035e07f1SKate Arzamastsevafunction tpl_mediaFileList() {
1407d9162c6cSKate Arzamastseva    global $AUTH;
1408d9162c6cSKate Arzamastseva    global $NS;
1409d9162c6cSKate Arzamastseva    global $JUMPTO;
141095b451bcSAdrian Lang    global $lang;
1411585bf44eSChristopher Smith    /** @var Input $INPUT */
1412ac7a515fSAndreas Gohr    global $INPUT;
1413d9162c6cSKate Arzamastseva
1414ac7a515fSAndreas Gohr    $opened_tab = $INPUT->str('tab_files');
1415*24870174SAndreas Gohr    if(!$opened_tab || !in_array($opened_tab, ['files', 'upload', 'search'])) $opened_tab = 'files';
1416ac7a515fSAndreas Gohr    if($INPUT->str('mediado') == 'update') $opened_tab = 'upload';
1417d9162c6cSKate Arzamastseva
141894add303SAnika Henke    echo '<h2 class="a11y">'.$lang['mediaselect'].'</h2>'.NL;
141995b451bcSAdrian Lang
1420ed69a2aeSKate Arzamastseva    media_tabs_files($opened_tab);
142123846a98SKate Arzamastseva
142294add303SAnika Henke    echo '<div class="panelHeader">'.NL;
142395b451bcSAdrian Lang    echo '<h3>';
1424*24870174SAndreas Gohr    $tabTitle = $NS ?: '['.$lang['mediaroot'].']';
1425c98f205eSAdrian Lang    printf($lang['media_'.$opened_tab], '<strong>'.hsc($tabTitle).'</strong>');
142694add303SAnika Henke    echo '</h3>'.NL;
142795b451bcSAdrian Lang    if($opened_tab === 'search' || $opened_tab === 'files') {
142895b451bcSAdrian Lang        media_tab_files_options();
142923846a98SKate Arzamastseva    }
143094add303SAnika Henke    echo '</div>'.NL;
1431d9162c6cSKate Arzamastseva
143294add303SAnika Henke    echo '<div class="panelContent">'.NL;
143395b451bcSAdrian Lang    if($opened_tab == 'files') {
143495b451bcSAdrian Lang        media_tab_files($NS, $AUTH, $JUMPTO);
143595b451bcSAdrian Lang    } elseif($opened_tab == 'upload') {
143695b451bcSAdrian Lang        media_tab_upload($NS, $AUTH, $JUMPTO);
143795b451bcSAdrian Lang    } elseif($opened_tab == 'search') {
143895b451bcSAdrian Lang        media_tab_search($NS, $AUTH);
143995b451bcSAdrian Lang    }
144094add303SAnika Henke    echo '</div>'.NL;
1441d9162c6cSKate Arzamastseva}
1442d9162c6cSKate Arzamastseva
1443d9162c6cSKate Arzamastseva/**
1444d9162c6cSKate Arzamastseva * Prints the third column in full-screen media manager
1445d9162c6cSKate Arzamastseva * Depending on the opened tab this may be details of the
1446d9162c6cSKate Arzamastseva * selected file, the meta editing dialog or
1447d9162c6cSKate Arzamastseva * list of file revisions
1448d9162c6cSKate Arzamastseva *
1449d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1450f50a239bSTakamura *
1451f50a239bSTakamura * @param string $image
1452f50a239bSTakamura * @param boolean $rev
1453d9162c6cSKate Arzamastseva */
1454035e07f1SKate Arzamastsevafunction tpl_mediaFileDetails($image, $rev) {
1455e8a2a143SMichael Hamann    global $conf, $DEL, $lang;
1456585bf44eSChristopher Smith    /** @var Input $INPUT */
1457585bf44eSChristopher Smith    global $INPUT;
1458d9162c6cSKate Arzamastseva
145964159a61SAndreas Gohr    $removed = (
146064159a61SAndreas Gohr        !file_exists(mediaFN($image)) &&
146164159a61SAndreas Gohr        file_exists(mediaMetaFN($image, '.changes')) &&
146264159a61SAndreas Gohr        $conf['mediarevisions']
146364159a61SAndreas Gohr    );
1464ac7a515fSAndreas Gohr    if(!$image || (!file_exists(mediaFN($image)) && !$removed) || $DEL) return;
14656dd095f5SKate Arzamastseva    if($rev && !file_exists(mediaFN($image, $rev))) $rev = false;
1466e8a2a143SMichael Hamann    $ns = getNS($image);
1467ac7a515fSAndreas Gohr    $do = $INPUT->str('mediado');
14681eeeced2SKate Arzamastseva
1469ac7a515fSAndreas Gohr    $opened_tab = $INPUT->str('tab_details');
1470e5d185e1SKate Arzamastseva
1471*24870174SAndreas Gohr    $tab_array = ['view'];
1472*24870174SAndreas Gohr    [, $mime] = mimetype($image);
1473e5d185e1SKate Arzamastseva    if($mime == 'image/jpeg') {
1474e5d185e1SKate Arzamastseva        $tab_array[] = 'edit';
1475e5d185e1SKate Arzamastseva    }
1476e5d185e1SKate Arzamastseva    if($conf['mediarevisions']) {
1477e5d185e1SKate Arzamastseva        $tab_array[] = 'history';
1478e5d185e1SKate Arzamastseva    }
1479e5d185e1SKate Arzamastseva
1480e5d185e1SKate Arzamastseva    if(!$opened_tab || !in_array($opened_tab, $tab_array)) $opened_tab = 'view';
1481ac7a515fSAndreas Gohr    if($INPUT->bool('edit')) $opened_tab = 'edit';
148223846a98SKate Arzamastseva    if($do == 'restore') $opened_tab = 'view';
1483d9162c6cSKate Arzamastseva
1484ed69a2aeSKate Arzamastseva    media_tabs_details($image, $opened_tab);
148523846a98SKate Arzamastseva
148659f3611bSAnika Henke    echo '<div class="panelHeader"><h3>';
1487*24870174SAndreas Gohr    [$ext] = mimetype($image, false);
148895b451bcSAdrian Lang    $class    = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
148995b451bcSAdrian Lang    $class    = 'select mediafile mf_'.$class;
1490*24870174SAndreas Gohr
1491750a0b51SMichael Große    $attributes = $rev ? ['rev' => $rev] : [];
149264159a61SAndreas Gohr    $tabTitle = '<strong><a href="'.ml($image, $attributes).'" class="'.$class.'" title="'.$lang['mediaview'].'">'.
149364159a61SAndreas Gohr        $image.'</a>'.'</strong>';
149408317413SAdrian Lang    if($opened_tab === 'view' && $rev) {
149508317413SAdrian Lang        printf($lang['media_viewold'], $tabTitle, dformat($rev));
149608317413SAdrian Lang    } else {
1497026d14a9SAnika Henke        printf($lang['media_'.$opened_tab], $tabTitle);
149808317413SAdrian Lang    }
1499b8a84c03SAndreas Gohr
150094add303SAnika Henke    echo '</h3></div>'.NL;
150195b451bcSAdrian Lang
150294add303SAnika Henke    echo '<div class="panelContent">'.NL;
150395b451bcSAdrian Lang
150423846a98SKate Arzamastseva    if($opened_tab == 'view') {
1505e8a2a143SMichael Hamann        media_tab_view($image, $ns, null, $rev);
150623846a98SKate Arzamastseva
150792cac9a9SKate Arzamastseva    } elseif($opened_tab == 'edit' && !$removed) {
1508e8a2a143SMichael Hamann        media_tab_edit($image, $ns);
150923846a98SKate Arzamastseva
1510e5d185e1SKate Arzamastseva    } elseif($opened_tab == 'history' && $conf['mediarevisions']) {
1511e8a2a143SMichael Hamann        media_tab_history($image, $ns);
151223846a98SKate Arzamastseva    }
151395b451bcSAdrian Lang
151494add303SAnika Henke    echo '</div>'.NL;
1515d9162c6cSKate Arzamastseva}
1516d9162c6cSKate Arzamastseva
1517d9162c6cSKate Arzamastseva/**
15187abc270fSGerrit Uitslag * prints the namespace tree in the mediamanager popup
15193df72098SAndreas Gohr *
15203df72098SAndreas Gohr * Only allowed in mediamanager.php
15213df72098SAndreas Gohr *
15223df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
15233df72098SAndreas Gohr */
1524fa8e5c77SKate Arzamastsevafunction tpl_mediaTree() {
15253df72098SAndreas Gohr    global $NS;
152623846a98SKate Arzamastseva    ptln('<div id="media__tree">');
15273df72098SAndreas Gohr    media_nstree($NS);
15283df72098SAndreas Gohr    ptln('</div>');
15293df72098SAndreas Gohr}
15303df72098SAndreas Gohr
1531a00de5b5SAndreas Gohr/**
1532a00de5b5SAndreas Gohr * Print a dropdown menu with all DokuWiki actions
1533a00de5b5SAndreas Gohr *
1534a00de5b5SAndreas Gohr * Note: this will not use any pretty URLs
1535a00de5b5SAndreas Gohr *
1536a00de5b5SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
153742ea7f44SGerrit Uitslag *
153842ea7f44SGerrit Uitslag * @param string $empty empty option label
153942ea7f44SGerrit Uitslag * @param string $button submit button label
1540affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
1541a00de5b5SAndreas Gohr */
1542a00de5b5SAndreas Gohrfunction tpl_actiondropdown($empty = '', $button = '&gt;') {
1543affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
1544*24870174SAndreas Gohr    $menu = new MobileMenu();
15451e875dcdSAndreas Gohr    echo $menu->getDropdown($empty, $button);
1546a00de5b5SAndreas Gohr}
1547a00de5b5SAndreas Gohr
1548066fee30SAndreas Gohr/**
1549066fee30SAndreas Gohr * Print a informational line about the used license
1550066fee30SAndreas Gohr *
1551066fee30SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
1552ac7a515fSAndreas Gohr * @param  string $img     print image? (|button|badge)
1553ac7a515fSAndreas Gohr * @param  bool   $imgonly skip the textual description?
1554ac7a515fSAndreas Gohr * @param  bool   $return  when true don't print, but return HTML
1555ac7a515fSAndreas Gohr * @param  bool   $wrap    wrap in div with class="license"?
1556ac7a515fSAndreas Gohr * @return string
1557066fee30SAndreas Gohr */
155880083a41SAndreas Gohrfunction tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap = true) {
1559066fee30SAndreas Gohr    global $license;
1560066fee30SAndreas Gohr    global $conf;
1561066fee30SAndreas Gohr    global $lang;
1562066fee30SAndreas Gohr    if(!$conf['license']) return '';
1563066fee30SAndreas Gohr    if(!is_array($license[$conf['license']])) return '';
1564066fee30SAndreas Gohr    $lic    = $license[$conf['license']];
156553e15c8bSAnika Henke    $target = ($conf['target']['extern']) ? ' target="'.$conf['target']['extern'].'"' : '';
1566066fee30SAndreas Gohr
156780083a41SAndreas Gohr    $out = '';
156880083a41SAndreas Gohr    if($wrap) $out .= '<div class="license">';
1569066fee30SAndreas Gohr    if($img) {
1570066fee30SAndreas Gohr        $src = license_img($img);
1571066fee30SAndreas Gohr        if($src) {
157253e15c8bSAnika Henke            $out .= '<a href="'.$lic['url'].'" rel="license"'.$target;
157353e15c8bSAnika Henke            $out .= '><img src="'.DOKU_BASE.$src.'" alt="'.$lic['name'].'" /></a>';
157453e15c8bSAnika Henke            if(!$imgonly) $out .= ' ';
1575066fee30SAndreas Gohr        }
1576066fee30SAndreas Gohr    }
15774cefd216SMichael Klier    if(!$imgonly) {
157853e15c8bSAnika Henke        $out .= $lang['license'].' ';
1579d317fb5dSAnika Henke        $out .= '<bdi><a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
1580d317fb5dSAnika Henke        $out .= '>'.$lic['name'].'</a></bdi>';
15814cefd216SMichael Klier    }
158280083a41SAndreas Gohr    if($wrap) $out .= '</div>';
1583066fee30SAndreas Gohr
1584066fee30SAndreas Gohr    if($return) return $out;
1585066fee30SAndreas Gohr    echo $out;
1586ac7a515fSAndreas Gohr    return '';
1587066fee30SAndreas Gohr}
1588066fee30SAndreas Gohr
1589a81910eeSAndreas Gohr/**
1590835dfcaeSAnika Henke * Includes the rendered HTML of a given page
1591a81910eeSAndreas Gohr *
1592a81910eeSAndreas Gohr * This function is useful to populate sidebars or similar features in a
1593a81910eeSAndreas Gohr * template
1594e0c26282SGerrit Uitslag *
15957a112df5SAndreas Gohr * @param string $pageid The page name you want to include
15967a112df5SAndreas Gohr * @param bool $print Should the content be printed or returned only
15977a112df5SAndreas Gohr * @param bool $propagate Search higher namespaces, too?
15987c3e4a67SAndreas Gohr * @param bool $useacl Include the page only if the ACLs check out?
1599e0c26282SGerrit Uitslag * @return bool|null|string
1600a81910eeSAndreas Gohr */
16017c3e4a67SAndreas Gohrfunction tpl_include_page($pageid, $print = true, $propagate = false, $useacl = true) {
16027a112df5SAndreas Gohr    if($propagate) {
16037c3e4a67SAndreas Gohr        $pageid = page_findnearest($pageid, $useacl);
16047c3e4a67SAndreas Gohr    } elseif($useacl && auth_quickaclcheck($pageid) == AUTH_NONE) {
16057a112df5SAndreas Gohr        return false;
16067a112df5SAndreas Gohr    }
1607c786a1b6SAnika Henke    if(!$pageid) return false;
1608835dfcaeSAnika Henke
1609c786a1b6SAnika Henke    global $TOC;
16109a2e250aSAndreas Gohr    $oldtoc = $TOC;
1611a81910eeSAndreas Gohr    $html   = p_wiki_xhtml($pageid, '', false);
16129a2e250aSAndreas Gohr    $TOC    = $oldtoc;
1613a81910eeSAndreas Gohr
1614a2e03c82SAndreas Gohr    if($print) echo $html;
1615e66d3e6dSAndreas Gohr    return $html;
1616e66d3e6dSAndreas Gohr}
1617e66d3e6dSAndreas Gohr
1618e66d3e6dSAndreas Gohr/**
16195b75cd1fSAdrian Lang * Display the subscribe form
16205b75cd1fSAdrian Lang *
16215b75cd1fSAdrian Lang * @author Adrian Lang <lang@cosmocode.de>
1622848cb786SSatoshi Sahara * @deprecated 2020-07-23
16235b75cd1fSAdrian Lang */
16245b75cd1fSAdrian Langfunction tpl_subscribe() {
1625*24870174SAndreas Gohr    dbg_deprecated(Subscribe::class .'::show()');
1626*24870174SAndreas Gohr    (new Subscribe)->show();
16275b75cd1fSAdrian Lang}
16285b75cd1fSAdrian Lang
1629d059ba9bSAndreas Gohr/**
1630d059ba9bSAndreas Gohr * Tries to send already created content right to the browser
1631d059ba9bSAndreas Gohr *
1632d059ba9bSAndreas Gohr * Wraps around ob_flush() and flush()
1633d059ba9bSAndreas Gohr *
1634d059ba9bSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
1635d059ba9bSAndreas Gohr */
1636d059ba9bSAndreas Gohrfunction tpl_flush() {
1637c2009796SZemoj    if( ob_get_level() > 0 ) ob_flush();
1638d059ba9bSAndreas Gohr    flush();
1639d059ba9bSAndreas Gohr}
1640d059ba9bSAndreas Gohr
1641afca7e7eSAnika Henke/**
1642378325f9SAndreas Gohr * Tries to find a ressource file in the given locations.
1643afca7e7eSAnika Henke *
1644378325f9SAndreas Gohr * If a given location starts with a colon it is assumed to be a media
1645378325f9SAndreas Gohr * file, otherwise it is assumed to be relative to the current template
1646378325f9SAndreas Gohr *
164742ea7f44SGerrit Uitslag * @param  string[] $search       locations to look at
1648378325f9SAndreas Gohr * @param  bool     $abs          if to use absolute URL
1649ac7a515fSAndreas Gohr * @param  array    &$imginfo     filled with getimagesize()
16506dc405e1SAndreas Gohr * @param  bool     $fallback     use fallback image if target isn't found or return 'false' if potential
16516dc405e1SAndreas Gohr *                                false result is required
1652ac7a515fSAndreas Gohr * @return string
165342ea7f44SGerrit Uitslag *
1654378325f9SAndreas Gohr * @author Andreas  Gohr <andi@splitbrain.org>
1655afca7e7eSAnika Henke */
1656c238d757SSimon DELAGEfunction tpl_getMediaFile($search, $abs = false, &$imginfo = null, $fallback = true) {
1657ac7a515fSAndreas Gohr    $img     = '';
1658ac7a515fSAndreas Gohr    $file    = '';
1659ac7a515fSAndreas Gohr    $ismedia = false;
1660378325f9SAndreas Gohr    // loop through candidates until a match was found:
1661378325f9SAndreas Gohr    foreach($search as $img) {
1662378325f9SAndreas Gohr        if(substr($img, 0, 1) == ':') {
1663378325f9SAndreas Gohr            $file    = mediaFN($img);
1664378325f9SAndreas Gohr            $ismedia = true;
1665378325f9SAndreas Gohr        } else {
1666c4766956SAndreas Gohr            $file    = tpl_incdir().$img;
1667378325f9SAndreas Gohr            $ismedia = false;
16681f13e33dSAnika Henke        }
16690f747863Slupo49
1670378325f9SAndreas Gohr        if(file_exists($file)) break;
1671872a6d29SAnika Henke    }
1672378325f9SAndreas Gohr
167308a13262SSimon DELAGE    // manage non existing target
167408a13262SSimon DELAGE    if (!file_exists($file)) {
167508a13262SSimon DELAGE        // give result for fallback image
1676*24870174SAndreas Gohr        if ($fallback) {
1677c238d757SSimon DELAGE            $file = DOKU_INC . 'lib/images/blank.gif';
167808a13262SSimon DELAGE            // stop process if false result is required (if $fallback is false)
167908a13262SSimon DELAGE        } else {
168008a13262SSimon DELAGE            return false;
168108a13262SSimon DELAGE        }
168208a13262SSimon DELAGE    }
1683ca5b6a64SSimon DELAGE
1684378325f9SAndreas Gohr    // fetch image data if requested
1685378325f9SAndreas Gohr    if(!is_null($imginfo)) {
1686378325f9SAndreas Gohr        $imginfo = getimagesize($file);
1687378325f9SAndreas Gohr    }
1688378325f9SAndreas Gohr
1689378325f9SAndreas Gohr    // build URL
1690378325f9SAndreas Gohr    if($ismedia) {
1691378325f9SAndreas Gohr        $url = ml($img, '', true, '', $abs);
1692378325f9SAndreas Gohr    } else {
1693c4766956SAndreas Gohr        $url = tpl_basedir().$img;
1694378325f9SAndreas Gohr        if($abs) $url = DOKU_URL.substr($url, strlen(DOKU_REL));
1695378325f9SAndreas Gohr    }
1696378325f9SAndreas Gohr
1697378325f9SAndreas Gohr    return $url;
1698a7e5f74cSlupo49}
16991f13e33dSAnika Henke
1700872a6d29SAnika Henke/**
1701e5d4768dSAndreas Gohr * PHP include a file
1702e5d4768dSAndreas Gohr *
1703e5d4768dSAndreas Gohr * either from the conf directory if it exists, otherwise use
1704e5d4768dSAndreas Gohr * file in the template's root directory.
1705e5d4768dSAndreas Gohr *
1706e5d4768dSAndreas Gohr * The function honours config cascade settings and looks for the given
1707e5d4768dSAndreas Gohr * file next to the ´main´ config files, in the order protected, local,
1708e5d4768dSAndreas Gohr * default.
1709e5d4768dSAndreas Gohr *
1710e5d4768dSAndreas Gohr * Note: no escaping or sanity checking is done here. Never pass user input
1711e5d4768dSAndreas Gohr * to this function!
1712e5d4768dSAndreas Gohr *
1713e5d4768dSAndreas Gohr * @author Anika Henke <anika@selfthinker.org>
1714e5d4768dSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
171542ea7f44SGerrit Uitslag *
171642ea7f44SGerrit Uitslag * @param string $file
1717e5d4768dSAndreas Gohr */
1718e5d4768dSAndreas Gohrfunction tpl_includeFile($file) {
1719e5d4768dSAndreas Gohr    global $config_cascade;
1720*24870174SAndreas Gohr    foreach(['protected', 'local', 'default'] as $config_group) {
1721e5d4768dSAndreas Gohr        if(empty($config_cascade['main'][$config_group])) continue;
1722e5d4768dSAndreas Gohr        foreach($config_cascade['main'][$config_group] as $conf_file) {
1723e5d4768dSAndreas Gohr            $dir = dirname($conf_file);
1724e5d4768dSAndreas Gohr            if(file_exists("$dir/$file")) {
1725f3a1225fSAnika Henke                include("$dir/$file");
1726e5d4768dSAndreas Gohr                return;
1727e5d4768dSAndreas Gohr            }
1728e5d4768dSAndreas Gohr        }
1729e5d4768dSAndreas Gohr    }
1730e5d4768dSAndreas Gohr
1731e5d4768dSAndreas Gohr    // still here? try the template dir
1732e5d4768dSAndreas Gohr    $file = tpl_incdir().$file;
1733e5d4768dSAndreas Gohr    if(file_exists($file)) {
1734f3a1225fSAnika Henke        include($file);
1735e5d4768dSAndreas Gohr    }
1736e5d4768dSAndreas Gohr}
1737e5d4768dSAndreas Gohr
1738e5d4768dSAndreas Gohr/**
1739872a6d29SAnika Henke * Returns <link> tag for various icon types (favicon|mobile|generic)
1740872a6d29SAnika Henke *
1741872a6d29SAnika Henke * @author Anika Henke <anika@selfthinker.org>
174242ea7f44SGerrit Uitslag *
1743ac7a515fSAndreas Gohr * @param  array $types - list of icon types to display (favicon|mobile|generic)
1744ac7a515fSAndreas Gohr * @return string
1745872a6d29SAnika Henke */
1746*24870174SAndreas Gohrfunction tpl_favicon($types = ['favicon']) {
1747872a6d29SAnika Henke
1748872a6d29SAnika Henke    $return = '';
1749872a6d29SAnika Henke
1750872a6d29SAnika Henke    foreach($types as $type) {
1751872a6d29SAnika Henke        switch($type) {
1752872a6d29SAnika Henke            case 'favicon':
1753*24870174SAndreas Gohr                $look = [':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'];
1754378325f9SAndreas Gohr                $return .= '<link rel="shortcut icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1755872a6d29SAnika Henke                break;
1756872a6d29SAnika Henke            case 'mobile':
1757*24870174SAndreas Gohr                $look = [':wiki:apple-touch-icon.png', ':apple-touch-icon.png', 'images/apple-touch-icon.png'];
1758378325f9SAndreas Gohr                $return .= '<link rel="apple-touch-icon" href="'.tpl_getMediaFile($look).'" />'.NL;
1759872a6d29SAnika Henke                break;
1760872a6d29SAnika Henke            case 'generic':
1761872a6d29SAnika Henke                // ideal world solution, which doesn't work in any browser yet
1762*24870174SAndreas Gohr                $look = [':wiki:favicon.svg', ':favicon.svg', 'images/favicon.svg'];
1763378325f9SAndreas Gohr                $return .= '<link rel="icon" href="'.tpl_getMediaFile($look).'" type="image/svg+xml" />'.NL;
1764872a6d29SAnika Henke                break;
1765872a6d29SAnika Henke        }
1766872a6d29SAnika Henke    }
1767872a6d29SAnika Henke
1768872a6d29SAnika Henke    return $return;
1769afca7e7eSAnika Henke}
1770afca7e7eSAnika Henke
1771d9162c6cSKate Arzamastseva/**
1772d9162c6cSKate Arzamastseva * Prints full-screen media manager
1773d9162c6cSKate Arzamastseva *
1774d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1775d9162c6cSKate Arzamastseva */
1776d9162c6cSKate Arzamastsevafunction tpl_media() {
1777ac7a515fSAndreas Gohr    global $NS, $IMG, $JUMPTO, $REV, $lang, $fullscreen, $INPUT;
177888a71175SKate Arzamastseva    $fullscreen = true;
177995b451bcSAdrian Lang    require_once DOKU_INC.'lib/exe/mediamanager.php';
1780d9162c6cSKate Arzamastseva
1781ac7a515fSAndreas Gohr    $rev   = '';
1782ac7a515fSAndreas Gohr    $image = cleanID($INPUT->str('image'));
178398f03b57SKate Arzamastseva    if(isset($IMG)) $image = $IMG;
178498f03b57SKate Arzamastseva    if(isset($JUMPTO)) $image = $JUMPTO;
17859c1bd4bcSKate Arzamastseva    if(isset($REV) && !$JUMPTO) $rev = $REV;
178698f03b57SKate Arzamastseva
178794add303SAnika Henke    echo '<div id="mediamanager__page">'.NL;
1788bc314c58SAnika Henke    echo '<h1>'.$lang['btn_media'].'</h1>'.NL;
1789d9162c6cSKate Arzamastseva    html_msgarea();
179094add303SAnika Henke
179194add303SAnika Henke    echo '<div class="panel namespaces">'.NL;
179294add303SAnika Henke    echo '<h2>'.$lang['namespaces'].'</h2>'.NL;
179395b451bcSAdrian Lang    echo '<div class="panelHeader">';
1794ba340a70SAnika Henke    echo $lang['media_namespaces'];
179594add303SAnika Henke    echo '</div>'.NL;
179695b451bcSAdrian Lang
179794add303SAnika Henke    echo '<div class="panelContent" id="media__tree">'.NL;
179895b451bcSAdrian Lang    media_nstree($NS);
179994add303SAnika Henke    echo '</div>'.NL;
180094add303SAnika Henke    echo '</div>'.NL;
1801fa8e5c77SKate Arzamastseva
180294add303SAnika Henke    echo '<div class="panel filelist">'.NL;
1803035e07f1SKate Arzamastseva    tpl_mediaFileList();
180494add303SAnika Henke    echo '</div>'.NL;
1805fa8e5c77SKate Arzamastseva
180694add303SAnika Henke    echo '<div class="panel file">'.NL;
180794add303SAnika Henke    echo '<h2 class="a11y">'.$lang['media_file'].'</h2>'.NL;
1808035e07f1SKate Arzamastseva    tpl_mediaFileDetails($image, $rev);
180994add303SAnika Henke    echo '</div>'.NL;
1810ba340a70SAnika Henke
181194add303SAnika Henke    echo '</div>'.NL;
1812d9162c6cSKate Arzamastseva}
1813afca7e7eSAnika Henke
1814c71db656SAnika Henke/**
1815c71db656SAnika Henke * Return useful layout classes
1816c71db656SAnika Henke *
1817c71db656SAnika Henke * @author Anika Henke <anika@selfthinker.org>
181842ea7f44SGerrit Uitslag *
181942ea7f44SGerrit Uitslag * @return string
1820c71db656SAnika Henke */
1821c71db656SAnika Henkefunction tpl_classes() {
1822c71db656SAnika Henke    global $ACT, $conf, $ID, $INFO;
1823585bf44eSChristopher Smith    /** @var Input $INPUT */
1824585bf44eSChristopher Smith    global $INPUT;
1825585bf44eSChristopher Smith
1826*24870174SAndreas Gohr    $classes = [
1827c71db656SAnika Henke        'dokuwiki',
1828c71db656SAnika Henke        'mode_'.$ACT,
1829c71db656SAnika Henke        'tpl_'.$conf['template'],
1830585bf44eSChristopher Smith        $INPUT->server->bool('REMOTE_USER') ? 'loggedIn' : '',
183190eb1b7bSEduardo Mozart de Oliveira        (isset($INFO['exists']) && $INFO['exists']) ? '' : 'notFound',
1832*24870174SAndreas Gohr        ($ID == $conf['start']) ? 'home' : ''
1833*24870174SAndreas Gohr    ];
1834*24870174SAndreas Gohr    return implode(' ', $classes);
1835c71db656SAnika Henke}
1836c71db656SAnika Henke
183784dd2b1aSGerrit Uitslag/**
183884dd2b1aSGerrit Uitslag * Create event for tools menues
183984dd2b1aSGerrit Uitslag *
184084dd2b1aSGerrit Uitslag * @author Anika Henke <anika@selfthinker.org>
184184dd2b1aSGerrit Uitslag * @param string $toolsname name of menu
184284dd2b1aSGerrit Uitslag * @param array $items
184384dd2b1aSGerrit Uitslag * @param string $view e.g. 'main', 'detail', ...
1844affc7ddfSAndreas Gohr * @deprecated 2017-09-01 see devel:menus
184584dd2b1aSGerrit Uitslag */
184684dd2b1aSGerrit Uitslagfunction tpl_toolsevent($toolsname, $items, $view = 'main') {
1847affc7ddfSAndreas Gohr    dbg_deprecated('see devel:menus');
1848*24870174SAndreas Gohr    $data = ['view' => $view, 'items' => $items];
184984dd2b1aSGerrit Uitslag
185084dd2b1aSGerrit Uitslag    $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY';
1851e1d9dcc8SAndreas Gohr    $evt = new Event($hook, $data);
185284dd2b1aSGerrit Uitslag    if($evt->advise_before()) {
1853*24870174SAndreas Gohr        foreach($evt->data['items'] as $html) echo $html;
185484dd2b1aSGerrit Uitslag    }
185584dd2b1aSGerrit Uitslag    $evt->advise_after();
185684dd2b1aSGerrit Uitslag}
185784dd2b1aSGerrit Uitslag
1858e3776c06SMichael Hamann//Setup VIM: ex: et ts=4 :
1859a00de5b5SAndreas Gohr
1860