xref: /template/mikio/mikio.php (revision 75adba8638f50344dacd00baf5c0b784c8835484)
1c165b184SJames Collins<?php
247161538SJames Collins
347161538SJames Collinsnamespace dokuwiki\template\mikio;
447161538SJames Collins
5c165b184SJames Collins/**
6c165b184SJames Collins * DokuWiki Mikio Template
7c165b184SJames Collins *
8c165b184SJames Collins * @link    http://dokuwiki.org/template:mikio
9c165b184SJames Collins * @author  James Collins <james.collins@outlook.com.au>
10c165b184SJames Collins * @license MIT License (https://raw.githubusercontent.com/nomadjimbob/Mikio/master/LICENSE)
11c165b184SJames Collins */
12c165b184SJames Collins
13c165b184SJames Collinsif (!defined('DOKU_INC')) die();
14c165b184SJames Collins
15c165b184SJames Collinsrequire_once('inc/simple_html_dom.php');
16c165b184SJames Collins
1747161538SJames Collinsclass Template {
18c165b184SJames Collins  public $tplDir  = '';
19c165b184SJames Collins  public $baseDir = '';
20c165b184SJames Collins
21c165b184SJames Collins
22c165b184SJames Collins    /**
23c165b184SJames Collins     * Class constructor
24c165b184SJames Collins     *
25c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
26c165b184SJames Collins     */
27c165b184SJames Collins    public function __construct() {
28c165b184SJames Collins      $this->tplDir  = tpl_incdir();
29c165b184SJames Collins      $this->baseDir = tpl_basedir();
30c165b184SJames Collins
31c165b184SJames Collins      $this->_registerHooks();
32c165b184SJames Collins     }
33c165b184SJames Collins
34c165b184SJames Collins
35c165b184SJames Collins    /**
3647161538SJames Collins     * Get the singleton instance
3747161538SJames Collins     *
3847161538SJames Collins     * @return Template
3947161538SJames Collins     */
4047161538SJames Collins    public static function getInstance()
4147161538SJames Collins    {
4247161538SJames Collins
4347161538SJames Collins        static $instance = null;
4447161538SJames Collins
4547161538SJames Collins        if ($instance === null) {
4647161538SJames Collins            $instance = new Template();
4747161538SJames Collins        }
4847161538SJames Collins
4947161538SJames Collins        return $instance;
5047161538SJames Collins
5147161538SJames Collins    }
5247161538SJames Collins
5347161538SJames Collins    /**
54c165b184SJames Collins     * Register themes DokuWiki hooks
55c165b184SJames Collins     *
56c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
57c165b184SJames Collins     */
58c165b184SJames Collins    private function _registerHooks() {
59c165b184SJames Collins        global $EVENT_HANDLER;
60c165b184SJames Collins
61c165b184SJames Collins         $events_dispatcher = array(
62c165b184SJames Collins            'TPL_METAHEADER_OUTPUT'     => 'metaheadersHandler',
63c165b184SJames Collins            'TPL_CONTENT_DISPLAY'       => 'contentHandler',
64c165b184SJames Collins        );
65c165b184SJames Collins
66c165b184SJames Collins        foreach ($events_dispatcher as $event => $method) {
67c165b184SJames Collins            $EVENT_HANDLER->register_hook($event, 'BEFORE', $this, $method);
68c165b184SJames Collins        }
69c165b184SJames Collins    }
70c165b184SJames Collins
71c165b184SJames Collins
72c165b184SJames Collins    /**
73c165b184SJames Collins     * DokuWiki META Header event handler
74c165b184SJames Collins     *
75c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
76c165b184SJames Collins     */
7747161538SJames Collins    public function metaHeadersHandler(\Doku_Event $event) {
78c165b184SJames Collins        $stylesheets    = array();
79c165b184SJames Collins        $scripts        = array();
80c165b184SJames Collins
81c165b184SJames Collins        if($this->getConf('useTheme') != '') {
82*75adba86SJames Collins            if(file_exists($this->tplDir . 'themes/' . $this->getConf('useTheme') . '/style.less')) {
83*75adba86SJames Collins                $stylesheets[] = $this->baseDir . 'themes/' . $this->getConf('useTheme') . '/style.less';
84c165b184SJames Collins            }
85c165b184SJames Collins        }
86c165b184SJames Collins
87*75adba86SJames Collins        // $stylesheets[] = $this->baseDir . 'css/mikio.less';
88*75adba86SJames Collins        // $stylesheets[] = $this->baseDir . 'css/bootstrap.min.css';
89c165b184SJames Collins
90c165b184SJames Collins        if($this->getConf('includeFontAwesome') == true) $stylesheets[] = $this->baseDir . 'assets/fontawesome/css/all.min.css';
91c165b184SJames Collins
92c165b184SJames Collins        $scripts[] = $this->baseDir . 'js/bootstrap.min.js';
93c165b184SJames Collins
94c165b184SJames Collins        foreach ($stylesheets as $style) {
95c165b184SJames Collins            array_unshift($event->data['link'], array(
96c165b184SJames Collins                'type' => 'text/css',
97c165b184SJames Collins                'rel'  => 'stylesheet',
98c165b184SJames Collins                'href' => $style
99c165b184SJames Collins            ));
100c165b184SJames Collins        }
101c165b184SJames Collins
102c165b184SJames Collins        foreach ($scripts as $script) {
103c165b184SJames Collins            $event->data['script'][] = array(
104c165b184SJames Collins                 'type'  => 'text/javascript',
105c165b184SJames Collins              '_data' => '',
106c165b184SJames Collins              'src'   => $script
107c165b184SJames Collins          );
108c165b184SJames Collins      }
109c165b184SJames Collins    }
110c165b184SJames Collins
111c165b184SJames Collins
112c165b184SJames Collins    /**
113c165b184SJames Collins     * DokuWiki content event handler
114c165b184SJames Collins     *
115c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
116c165b184SJames Collins     */
11747161538SJames Collins    public function contentHandler(\Doku_Event $event)
118c165b184SJames Collins    {
119*75adba86SJames Collins        $event->data = $this->parseContent($event->data);
120c165b184SJames Collins    }
121c165b184SJames Collins
122c165b184SJames Collins
123c165b184SJames Collins    /**
124c165b184SJames Collins     * Parse configuration options
125c165b184SJames Collins     *
126c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
127c165b184SJames Collins     *
128c165b184SJames Collins     * @param   string  $key        The configuration key to retreive
129c165b184SJames Collins     * @param   mixed   $default    If key doesn't exist, return this value
130c165b184SJames Collins     * @return  mixed               Parsed value of configuration
131c165b184SJames Collins     */
132c165b184SJames Collins    public function getConf($key, $default = false) {
133c165b184SJames Collins        global $ACT, $conf;
134c165b184SJames Collins
135c165b184SJames Collins        $value = tpl_getConf($key, $default);
136c165b184SJames Collins
137c165b184SJames Collins        switch($key) {
138c165b184SJames Collins
139c165b184SJames Collins            case 'navbar':  // TODO is this needed?
140c165b184SJames Collins                $value = explode(',', $value);
141c165b184SJames Collins                break;
142c165b184SJames Collins
143c165b184SJames Collins            case 'showSidebar':
144c165b184SJames Collins                if ($ACT !== 'show') {
145c165b184SJames Collins                    return false;
146c165b184SJames Collins                }
147c165b184SJames Collins
148c165b184SJames Collins                return page_findnearest($conf['sidebar'], $this->getConf('useACL'));
149c165b184SJames Collins
150c165b184SJames Collins            case 'navbarMenuStyle':
151c165b184SJames Collins                if($value != 'text') {
152c165b184SJames Collins                    if(!$this->getConf('useFontAwesome')) {
153c165b184SJames Collins                        return 'text';
154c165b184SJames Collins                    }
155c165b184SJames Collins                }
156*75adba86SJames Collins
157*75adba86SJames Collins            break;
158*75adba86SJames Collins
159*75adba86SJames Collins            case 'navbarMenuPosition':
160*75adba86SJames Collins                if($value == 'right') {
161*75adba86SJames Collins                    return 'ml-md-auto';
162*75adba86SJames Collins                }
163*75adba86SJames Collins
164*75adba86SJames Collins                return '';
165*75adba86SJames Collins
166*75adba86SJames Collins            case 'breadcrumbsLoc':
167*75adba86SJames Collins                if(!$this->getConf('useHeroTitle') && $value == 'hero') {
168*75adba86SJames Collins                    return 'top';
169*75adba86SJames Collins                }
170*75adba86SJames Collins
171*75adba86SJames Collins                if($value != 'top' && $value != 'hero' && $value != 'page') {
172*75adba86SJames Collins                    return 'page';
173*75adba86SJames Collins                }
174*75adba86SJames Collins
175*75adba86SJames Collins                break;
176c165b184SJames Collins        }
177c165b184SJames Collins
178c165b184SJames Collins        return $value;
179c165b184SJames Collins    }
180c165b184SJames Collins
181c165b184SJames Collins
182c165b184SJames Collins    /**
183c165b184SJames Collins     * Icon
184c165b184SJames Collins     *
185c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
186c165b184SJames Collins     *
187c165b184SJames Collins     * @param   string  $type       The type of icon to return
188c165b184SJames Collins     * @return  string              HTML for icon element
189c165b184SJames Collins     */
190c165b184SJames Collins    public function icon($type) {
191c165b184SJames Collins        if($this->getConf('useFontAwesome')) {
192c165b184SJames Collins            return '<i class="fa fa-' . $type . '" aria-hidden="true"></i>';
193c165b184SJames Collins        }
194c165b184SJames Collins
195c165b184SJames Collins        return '';
196c165b184SJames Collins    }
197c165b184SJames Collins
198c165b184SJames Collins
199c165b184SJames Collins    /**
200c165b184SJames Collins     * Print the Navbar menu title/icon
201c165b184SJames Collins     *
202c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
203c165b184SJames Collins     *
204c165b184SJames Collins     * @param   string  $type       The type of icon to return
205c165b184SJames Collins     * @return  string              HTML for icon element
206c165b184SJames Collins     */
207c165b184SJames Collins    public function navbarMenuTitle($title, $icon) {
208c165b184SJames Collins        global $lang;
209c165b184SJames Collins
210c165b184SJames Collins        $title = '';
211c165b184SJames Collins
212c165b184SJames Collins        if($this->getConf('navbarMenuStyle') != 'text') {
213c165b184SJames Collins            $title .= $this->icon($icon);
214c165b184SJames Collins        }
215c165b184SJames Collins
216c165b184SJames Collins        if($this->getConf('navbarMenuStyle') != 'icon') {
217c165b184SJames Collins            $title .= $lang['user_tools'];
218c165b184SJames Collins        }
219c165b184SJames Collins
220c165b184SJames Collins        echo $title;
221c165b184SJames Collins    }
222c165b184SJames Collins
223c165b184SJames Collins
224c165b184SJames Collins     /**
225c165b184SJames Collins     * Add class to first DOM element
226c165b184SJames Collins     *
227c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
228c165b184SJames Collins     *
229c165b184SJames Collins     * @param   string  $content    HTML DOM
230c165b184SJames Collins     * @param   string  $class      Class to add DOM elements
231c165b184SJames Collins     * @return  string              HTML DOM with class added
232c165b184SJames Collins     */
233c165b184SJames Collins    public function elementAddClass($html, $class) {
234c165b184SJames Collins        preg_match('/class.*?".*?"/', $html, $matches);
235c165b184SJames Collins        if(count($matches) > 0) {
236c165b184SJames Collins            preg_match('/[" ]'.$class.'[" ]/', $matches[0], $matches);
237c165b184SJames Collins            if(count($matches) == 0) {
238c165b184SJames Collins                return preg_replace('/(class.*?=.*?")/', '${1}'.$class.' ', $html, 1);
239c165b184SJames Collins            }
240c165b184SJames Collins        } else {
241c165b184SJames Collins            return preg_replace('/>/', 'class="'.$class.'">', $html, 1);
242c165b184SJames Collins        }
243c165b184SJames Collins
244c165b184SJames Collins        return $html;
245c165b184SJames Collins    }
246c165b184SJames Collins
247c165b184SJames Collins
248c165b184SJames Collins    /**
249c165b184SJames Collins     * Include Sidebar
250c165b184SJames Collins     *
251c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
252c165b184SJames Collins     *
253c165b184SJames Collins     * @param   string  $type       Sidebar type
254c165b184SJames Collins     * @return  boolean             If sidebar was added
255c165b184SJames Collins     */
256c165b184SJames Collins    public function includeSidebar($type) {
257c165b184SJames Collins        global $conf;
258c165b184SJames Collins
259c165b184SJames Collins        switch($type) {
260c165b184SJames Collins            case 'left':
261c165b184SJames Collins                if($this->getConf('showSidebar')) {
262c165b184SJames Collins                    echo '<aside>';
263c165b184SJames Collins                    tpl_includeFile('sidebarheader.html');
264c165b184SJames Collins                    tpl_include_page($conf['sidebar'], 1, 1);
265c165b184SJames Collins                    tpl_includeFile('sidebarfooter.html');
266c165b184SJames Collins                    echo '</aside>';
267c165b184SJames Collins
268c165b184SJames Collins                    return true;
269c165b184SJames Collins                }
270c165b184SJames Collins
271c165b184SJames Collins                return false;
272c165b184SJames Collins        }
273c165b184SJames Collins
274c165b184SJames Collins        return false;
275c165b184SJames Collins    }
276c165b184SJames Collins
277c165b184SJames Collins
278*75adba86SJames Collins    /**
279*75adba86SJames Collins     * Print out breadcrumbs
280*75adba86SJames Collins     *
281*75adba86SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
282*75adba86SJames Collins     *
283*75adba86SJames Collins     * @param   string  $location   Location of breadcrumbs
284*75adba86SJames Collins     */
285*75adba86SJames Collins    public function includeBreadcrumbs($location) {
286*75adba86SJames Collins        if($location == $this->getConf('breadcrumbsLoc')) {
28747161538SJames Collins            global $conf;
28847161538SJames Collins
289*75adba86SJames Collins            print '<div class="mikio-breadcrumbs">';
290*75adba86SJames Collins
29147161538SJames Collins            if($conf['breadcrumbs']) {
292*75adba86SJames Collins                tpl_breadcrumbs();
29347161538SJames Collins            }
29447161538SJames Collins
29547161538SJames Collins            if($conf['youarehere']) {
296*75adba86SJames Collins                tpl_youarehere();
297*75adba86SJames Collins            }
298*75adba86SJames Collins
299*75adba86SJames Collins            print '</div>';
300*75adba86SJames Collins        }
30147161538SJames Collins    }
30247161538SJames Collins
30347161538SJames Collins
304*75adba86SJames Collins    /**
305*75adba86SJames Collins     * Print out hero
306*75adba86SJames Collins     *
307*75adba86SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
308*75adba86SJames Collins     */
309*75adba86SJames Collins    public function includeHero() {
310*75adba86SJames Collins        global $ACT;
31147161538SJames Collins
312*75adba86SJames Collins        if($ACT === 'show') {
313*75adba86SJames Collins            if($this->getConf('useHeroTitle')) {
314*75adba86SJames Collins                print '<div class="mikio-hero d-flex flex-row">';
315*75adba86SJames Collins                    print '<div class="mikio-hero-text flex-grow-1">';
316*75adba86SJames Collins                        $this->includeBreadcrumbs('hero');
317*75adba86SJames Collins                        print '<h1 id="mikio-hero-title">';
318*75adba86SJames Collins                            tpl_pagetitle();
319*75adba86SJames Collins                        print '</h1>';
320*75adba86SJames Collins                        print '<h2 id="mikio-hero-subtext">';
321*75adba86SJames Collins                            print '';   // TODO Find subtext in page?
322*75adba86SJames Collins                        print '</h2>';
323*75adba86SJames Collins                    print '</div>';
32447161538SJames Collins
325*75adba86SJames Collins                    $hero_image = tpl_getMediaFile(array(':hero.png', ':hero.jpg', ':wiki:hero.png', ':wiki:hero.jpg', 'images/hero.png', 'images/hero.jpg'), false);
326*75adba86SJames Collins                    if($hero_image != '') $hero_image = ' style="background-image:url(\''.$hero_image.'\');"';
32747161538SJames Collins
328*75adba86SJames Collins                    print '<div class="mikio-hero-image"' . $hero_image . '></div>';
329*75adba86SJames Collins                print '</div>';
33047161538SJames Collins            }
331*75adba86SJames Collins        }
332*75adba86SJames Collins    }
333*75adba86SJames Collins
334*75adba86SJames Collins
335*75adba86SJames Collins    /**
336*75adba86SJames Collins     * Print out TOC
337*75adba86SJames Collins     *
338*75adba86SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
339*75adba86SJames Collins     */
340*75adba86SJames Collins    public function includeTOC($location) {
341*75adba86SJames Collins        if($this->getConf('tocfullheight') && $location === 'full') {
342*75adba86SJames Collins            print '<div class="mikio-toc mikio-toc-full">';
343*75adba86SJames Collins            tpl_toc();
344*75adba86SJames Collins            print '</div>';
345*75adba86SJames Collins        } else if(!$this->getConf('tocfullheight') && $location === 'float') {
346*75adba86SJames Collins            print '<div class="mikio-toc mikio-toc-float">';
347*75adba86SJames Collins            tpl_toc();
348*75adba86SJames Collins            print '</div>';
349*75adba86SJames Collins        }
350*75adba86SJames Collins    }
351*75adba86SJames Collins
35247161538SJames Collins
353c165b184SJames Collins    /**
354c165b184SJames Collins     * Parse HTML for bootstrap
355c165b184SJames Collins     *
356c165b184SJames Collins     * @author  James Collins <james.collins@outlook.com.au>
357c165b184SJames Collins     *
358c165b184SJames Collins     * @param   string  $content    HTML content to parse
359c165b184SJames Collins     * @return  string              Parsed HTML for bootstrap
360c165b184SJames Collins     */
361*75adba86SJames Collins    public function parseContent($content) {
36247161538SJames Collins        $html = new \simple_html_dom;
363c165b184SJames Collins        $html->load($content, true, false);
364c165b184SJames Collins
365c165b184SJames Collins        # Return original content if Simple HTML DOM fail or exceeded page size (default MAX_FILE_SIZE => 600KB)
366c165b184SJames Collins        if (!$html) {
367c165b184SJames Collins            return $content;
368c165b184SJames Collins        }
369c165b184SJames Collins
370*75adba86SJames Collins
37147161538SJames Collins        # Hide page title if hero is enabled
37247161538SJames Collins        if($this->getConf('useHeroTitle')) {
37347161538SJames Collins            $pageTitle = tpl_pagetitle(null, true);
37447161538SJames Collins
37547161538SJames Collins            foreach($html->find('h1,h2,h3,h4') as $elm) {
37647161538SJames Collins                if($elm->innertext == $pageTitle) {
37747161538SJames Collins                    $elm->innertext = '';
37847161538SJames Collins                    break;
37947161538SJames Collins                }
38047161538SJames Collins            }
38147161538SJames Collins        }
382c165b184SJames Collins
383c165b184SJames Collins        # Buttons
384c165b184SJames Collins        foreach ($html->find('.button') as $elm) {
385c165b184SJames Collins            if ($elm->tag == 'form') {
386c165b184SJames Collins                continue;
387c165b184SJames Collins            }
388c165b184SJames Collins            $elm->class .= ' btn';
389c165b184SJames Collins        }
390c165b184SJames Collins
391c165b184SJames Collins        foreach ($html->find('[type=button], [type=submit], [type=reset]') as $elm) {
392c165b184SJames Collins            $elm->class .= ' btn btn-outline-secondary';
393c165b184SJames Collins        }
394c165b184SJames Collins
395c165b184SJames Collins        # Section Edit Button
396c165b184SJames Collins        foreach ($html->find('.btn_secedit [type=submit]') as $elm) {
397c165b184SJames Collins            $elm->class .= ' btn-sm';
398c165b184SJames Collins        }
399c165b184SJames Collins
400c165b184SJames Collins        # Section Edit icons
401c165b184SJames Collins        foreach ($html->find('.secedit.editbutton_section button') as $elm) {
402c165b184SJames Collins            $elm->innertext = '<i class="fa fa-edit" aria-hidden="true"></i> ' . $elm->innertext;
403c165b184SJames Collins        }
404c165b184SJames Collins
405c165b184SJames Collins        $content = $html->save();
406c165b184SJames Collins
407c165b184SJames Collins        $html->clear();
408c165b184SJames Collins        unset($html);
409c165b184SJames Collins
410c165b184SJames Collins        return $content;
411c165b184SJames Collins    }
412c165b184SJames Collins}
41347161538SJames Collins
41447161538SJames Collinsglobal $TEMPLATE;
41547161538SJames Collins
41647161538SJames Collins$TEMPLATE = \dokuwiki\template\mikio\Template::getInstance();