1<?php 2/** 3 * Template Functions 4 * 5 * This file provides template specific custom functions that are 6 * not provided by the DokuWiki core. 7 * It is common practice to start each function with an underscore 8 * to make sure it won't interfere with future core functions. 9 */ 10 11// must be run from within DokuWiki 12if (!defined('DOKU_INC')) die(); 13 14/** 15 * Create link/button to discussion page and back 16 * 17 * @author Anika Henke <anika@selfthinker.org> 18 */ 19function _tpl_discussion($discussionPage, $title, $backTitle, $link=0, $wrapper=0) { 20 global $ID; 21 22 $discussPage = str_replace('@ID@', $ID, $discussionPage); 23 $discussPageRaw = str_replace('@ID@', '', $discussionPage); 24 $isDiscussPage = strpos($ID, $discussPageRaw) !== false; 25 $backID = str_replace($discussPageRaw, '', $ID); 26 27 if ($wrapper) echo "<$wrapper>"; 28 29 if ($isDiscussPage) { 30 if ($link) 31 tpl_pagelink($backID, $backTitle); 32 else 33 echo html_btn('back2article', $backID, '', array(), 'get', 0, $backTitle); 34 } else { 35 if ($link) 36 tpl_pagelink($discussPage, $title); 37 else 38 echo html_btn('discussion', $discussPage, '', array(), 'get', 0, $title); 39 } 40 41 if ($wrapper) echo "</$wrapper>"; 42} 43 44/** 45 * Create link/button to user page 46 * 47 * @author Anika Henke <anika@selfthinker.org> 48 */ 49function _tpl_userpage($userPage, $title, $link=0, $wrapper=0) { 50 if (!$_SERVER['REMOTE_USER']) return; 51 52 global $conf; 53 $userPage = str_replace('@USER@', $_SERVER['REMOTE_USER'], $userPage); 54 55 if ($wrapper) echo "<$wrapper>"; 56 57 if ($link) 58 tpl_pagelink($userPage, $title); 59 else 60 echo html_btn('userpage', $userPage, '', array(), 'get', 0, $title); 61 62 if ($wrapper) echo "</$wrapper>"; 63} 64 65/** 66 * Create link/button to register page 67 * @deprecated DW versions > 2011-02-20 can use the core function tpl_action('register') 68 * 69 * @author Anika Henke <anika@selfthinker.org> 70 */ 71function _tpl_register($link=0, $wrapper=0) { 72 global $conf; 73 global $lang; 74 global $ID; 75 $lang_register = !empty($lang['btn_register']) ? $lang['btn_register'] : $lang['register']; 76 77 if ($_SERVER['REMOTE_USER'] || !$conf['useacl'] || !actionOK('register')) return; 78 79 if ($wrapper) echo "<$wrapper>"; 80 81 if ($link) 82 tpl_link(wl($ID, 'do=register'), $lang_register, 'class="action register" rel="nofollow"'); 83 else 84 echo html_btn('register', $ID, '', array('do'=>'register'), 'get', 0, $lang_register); 85 86 if ($wrapper) echo "</$wrapper>"; 87} 88 89/** 90 * Wrapper around custom template actions 91 * 92 * @author Anika Henke <anika@selfthinker.org> 93 */ 94function _tpl_action($type, $link=0, $wrapper=0) { 95 switch ($type) { 96 case 'discussion': 97 if (tpl_getConf('discussionPage')) { 98 _tpl_discussion(tpl_getConf('discussionPage'), tpl_getLang('discussion'), tpl_getLang('back_to_article'), $link, $wrapper); 99 } 100 break; 101 case 'userpage': 102 if (tpl_getConf('userPage')) { 103 _tpl_userpage(tpl_getConf('userPage'), tpl_getLang('userpage'), $link, $wrapper); 104 } 105 break; 106 case 'register': // deprecated 107 _tpl_register($link, $wrapper); 108 break; 109 } 110} 111 112 113 114/* fallbacks for things missing in older DokuWiki versions 115********************************************************************/ 116 117 118/* if newer settings exist in the core, use them, otherwise fall back to template settings */ 119 120if (!isset($conf['tagline'])) { 121 $conf['tagline'] = tpl_getConf('tagline'); 122} 123 124if (!isset($conf['sidebar'])) { 125 $conf['sidebar'] = tpl_getConf('sidebarID'); 126} 127 128/* these $lang strings are now in the core */ 129 130if (!isset($lang['user_tools'])) { 131 $lang['user_tools'] = tpl_getLang('user_tools'); 132} 133if (!isset($lang['site_tools'])) { 134 $lang['site_tools'] = tpl_getLang('site_tools'); 135} 136if (!isset($lang['page_tools'])) { 137 $lang['page_tools'] = tpl_getLang('page_tools'); 138} 139if (!isset($lang['skip_to_content'])) { 140 $lang['skip_to_content'] = tpl_getLang('skip_to_content'); 141} 142 143 144/** 145 * copied from core (available since Adora Belle) 146 */ 147if (!function_exists('tpl_getMediaFile')) { 148 function tpl_getMediaFile($search, $abs = false, &$imginfo = null) { 149 $img = ''; 150 $file = ''; 151 $ismedia = false; 152 // loop through candidates until a match was found: 153 foreach($search as $img) { 154 if(substr($img, 0, 1) == ':') { 155 $file = mediaFN($img); 156 $ismedia = true; 157 } else { 158 $file = tpl_incdir().$img; 159 $ismedia = false; 160 } 161 162 if(file_exists($file)) break; 163 } 164 165 // fetch image data if requested 166 if(!is_null($imginfo)) { 167 $imginfo = getimagesize($file); 168 } 169 170 // build URL 171 if($ismedia) { 172 $url = ml($img, '', true, '', $abs); 173 } else { 174 $url = tpl_basedir().$img; 175 if($abs) $url = DOKU_URL.substr($url, strlen(DOKU_REL)); 176 } 177 178 return $url; 179 } 180} 181 182/** 183 * copied from core (available since Angua) 184 */ 185if (!function_exists('tpl_favicon')) { 186 function tpl_favicon($types = array('favicon')) { 187 188 $return = ''; 189 190 foreach($types as $type) { 191 switch($type) { 192 case 'favicon': 193 $look = array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'); 194 $return .= '<link rel="shortcut icon" href="'.tpl_getMediaFile($look).'" />'.NL; 195 break; 196 case 'mobile': 197 $look = array(':wiki:apple-touch-icon.png', ':apple-touch-icon.png', 'images/apple-touch-icon.png'); 198 $return .= '<link rel="apple-touch-icon" href="'.tpl_getMediaFile($look).'" />'.NL; 199 break; 200 case 'generic': 201 // ideal world solution, which doesn't work in any browser yet 202 $look = array(':wiki:favicon.svg', ':favicon.svg', 'images/favicon.svg'); 203 $return .= '<link rel="icon" href="'.tpl_getMediaFile($look).'" type="image/svg+xml" />'.NL; 204 break; 205 } 206 } 207 208 return $return; 209 } 210} 211 212/** 213 * copied from core (available since Adora Belle) 214 */ 215if (!function_exists('tpl_includeFile')) { 216 function tpl_includeFile($file) { 217 global $config_cascade; 218 foreach(array('protected', 'local', 'default') as $config_group) { 219 if(empty($config_cascade['main'][$config_group])) continue; 220 foreach($config_cascade['main'][$config_group] as $conf_file) { 221 $dir = dirname($conf_file); 222 if(file_exists("$dir/$file")) { 223 include("$dir/$file"); 224 return; 225 } 226 } 227 } 228 229 // still here? try the template dir 230 $file = tpl_incdir().$file; 231 if(file_exists($file)) { 232 include($file); 233 } 234 } 235} 236 237/** 238 * copied from core (available since Adora Belle) 239 */ 240if (!function_exists('tpl_incdir')) { 241 function tpl_incdir() { 242 global $conf; 243 return DOKU_INC.'lib/tpl/'.$conf['template'].'/'; 244 } 245} 246 247function _tpl_toc_to_twitter_bootstrap_event_hander_dump_level($data, $header='', $firstlevel=false) 248{ 249 250 251 if (count($data) == 0) 252 { 253 return ''; 254 } 255 256 if (tpl_getConf('useSideToCChevrons') == 1) 257 { 258 $chevronHTML = '<i class="glyphicon glyphicon-chevron-right"></i> '; 259 } else { 260 $chevronHTML = ''; 261 } 262 263 $ret = ''; 264 $ret .= '<ul class="nav list-group">'; 265 if ($header != '') { 266 $ret .= '<li class="list-group-item nav-header">'.$header.'</li>'; 267 } 268 $ret .= '<li class="divider"></li>'; 269 270 $first = true; 271 $li_inner = ' class ="active"'; 272 273 //Only supports top level links for now. 274 foreach($data as $heading) 275 { 276 $ret .= '<li' . $li_inner . '><a href="#' . $heading['link'] . '">'. $chevronHTML . $heading['title'] . '</a></li>'; 277 278 $li_inner = ''; 279 } 280 281 $ret .= '<li class="divider"></li>'; 282 $ret .= '</ul>'; 283 284 return $ret; 285} 286 287function _tpl_toc_to_twitter_bootstrap_event_hander(&$event, $param) 288{ 289 global $conf; 290 //This is tied to the specific format of the DokuWiki TOC. 291 echo _tpl_toc_to_twitter_bootstrap_event_hander_dump_level($event->data, $conf['sidebar'], true); 292} 293 294function _tpl_toc_to_twitter_bootstrap() 295{ 296 //Force generation of TOC, request that the TOC is returned as HTML, but then ignore the returned string. The hook will instead dump out the TOC. 297 global $EVENT_HANDLER; 298 $EVENT_HANDLER->register_hook('TPL_TOC_RENDER', 'AFTER', NULL, '_tpl_toc_to_twitter_bootstrap_event_hander'); 299 tpl_toc(true); 300} 301 302 303//Output various links to user tools wrapped in a user-specified element. 304function _tpl_output_tools_twitter_bootstrap($showTools = true, $element = 'li') 305{ 306 if ($showTools) { 307 //Separate whatever was there from these links. 308 echo '<li class="divider-vertical"></li>'; 309 tpl_action('recent', 1, 'li'); 310 tpl_action('media', 1, 'li'); 311 tpl_action('index', 1, 'li'); 312 313 echo '<li class="divider-vertical"></li>'; 314 315 tpl_action('admin', 1, $element); 316 _tpl_action('userpage', 1, $element); 317 tpl_action('profile', 1, $element); 318 tpl_action('register', 1, $element); 319 tpl_action('login', 1, $element); 320 } 321} 322 323function _tpl_output_page_tools($showTools = true, $element = 'li'){ 324 global $lang; 325 326 $textonly = true; 327 $spandivider = ''; 328 $elementbegin = "<$element>"; 329 $elementend = "</$element>"; 330 331 if ($showTools) { 332 echo '<ul class="nav navbar-nav">'; 333 //echo '<li>'.$lang['page_tools'].$spandivider; 334 335 $content = tpl_action('edit', $textonly, '', true); 336 if ($content != '') { echo $elementbegin.$content.$spandivider.$elementend; } 337 338 echo $elementbegin; 339 //Notice the use of _tpl_action instead of tpl_action. This doesn't 340 //actully return the string and instead automatically prints it 341 //out. 342 _tpl_action('discussion', $textonly, '', true); 343 echo $spandivider; 344 echo $elementend; 345 346 $content = tpl_action('revisions', $textonly, '', true); 347 if ($content != '') { echo $elementbegin.$content.$spandivider.$elementend; } 348 349 $content = tpl_action('backlink', $textonly, '', true); 350 if ($content != '') { echo $elementbegin.$content.$spandivider.$elementend; } 351 352 $content = tpl_action('subscribe', $textonly, '', true); 353 if ($content != '') { echo $elementbegin.$content.$spandivider.$elementend; } 354 355 $content = tpl_action('revert', $textonly, '', true); 356 if ($content != '') { echo $elementbegin.$content.$spandivider.$elementend; } 357 358 echo $elementbegin; 359 $content = tpl_action('top', $textonly, '', true); 360 echo $content; 361 echo $elementend; 362 echo '</ul>'; 363 } 364} 365 366function _tpl_output_search_bar() 367{ 368 //Modified from the official tpl_searchform function. 369 global $lang; 370 global $ACT; 371 global $QUERY; 372 373 // don't print the search form if search action has been disabled 374 if(!actionOk('search')) return false; 375 376 print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get"><div class="no">'; 377 print '<input type="hidden" name="do" value="search" />'; 378 print '<input type="text" placeholder="'.$lang['btn_search'].'" '; 379 if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" '; 380 if(!$autocomplete) print 'autocomplete="off" '; 381 print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]" />'; 382 383 print '<button type="submit" value="" class="button btn" title="'.$lang['btn_search'].'">'; 384 print '<i class="glyphicon glyphicon-search"></i></button>'; 385 386 if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>'; 387 print '</div></form>'; 388 return true; 389 390} 391