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') != '') { 8275adba86SJames Collins if(file_exists($this->tplDir . 'themes/' . $this->getConf('useTheme') . '/style.less')) { 8375adba86SJames Collins $stylesheets[] = $this->baseDir . 'themes/' . $this->getConf('useTheme') . '/style.less'; 84c165b184SJames Collins } 85c165b184SJames Collins } 86c165b184SJames Collins 8775adba86SJames Collins // $stylesheets[] = $this->baseDir . 'css/mikio.less'; 8875adba86SJames 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 { 11975adba86SJames 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 } 15675adba86SJames Collins 15775adba86SJames Collins break; 15875adba86SJames Collins 15975adba86SJames Collins case 'navbarMenuPosition': 16075adba86SJames Collins if($value == 'right') { 16175adba86SJames Collins return 'ml-md-auto'; 16275adba86SJames Collins } 16375adba86SJames Collins 16475adba86SJames Collins return ''; 16575adba86SJames Collins 16675adba86SJames Collins case 'breadcrumbsLoc': 16775adba86SJames Collins if(!$this->getConf('useHeroTitle') && $value == 'hero') { 16875adba86SJames Collins return 'top'; 16975adba86SJames Collins } 17075adba86SJames Collins 17175adba86SJames Collins if($value != 'top' && $value != 'hero' && $value != 'page') { 17275adba86SJames Collins return 'page'; 17375adba86SJames Collins } 17475adba86SJames Collins 17575adba86SJames 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 210*addbeb3bSJames Collins $menu = ''; 211c165b184SJames Collins 212c165b184SJames Collins if($this->getConf('navbarMenuStyle') != 'text') { 213*addbeb3bSJames Collins $menu .= $this->icon($icon); 214c165b184SJames Collins } 215c165b184SJames Collins 216c165b184SJames Collins if($this->getConf('navbarMenuStyle') != 'icon') { 217*addbeb3bSJames Collins $menu .= $lang[$title]; 218c165b184SJames Collins } 219c165b184SJames Collins 220*addbeb3bSJames Collins echo $menu; 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 27875adba86SJames Collins /** 27975adba86SJames Collins * Print out breadcrumbs 28075adba86SJames Collins * 28175adba86SJames Collins * @author James Collins <james.collins@outlook.com.au> 28275adba86SJames Collins * 28375adba86SJames Collins * @param string $location Location of breadcrumbs 28475adba86SJames Collins */ 28575adba86SJames Collins public function includeBreadcrumbs($location) { 28675adba86SJames Collins if($location == $this->getConf('breadcrumbsLoc')) { 28747161538SJames Collins global $conf; 28847161538SJames Collins 28975adba86SJames Collins print '<div class="mikio-breadcrumbs">'; 29075adba86SJames Collins 29147161538SJames Collins if($conf['breadcrumbs']) { 29275adba86SJames Collins tpl_breadcrumbs(); 29347161538SJames Collins } 29447161538SJames Collins 29547161538SJames Collins if($conf['youarehere']) { 29675adba86SJames Collins tpl_youarehere(); 29775adba86SJames Collins } 29875adba86SJames Collins 29975adba86SJames Collins print '</div>'; 30075adba86SJames Collins } 30147161538SJames Collins } 30247161538SJames Collins 30347161538SJames Collins 30475adba86SJames Collins /** 30575adba86SJames Collins * Print out hero 30675adba86SJames Collins * 30775adba86SJames Collins * @author James Collins <james.collins@outlook.com.au> 30875adba86SJames Collins */ 30975adba86SJames Collins public function includeHero() { 31075adba86SJames Collins global $ACT; 31147161538SJames Collins 31275adba86SJames Collins if($ACT === 'show') { 31375adba86SJames Collins if($this->getConf('useHeroTitle')) { 31475adba86SJames Collins print '<div class="mikio-hero d-flex flex-row">'; 31575adba86SJames Collins print '<div class="mikio-hero-text flex-grow-1">'; 31675adba86SJames Collins $this->includeBreadcrumbs('hero'); 31775adba86SJames Collins print '<h1 id="mikio-hero-title">'; 31875adba86SJames Collins tpl_pagetitle(); 31975adba86SJames Collins print '</h1>'; 32075adba86SJames Collins print '<h2 id="mikio-hero-subtext">'; 32175adba86SJames Collins print ''; // TODO Find subtext in page? 32275adba86SJames Collins print '</h2>'; 32375adba86SJames Collins print '</div>'; 32447161538SJames Collins 32575adba86SJames Collins $hero_image = tpl_getMediaFile(array(':hero.png', ':hero.jpg', ':wiki:hero.png', ':wiki:hero.jpg', 'images/hero.png', 'images/hero.jpg'), false); 32675adba86SJames Collins if($hero_image != '') $hero_image = ' style="background-image:url(\''.$hero_image.'\');"'; 32747161538SJames Collins 32875adba86SJames Collins print '<div class="mikio-hero-image"' . $hero_image . '></div>'; 32975adba86SJames Collins print '</div>'; 33047161538SJames Collins } 33175adba86SJames Collins } 33275adba86SJames Collins } 33375adba86SJames Collins 33475adba86SJames Collins 33575adba86SJames Collins /** 33675adba86SJames Collins * Print out TOC 33775adba86SJames Collins * 33875adba86SJames Collins * @author James Collins <james.collins@outlook.com.au> 33975adba86SJames Collins */ 34075adba86SJames Collins public function includeTOC($location) { 34175adba86SJames Collins if($this->getConf('tocfullheight') && $location === 'full') { 34275adba86SJames Collins print '<div class="mikio-toc mikio-toc-full">'; 34375adba86SJames Collins tpl_toc(); 34475adba86SJames Collins print '</div>'; 34575adba86SJames Collins } else if(!$this->getConf('tocfullheight') && $location === 'float') { 34675adba86SJames Collins print '<div class="mikio-toc mikio-toc-float">'; 34775adba86SJames Collins tpl_toc(); 34875adba86SJames Collins print '</div>'; 34975adba86SJames Collins } 35075adba86SJames Collins } 35175adba86SJames 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 */ 36175adba86SJames 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 37075adba86SJames 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();