1<?php 2 3namespace dokuwiki\template\sprintdoc; 4 5/** 6 * Class Template 7 * 8 * provides additional logic for the sprintdoc template 9 * 10 * @package dokuwiki\template\sprintdoc 11 */ 12class Template { 13 14 /** @var array loaded plugins */ 15 protected $plugins = array( 16 'sqlite' => null, 17 'tagging' => null, 18 'magicmatcher' => null, 19 'tplinc' => null, 20 'sitemapnavi' => null, 21 ); 22 23 /** @var string the type of special navigation to use */ 24 protected $nav = ''; 25 26 27 /** 28 * Get the singleton instance 29 * 30 * @return Template 31 */ 32 public static function getInstance() { 33 static $instance = null; 34 if($instance === null) $instance = new Template(); 35 return $instance; 36 } 37 38 /** 39 * Template constructor. 40 */ 41 protected function __construct() { 42 $this->initializePlugins(); 43 $this->initNavigationCookie(); 44 45 /** @var \Doku_Event_Handler */ 46 global $EVENT_HANDLER; 47 $EVENT_HANDLER->register_hook('PLUGIN_TPLINC_LOCATIONS_SET', 'BEFORE', $this, 'registerIncludes'); 48 } 49 50 /** 51 * Load all the plugins we support directly 52 */ 53 protected function initializePlugins() { 54 $this->plugins['sqlite'] = plugin_load('helper', 'sqlite'); 55 if($this->plugins['sqlite']) { 56 $this->plugins['tagging'] = plugin_load('helper', 'tagging'); 57 $this->plugins['magicmatcher'] = plugin_load('syntax', 'magicmatcher_issuelist'); 58 } 59 $this->plugins['tplinc'] = plugin_load('helper', 'tplinc'); 60 $this->plugins['sitemapnavi'] = plugin_load('helper', 'sitemapnavi'); 61 } 62 63 /** 64 * Makes include position info available to the tplinc plugin 65 * 66 * @param \Doku_Event $event 67 */ 68 public function registerIncludes(\Doku_Event $event) { 69 $event->data['footer'] = 'Footer below the page content'; 70 $event->data['sidebarfooter'] = 'Footer below the sidebar'; 71 $event->data['sidebarheader'] = 'Header above the sidebar'; 72 } 73 74 /** 75 * Get the content to include from the tplinc plugin 76 * 77 * prefix and postfix are only added when there actually is any content 78 * 79 * @param string $location 80 * @param string $pre prepend this before the content 81 * @param string $post append this to the content 82 * @return string 83 */ 84 public function getInclude($location, $pre = '', $post = '') { 85 if(!$this->plugins['tplinc']) return ''; 86 $content = $this->plugins['tplinc']->renderIncludes($location); 87 if($content === '') return ''; 88 return $pre . $content . $post; 89 } 90 91 /** 92 * Sets a cookie to remember the requested special navigation 93 */ 94 protected function initNavigationCookie() { 95 if ($this->plugins['sitemapnavi'] === null) return; 96 global $INPUT; 97 98 $nav = $INPUT->str('nav'); 99 if($nav) { 100 set_doku_pref('nav', $nav); 101 $this->nav = $INPUT->str('nav'); 102 } else { 103 $this->nav = get_doku_pref('nav', 'sidebar'); 104 } 105 } 106 107 /** 108 * Return the navigation for the sidebar 109 * 110 * Defaults to the standard sidebar mechanism, but supports also the sitemapnavi plugin 111 * 112 * @return string 113 */ 114 public function getNavigation() { 115 global $ID; 116 global $conf; 117 118 // add tabs if multiple navigation types available 119 $header = ''; 120 if ($this->plugins['sitemapnavi'] !== null) { 121 $header = '<ul class="sidebar-tabs">'; 122 $header .= '<li class="' . ($this->nav === 'sidebar' ? 'active' : '') . '">' . 123 '<a href="' . wl($ID, ['nav' => 'sidebar']) . '">'.tpl_getLang('nav_sidebar').'</a></li>'; 124 $header .= '<li class="' . ($this->nav === 'sitemap' ? 'active' : '') . '">' . 125 '<a href="' . wl($ID, ['nav' => 'sitemap']) . '">'.tpl_getLang('nav_sitemap').'</a></li>'; 126 $header .= '</ul>'; 127 } 128 129 // decide what to show 130 if ($this->nav === 'sitemap') { 131 // site tree created by sitemapnavi plugin 132 $nav = '<nav class="nav-sitemapnavi" id="plugin__sitemapnavi">'; 133 $nav .= $this->plugins['sitemapnavi']->getSiteMap(':'); 134 $nav .= '</nav>'; 135 } else { 136 // main navigation, loaded from standard sidebar, fixed up by javascript 137 $nav = '<nav class="nav-main">'; 138 // immeadiately hide the navigation (if javascript available) 139 // it will be restyled and made visible again by our script later 140 $nav .= '<script type="application/javascript"> 141 document.getElementsByClassName("nav-main")[0].style.visibility = "hidden"; 142 </script>'; 143 $nav .= tpl_include_page($conf['sidebar'], false, true); 144 $nav .= '</nav>'; 145 } 146 147 return $header . $nav; 148 } 149 150 /** 151 * Get all the tabs to display 152 * 153 * @return array 154 */ 155 public function getMetaBoxTabs() { 156 global $lang, $INFO; 157 $tabs = array(); 158 159 $toc = tpl_toc(true); 160 if($toc) { 161 $tabs[] = array( 162 'id' => 'spr__tab-toc', 163 'label' => $lang['toc'], 164 'tab' => $toc, 165 'count' => null, 166 ); 167 } 168 169 if($this->plugins['tagging']) { 170 $tabs[] = array( 171 'id' => 'spr__tab-tags', 172 'label' => tpl_getLang('tab_tags'), 173 'tab' => $this->plugins['tagging']->tpl_tags(false), 174 'count' => count($this->plugins['tagging']->findItems(array('pid' => $INFO['id']), 'tag')), 175 ); 176 } 177 178 if ($this->plugins['magicmatcher']) { 179 $tabs[] = array( 180 'id' => 'spr__tab-issues', 181 'label' => tpl_getLang('tab_issues'), 182 'tab' => $this->plugins['magicmatcher']->getIssueListHTML(), 183 'count' => $this->plugins['magicmatcher']->getCountIssues(), 184 ); 185 } 186 187 return $tabs; 188 } 189 190 /** 191 * Creates an image tag and includes the first found image correctly resized 192 * 193 * @param string $tag 194 * @param array $attributes 195 * @param int $w 196 * @param int $h 197 * @param bool $crop 198 * @return string 199 */ 200 public static function getResizedImgTag($tag, $attributes, $w, $h, $crop = true) { 201 $attr = ''; 202 $medias = array(); 203 204 // the attribute having an array defines where the image goes 205 foreach($attributes as $attribute => $data) { 206 if(is_array($data)) { 207 $medias = $data; 208 $attr = $attribute; 209 } 210 } 211 // if the image attribute could not be found return 212 if(!$attr || !$medias) return ''; 213 214 // try all medias until an existing one is found 215 $media = ''; 216 foreach($medias as $media) { 217 if(file_exists(mediaFN($media))) break; 218 $media = ''; 219 } 220 if($media === '') return ''; 221 222 // replace the array 223 $media = ml($media, array('w' => $w, 'h' => $h, 'crop' => (int) $crop), true, '&'); 224 $attributes[$attr] = $media; 225 226 // return the full tag 227 return '<' . $tag . ' ' . buildAttributes($attributes) . ' />' . "\n"; 228 } 229 230 /** 231 * Embed the main logo 232 * 233 * Tries a few different locations 234 */ 235 public function mainLogo() { 236 global $conf; 237 238 // homepage logo should not link to itself (BITV accessibility requirement) 239 $linkit = (strcmp(wl(), $_SERVER['REQUEST_URI']) !== 0); 240 if($linkit) { 241 $title = $conf['title'] . tpl_getLang('adjunct_linked_logo_text'); 242 } else { 243 $title = tpl_getLang('adjunct_start_logo_text') . $conf['title']; 244 } 245 246 $desktop = self::getResizedImgTag( 247 'img', 248 array( 249 'class' => 'mobile-hide', 250 'src' => array('wiki:logo-wide.png', 'wiki:logo.png'), 251 'alt' => $title, 252 ), 253 0, 50, false 254 ); 255 $mobile = self::getResizedImgTag( 256 'img', 257 array( 258 'class' => 'mobile-only', 259 'src' => array('wiki:logo-32x32.png', 'wiki:favicon.png', 'wiki:logo-square.png', 'wiki:logo.png'), 260 'alt' => $title, 261 ), 262 32, 32 263 ); 264 265 // homepage logo should not link to itself (BITV accessibility requirement) 266 if($linkit) { 267 tpl_link(wl(), $desktop, 'accesskey="h" title="[H]"'); 268 tpl_link(wl(), $mobile, 'accesskey="h" title="[H]"'); 269 } else { 270 echo $desktop; 271 echo $mobile; 272 } 273 } 274 275 /** 276 * Add the current mode information to the hierarchical breadcrumbs 277 */ 278 public function breadcrumbSuffix() { 279 global $ACT; 280 global $lang; 281 global $INPUT; 282 global $ID; 283 global $conf; 284 global $IMG; 285 if($ACT == 'show') return; 286 287 // find an apropriate label for the current mode 288 if($ACT) { 289 $label = tpl_getLang('mode_' . $ACT); 290 if(!$label) { 291 if(isset($lang['btn_' . $ACT])) { 292 $label = $lang['btn_' . $ACT]; 293 } else { 294 $label = $ACT; 295 } 296 } 297 } else { 298 // actually we would need to create a proper namespace breadcrumb path here, 299 // but this is the most simplest thing we can do for now 300 if(defined('DOKU_MEDIADETAIL')) { 301 $label = hsc(noNS($IMG)); 302 } else { 303 return; 304 } 305 } 306 307 if($ACT == 'admin' && $INPUT->has('page')) { 308 $link = wl($ID, array('do' => 'admin')); 309 echo '<bdi> : <a href="' . $link . '"><strong>' . $label . '</strong></a></bdi>'; 310 311 /** @var \DokuWiki_Admin_Plugin $plugin */ 312 $plugin = plugin_load('admin', $INPUT->str('page')); 313 if(!$plugin) return; 314 315 $label = $plugin->getMenuText($conf['lang']); 316 } 317 318 echo '<bdi><span class="curid"> : <strong>' . $label . '</strong></span></bdi>'; 319 } 320} 321