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'; 72cad2e674SAndreas Gohr } 73cad2e674SAndreas Gohr 74cad2e674SAndreas Gohr /** 75cad2e674SAndreas Gohr * Get the content to include from the tplinc plugin 76cad2e674SAndreas Gohr * 77cad2e674SAndreas Gohr * prefix and postfix are only added when there actually is any content 78cad2e674SAndreas Gohr * 79cad2e674SAndreas Gohr * @param string $location 80cad2e674SAndreas Gohr * @param string $pre prepend this before the content 81cad2e674SAndreas Gohr * @param string $post append this to the content 82cad2e674SAndreas Gohr * @return string 83cad2e674SAndreas Gohr */ 84cad2e674SAndreas Gohr public function getInclude($location, $pre = '', $post = '') { 85cad2e674SAndreas Gohr if(!$this->plugins['tplinc']) return ''; 86cad2e674SAndreas Gohr $content = $this->plugins['tplinc']->renderIncludes($location); 87cad2e674SAndreas Gohr if($content === '') return ''; 88cad2e674SAndreas Gohr return $pre . $content . $post; 892387fd46SAndreas Gohr } 902387fd46SAndreas Gohr 912387fd46SAndreas Gohr /** 92c1e0eaa8SAndreas Gohr * Sets a cookie to remember the requested special navigation 932387fd46SAndreas Gohr */ 94c1e0eaa8SAndreas Gohr protected function initNavigationCookie() { 95c1e0eaa8SAndreas Gohr if ($this->plugins['sitemapnavi'] === null) return; 96c1e0eaa8SAndreas Gohr global $INPUT; 97c1e0eaa8SAndreas Gohr 98c1e0eaa8SAndreas Gohr $nav = $INPUT->str('nav'); 99c1e0eaa8SAndreas Gohr if($nav) { 100c1e0eaa8SAndreas Gohr set_doku_pref('nav', $nav); 101c1e0eaa8SAndreas Gohr $this->nav = $INPUT->str('nav'); 102c1e0eaa8SAndreas Gohr } else { 103c1e0eaa8SAndreas Gohr $this->nav = get_doku_pref('nav', 'sidebar'); 1042387fd46SAndreas Gohr } 105c1e0eaa8SAndreas Gohr } 106c1e0eaa8SAndreas Gohr 107c1e0eaa8SAndreas Gohr /** 108c1e0eaa8SAndreas Gohr * Return the navigation for the sidebar 109c1e0eaa8SAndreas Gohr * 110c1e0eaa8SAndreas Gohr * Defaults to the standard sidebar mechanism, but supports also the sitemapnavi plugin 111c1e0eaa8SAndreas Gohr * 112c1e0eaa8SAndreas Gohr * @return string 113c1e0eaa8SAndreas Gohr */ 114c1e0eaa8SAndreas Gohr public function getNavigation() { 115c1e0eaa8SAndreas Gohr global $ID; 116c1e0eaa8SAndreas Gohr global $conf; 117c1e0eaa8SAndreas Gohr 118e78ffc6cSAnna Dabrowska // id of the current sidebar, each sidebar must have its own state 11975a0a8e4SAnna Dabrowska $header = sprintf('<div id="sidebarId" class="%s"></div>', md5(page_findnearest($conf['sidebar']))); 120c1e0eaa8SAndreas Gohr // add tabs if multiple navigation types available 121c1e0eaa8SAndreas Gohr if ($this->plugins['sitemapnavi'] !== null) { 122e78ffc6cSAnna Dabrowska $header .= '<ul class="sidebar-tabs">'; 123c1e0eaa8SAndreas Gohr $header .= '<li class="' . ($this->nav === 'sidebar' ? 'active' : '') . '">' . 124c1e0eaa8SAndreas Gohr '<a href="' . wl($ID, ['nav' => 'sidebar']) . '">'.tpl_getLang('nav_sidebar').'</a></li>'; 125c1e0eaa8SAndreas Gohr $header .= '<li class="' . ($this->nav === 'sitemap' ? 'active' : '') . '">' . 126c1e0eaa8SAndreas Gohr '<a href="' . wl($ID, ['nav' => 'sitemap']) . '">'.tpl_getLang('nav_sitemap').'</a></li>'; 127c1e0eaa8SAndreas Gohr $header .= '</ul>'; 128c1e0eaa8SAndreas Gohr } 129c1e0eaa8SAndreas Gohr 130c1e0eaa8SAndreas Gohr // decide what to show 131046583e2SAndreas Gohr if ($this->nav === 'sitemap') { 132c1e0eaa8SAndreas Gohr // site tree created by sitemapnavi plugin 133c1e0eaa8SAndreas Gohr $nav = '<nav class="nav-sitemapnavi" id="plugin__sitemapnavi">'; 134c1e0eaa8SAndreas Gohr $nav .= $this->plugins['sitemapnavi']->getSiteMap(':'); 135c1e0eaa8SAndreas Gohr $nav .= '</nav>'; 136c1e0eaa8SAndreas Gohr } else { 137c1e0eaa8SAndreas Gohr // main navigation, loaded from standard sidebar, fixed up by javascript 138c1e0eaa8SAndreas Gohr $nav = '<nav class="nav-main">'; 1394ac10cf3SAndreas Gohr // immeadiately hide the navigation (if javascript available) 1404ac10cf3SAndreas Gohr // it will be restyled and made visible again by our script later 1414ac10cf3SAndreas Gohr $nav .= '<script type="application/javascript"> 1424ac10cf3SAndreas Gohr document.getElementsByClassName("nav-main")[0].style.visibility = "hidden"; 1434ac10cf3SAndreas Gohr </script>'; 144c1e0eaa8SAndreas Gohr $nav .= tpl_include_page($conf['sidebar'], false, true); 145c1e0eaa8SAndreas Gohr $nav .= '</nav>'; 146c1e0eaa8SAndreas Gohr } 147c1e0eaa8SAndreas Gohr 148c1e0eaa8SAndreas Gohr return $header . $nav; 1492387fd46SAndreas Gohr } 1502387fd46SAndreas Gohr 1512387fd46SAndreas Gohr /** 152*3e1e2a1fSAndreas Gohr * Default class defining is the sidebar should collapse 153*3e1e2a1fSAndreas Gohr * 154*3e1e2a1fSAndreas Gohr * @return string 155*3e1e2a1fSAndreas Gohr */ 156*3e1e2a1fSAndreas Gohr public function fullWidthClass() { 157*3e1e2a1fSAndreas Gohr global $ACT; 158*3e1e2a1fSAndreas Gohr // no auto collapsing? empty class 159*3e1e2a1fSAndreas Gohr if (!tpl_getConf('autocollapse')) return ''; 160*3e1e2a1fSAndreas Gohr // mode show? empty class 161*3e1e2a1fSAndreas Gohr if ($ACT === "show") return ''; 162*3e1e2a1fSAndreas Gohr // anything else? wide content 163*3e1e2a1fSAndreas Gohr return 'wide-content '; 164*3e1e2a1fSAndreas Gohr } 165*3e1e2a1fSAndreas Gohr 166*3e1e2a1fSAndreas Gohr /** 1672387fd46SAndreas Gohr * Get all the tabs to display 1682387fd46SAndreas Gohr * 1692387fd46SAndreas Gohr * @return array 1702387fd46SAndreas Gohr */ 1712387fd46SAndreas Gohr public function getMetaBoxTabs() { 17267d7dea5SMichael Große global $lang, $INFO; 1732387fd46SAndreas Gohr $tabs = array(); 1742387fd46SAndreas Gohr 1752387fd46SAndreas Gohr $toc = tpl_toc(true); 1762387fd46SAndreas Gohr if($toc) { 1772387fd46SAndreas Gohr $tabs[] = array( 1782387fd46SAndreas Gohr 'id' => 'spr__tab-toc', 1792387fd46SAndreas Gohr 'label' => $lang['toc'], 1802387fd46SAndreas Gohr 'tab' => $toc, 1812387fd46SAndreas Gohr 'count' => null, 1822387fd46SAndreas Gohr ); 1832387fd46SAndreas Gohr } 1842387fd46SAndreas Gohr 1852387fd46SAndreas Gohr if($this->plugins['tagging']) { 1862387fd46SAndreas Gohr $tabs[] = array( 1872387fd46SAndreas Gohr 'id' => 'spr__tab-tags', 1882387fd46SAndreas Gohr 'label' => tpl_getLang('tab_tags'), 1892387fd46SAndreas Gohr 'tab' => $this->plugins['tagging']->tpl_tags(false), 19067d7dea5SMichael Große 'count' => count($this->plugins['tagging']->findItems(array('pid' => $INFO['id']), 'tag')), 1912387fd46SAndreas Gohr ); 1922387fd46SAndreas Gohr } 1932387fd46SAndreas Gohr 1941f3641a8SMichael Große if ($this->plugins['magicmatcher']) { 1951f3641a8SMichael Große $tabs[] = array( 1961f3641a8SMichael Große 'id' => 'spr__tab-issues', 1979cae5e77SMichael Große 'label' => tpl_getLang('tab_issues'), 1981f3641a8SMichael Große 'tab' => $this->plugins['magicmatcher']->getIssueListHTML(), 1991f3641a8SMichael Große 'count' => $this->plugins['magicmatcher']->getCountIssues(), 2001f3641a8SMichael Große ); 2011f3641a8SMichael Große } 2022387fd46SAndreas Gohr 2032387fd46SAndreas Gohr return $tabs; 2042387fd46SAndreas Gohr } 20506cdf148SAndreas Gohr 20606cdf148SAndreas Gohr /** 20706cdf148SAndreas Gohr * Creates an image tag and includes the first found image correctly resized 20806cdf148SAndreas Gohr * 20906cdf148SAndreas Gohr * @param string $tag 21006cdf148SAndreas Gohr * @param array $attributes 21106cdf148SAndreas Gohr * @param int $w 21206cdf148SAndreas Gohr * @param int $h 21319958800SAndreas Gohr * @param bool $crop 21406cdf148SAndreas Gohr * @return string 21506cdf148SAndreas Gohr */ 21619958800SAndreas Gohr public static function getResizedImgTag($tag, $attributes, $w, $h, $crop = true) { 21706cdf148SAndreas Gohr $attr = ''; 21806cdf148SAndreas Gohr $medias = array(); 21906cdf148SAndreas Gohr 22006cdf148SAndreas Gohr // the attribute having an array defines where the image goes 22106cdf148SAndreas Gohr foreach($attributes as $attribute => $data) { 22206cdf148SAndreas Gohr if(is_array($data)) { 22306cdf148SAndreas Gohr $medias = $data; 22406cdf148SAndreas Gohr $attr = $attribute; 22506cdf148SAndreas Gohr } 22606cdf148SAndreas Gohr } 22706cdf148SAndreas Gohr // if the image attribute could not be found return 22806cdf148SAndreas Gohr if(!$attr || !$medias) return ''; 22906cdf148SAndreas Gohr 23006cdf148SAndreas Gohr // try all medias until an existing one is found 23106cdf148SAndreas Gohr $media = ''; 23206cdf148SAndreas Gohr foreach($medias as $media) { 23306cdf148SAndreas Gohr if(file_exists(mediaFN($media))) break; 23406cdf148SAndreas Gohr $media = ''; 23506cdf148SAndreas Gohr } 23606cdf148SAndreas Gohr if($media === '') return ''; 23706cdf148SAndreas Gohr 23806cdf148SAndreas Gohr // replace the array 23919958800SAndreas Gohr $media = ml($media, array('w' => $w, 'h' => $h, 'crop' => (int) $crop), true, '&'); 24006cdf148SAndreas Gohr $attributes[$attr] = $media; 24106cdf148SAndreas Gohr 24206cdf148SAndreas Gohr // return the full tag 2439dbc42beSAndreas Gohr return '<' . $tag . ' ' . buildAttributes($attributes) . ' />' . "\n"; 24406cdf148SAndreas Gohr } 2453a6eaa0bSAndreas Gohr 2463a6eaa0bSAndreas Gohr /** 2473a6eaa0bSAndreas Gohr * Embed the main logo 2483a6eaa0bSAndreas Gohr * 2493a6eaa0bSAndreas Gohr * Tries a few different locations 2503a6eaa0bSAndreas Gohr */ 2513a6eaa0bSAndreas Gohr public function mainLogo() { 2523a6eaa0bSAndreas Gohr global $conf; 2533a6eaa0bSAndreas Gohr 254e17d84d6SAndreas Gohr // homepage logo should not link to itself (BITV accessibility requirement) 255e17d84d6SAndreas Gohr $linkit = (strcmp(wl(), $_SERVER['REQUEST_URI']) !== 0); 256e17d84d6SAndreas Gohr if($linkit) { 257e17d84d6SAndreas Gohr $title = $conf['title'] . tpl_getLang('adjunct_linked_logo_text'); 258e17d84d6SAndreas Gohr } else { 259e17d84d6SAndreas Gohr $title = tpl_getLang('adjunct_start_logo_text') . $conf['title']; 260e17d84d6SAndreas Gohr } 261e17d84d6SAndreas Gohr 2623a6eaa0bSAndreas Gohr $desktop = self::getResizedImgTag( 2633a6eaa0bSAndreas Gohr 'img', 2643a6eaa0bSAndreas Gohr array( 2653a6eaa0bSAndreas Gohr 'class' => 'mobile-hide', 266f9746258SAndreas Gohr 'src' => array('wiki:logo-wide.svg', 'wiki:logo.svg', 'wiki:logo-wide.png', 'wiki:logo.png'), 267e17d84d6SAndreas Gohr 'alt' => $title, 2683a6eaa0bSAndreas Gohr ), 26999cb0c43SAndreas Gohr 0, 250, false 2703a6eaa0bSAndreas Gohr ); 2713a6eaa0bSAndreas Gohr $mobile = self::getResizedImgTag( 2723a6eaa0bSAndreas Gohr 'img', 2733a6eaa0bSAndreas Gohr array( 2743a6eaa0bSAndreas Gohr 'class' => 'mobile-only', 275f9746258SAndreas Gohr 'src' => array( 276f9746258SAndreas Gohr 'wiki:logo-32x32.svg', 'wiki:favicon.svg', 'wiki:logo-square.svg', 'wiki:logo.svg', 277f9746258SAndreas Gohr 'wiki:logo-32x32.png', 'wiki:favicon.png', 'wiki:logo-square.png', 'wiki:logo.png' 278f9746258SAndreas Gohr ), 279e17d84d6SAndreas Gohr 'alt' => $title, 2803a6eaa0bSAndreas Gohr ), 2813a6eaa0bSAndreas Gohr 32, 32 2823a6eaa0bSAndreas Gohr ); 2833a6eaa0bSAndreas Gohr 2843a6eaa0bSAndreas Gohr // homepage logo should not link to itself (BITV accessibility requirement) 285e17d84d6SAndreas Gohr if($linkit) { 2863a6eaa0bSAndreas Gohr tpl_link(wl(), $desktop, 'accesskey="h" title="[H]"'); 2873a6eaa0bSAndreas Gohr tpl_link(wl(), $mobile, 'accesskey="h" title="[H]"'); 288e17d84d6SAndreas Gohr } else { 289e17d84d6SAndreas Gohr echo $desktop; 290e17d84d6SAndreas Gohr echo $mobile; 2913a6eaa0bSAndreas Gohr } 2923a6eaa0bSAndreas Gohr } 29384f94641SAndreas Gohr 29484f94641SAndreas Gohr /** 29584f94641SAndreas Gohr * Add the current mode information to the hierarchical breadcrumbs 29684f94641SAndreas Gohr */ 29784f94641SAndreas Gohr public function breadcrumbSuffix() { 29884f94641SAndreas Gohr global $ACT; 29984f94641SAndreas Gohr global $lang; 30084f94641SAndreas Gohr global $INPUT; 30184f94641SAndreas Gohr global $ID; 30284f94641SAndreas Gohr global $conf; 30384f94641SAndreas Gohr global $IMG; 30484f94641SAndreas Gohr if($ACT == 'show') return; 30584f94641SAndreas Gohr 30684f94641SAndreas Gohr // find an apropriate label for the current mode 30784f94641SAndreas Gohr if($ACT) { 30884f94641SAndreas Gohr $label = tpl_getLang('mode_' . $ACT); 30984f94641SAndreas Gohr if(!$label) { 31084f94641SAndreas Gohr if(isset($lang['btn_' . $ACT])) { 31184f94641SAndreas Gohr $label = $lang['btn_' . $ACT]; 31284f94641SAndreas Gohr } else { 31384f94641SAndreas Gohr $label = $ACT; 31484f94641SAndreas Gohr } 31584f94641SAndreas Gohr } 31684f94641SAndreas Gohr } else { 31784f94641SAndreas Gohr // actually we would need to create a proper namespace breadcrumb path here, 31884f94641SAndreas Gohr // but this is the most simplest thing we can do for now 31984f94641SAndreas Gohr if(defined('DOKU_MEDIADETAIL')) { 32084f94641SAndreas Gohr $label = hsc(noNS($IMG)); 32184f94641SAndreas Gohr } else { 32284f94641SAndreas Gohr return; 32384f94641SAndreas Gohr } 32484f94641SAndreas Gohr } 32584f94641SAndreas Gohr 32684f94641SAndreas Gohr if($ACT == 'admin' && $INPUT->has('page')) { 32784f94641SAndreas Gohr $link = wl($ID, array('do' => 'admin')); 32884f94641SAndreas Gohr echo '<bdi> : <a href="' . $link . '"><strong>' . $label . '</strong></a></bdi>'; 32984f94641SAndreas Gohr 33084f94641SAndreas Gohr /** @var \DokuWiki_Admin_Plugin $plugin */ 33184f94641SAndreas Gohr $plugin = plugin_load('admin', $INPUT->str('page')); 33284f94641SAndreas Gohr if(!$plugin) return; 33384f94641SAndreas Gohr 33484f94641SAndreas Gohr $label = $plugin->getMenuText($conf['lang']); 33584f94641SAndreas Gohr } 33684f94641SAndreas Gohr 33784f94641SAndreas Gohr echo '<bdi><span class="curid"> : <strong>' . $label . '</strong></span></bdi>'; 33884f94641SAndreas Gohr } 3392387fd46SAndreas Gohr} 340