PageRenderTime 652ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/cms/clases/Doku/inc/template.php

https://github.com/bng5/CMS
PHP | 1035 lines | 693 code | 90 blank | 252 comment | 153 complexity | f68d109406dfb1421e1becc5b2220755 MD5 | raw file
  1. <?php
  2. /**
  3. * DokuWiki template functions
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Andreas Gohr <andi@splitbrain.org>
  7. */
  8. if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
  9. require_once(DOKU_CONF.'dokuwiki.php');
  10. /**
  11. * Returns the path to the given template, uses
  12. * default one if the custom version doesn't exist.
  13. * Also enables gzip compression if configured.
  14. *
  15. * @author Andreas Gohr <andi@splitbrain.org>
  16. */
  17. function template($tpl){
  18. global $conf;
  19. if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl))
  20. return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl;
  21. return DOKU_INC.'lib/tpl/default/'.$tpl;
  22. }
  23. /**
  24. * Print the content
  25. *
  26. * This function is used for printing all the usual content
  27. * (defined by the global $ACT var) by calling the appropriate
  28. * outputfunction(s) from html.php
  29. *
  30. * Everything that doesn't use the main template file isn't
  31. * handled by this function. ACL stuff is not done here either.
  32. *
  33. * @author Andreas Gohr <andi@splitbrain.org>
  34. */
  35. function tpl_content() {
  36. global $ACT;
  37. ob_start();
  38. trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core');
  39. $html_output = ob_get_clean();
  40. trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln');
  41. return !empty($html_output);
  42. }
  43. function tpl_content_core(){
  44. global $ACT;
  45. global $TEXT;
  46. global $PRE;
  47. global $SUF;
  48. global $SUM;
  49. global $IDX;
  50. switch($ACT){
  51. case 'show':
  52. html_show();
  53. break;
  54. case 'preview':
  55. html_edit($TEXT);
  56. html_show($TEXT);
  57. break;
  58. case 'recover':
  59. html_edit($TEXT);
  60. break;
  61. case 'edit':
  62. html_edit();
  63. break;
  64. case 'draft':
  65. html_draft();
  66. break;
  67. case 'wordblock':
  68. html_edit($TEXT,'wordblock');
  69. break;
  70. case 'search':
  71. html_search();
  72. break;
  73. case 'revisions':
  74. $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  75. html_revisions($first);
  76. break;
  77. case 'diff':
  78. html_diff();
  79. break;
  80. case 'recent':
  81. $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  82. html_recent($first);
  83. break;
  84. case 'index':
  85. html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
  86. break;
  87. case 'backlink':
  88. html_backlinks();
  89. break;
  90. case 'conflict':
  91. html_conflict(con($PRE,$TEXT,$SUF),$SUM);
  92. html_diff(con($PRE,$TEXT,$SUF),false);
  93. break;
  94. case 'locked':
  95. html_locked();
  96. break;
  97. case 'login':
  98. html_login();
  99. break;
  100. case 'register':
  101. html_register();
  102. break;
  103. case 'resendpwd':
  104. html_resendpwd();
  105. break;
  106. case 'denied':
  107. print p_locale_xhtml('denied');
  108. break;
  109. case 'profile' :
  110. html_updateprofile();
  111. break;
  112. case 'admin':
  113. tpl_admin();
  114. break;
  115. default:
  116. $evt = new Doku_Event('TPL_ACT_UNKNOWN',$ACT);
  117. if ($evt->advise_before())
  118. msg("Failed to handle command: ".hsc($ACT),-1);
  119. $evt->advise_after();
  120. unset($evt);
  121. return false;
  122. }
  123. return true;
  124. }
  125. /**
  126. * Handle the admin page contents
  127. *
  128. * @author Andreas Gohr <andi@splitbrain.org>
  129. */
  130. function tpl_admin(){
  131. global $INFO;
  132. $plugin = NULL;
  133. if (!empty($_REQUEST['page'])) {
  134. $pluginlist = plugin_list('admin');
  135. if (in_array($_REQUEST['page'], $pluginlist)) {
  136. // attempt to load the plugin
  137. $plugin =& plugin_load('admin',$_REQUEST['page']);
  138. }
  139. }
  140. if ($plugin !== NULL){
  141. if($plugin->forAdminOnly() && !$INFO['isadmin']){
  142. msg('For admins only',-1);
  143. html_admin();
  144. }else{
  145. $plugin->html();
  146. }
  147. }else{
  148. html_admin();
  149. }
  150. return true;
  151. }
  152. /**
  153. * Print the correct HTML meta headers
  154. *
  155. * This has to go into the head section of your template.
  156. *
  157. * @triggers TPL_METAHEADER_OUTPUT
  158. * @param boolean $alt Should feeds and alternative format links be added?
  159. * @author Andreas Gohr <andi@splitbrain.org>
  160. */
  161. function tpl_metaheaders($alt=true){
  162. global $ID;
  163. global $REV;
  164. global $INFO;
  165. global $ACT;
  166. global $lang;
  167. global $conf;
  168. $it=2;
  169. // prepare the head array
  170. $head = array();
  171. // the usual stuff
  172. $head['meta'][] = array( 'name'=>'generator', 'content'=>'DokuWiki '.getVersion() );
  173. $head['link'][] = array( 'rel'=>'search', 'type'=>'application/opensearchdescription+xml',
  174. 'href'=>DOKU_BASE.'lib/exe/opensearch.php', 'title'=>$conf['title'] );
  175. $head['link'][] = array( 'rel'=>'start', 'href'=>DOKU_BASE );
  176. $head['link'][] = array( 'rel'=>'contents', 'href'=> wl($ID,'do=index',false,'&'),
  177. 'title'=>$lang['btn_index'] );
  178. if($alt){
  179. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
  180. 'title'=>'Recent Changes', 'href'=>DOKU_BASE.'feed.php');
  181. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
  182. 'title'=>'Current Namespace',
  183. 'href'=>DOKU_BASE.'feed.php?mode=list&ns='.$INFO['namespace']);
  184. if(actionOK('export_xhtml')){
  185. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/html', 'title'=>'Plain HTML',
  186. 'href'=>exportlink($ID, 'xhtml', '', false, '&'));
  187. }
  188. if(actionOK('export_raw')){
  189. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/plain', 'title'=>'Wiki Markup',
  190. 'href'=>exportlink($ID, 'raw', '', false, '&'));
  191. }
  192. }
  193. // setup robot tags apropriate for different modes
  194. if( ($ACT=='show' || $ACT=='export_xhtml') && !$REV){
  195. if($INFO['exists']){
  196. //delay indexing:
  197. if((time() - $INFO['lastmod']) >= $conf['indexdelay']){
  198. $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
  199. }else{
  200. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
  201. }
  202. }else{
  203. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,follow');
  204. }
  205. }elseif(defined('DOKU_MEDIADETAIL')){
  206. $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
  207. }else{
  208. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
  209. }
  210. // set metadata
  211. if($ACT == 'show' || $ACT=='export_xhtml'){
  212. // date of modification
  213. if($REV){
  214. $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$REV));
  215. }else{
  216. $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$INFO['lastmod']));
  217. }
  218. // keywords (explicit or implicit)
  219. if(!empty($INFO['meta']['subject'])){
  220. $head['meta'][] = array( 'name'=>'keywords', 'content'=>join(',',$INFO['meta']['subject']));
  221. }else{
  222. $head['meta'][] = array( 'name'=>'keywords', 'content'=>str_replace(':',',',$ID));
  223. }
  224. }
  225. // load stylesheets
  226. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'all', 'type'=>'text/css',
  227. 'href'=>DOKU_BASE.'lib/exe/css.php?s=all');
  228. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'screen', 'type'=>'text/css',
  229. 'href'=>DOKU_BASE.'lib/exe/css.php');
  230. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'print', 'type'=>'text/css',
  231. 'href'=>DOKU_BASE.'lib/exe/css.php?s=print');
  232. // load javascript
  233. $js_edit = ($ACT=='edit' || $ACT=='preview' || $ACT=='recover' || $ACT=='wordblock' ) ? 1 : 0;
  234. $js_write = ($INFO['writable']) ? 1 : 0;
  235. if(defined('DOKU_MEDIAMANAGER')){
  236. $js_edit = 1;
  237. $js_write = 0;
  238. }
  239. if(($js_edit && $js_write) || defined('DOKU_MEDIAMANAGER')){
  240. $script = "NS='".$INFO['namespace']."';";
  241. if($conf['useacl'] && $_SERVER['REMOTE_USER']){
  242. require_once(DOKU_INC.'inc/toolbar.php');
  243. $script .= "SIG='".toolbar_signature()."';";
  244. }
  245. $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8',
  246. '_data'=> $script);
  247. }
  248. $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8', '_data'=>'',
  249. 'src'=>DOKU_BASE.'lib/exe/js.php?edit='.$js_edit.'&write='.$js_write);
  250. // trigger event here
  251. trigger_event('TPL_METAHEADER_OUTPUT',$head,'_tpl_metaheaders_action',true);
  252. return true;
  253. }
  254. /**
  255. * prints the array build by tpl_metaheaders
  256. *
  257. * $data is an array of different header tags. Each tag can have multiple
  258. * instances. Attributes are given as key value pairs. Values will be HTML
  259. * encoded automatically so they should be provided as is in the $data array.
  260. *
  261. * For tags having a body attribute specify the the body data in the special
  262. * attribute '_data'. This field will NOT BE ESCAPED automatically.
  263. *
  264. * @author Andreas Gohr <andi@splitbrain.org>
  265. */
  266. function _tpl_metaheaders_action($data){
  267. foreach($data as $tag => $inst){
  268. foreach($inst as $attr){
  269. echo '<',$tag,' ',buildAttributes($attr);
  270. if(isset($attr['_data'])){
  271. if($tag == 'script' && $attr['_data'])
  272. $attr['_data'] = "<!--//--><![CDATA[//><!--\n".
  273. $attr['_data'].
  274. "\n//--><!]]>";
  275. echo '>',$attr['_data'],'</',$tag,'>';
  276. }else{
  277. echo '/>';
  278. }
  279. echo "\n";
  280. }
  281. }
  282. }
  283. /**
  284. * Print a link
  285. *
  286. * Just builds a link.
  287. *
  288. * @author Andreas Gohr <andi@splitbrain.org>
  289. */
  290. function tpl_link($url,$name,$more=''){
  291. print '<a href="'.$url.'" ';
  292. if ($more) print ' '.$more;
  293. print ">$name</a>";
  294. return true;
  295. }
  296. /**
  297. * Prints a link to a WikiPage
  298. *
  299. * Wrapper around html_wikilink
  300. *
  301. * @author Andreas Gohr <andi@splitbrain.org>
  302. */
  303. function tpl_pagelink($id,$name=NULL){
  304. print html_wikilink($id,$name);
  305. return true;
  306. }
  307. /**
  308. * get the parent page
  309. *
  310. * Tries to find out which page is parent.
  311. * returns false if none is available
  312. *
  313. * @author Andreas Gohr <andi@splitbrain.org>
  314. */
  315. function tpl_getparent($id){
  316. global $conf;
  317. $parent = getNS($id).':';
  318. resolve_pageid('',$parent,$exists);
  319. if($parent == $id) {
  320. $pos = strrpos (getNS($id),':');
  321. $parent = substr($parent,0,$pos).':';
  322. resolve_pageid('',$parent,$exists);
  323. if($parent == $id) return false;
  324. }
  325. return $parent;
  326. }
  327. /**
  328. * Print one of the buttons
  329. *
  330. * Available Buttons are
  331. *
  332. * edit - edit/create/show/draft button
  333. * history - old revisions
  334. * recent - recent changes
  335. * login - login/logout button - if ACL enabled
  336. * profile - user profile button (if logged in)
  337. * index - The index
  338. * admin - admin page - if enough rights
  339. * top - a back to top button
  340. * back - a back to parent button - if available
  341. * backlink - links to the list of backlinks
  342. * subscription- subscribe/unsubscribe button
  343. *
  344. * @author Andreas Gohr <andi@splitbrain.org>
  345. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  346. */
  347. function tpl_button($type){
  348. global $ACT;
  349. global $ID;
  350. global $REV;
  351. global $NS;
  352. global $INFO;
  353. global $conf;
  354. global $auth;
  355. // check disabled actions and fix the badly named ones
  356. $ctype = $type;
  357. if($type == 'history') $ctype='revisions';
  358. if(!actionOK($ctype)) return false;
  359. switch($type){
  360. case 'edit':
  361. #most complicated type - we need to decide on current action
  362. if($ACT == 'show' || $ACT == 'search'){
  363. if($INFO['writable']){
  364. if(!empty($INFO['draft'])){
  365. echo html_btn('draft',$ID,'e',array('do' => 'draft'),'post');
  366. }else{
  367. if($INFO['exists']){
  368. echo html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
  369. }else{
  370. echo html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
  371. }
  372. }
  373. }else{
  374. if(!actionOK('source')) return false; //pseudo action
  375. echo html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post');
  376. }
  377. }else{
  378. echo html_btn('show',$ID,'v',array('do' => 'show'));
  379. }
  380. return true;
  381. case 'history':
  382. print html_btn('revs',$ID,'o',array('do' => 'revisions'));
  383. return true;
  384. case 'recent':
  385. print html_btn('recent','','r',array('do' => 'recent'));
  386. return true;
  387. case 'index':
  388. print html_btn('index',$ID,'x',array('do' => 'index'));
  389. return true;
  390. case 'back':
  391. if ($parent = tpl_getparent($ID)) {
  392. print html_btn('back',$parent,'b',array('do' => 'show'));
  393. return true;
  394. }
  395. return false;
  396. case 'top':
  397. print html_topbtn();
  398. return true;
  399. case 'login':
  400. if($conf['useacl']){
  401. if($_SERVER['REMOTE_USER']){
  402. print html_btn('logout',$ID,'',array('do' => 'logout',));
  403. }else{
  404. print html_btn('login',$ID,'',array('do' => 'login'));
  405. }
  406. return true;
  407. }
  408. return false;
  409. case 'admin':
  410. if($INFO['ismanager']){
  411. print html_btn('admin',$ID,'',array('do' => 'admin'));
  412. return true;
  413. }
  414. return false;
  415. case 'subscription':
  416. if($conf['useacl'] && $ACT == 'show' && $conf['subscribers'] == 1){
  417. if($_SERVER['REMOTE_USER']){
  418. if($INFO['subscribed']){
  419. print html_btn('unsubscribe',$ID,'',array('do' => 'unsubscribe',));
  420. } else {
  421. print html_btn('subscribe',$ID,'',array('do' => 'subscribe',));
  422. }
  423. return true;
  424. }
  425. }
  426. return false;
  427. case 'backlink':
  428. print html_btn('backlink',$ID,'',array('do' => 'backlink'));
  429. return true;
  430. case 'profile':
  431. if($conf['useacl'] && $_SERVER['REMOTE_USER'] &&
  432. $auth->canDo('Profile') && ($ACT!='profile')){
  433. print html_btn('profile',$ID,'',array('do' => 'profile'));
  434. return true;
  435. }
  436. return false;
  437. default:
  438. print '[unknown button type]';
  439. return true;
  440. }
  441. }
  442. /**
  443. * Like the action buttons but links
  444. *
  445. * Available links are
  446. *
  447. * edit - edit/create/show link
  448. * history - old revisions
  449. * recent - recent changes
  450. * login - login/logout link - if ACL enabled
  451. * profile - user profile link (if logged in)
  452. * index - The index
  453. * admin - admin page - if enough rights
  454. * top - a back to top link
  455. * back - a back to parent link - if available
  456. * backlink - links to the list of backlinks
  457. * subscribe/subscription - subscribe/unsubscribe link
  458. *
  459. * @author Andreas Gohr <andi@splitbrain.org>
  460. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  461. * @see tpl_button
  462. */
  463. function tpl_actionlink($type,$pre='',$suf=''){
  464. global $ID;
  465. global $INFO;
  466. global $REV;
  467. global $ACT;
  468. global $conf;
  469. global $lang;
  470. global $auth;
  471. // check disabled actions and fix the badly named ones
  472. $ctype = $type;
  473. if($type == 'history') $ctype='revisions';
  474. if(!actionOK($ctype)) return false;
  475. switch($type){
  476. case 'edit':
  477. #most complicated type - we need to decide on current action
  478. if($ACT == 'show' || $ACT == 'search'){
  479. if($INFO['writable']){
  480. if(!empty($INFO['draft'])) {
  481. tpl_link(wl($ID,'do=draft'),
  482. $pre.$lang['btn_draft'].$suf,
  483. 'class="action edit" acceskey="e" rel="nofollow"');
  484. } else {
  485. if($INFO['exists']){
  486. tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  487. $pre.$lang['btn_edit'].$suf,
  488. 'class="action edit" accesskey="e" rel="nofollow"');
  489. }else{
  490. tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  491. $pre.$lang['btn_create'].$suf,
  492. 'class="action create" accesskey="e" rel="nofollow"');
  493. }
  494. }
  495. }else{
  496. if(!actionOK('source')) return false; //pseudo action
  497. tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  498. $pre.$lang['btn_source'].$suf,
  499. 'class="action source" accesskey="v" rel="nofollow"');
  500. }
  501. }else{
  502. tpl_link(wl($ID,'do=show'),
  503. $pre.$lang['btn_show'].$suf,
  504. 'class="action show" accesskey="v" rel="nofollow"');
  505. }
  506. return true;
  507. case 'history':
  508. tpl_link(wl($ID,'do=revisions'),$pre.$lang['btn_revs'].$suf,'class="action revisions" accesskey="o" rel="nofollow"');
  509. return true;
  510. case 'recent':
  511. tpl_link(wl('','do=recent'),$pre.$lang['btn_recent'].$suf,'class="action recent" accesskey="r" rel="nofollow"');
  512. return true;
  513. case 'index':
  514. tpl_link(wl($ID,'do=index'),$pre.$lang['btn_index'].$suf,'class="action index" accesskey="x" rel="nofollow"');
  515. return true;
  516. case 'top':
  517. print '<a href="#dokuwiki__top" class="action top" accesskey="x">'.$pre.$lang['btn_top'].$suf.'</a>';
  518. return true;
  519. case 'back':
  520. if ($parent = tpl_getparent($ID)) {
  521. tpl_link(wl($parent,'do=show'),$pre.$lang['btn_back'].$suf,'class="action back" accesskey="b" rel="nofollow"');
  522. return true;
  523. }
  524. return false;
  525. case 'login':
  526. if($conf['useacl']){
  527. if($_SERVER['REMOTE_USER']){
  528. tpl_link(wl($ID,'do=logout'),$pre.$lang['btn_logout'].$suf,'class="action logout" rel="nofollow"');
  529. }else{
  530. tpl_link(wl($ID,'do=login'),$pre.$lang['btn_login'].$suf,'class="action login" rel="nofollow"');
  531. }
  532. return true;
  533. }
  534. return false;
  535. case 'admin':
  536. if($INFO['ismanager']){
  537. tpl_link(wl($ID,'do=admin'),$pre.$lang['btn_admin'].$suf,'class="action admin" rel="nofollow"');
  538. return true;
  539. }
  540. return false;
  541. case 'subscribe':
  542. case 'subscription':
  543. if($conf['useacl'] && $ACT == 'show' && $conf['subscribers'] == 1){
  544. if($_SERVER['REMOTE_USER']){
  545. if($INFO['subscribed']) {
  546. tpl_link(wl($ID,'do=unsubscribe'),$pre.$lang['btn_unsubscribe'].$suf,'class="action unsubscribe" rel="nofollow"');
  547. } else {
  548. tpl_link(wl($ID,'do=subscribe'),$pre.$lang['btn_subscribe'].$suf,'class="action subscribe" rel="nofollow"');
  549. }
  550. return true;
  551. }
  552. }
  553. return false;
  554. case 'backlink':
  555. tpl_link(wl($ID,'do=backlink'),$pre.$lang['btn_backlink'].$suf, 'class="action backlink" rel="nofollow"');
  556. return true;
  557. case 'profile':
  558. if($conf['useacl'] && $_SERVER['REMOTE_USER'] &&
  559. $auth->canDo('Profile') && ($ACT!='profile')){
  560. tpl_link(wl($ID,'do=profile'),$pre.$lang['btn_profile'].$suf, 'class="action profile" rel="nofollow"');
  561. return true;
  562. }
  563. return false;
  564. default:
  565. print '[unknown link type]';
  566. return true;
  567. }
  568. }
  569. /**
  570. * Print the search form
  571. *
  572. * If the first parameter is given a div with the ID 'qsearch_out' will
  573. * be added which instructs the ajax pagequicksearch to kick in and place
  574. * its output into this div. The second parameter controls the propritary
  575. * attribute autocomplete. If set to false this attribute will be set with an
  576. * value of "off" to instruct the browser to disable it's own built in
  577. * autocompletion feature (MSIE and Firefox)
  578. *
  579. * @author Andreas Gohr <andi@splitbrain.org>
  580. */
  581. function tpl_searchform($ajax=true,$autocomplete=true){
  582. global $lang;
  583. global $ACT;
  584. // don't print the search form if search action has been disabled
  585. if (!actionOk('search')) return false;
  586. print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search"><div class="no">';
  587. print '<input type="hidden" name="do" value="search" />';
  588. print '<input type="text" ';
  589. if($ACT == 'search') print 'value="'.htmlspecialchars($_REQUEST['id']).'" ';
  590. if(!$autocomplete) print 'autocomplete="off" ';
  591. print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[ALT+F]" />';
  592. print '<input type="submit" value="'.$lang['btn_search'].'" class="button" title="'.$lang['btn_search'].'" />';
  593. if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
  594. print '</div></form>';
  595. return true;
  596. }
  597. /**
  598. * Print the breadcrumbs trace
  599. *
  600. * @author Andreas Gohr <andi@splitbrain.org>
  601. */
  602. function tpl_breadcrumbs($sep='&raquo;'){
  603. global $lang;
  604. global $conf;
  605. //check if enabled
  606. if(!$conf['breadcrumbs']) return false;
  607. $crumbs = breadcrumbs(); //setup crumb trace
  608. //reverse crumborder in right-to-left mode, add RLM character to fix heb/eng display mixups
  609. if($lang['direction'] == 'rtl') {
  610. $crumbs = array_reverse($crumbs,true);
  611. $crumbs_sep = ' &#8207;<span class="bcsep">'.$sep.'</span>&#8207; ';
  612. } else {
  613. $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
  614. }
  615. //render crumbs, highlight the last one
  616. print $lang['breadcrumb'].':';
  617. $last = count($crumbs);
  618. $i = 0;
  619. foreach ($crumbs as $id => $name){
  620. $i++;
  621. echo $crumbs_sep;
  622. if ($i == $last) print '<span class="curid">';
  623. tpl_link(wl($id),hsc($name),'class="breadcrumbs" title="'.$id.'"');
  624. if ($i == $last) print '</span>';
  625. }
  626. return true;
  627. }
  628. /**
  629. * Hierarchical breadcrumbs
  630. *
  631. * This code was suggested as replacement for the usual breadcrumbs.
  632. * It only makes sense with a deep site structure.
  633. *
  634. * @author Andreas Gohr <andi@splitbrain.org>
  635. * @author Nigel McNie <oracle.shinoda@gmail.com>
  636. * @author Sean Coates <sean@caedmon.net>
  637. * @link http://wiki.splitbrain.org/wiki:tipsandtricks:hierarchicalbreadcrumbs
  638. * @todo May behave strangely in RTL languages
  639. */
  640. function tpl_youarehere($sep=' &raquo; '){
  641. global $conf;
  642. global $ID;
  643. global $lang;
  644. // check if enabled
  645. if(!$conf['youarehere']) return false;
  646. $parts = explode(':', $ID);
  647. $count = count($parts);
  648. echo $lang['youarehere'].': ';
  649. // always print the startpage
  650. $title = p_get_first_heading($conf['start']);
  651. if(!$title) $title = $conf['start'];
  652. tpl_link(wl($conf['start']),hsc($title),'title="'.$conf['start'].'"');
  653. // print intermediate namespace links
  654. $part = '';
  655. for($i=0; $i<$count - 1; $i++){
  656. $part .= $parts[$i].':';
  657. $page = $part;
  658. resolve_pageid('',$page,$exists);
  659. if ($page == $conf['start']) continue; // Skip startpage
  660. // output
  661. echo $sep;
  662. if($exists){
  663. $title = p_get_first_heading($page);
  664. if(!$title) $title = $parts[$i];
  665. tpl_link(wl($page),hsc($title),'title="'.$page.'"');
  666. }else{
  667. tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2"');
  668. }
  669. }
  670. // print current page, skipping start page, skipping for namespace index
  671. if(isset($page) && $page==$part.$parts[$i]) return;
  672. $page = $part.$parts[$i];
  673. if($page == $conf['start']) return;
  674. echo $sep;
  675. if(@file_exists(wikiFN($page))){
  676. $title = p_get_first_heading($page);
  677. if(!$title) $title = $parts[$i];
  678. tpl_link(wl($page),hsc($title),'title="'.$page.'"');
  679. }else{
  680. tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2"');
  681. }
  682. return true;
  683. }
  684. /**
  685. * Print info if the user is logged in
  686. * and show full name in that case
  687. *
  688. * Could be enhanced with a profile link in future?
  689. *
  690. * @author Andreas Gohr <andi@splitbrain.org>
  691. */
  692. function tpl_userinfo(){
  693. global $lang;
  694. global $INFO;
  695. if($_SERVER['REMOTE_USER']){
  696. print $lang['loggedinas'].': '.$INFO['userinfo']['name'];
  697. return true;
  698. }
  699. return false;
  700. }
  701. /**
  702. * Print some info about the current page
  703. *
  704. * @author Andreas Gohr <andi@splitbrain.org>
  705. */
  706. function tpl_pageinfo(){
  707. global $conf;
  708. global $lang;
  709. global $INFO;
  710. global $REV;
  711. global $ID;
  712. // return if we are not allowed to view the page
  713. if (!auth_quickaclcheck($ID)) { return; }
  714. // prepare date and path
  715. $fn = $INFO['filepath'];
  716. if(!$conf['fullpath']){
  717. if($REV){
  718. $fn = str_replace(realpath($conf['olddir']).DIRECTORY_SEPARATOR,'',$fn);
  719. }else{
  720. $fn = str_replace(realpath($conf['datadir']).DIRECTORY_SEPARATOR,'',$fn);
  721. }
  722. }
  723. $fn = utf8_decodeFN($fn);
  724. $date = date($conf['dformat'],$INFO['lastmod']);
  725. // print it
  726. if($INFO['exists']){
  727. print $fn;
  728. print ' &middot; ';
  729. print $lang['lastmod'];
  730. print ': ';
  731. print $date;
  732. if($INFO['editor']){
  733. print ' '.$lang['by'].' ';
  734. print $INFO['editor'];
  735. }else{
  736. print ' ('.$lang['external_edit'].')';
  737. }
  738. if($INFO['locked']){
  739. print ' &middot; ';
  740. print $lang['lockedby'];
  741. print ': ';
  742. print $INFO['locked'];
  743. }
  744. return true;
  745. }
  746. return false;
  747. }
  748. /**
  749. * Prints or returns the name of the given page (current one if none given).
  750. *
  751. * If useheading is enabled this will use the first headline else
  752. * the given ID is used.
  753. *
  754. * @author Andreas Gohr <andi@splitbrain.org>
  755. */
  756. function tpl_pagetitle($id=null, $ret=false){
  757. global $conf;
  758. if(is_null($id)){
  759. global $ID;
  760. $id = $ID;
  761. }
  762. $name = $id;
  763. if ($conf['useheading']) {
  764. $title = p_get_first_heading($id);
  765. if ($title) $name = $title;
  766. }
  767. if ($ret) {
  768. return hsc($name);
  769. } else {
  770. print hsc($name);
  771. return true;
  772. }
  773. }
  774. /**
  775. * Returns the requested EXIF/IPTC tag from the current image
  776. *
  777. * If $tags is an array all given tags are tried until a
  778. * value is found. If no value is found $alt is returned.
  779. *
  780. * Which texts are known is defined in the functions _exifTagNames
  781. * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
  782. * to the names of the latter one)
  783. *
  784. * Only allowed in: detail.php
  785. *
  786. * @author Andreas Gohr <andi@splitbrain.org>
  787. */
  788. function tpl_img_getTag($tags,$alt='',$src=null){
  789. // Init Exif Reader
  790. global $SRC;
  791. if(is_null($src)) $src = $SRC;
  792. static $meta = null;
  793. if(is_null($meta)) $meta = new JpegMeta($src);
  794. if($meta === false) return $alt;
  795. $info = $meta->getField($tags);
  796. if($info == false) return $alt;
  797. return $info;
  798. }
  799. /**
  800. * Prints the image with a link to the full sized version
  801. *
  802. * Only allowed in: detail.php
  803. */
  804. function tpl_img($maxwidth=0,$maxheight=0){
  805. global $IMG;
  806. $w = tpl_img_getTag('File.Width');
  807. $h = tpl_img_getTag('File.Height');
  808. //resize to given max values
  809. $ratio = 1;
  810. if($w >= $h){
  811. if($maxwidth && $w >= $maxwidth){
  812. $ratio = $maxwidth/$w;
  813. }elseif($maxheight && $h > $maxheight){
  814. $ratio = $maxheight/$h;
  815. }
  816. }else{
  817. if($maxheight && $h >= $maxheight){
  818. $ratio = $maxheight/$h;
  819. }elseif($maxwidth && $w > $maxwidth){
  820. $ratio = $maxwidth/$w;
  821. }
  822. }
  823. if($ratio){
  824. $w = floor($ratio*$w);
  825. $h = floor($ratio*$h);
  826. }
  827. //prepare URLs
  828. $url=ml($IMG,array('cache'=>$_REQUEST['cache']));
  829. $src=ml($IMG,array('cache'=>$_REQUEST['cache'],'w'=>$w,'h'=>$h));
  830. //prepare attributes
  831. $alt=tpl_img_getTag('Simple.Title');
  832. $p = array();
  833. if($w) $p['width'] = $w;
  834. if($h) $p['height'] = $h;
  835. $p['class'] = 'img_detail';
  836. if($alt){
  837. $p['alt'] = $alt;
  838. $p['title'] = $alt;
  839. }else{
  840. $p['alt'] = '';
  841. }
  842. $p = buildAttributes($p);
  843. print '<a href="'.$url.'">';
  844. print '<img src="'.$src.'" '.$p.'/>';
  845. print '</a>';
  846. return true;
  847. }
  848. /**
  849. * This function inserts a 1x1 pixel gif which in reality
  850. * is the inexer function.
  851. *
  852. * Should be called somewhere at the very end of the main.php
  853. * template
  854. */
  855. function tpl_indexerWebBug(){
  856. global $ID;
  857. global $INFO;
  858. if(!$INFO['exists']) return false;
  859. if(isHiddenPage($ID)) return false; //no need to index hidden pages
  860. $p = array();
  861. $p['src'] = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
  862. '&'.time();
  863. $p['width'] = 1;
  864. $p['height'] = 1;
  865. $p['alt'] = '';
  866. $att = buildAttributes($p);
  867. print "<img $att />";
  868. return true;
  869. }
  870. // configuration methods
  871. /**
  872. * tpl_getConf($id)
  873. *
  874. * use this function to access template configuration variables
  875. */
  876. function tpl_getConf($id){
  877. global $conf;
  878. global $tpl_configloaded;
  879. $tpl = $conf['template'];
  880. if (!$tpl_configloaded){
  881. $tconf = tpl_loadConfig();
  882. if ($tconf !== false){
  883. foreach ($tconf as $key => $value){
  884. if (isset($conf['tpl'][$tpl][$key])) continue;
  885. $conf['tpl'][$tpl][$key] = $value;
  886. }
  887. $tpl_configloaded = true;
  888. }
  889. }
  890. return $conf['tpl'][$tpl][$id];
  891. }
  892. /**
  893. * tpl_loadConfig()
  894. * reads all template configuration variables
  895. * this function is automatically called by tpl_getConf()
  896. */
  897. function tpl_loadConfig(){
  898. $file = DOKU_TPLINC.'/conf/default.php';
  899. $conf = array();
  900. if (!@file_exists($file)) return false;
  901. // load default config file
  902. include($file);
  903. return $conf;
  904. }
  905. /**
  906. * prints the "main content" in the mediamanger popup
  907. *
  908. * Depending on the user's actions this may be a list of
  909. * files in a namespace, the meta editing dialog or
  910. * a message of referencing pages
  911. *
  912. * Only allowed in mediamanager.php
  913. *
  914. * @author Andreas Gohr <andi@splitbrain.org>
  915. */
  916. function tpl_mediaContent(){
  917. global $IMG;
  918. global $AUTH;
  919. global $INUSE;
  920. global $NS;
  921. global $JUMPTO;
  922. ptln('<div id="media__content">');
  923. if($_REQUEST['edit']){
  924. media_metaform($IMG,$AUTH);
  925. }elseif(is_array($INUSE)){
  926. media_filesinuse($INUSE,$IMG);
  927. }else{
  928. media_filelist($NS,$AUTH,$JUMPTO);
  929. }
  930. ptln('</div>');
  931. }
  932. /**
  933. * prints the namespace tree in the mediamanger popup
  934. *
  935. * Only allowed in mediamanager.php
  936. *
  937. * @author Andreas Gohr <andi@splitbrain.org>
  938. */
  939. function tpl_mediaTree(){
  940. global $NS;
  941. ptln('<div id="media__tree">');
  942. media_nstree($NS);
  943. ptln('</div>');
  944. }
  945. //Setup VIM: ex: et ts=2 enc=utf-8 :