xref: /template/sprintdoc/Template.php (revision 9510c08045a0ee042769c1203a7389a980833d07)
12387fd46SAndreas Gohr<?php
22387fd46SAndreas Gohr
32387fd46SAndreas Gohrnamespace dokuwiki\template\sprintdoc;
42387fd46SAndreas Gohr
52387fd46SAndreas Gohr/**
62387fd46SAndreas Gohr * Class Template
72387fd46SAndreas Gohr *
82387fd46SAndreas Gohr * provides additional logic for the sprintdoc template
92387fd46SAndreas Gohr *
102387fd46SAndreas Gohr * @package dokuwiki\template\sprintdoc
112387fd46SAndreas Gohr */
122387fd46SAndreas Gohrclass Template {
132387fd46SAndreas Gohr
14c1e0eaa8SAndreas Gohr    /** @var array loaded plugins */
152387fd46SAndreas Gohr    protected $plugins = array(
162387fd46SAndreas Gohr        'sqlite' => null,
172387fd46SAndreas Gohr        'tagging' => null,
181f3641a8SMichael Große        'magicmatcher' => null,
19c1e0eaa8SAndreas Gohr        'tplinc' => null,
20c1e0eaa8SAndreas Gohr        'sitemapnavi' => null,
212387fd46SAndreas Gohr    );
222387fd46SAndreas Gohr
23c1e0eaa8SAndreas Gohr    /** @var string the type of special navigation to use */
24c1e0eaa8SAndreas Gohr    protected $nav = '';
25c1e0eaa8SAndreas Gohr
26c1e0eaa8SAndreas Gohr
272387fd46SAndreas Gohr    /**
282387fd46SAndreas Gohr     * Get the singleton instance
292387fd46SAndreas Gohr     *
302387fd46SAndreas Gohr     * @return Template
312387fd46SAndreas Gohr     */
322387fd46SAndreas Gohr    public static function getInstance() {
332387fd46SAndreas Gohr        static $instance = null;
342387fd46SAndreas Gohr        if($instance === null) $instance = new Template();
352387fd46SAndreas Gohr        return $instance;
362387fd46SAndreas Gohr    }
372387fd46SAndreas Gohr
382387fd46SAndreas Gohr    /**
392387fd46SAndreas Gohr     * Template constructor.
402387fd46SAndreas Gohr     */
412387fd46SAndreas Gohr    protected function __construct() {
422387fd46SAndreas Gohr        $this->initializePlugins();
43c1e0eaa8SAndreas Gohr        $this->initNavigationCookie();
44cad2e674SAndreas Gohr
45cad2e674SAndreas Gohr        /** @var \Doku_Event_Handler */
46cad2e674SAndreas Gohr        global $EVENT_HANDLER;
47cad2e674SAndreas Gohr        $EVENT_HANDLER->register_hook('PLUGIN_TPLINC_LOCATIONS_SET', 'BEFORE', $this, 'registerIncludes');
48cad2e674SAndreas Gohr    }
49cad2e674SAndreas Gohr
50cad2e674SAndreas Gohr    /**
51c1e0eaa8SAndreas Gohr     * Load all the plugins we support directly
52c1e0eaa8SAndreas Gohr     */
53c1e0eaa8SAndreas Gohr    protected function initializePlugins() {
54c1e0eaa8SAndreas Gohr        $this->plugins['sqlite'] = plugin_load('helper', 'sqlite');
55c1e0eaa8SAndreas Gohr        if($this->plugins['sqlite']) {
56c1e0eaa8SAndreas Gohr            $this->plugins['tagging'] = plugin_load('helper', 'tagging');
57c1e0eaa8SAndreas Gohr            $this->plugins['magicmatcher'] = plugin_load('syntax', 'magicmatcher_issuelist');
58c1e0eaa8SAndreas Gohr        }
59c1e0eaa8SAndreas Gohr        $this->plugins['tplinc'] = plugin_load('helper', 'tplinc');
60c1e0eaa8SAndreas Gohr        $this->plugins['sitemapnavi'] = plugin_load('helper', 'sitemapnavi');
61c1e0eaa8SAndreas Gohr    }
62c1e0eaa8SAndreas Gohr
63c1e0eaa8SAndreas Gohr    /**
64cad2e674SAndreas Gohr     * Makes include position info available to the tplinc plugin
65cad2e674SAndreas Gohr     *
66cad2e674SAndreas Gohr     * @param \Doku_Event $event
67cad2e674SAndreas Gohr     */
68cad2e674SAndreas Gohr    public function registerIncludes(\Doku_Event $event) {
69cad2e674SAndreas Gohr        $event->data['footer'] = 'Footer below the page content';
70485e7ff4SMichael Große        $event->data['sidebarfooter'] = 'Footer below the sidebar';
71485e7ff4SMichael Große        $event->data['sidebarheader'] = 'Header above the sidebar';
72*9510c080SAndreas Gohr        $event->data['navtop'] = 'Additional navigation items at the top';
73*9510c080SAndreas Gohr        $event->data['navbottom'] = 'Additional navigation items at the bottom';
74cad2e674SAndreas Gohr    }
75cad2e674SAndreas Gohr
76cad2e674SAndreas Gohr    /**
77cad2e674SAndreas Gohr     * Get the content to include from the tplinc plugin
78cad2e674SAndreas Gohr     *
79cad2e674SAndreas Gohr     * prefix and postfix are only added when there actually is any content
80cad2e674SAndreas Gohr     *
81cad2e674SAndreas Gohr     * @param string $location
82cad2e674SAndreas Gohr     * @param string $pre prepend this before the content
83cad2e674SAndreas Gohr     * @param string $post append this to the content
84cad2e674SAndreas Gohr     * @return string
85cad2e674SAndreas Gohr     */
86cad2e674SAndreas Gohr    public function getInclude($location, $pre = '', $post = '') {
87cad2e674SAndreas Gohr        if(!$this->plugins['tplinc']) return '';
88cad2e674SAndreas Gohr        $content = $this->plugins['tplinc']->renderIncludes($location);
89cad2e674SAndreas Gohr        if($content === '') return '';
90cad2e674SAndreas Gohr        return $pre . $content . $post;
912387fd46SAndreas Gohr    }
922387fd46SAndreas Gohr
932387fd46SAndreas Gohr    /**
94c1e0eaa8SAndreas Gohr     * Sets a cookie to remember the requested special navigation
952387fd46SAndreas Gohr     */
96c1e0eaa8SAndreas Gohr    protected function initNavigationCookie() {
97c1e0eaa8SAndreas Gohr        if ($this->plugins['sitemapnavi'] === null) return;
98c1e0eaa8SAndreas Gohr        global $INPUT;
99c1e0eaa8SAndreas Gohr
100c1e0eaa8SAndreas Gohr        $nav = $INPUT->str('nav');
101c1e0eaa8SAndreas Gohr        if($nav) {
102c1e0eaa8SAndreas Gohr            set_doku_pref('nav', $nav);
103c1e0eaa8SAndreas Gohr            $this->nav = $INPUT->str('nav');
104c1e0eaa8SAndreas Gohr        } else {
105c1e0eaa8SAndreas Gohr            $this->nav = get_doku_pref('nav', 'sidebar');
1062387fd46SAndreas Gohr        }
107c1e0eaa8SAndreas Gohr    }
108c1e0eaa8SAndreas Gohr
109c1e0eaa8SAndreas Gohr    /**
110c1e0eaa8SAndreas Gohr     * Return the navigation for the sidebar
111c1e0eaa8SAndreas Gohr     *
112c1e0eaa8SAndreas Gohr     * Defaults to the standard sidebar mechanism, but supports also the sitemapnavi plugin
113c1e0eaa8SAndreas Gohr     *
114c1e0eaa8SAndreas Gohr     * @return string
115c1e0eaa8SAndreas Gohr     */
116c1e0eaa8SAndreas Gohr    public function getNavigation() {
117c1e0eaa8SAndreas Gohr        global $ID;
118c1e0eaa8SAndreas Gohr        global $conf;
119c1e0eaa8SAndreas Gohr
120e78ffc6cSAnna Dabrowska        // id of the current sidebar, each sidebar must have its own state
12175a0a8e4SAnna Dabrowska        $header = sprintf('<div id="sidebarId" class="%s"></div>', md5(page_findnearest($conf['sidebar'])));
122c1e0eaa8SAndreas Gohr        // add tabs if multiple navigation types available
123c1e0eaa8SAndreas Gohr        if ($this->plugins['sitemapnavi'] !== null) {
124e78ffc6cSAnna Dabrowska            $header .= '<ul class="sidebar-tabs">';
125c1e0eaa8SAndreas Gohr            $header .= '<li class="' . ($this->nav === 'sidebar' ? 'active' : '') . '">' .
126c1e0eaa8SAndreas Gohr                '<a href="' . wl($ID, ['nav' => 'sidebar']) . '">'.tpl_getLang('nav_sidebar').'</a></li>';
127c1e0eaa8SAndreas Gohr            $header .= '<li class="' . ($this->nav === 'sitemap' ? 'active' : '') . '">' .
128c1e0eaa8SAndreas Gohr                '<a href="' . wl($ID, ['nav' => 'sitemap']) . '">'.tpl_getLang('nav_sitemap').'</a></li>';
129c1e0eaa8SAndreas Gohr            $header .= '</ul>';
130c1e0eaa8SAndreas Gohr        }
131c1e0eaa8SAndreas Gohr
132c1e0eaa8SAndreas Gohr        // decide what to show
133046583e2SAndreas Gohr        if ($this->nav === 'sitemap') {
134c1e0eaa8SAndreas Gohr            // site tree created by sitemapnavi plugin
135c1e0eaa8SAndreas Gohr            $nav = '<nav class="nav-sitemapnavi" id="plugin__sitemapnavi">';
136c1e0eaa8SAndreas Gohr            $nav .= $this->plugins['sitemapnavi']->getSiteMap(':');
137c1e0eaa8SAndreas Gohr            $nav .= '</nav>';
138c1e0eaa8SAndreas Gohr        } else {
139c1e0eaa8SAndreas Gohr            // main navigation, loaded from standard sidebar, fixed up by javascript
140c1e0eaa8SAndreas Gohr            $nav = '<nav class="nav-main">';
1414ac10cf3SAndreas Gohr            // immeadiately hide the navigation (if javascript available)
1424ac10cf3SAndreas Gohr            // it will be restyled and made visible again by our script later
1434ac10cf3SAndreas Gohr            $nav .= '<script type="application/javascript">
1444ac10cf3SAndreas Gohr                        document.getElementsByClassName("nav-main")[0].style.visibility = "hidden";
1454ac10cf3SAndreas Gohr                     </script>';
146*9510c080SAndreas Gohr
147*9510c080SAndreas Gohr            $nav .= $this->getInclude('navtop');
148c1e0eaa8SAndreas Gohr            $nav .= tpl_include_page($conf['sidebar'], false, true);
149*9510c080SAndreas Gohr            $nav .= $this->getInclude('navbottom');
150c1e0eaa8SAndreas Gohr            $nav .= '</nav>';
151c1e0eaa8SAndreas Gohr        }
152c1e0eaa8SAndreas Gohr
153c1e0eaa8SAndreas Gohr        return $header . $nav;
1542387fd46SAndreas Gohr    }
1552387fd46SAndreas Gohr
1562387fd46SAndreas Gohr    /**
1573e1e2a1fSAndreas Gohr     * Default class defining is the sidebar should collapse
1583e1e2a1fSAndreas Gohr     *
1593e1e2a1fSAndreas Gohr     * @return string
1603e1e2a1fSAndreas Gohr     */
1613e1e2a1fSAndreas Gohr    public function fullWidthClass() {
1623e1e2a1fSAndreas Gohr        global $ACT;
1633e1e2a1fSAndreas Gohr        // no auto collapsing? empty class
1643e1e2a1fSAndreas Gohr        if (!tpl_getConf('autocollapse')) return '';
1653e1e2a1fSAndreas Gohr        // mode show? empty class
1663e1e2a1fSAndreas Gohr        if ($ACT === "show") return '';
1673e1e2a1fSAndreas Gohr        // anything else? wide content
1683e1e2a1fSAndreas Gohr        return 'wide-content ';
1693e1e2a1fSAndreas Gohr    }
1703e1e2a1fSAndreas Gohr
1713e1e2a1fSAndreas Gohr    /**
1722387fd46SAndreas Gohr     * Get all the tabs to display
1732387fd46SAndreas Gohr     *
1742387fd46SAndreas Gohr     * @return array
1752387fd46SAndreas Gohr     */
1762387fd46SAndreas Gohr    public function getMetaBoxTabs() {
17767d7dea5SMichael Große        global $lang, $INFO;
1782387fd46SAndreas Gohr        $tabs = array();
1792387fd46SAndreas Gohr
1802387fd46SAndreas Gohr        $toc = tpl_toc(true);
1812387fd46SAndreas Gohr        if($toc) {
1822387fd46SAndreas Gohr            $tabs[] = array(
1832387fd46SAndreas Gohr                'id' => 'spr__tab-toc',
1842387fd46SAndreas Gohr                'label' => $lang['toc'],
1852387fd46SAndreas Gohr                'tab' => $toc,
1862387fd46SAndreas Gohr                'count' => null,
1872387fd46SAndreas Gohr            );
1882387fd46SAndreas Gohr        }
1892387fd46SAndreas Gohr
1902387fd46SAndreas Gohr        if($this->plugins['tagging']) {
1912387fd46SAndreas Gohr            $tabs[] = array(
1922387fd46SAndreas Gohr                'id' => 'spr__tab-tags',
1932387fd46SAndreas Gohr                'label' => tpl_getLang('tab_tags'),
1942387fd46SAndreas Gohr                'tab' => $this->plugins['tagging']->tpl_tags(false),
19567d7dea5SMichael Große                'count' => count($this->plugins['tagging']->findItems(array('pid' => $INFO['id']), 'tag')),
1962387fd46SAndreas Gohr            );
1972387fd46SAndreas Gohr        }
1982387fd46SAndreas Gohr
1991f3641a8SMichael Große        if ($this->plugins['magicmatcher']) {
2001f3641a8SMichael Große            $tabs[] = array(
2011f3641a8SMichael Große                'id' => 'spr__tab-issues',
2029cae5e77SMichael Große                'label' => tpl_getLang('tab_issues'),
2031f3641a8SMichael Große                'tab' => $this->plugins['magicmatcher']->getIssueListHTML(),
2041f3641a8SMichael Große                'count' =>  $this->plugins['magicmatcher']->getCountIssues(),
2051f3641a8SMichael Große            );
2061f3641a8SMichael Große        }
2072387fd46SAndreas Gohr
2082387fd46SAndreas Gohr        return $tabs;
2092387fd46SAndreas Gohr    }
21006cdf148SAndreas Gohr
21106cdf148SAndreas Gohr    /**
21206cdf148SAndreas Gohr     * Creates an image tag and includes the first found image correctly resized
21306cdf148SAndreas Gohr     *
21406cdf148SAndreas Gohr     * @param string $tag
21506cdf148SAndreas Gohr     * @param array $attributes
21606cdf148SAndreas Gohr     * @param int $w
21706cdf148SAndreas Gohr     * @param int $h
21819958800SAndreas Gohr     * @param bool $crop
21906cdf148SAndreas Gohr     * @return string
22006cdf148SAndreas Gohr     */
22119958800SAndreas Gohr    public static function getResizedImgTag($tag, $attributes, $w, $h, $crop = true) {
22206cdf148SAndreas Gohr        $attr = '';
22306cdf148SAndreas Gohr        $medias = array();
22406cdf148SAndreas Gohr
22506cdf148SAndreas Gohr        // the attribute having an array defines where the image goes
22606cdf148SAndreas Gohr        foreach($attributes as $attribute => $data) {
22706cdf148SAndreas Gohr            if(is_array($data)) {
22806cdf148SAndreas Gohr                $medias = $data;
22906cdf148SAndreas Gohr                $attr = $attribute;
23006cdf148SAndreas Gohr            }
23106cdf148SAndreas Gohr        }
23206cdf148SAndreas Gohr        // if the image attribute could not be found return
23306cdf148SAndreas Gohr        if(!$attr || !$medias) return '';
23406cdf148SAndreas Gohr
23506cdf148SAndreas Gohr        // try all medias until an existing one is found
23606cdf148SAndreas Gohr        $media = '';
23706cdf148SAndreas Gohr        foreach($medias as $media) {
23806cdf148SAndreas Gohr            if(file_exists(mediaFN($media))) break;
23906cdf148SAndreas Gohr            $media = '';
24006cdf148SAndreas Gohr        }
24106cdf148SAndreas Gohr        if($media === '') return '';
24206cdf148SAndreas Gohr
24306cdf148SAndreas Gohr        // replace the array
24419958800SAndreas Gohr        $media = ml($media, array('w' => $w, 'h' => $h, 'crop' => (int) $crop), true, '&');
24506cdf148SAndreas Gohr        $attributes[$attr] = $media;
24606cdf148SAndreas Gohr
24706cdf148SAndreas Gohr        // return the full tag
2489dbc42beSAndreas Gohr        return '<' . $tag . ' ' . buildAttributes($attributes) . ' />' . "\n";
24906cdf148SAndreas Gohr    }
2503a6eaa0bSAndreas Gohr
2513a6eaa0bSAndreas Gohr    /**
2523a6eaa0bSAndreas Gohr     * Embed the main logo
2533a6eaa0bSAndreas Gohr     *
2543a6eaa0bSAndreas Gohr     * Tries a few different locations
2553a6eaa0bSAndreas Gohr     */
2563a6eaa0bSAndreas Gohr    public function mainLogo() {
2573a6eaa0bSAndreas Gohr        global $conf;
2583a6eaa0bSAndreas Gohr
259e17d84d6SAndreas Gohr        // homepage logo should not link to itself (BITV accessibility requirement)
260e17d84d6SAndreas Gohr        $linkit = (strcmp(wl(), $_SERVER['REQUEST_URI']) !== 0);
261e17d84d6SAndreas Gohr        if($linkit) {
262e17d84d6SAndreas Gohr            $title = $conf['title'] . tpl_getLang('adjunct_linked_logo_text');
263e17d84d6SAndreas Gohr        } else {
264e17d84d6SAndreas Gohr            $title = tpl_getLang('adjunct_start_logo_text') . $conf['title'];
265e17d84d6SAndreas Gohr        }
266e17d84d6SAndreas Gohr
2673a6eaa0bSAndreas Gohr        $desktop = self::getResizedImgTag(
2683a6eaa0bSAndreas Gohr            'img',
2693a6eaa0bSAndreas Gohr            array(
2703a6eaa0bSAndreas Gohr                'class' => 'mobile-hide',
271f9746258SAndreas Gohr                'src' => array('wiki:logo-wide.svg', 'wiki:logo.svg', 'wiki:logo-wide.png', 'wiki:logo.png'),
272e17d84d6SAndreas Gohr                'alt' => $title,
2733a6eaa0bSAndreas Gohr            ),
27499cb0c43SAndreas Gohr            0, 250, false
2753a6eaa0bSAndreas Gohr        );
2763a6eaa0bSAndreas Gohr        $mobile = self::getResizedImgTag(
2773a6eaa0bSAndreas Gohr            'img',
2783a6eaa0bSAndreas Gohr            array(
2793a6eaa0bSAndreas Gohr                'class' => 'mobile-only',
280f9746258SAndreas Gohr                'src' => array(
281f9746258SAndreas Gohr                    'wiki:logo-32x32.svg', 'wiki:favicon.svg', 'wiki:logo-square.svg', 'wiki:logo.svg',
282f9746258SAndreas Gohr                    'wiki:logo-32x32.png', 'wiki:favicon.png', 'wiki:logo-square.png', 'wiki:logo.png'
283f9746258SAndreas Gohr                ),
284e17d84d6SAndreas Gohr                'alt' => $title,
2853a6eaa0bSAndreas Gohr            ),
2863a6eaa0bSAndreas Gohr            32, 32
2873a6eaa0bSAndreas Gohr        );
2883a6eaa0bSAndreas Gohr
2893a6eaa0bSAndreas Gohr        // homepage logo should not link to itself (BITV accessibility requirement)
290e17d84d6SAndreas Gohr        if($linkit) {
2913a6eaa0bSAndreas Gohr            tpl_link(wl(), $desktop, 'accesskey="h" title="[H]"');
2923a6eaa0bSAndreas Gohr            tpl_link(wl(), $mobile, 'accesskey="h" title="[H]"');
293e17d84d6SAndreas Gohr        } else {
294e17d84d6SAndreas Gohr            echo $desktop;
295e17d84d6SAndreas Gohr            echo $mobile;
2963a6eaa0bSAndreas Gohr        }
2973a6eaa0bSAndreas Gohr    }
29884f94641SAndreas Gohr
29984f94641SAndreas Gohr    /**
30084f94641SAndreas Gohr     * Add the current mode information to the hierarchical breadcrumbs
30184f94641SAndreas Gohr     */
30284f94641SAndreas Gohr    public function breadcrumbSuffix() {
30384f94641SAndreas Gohr        global $ACT;
30484f94641SAndreas Gohr        global $lang;
30584f94641SAndreas Gohr        global $INPUT;
30684f94641SAndreas Gohr        global $ID;
30784f94641SAndreas Gohr        global $conf;
30884f94641SAndreas Gohr        global $IMG;
30984f94641SAndreas Gohr        if($ACT == 'show') return;
31084f94641SAndreas Gohr
31184f94641SAndreas Gohr        // find an apropriate label for the current mode
31284f94641SAndreas Gohr        if($ACT) {
31384f94641SAndreas Gohr            $label = tpl_getLang('mode_' . $ACT);
31484f94641SAndreas Gohr            if(!$label) {
31584f94641SAndreas Gohr                if(isset($lang['btn_' . $ACT])) {
31684f94641SAndreas Gohr                    $label = $lang['btn_' . $ACT];
31784f94641SAndreas Gohr                } else {
31884f94641SAndreas Gohr                    $label = $ACT;
31984f94641SAndreas Gohr                }
32084f94641SAndreas Gohr            }
32184f94641SAndreas Gohr        } else {
32284f94641SAndreas Gohr            // actually we would need to create a proper namespace breadcrumb path here,
32384f94641SAndreas Gohr            // but this is the most simplest thing we can do for now
32484f94641SAndreas Gohr            if(defined('DOKU_MEDIADETAIL')) {
32584f94641SAndreas Gohr                $label = hsc(noNS($IMG));
32684f94641SAndreas Gohr            } else {
32784f94641SAndreas Gohr                return;
32884f94641SAndreas Gohr            }
32984f94641SAndreas Gohr        }
33084f94641SAndreas Gohr
33184f94641SAndreas Gohr        if($ACT == 'admin' && $INPUT->has('page')) {
33284f94641SAndreas Gohr            $link = wl($ID, array('do' => 'admin'));
33384f94641SAndreas Gohr            echo '<bdi> : <a href="' . $link . '"><strong>' . $label . '</strong></a></bdi>';
33484f94641SAndreas Gohr
33584f94641SAndreas Gohr            /** @var \DokuWiki_Admin_Plugin $plugin */
33684f94641SAndreas Gohr            $plugin = plugin_load('admin', $INPUT->str('page'));
33784f94641SAndreas Gohr            if(!$plugin) return;
33884f94641SAndreas Gohr
33984f94641SAndreas Gohr            $label = $plugin->getMenuText($conf['lang']);
34084f94641SAndreas Gohr        }
34184f94641SAndreas Gohr
34284f94641SAndreas Gohr        echo '<bdi><span class="curid"> : <strong>' . $label . '</strong></span></bdi>';
34384f94641SAndreas Gohr    }
3442387fd46SAndreas Gohr}
345