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