PageRenderTime 114ms CodeModel.GetById 26ms RepoModel.GetById 2ms app.codeStats 0ms

/inc/template.php

https://repo.or.cz/dokuwiki/radio.git
PHP | 1415 lines | 992 code | 123 blank | 300 comment | 255 complexity | f3ac15feb6b6ebf15bfc8a7ab534200f MD5 | raw file
Possible License(s): GPL-2.0
  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')) die('meh.');
  9. /**
  10. * Returns the path to the given template, uses
  11. * default one if the custom version doesn't exist.
  12. *
  13. * @author Andreas Gohr <andi@splitbrain.org>
  14. */
  15. function template($tpl){
  16. global $conf;
  17. if(@is_readable(DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl))
  18. return DOKU_INC.'lib/tpl/'.$conf['template'].'/'.$tpl;
  19. return DOKU_INC.'lib/tpl/default/'.$tpl;
  20. }
  21. /**
  22. * Print the content
  23. *
  24. * This function is used for printing all the usual content
  25. * (defined by the global $ACT var) by calling the appropriate
  26. * outputfunction(s) from html.php
  27. *
  28. * Everything that doesn't use the main template file isn't
  29. * handled by this function. ACL stuff is not done here either.
  30. *
  31. * @author Andreas Gohr <andi@splitbrain.org>
  32. */
  33. function tpl_content($prependTOC=true) {
  34. global $ACT;
  35. global $INFO;
  36. $INFO['prependTOC'] = $prependTOC;
  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 = isset($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  75. html_revisions($first);
  76. break;
  77. case 'diff':
  78. html_diff();
  79. break;
  80. case 'recent':
  81. if (is_array($_REQUEST['first'])) {
  82. $_REQUEST['first'] = array_keys($_REQUEST['first']);
  83. $_REQUEST['first'] = $_REQUEST['first'][0];
  84. }
  85. $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0;
  86. html_recent($first);
  87. break;
  88. case 'index':
  89. html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly?
  90. break;
  91. case 'backlink':
  92. html_backlinks();
  93. break;
  94. case 'conflict':
  95. html_conflict(con($PRE,$TEXT,$SUF),$SUM);
  96. html_diff(con($PRE,$TEXT,$SUF),false);
  97. break;
  98. case 'locked':
  99. html_locked();
  100. html_edit();
  101. break;
  102. case 'login':
  103. html_login();
  104. break;
  105. case 'register':
  106. html_register();
  107. break;
  108. case 'resendpwd':
  109. html_resendpwd();
  110. break;
  111. case 'denied':
  112. print p_locale_xhtml('denied');
  113. break;
  114. case 'profile' :
  115. html_updateprofile();
  116. break;
  117. case 'admin':
  118. tpl_admin();
  119. break;
  120. case 'subscribe':
  121. tpl_subscribe();
  122. break;
  123. default:
  124. $evt = new Doku_Event('TPL_ACT_UNKNOWN',$ACT);
  125. if ($evt->advise_before())
  126. msg("Failed to handle command: ".hsc($ACT),-1);
  127. $evt->advise_after();
  128. unset($evt);
  129. return false;
  130. }
  131. return true;
  132. }
  133. /**
  134. * Places the TOC where the function is called
  135. *
  136. * If you use this you most probably want to call tpl_content with
  137. * a false argument
  138. *
  139. * @author Andreas Gohr <andi@splitbrain.org>
  140. */
  141. function tpl_toc($return=false){
  142. global $TOC;
  143. global $ACT;
  144. global $ID;
  145. global $REV;
  146. global $INFO;
  147. global $conf;
  148. $toc = array();
  149. if(is_array($TOC)){
  150. // if a TOC was prepared in global scope, always use it
  151. $toc = $TOC;
  152. }elseif(($ACT == 'show' || substr($ACT,0,6) == 'export') && !$REV && $INFO['exists']){
  153. // get TOC from metadata, render if neccessary
  154. $meta = p_get_metadata($ID, false, true);
  155. if(isset($meta['internal']['toc'])){
  156. $tocok = $meta['internal']['toc'];
  157. }else{
  158. $tocok = true;
  159. }
  160. $toc = $meta['description']['tableofcontents'];
  161. if(!$tocok || !is_array($toc) || !$conf['tocminheads'] || count($toc) < $conf['tocminheads']){
  162. $toc = array();
  163. }
  164. }elseif($ACT == 'admin'){
  165. // try to load admin plugin TOC FIXME: duplicates code from tpl_admin
  166. $plugin = null;
  167. if (!empty($_REQUEST['page'])) {
  168. $pluginlist = plugin_list('admin');
  169. if (in_array($_REQUEST['page'], $pluginlist)) {
  170. // attempt to load the plugin
  171. $plugin =& plugin_load('admin',$_REQUEST['page']);
  172. }
  173. }
  174. if ( ($plugin !== null) &&
  175. (!$plugin->forAdminOnly() || $INFO['isadmin']) ){
  176. $toc = $plugin->getTOC();
  177. $TOC = $toc; // avoid later rebuild
  178. }
  179. }
  180. trigger_event('TPL_TOC_RENDER', $toc, null, false);
  181. $html = html_TOC($toc);
  182. if($return) return $html;
  183. echo $html;
  184. }
  185. /**
  186. * Handle the admin page contents
  187. *
  188. * @author Andreas Gohr <andi@splitbrain.org>
  189. */
  190. function tpl_admin(){
  191. global $INFO;
  192. global $TOC;
  193. $plugin = null;
  194. if (!empty($_REQUEST['page'])) {
  195. $pluginlist = plugin_list('admin');
  196. if (in_array($_REQUEST['page'], $pluginlist)) {
  197. // attempt to load the plugin
  198. $plugin =& plugin_load('admin',$_REQUEST['page']);
  199. }
  200. }
  201. if ($plugin !== null){
  202. if($plugin->forAdminOnly() && !$INFO['isadmin']){
  203. msg('For admins only',-1);
  204. html_admin();
  205. }else{
  206. if(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet
  207. if($INFO['prependTOC']) tpl_toc();
  208. $plugin->html();
  209. }
  210. }else{
  211. html_admin();
  212. }
  213. return true;
  214. }
  215. /**
  216. * Print the correct HTML meta headers
  217. *
  218. * This has to go into the head section of your template.
  219. *
  220. * @triggers TPL_METAHEADER_OUTPUT
  221. * @param boolean $alt Should feeds and alternative format links be added?
  222. * @author Andreas Gohr <andi@splitbrain.org>
  223. */
  224. function tpl_metaheaders($alt=true){
  225. global $ID;
  226. global $REV;
  227. global $INFO;
  228. global $JSINFO;
  229. global $ACT;
  230. global $QUERY;
  231. global $lang;
  232. global $conf;
  233. $it=2;
  234. // prepare the head array
  235. $head = array();
  236. // prepare seed for js and css
  237. $tseed = 0;
  238. $depends = getConfigFiles('main');
  239. foreach($depends as $f) {
  240. $time = @filemtime($f);
  241. if($time > $tseed) $tseed = $time;
  242. }
  243. // the usual stuff
  244. $head['meta'][] = array( 'name'=>'generator', 'content'=>'DokuWiki '.getVersion() );
  245. $head['link'][] = array( 'rel'=>'search', 'type'=>'application/opensearchdescription+xml',
  246. 'href'=>DOKU_BASE.'lib/exe/opensearch.php', 'title'=>$conf['title'] );
  247. $head['link'][] = array( 'rel'=>'start', 'href'=>DOKU_BASE );
  248. if(actionOK('index')){
  249. $head['link'][] = array( 'rel'=>'contents', 'href'=> wl($ID,'do=index',false,'&'),
  250. 'title'=>$lang['btn_index'] );
  251. }
  252. if($alt){
  253. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
  254. 'title'=>'Recent Changes', 'href'=>DOKU_BASE.'feed.php');
  255. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
  256. 'title'=>'Current Namespace',
  257. 'href'=>DOKU_BASE.'feed.php?mode=list&ns='.$INFO['namespace']);
  258. if(($ACT == 'show' || $ACT == 'search') && $INFO['writable']){
  259. $head['link'][] = array( 'rel'=>'edit',
  260. 'title'=>$lang['btn_edit'],
  261. 'href'=> wl($ID,'do=edit',false,'&'));
  262. }
  263. if($ACT == 'search'){
  264. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'application/rss+xml',
  265. 'title'=>'Search Result',
  266. 'href'=>DOKU_BASE.'feed.php?mode=search&q='.$QUERY);
  267. }
  268. if(actionOK('export_xhtml')){
  269. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/html', 'title'=>'Plain HTML',
  270. 'href'=>exportlink($ID, 'xhtml', '', false, '&'));
  271. }
  272. if(actionOK('export_raw')){
  273. $head['link'][] = array( 'rel'=>'alternate', 'type'=>'text/plain', 'title'=>'Wiki Markup',
  274. 'href'=>exportlink($ID, 'raw', '', false, '&'));
  275. }
  276. }
  277. // setup robot tags apropriate for different modes
  278. if( ($ACT=='show' || $ACT=='export_xhtml') && !$REV){
  279. if($INFO['exists']){
  280. //delay indexing:
  281. if((time() - $INFO['lastmod']) >= $conf['indexdelay']){
  282. $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
  283. }else{
  284. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
  285. }
  286. $head['link'][] = array( 'rel'=>'canonical', 'href'=>wl($ID,'',true,'&') );
  287. }else{
  288. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,follow');
  289. }
  290. }elseif(defined('DOKU_MEDIADETAIL')){
  291. $head['meta'][] = array( 'name'=>'robots', 'content'=>'index,follow');
  292. }else{
  293. $head['meta'][] = array( 'name'=>'robots', 'content'=>'noindex,nofollow');
  294. }
  295. // set metadata
  296. if($ACT == 'show' || $ACT=='export_xhtml'){
  297. // date of modification
  298. if($REV){
  299. $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$REV));
  300. }else{
  301. $head['meta'][] = array( 'name'=>'date', 'content'=>date('Y-m-d\TH:i:sO',$INFO['lastmod']));
  302. }
  303. // keywords (explicit or implicit)
  304. if(!empty($INFO['meta']['subject'])){
  305. $head['meta'][] = array( 'name'=>'keywords', 'content'=>join(',',$INFO['meta']['subject']));
  306. }else{
  307. $head['meta'][] = array( 'name'=>'keywords', 'content'=>str_replace(':',',',$ID));
  308. }
  309. }
  310. // load stylesheets
  311. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'screen', 'type'=>'text/css',
  312. 'href'=>DOKU_BASE.'lib/exe/css.php?t='.$conf['template'].'&tseed='.$tseed);
  313. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'all', 'type'=>'text/css',
  314. 'href'=>DOKU_BASE.'lib/exe/css.php?s=all&t='.$conf['template'].'&tseed='.$tseed);
  315. $head['link'][] = array('rel'=>'stylesheet', 'media'=>'print', 'type'=>'text/css',
  316. 'href'=>DOKU_BASE.'lib/exe/css.php?s=print&t='.$conf['template'].'&tseed='.$tseed);
  317. // make $INFO and other vars available to JavaScripts
  318. require_once(DOKU_INC.'inc/JSON.php');
  319. $json = new JSON();
  320. $script = "var NS='".$INFO['namespace']."';";
  321. if($conf['useacl'] && $_SERVER['REMOTE_USER']){
  322. require_once(DOKU_INC.'inc/toolbar.php');
  323. $script .= "var SIG='".toolbar_signature()."';";
  324. }
  325. $script .= 'var JSINFO = '.$json->encode($JSINFO).';';
  326. $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8',
  327. '_data'=> $script);
  328. // load external javascript
  329. $head['script'][] = array( 'type'=>'text/javascript', 'charset'=>'utf-8', '_data'=>'',
  330. 'src'=>DOKU_BASE.'lib/exe/js.php'.'?tseed='.$tseed);
  331. // trigger event here
  332. trigger_event('TPL_METAHEADER_OUTPUT',$head,'_tpl_metaheaders_action',true);
  333. return true;
  334. }
  335. /**
  336. * prints the array build by tpl_metaheaders
  337. *
  338. * $data is an array of different header tags. Each tag can have multiple
  339. * instances. Attributes are given as key value pairs. Values will be HTML
  340. * encoded automatically so they should be provided as is in the $data array.
  341. *
  342. * For tags having a body attribute specify the the body data in the special
  343. * attribute '_data'. This field will NOT BE ESCAPED automatically.
  344. *
  345. * @author Andreas Gohr <andi@splitbrain.org>
  346. */
  347. function _tpl_metaheaders_action($data){
  348. foreach($data as $tag => $inst){
  349. foreach($inst as $attr){
  350. echo '<',$tag,' ',buildAttributes($attr);
  351. if(isset($attr['_data']) || $tag == 'script'){
  352. if($tag == 'script' && $attr['_data'])
  353. $attr['_data'] = "<!--//--><![CDATA[//><!--\n".
  354. $attr['_data'].
  355. "\n//--><!]]>";
  356. echo '>',$attr['_data'],'</',$tag,'>';
  357. }else{
  358. echo '/>';
  359. }
  360. echo "\n";
  361. }
  362. }
  363. }
  364. /**
  365. * Print a link
  366. *
  367. * Just builds a link.
  368. *
  369. * @author Andreas Gohr <andi@splitbrain.org>
  370. */
  371. function tpl_link($url,$name,$more='',$return=false){
  372. $out = '<a href="'.$url.'" ';
  373. if ($more) $out .= ' '.$more;
  374. $out .= ">$name</a>";
  375. if ($return) return $out;
  376. print $out;
  377. return true;
  378. }
  379. /**
  380. * Prints a link to a WikiPage
  381. *
  382. * Wrapper around html_wikilink
  383. *
  384. * @author Andreas Gohr <andi@splitbrain.org>
  385. */
  386. function tpl_pagelink($id,$name=null){
  387. print html_wikilink($id,$name);
  388. return true;
  389. }
  390. /**
  391. * get the parent page
  392. *
  393. * Tries to find out which page is parent.
  394. * returns false if none is available
  395. *
  396. * @author Andreas Gohr <andi@splitbrain.org>
  397. */
  398. function tpl_getparent($id){
  399. global $conf;
  400. $parent = getNS($id).':';
  401. resolve_pageid('',$parent,$exists);
  402. if($parent == $id) {
  403. $pos = strrpos (getNS($id),':');
  404. $parent = substr($parent,0,$pos).':';
  405. resolve_pageid('',$parent,$exists);
  406. if($parent == $id) return false;
  407. }
  408. return $parent;
  409. }
  410. /**
  411. * Print one of the buttons
  412. *
  413. * Available Buttons are
  414. *
  415. * edit - edit/create/show/draft button
  416. * history - old revisions
  417. * recent - recent changes
  418. * login - login/logout button - if ACL enabled
  419. * profile - user profile button (if logged in)
  420. * index - The index
  421. * admin - admin page - if enough rights
  422. * top - a back to top button
  423. * back - a back to parent button - if available
  424. * backlink - links to the list of backlinks
  425. * subscription- subscribe/unsubscribe button
  426. *
  427. * @author Andreas Gohr <andi@splitbrain.org>
  428. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  429. */
  430. function tpl_button($type,$return=false){
  431. global $ACT;
  432. global $ID;
  433. global $REV;
  434. global $NS;
  435. global $INFO;
  436. global $conf;
  437. global $auth;
  438. // check disabled actions and fix the badly named ones
  439. $ctype = $type;
  440. if($type == 'history') $ctype='revisions';
  441. if(!actionOK($ctype)) return false;
  442. $out = '';
  443. switch($type){
  444. case 'edit':
  445. // most complicated type - we need to decide on current action
  446. if($ACT == 'show' || $ACT == 'search'){
  447. if($INFO['writable']){
  448. if(!empty($INFO['draft'])){
  449. $out .= html_btn('draft',$ID,'e',array('do' => 'draft'),'post');
  450. }else{
  451. if($INFO['exists']){
  452. $out .= html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
  453. }else{
  454. $out .= html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post');
  455. }
  456. }
  457. }else{
  458. if(!actionOK('source')) return false; //pseudo action
  459. $out .= html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post');
  460. }
  461. }else{
  462. $out .= html_btn('show',$ID,'v',array('do' => 'show'));
  463. }
  464. break;
  465. case 'history':
  466. if(actionOK('revisions'))
  467. $out .= html_btn('revs',$ID,'o',array('do' => 'revisions'));
  468. break;
  469. case 'recent':
  470. if(actionOK('recent'))
  471. $out .= html_btn('recent',$ID,'r',array('do' => 'recent'));
  472. break;
  473. case 'index':
  474. if(actionOK('index'))
  475. $out .= html_btn('index',$ID,'x',array('do' => 'index'));
  476. break;
  477. case 'back':
  478. if ($parent = tpl_getparent($ID)) {
  479. $out .= html_btn('back',$parent,'b',array('do' => 'show'));
  480. }
  481. break;
  482. case 'top':
  483. $out .= html_topbtn();
  484. break;
  485. case 'login':
  486. if($conf['useacl'] && $auth){
  487. if(isset($_SERVER['REMOTE_USER'])){
  488. $out .= html_btn('logout',$ID,'',array('do' => 'logout', 'sectok' => getSecurityToken()));
  489. }else{
  490. $out .= html_btn('login',$ID,'',array('do' => 'login', 'sectok' => getSecurityToken()));
  491. }
  492. }
  493. break;
  494. case 'admin':
  495. if($INFO['ismanager']){
  496. $out .= html_btn('admin',$ID,'',array('do' => 'admin'));
  497. }
  498. break;
  499. case 'revert':
  500. if($INFO['ismanager'] && $REV && $INFO['writable'] && actionOK('revert')){
  501. $out .= html_btn('revert',$ID,'',array('do' => 'revert', 'rev' => $REV, 'sectok' => getSecurityToken()));
  502. }
  503. break;
  504. case 'subscribe':
  505. if ($conf['useacl'] && $auth && $ACT == 'show' &&
  506. $conf['subscribers'] && isset($_SERVER['REMOTE_USER']) &&
  507. actionOK('subscribe')) {
  508. $out .= html_btn('subscribe',$ID,'',array('do' => 'subscribe',));
  509. }
  510. break;
  511. case 'backlink':
  512. if(actionOK('backlink'))
  513. $out .= html_btn('backlink',$ID,'',array('do' => 'backlink'));
  514. break;
  515. case 'profile':
  516. if($conf['useacl'] && isset($_SERVER['REMOTE_USER']) && $auth &&
  517. $auth->canDo('Profile') && ($ACT!='profile')){
  518. $out .= html_btn('profile',$ID,'',array('do' => 'profile'));
  519. }
  520. break;
  521. default:
  522. $out .= '[unknown button type]';
  523. break;
  524. }
  525. if ($return) return $out;
  526. print $out;
  527. return $out ? true : false;
  528. }
  529. /**
  530. * Like the action buttons but links
  531. *
  532. * Available links are
  533. *
  534. * edit - edit/create/show link
  535. * history - old revisions
  536. * recent - recent changes
  537. * login - login/logout link - if ACL enabled
  538. * profile - user profile link (if logged in)
  539. * index - The index
  540. * admin - admin page - if enough rights
  541. * top - a back to top link
  542. * back - a back to parent link - if available
  543. * backlink - links to the list of backlinks
  544. * subscribe/subscription - subscribe/unsubscribe link
  545. *
  546. * @author Andreas Gohr <andi@splitbrain.org>
  547. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  548. * @see tpl_button
  549. */
  550. function tpl_actionlink($type,$pre='',$suf='',$inner='',$return=false){
  551. global $ID;
  552. global $INFO;
  553. global $REV;
  554. global $ACT;
  555. global $conf;
  556. global $lang;
  557. global $auth;
  558. // check disabled actions and fix the badly named ones
  559. $ctype = $type;
  560. if($type == 'history') $ctype='revisions';
  561. if(!actionOK($ctype)) return false;
  562. $out = '';
  563. switch($type){
  564. case 'edit':
  565. // most complicated type - we need to decide on current action
  566. if($ACT == 'show' || $ACT == 'search'){
  567. if($INFO['writable']){
  568. if(!empty($INFO['draft'])) {
  569. $out .= tpl_link(wl($ID,'do=draft'),
  570. $pre.(($inner)?$inner:$lang['btn_draft']).$suf,
  571. 'class="action edit" accesskey="e" rel="nofollow"',1);
  572. } else {
  573. if($INFO['exists']){
  574. $out .= tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  575. $pre.(($inner)?$inner:$lang['btn_edit']).$suf,
  576. 'class="action edit" accesskey="e" rel="nofollow"',1);
  577. }else{
  578. $out .= tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  579. $pre.(($inner)?$inner:$lang['btn_create']).$suf,
  580. 'class="action create" accesskey="e" rel="nofollow"',1);
  581. }
  582. }
  583. }else{
  584. if(actionOK('source')) //pseudo action
  585. $out .= tpl_link(wl($ID,'do=edit&amp;rev='.$REV),
  586. $pre.(($inner)?$inner:$lang['btn_source']).$suf,
  587. 'class="action source" accesskey="v" rel="nofollow"',1);
  588. }
  589. }else{
  590. $out .= tpl_link(wl($ID,'do=show'),
  591. $pre.(($inner)?$inner:$lang['btn_show']).$suf,
  592. 'class="action show" accesskey="v" rel="nofollow"',1);
  593. }
  594. break;
  595. case 'history':
  596. if(actionOK('revisions'))
  597. $out .= tpl_link(wl($ID,'do=revisions'),
  598. $pre.(($inner)?$inner:$lang['btn_revs']).$suf,
  599. 'class="action revisions" accesskey="o" rel="nofollow"',1);
  600. break;
  601. case 'recent':
  602. if(actionOK('recent'))
  603. $out .= tpl_link(wl($ID,'do=recent'),
  604. $pre.(($inner)?$inner:$lang['btn_recent']).$suf,
  605. 'class="action recent" accesskey="r" rel="nofollow"',1);
  606. break;
  607. case 'index':
  608. if(actionOK('index'))
  609. $out .= tpl_link(wl($ID,'do=index'),
  610. $pre.(($inner)?$inner:$lang['btn_index']).$suf,
  611. 'class="action index" accesskey="x" rel="nofollow"',1);
  612. break;
  613. case 'top':
  614. $out .= '<a href="#dokuwiki__top" class="action top" accesskey="x">'.
  615. $pre.(($inner)?$inner:$lang['btn_top']).$suf.'</a>';
  616. break;
  617. case 'back':
  618. if ($parent = tpl_getparent($ID)) {
  619. $out .= tpl_link(wl($parent,'do=show'),
  620. $pre.(($inner)?$inner:$lang['btn_back']).$suf,
  621. 'class="action back" accesskey="b" rel="nofollow"',1);
  622. }
  623. break;
  624. case 'login':
  625. if($conf['useacl'] && $auth){
  626. if($_SERVER['REMOTE_USER']){
  627. $out .= tpl_link(wl($ID,'do=logout&amp;sectok='.getSecurityToken()),
  628. $pre.(($inner)?$inner:$lang['btn_logout']).$suf,
  629. 'class="action logout" rel="nofollow"',1);
  630. }else{
  631. $out .= tpl_link(wl($ID,'do=login&amp;sectok='.getSecurityToken()),
  632. $pre.(($inner)?$inner:$lang['btn_login']).$suf,
  633. 'class="action login" rel="nofollow"',1);
  634. }
  635. }
  636. break;
  637. case 'admin':
  638. if($INFO['ismanager']){
  639. $out .= tpl_link(wl($ID,'do=admin'),
  640. $pre.(($inner)?$inner:$lang['btn_admin']).$suf,
  641. 'class="action admin" rel="nofollow"',1);
  642. }
  643. break;
  644. case 'revert':
  645. if($INFO['ismanager'] && $REV && $INFO['writable'] && actionOK('revert')){
  646. $out .= tpl_link(wl($ID,array('do' => 'revert', 'rev' => $REV, 'sectok' => getSecurityToken())),
  647. $pre.(($inner)?$inner:$lang['btn_revert']).$suf,
  648. 'class="action revert" rel="nofollow"',1);
  649. }
  650. break;
  651. case 'subscribe':
  652. case 'subscription':
  653. if($conf['useacl'] && $auth && $ACT == 'show' && $conf['subscribers']) {
  654. if($_SERVER['REMOTE_USER']){
  655. if(actionOK('subscribe'))
  656. $out .= tpl_link(wl($ID,'do=subscribe'),
  657. $pre.(($inner)?$inner:$lang['btn_subscribe']).$suf,
  658. 'class="action subscribe" rel="nofollow"',1);
  659. }
  660. }
  661. break;
  662. case 'backlink':
  663. if(actionOK('backlink'))
  664. $out .= tpl_link(wl($ID,'do=backlink'),
  665. $pre.(($inner)?$inner:$lang['btn_backlink']).$suf,
  666. 'class="action backlink" rel="nofollow"',1);
  667. break;
  668. case 'profile':
  669. if($conf['useacl'] && $auth && $_SERVER['REMOTE_USER'] &&
  670. $auth->canDo('Profile') && ($ACT!='profile')){
  671. $out .= tpl_link(wl($ID,'do=profile'),
  672. $pre.(($inner)?$inner:$lang['btn_profile']).$suf,
  673. 'class="action profile" rel="nofollow"',1);
  674. }
  675. break;
  676. default:
  677. $out .= '[unknown link type]';
  678. break;
  679. }
  680. if ($return) return $out;
  681. print $out;
  682. return $out ? true : false;
  683. }
  684. /**
  685. * Wrapper around tpl_button() and tpl_actionlink()
  686. *
  687. * @author Anika Henke <anika@selfthinker.org>
  688. */
  689. function tpl_action($type,$link=0,$wrapper=false,$return=false,$pre='',$suf='',$inner='') {
  690. $out = '';
  691. if ($link) $out .= tpl_actionlink($type,$pre,$suf,$inner,1);
  692. else $out .= tpl_button($type,1);
  693. if ($out && $wrapper) $out = "<$wrapper>$out</$wrapper>";
  694. if ($return) return $out;
  695. print $out;
  696. return $out ? true : false;
  697. }
  698. /**
  699. * Print the search form
  700. *
  701. * If the first parameter is given a div with the ID 'qsearch_out' will
  702. * be added which instructs the ajax pagequicksearch to kick in and place
  703. * its output into this div. The second parameter controls the propritary
  704. * attribute autocomplete. If set to false this attribute will be set with an
  705. * value of "off" to instruct the browser to disable it's own built in
  706. * autocompletion feature (MSIE and Firefox)
  707. *
  708. * @author Andreas Gohr <andi@splitbrain.org>
  709. */
  710. function tpl_searchform($ajax=true,$autocomplete=true){
  711. global $lang;
  712. global $ACT;
  713. global $QUERY;
  714. // don't print the search form if search action has been disabled
  715. if (!actionOk('search')) return false;
  716. print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search"><div class="no">';
  717. print '<input type="hidden" name="do" value="search" />';
  718. print '<input type="text" ';
  719. if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" ';
  720. if(!$autocomplete) print 'autocomplete="off" ';
  721. print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]" />';
  722. print '<input type="submit" value="'.$lang['btn_search'].'" class="button" title="'.$lang['btn_search'].'" />';
  723. if($ajax) print '<div id="qsearch__out" class="ajax_qsearch JSpopup"></div>';
  724. print '</div></form>';
  725. return true;
  726. }
  727. /**
  728. * Print the breadcrumbs trace
  729. *
  730. * @author Andreas Gohr <andi@splitbrain.org>
  731. */
  732. function tpl_breadcrumbs($sep='&raquo;'){
  733. global $lang;
  734. global $conf;
  735. //check if enabled
  736. if(!$conf['breadcrumbs']) return false;
  737. $crumbs = breadcrumbs(); //setup crumb trace
  738. //reverse crumborder in right-to-left mode, add RLM character to fix heb/eng display mixups
  739. if($lang['direction'] == 'rtl') {
  740. $crumbs = array_reverse($crumbs,true);
  741. $crumbs_sep = ' &#8207;<span class="bcsep">'.$sep.'</span>&#8207; ';
  742. } else {
  743. $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
  744. }
  745. //render crumbs, highlight the last one
  746. print '<span class="bchead">'.$lang['breadcrumb'].':</span>';
  747. $last = count($crumbs);
  748. $i = 0;
  749. foreach ($crumbs as $id => $name){
  750. $i++;
  751. echo $crumbs_sep;
  752. if ($i == $last) print '<span class="curid">';
  753. tpl_link(wl($id),hsc($name),'class="breadcrumbs" title="'.$id.'"');
  754. if ($i == $last) print '</span>';
  755. }
  756. return true;
  757. }
  758. /**
  759. * Hierarchical breadcrumbs
  760. *
  761. * This code was suggested as replacement for the usual breadcrumbs.
  762. * It only makes sense with a deep site structure.
  763. *
  764. * @author Andreas Gohr <andi@splitbrain.org>
  765. * @author Nigel McNie <oracle.shinoda@gmail.com>
  766. * @author Sean Coates <sean@caedmon.net>
  767. * @author <fredrik@averpil.com>
  768. * @todo May behave strangely in RTL languages
  769. */
  770. function tpl_youarehere($sep=' &raquo; '){
  771. global $conf;
  772. global $ID;
  773. global $lang;
  774. // check if enabled
  775. if(!$conf['youarehere']) return false;
  776. $parts = explode(':', $ID);
  777. $count = count($parts);
  778. if($GLOBALS['ACT'] == 'search')
  779. {
  780. $parts = array($conf['start']);
  781. $count = 1;
  782. }
  783. echo '<span class="bchead">'.$lang['youarehere'].': </span>';
  784. // always print the startpage
  785. $title = useHeading('navigation') ? p_get_first_heading($conf['start']) : $conf['start'];
  786. if(!$title) $title = $conf['start'];
  787. tpl_link(wl($conf['start']),hsc($title),'title="'.$conf['start'].'"');
  788. // print intermediate namespace links
  789. $part = '';
  790. for($i=0; $i<$count - 1; $i++){
  791. $part .= $parts[$i].':';
  792. $page = $part;
  793. resolve_pageid('',$page,$exists);
  794. if ($page == $conf['start']) continue; // Skip startpage
  795. // output
  796. echo $sep;
  797. if($exists){
  798. $title = useHeading('navigation') ? p_get_first_heading($page) : $parts[$i];
  799. tpl_link(wl($page),hsc($title),'title="'.$page.'"');
  800. }else{
  801. tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2" rel="nofollow"');
  802. }
  803. }
  804. // print current page, skipping start page, skipping for namespace index
  805. if(isset($page) && $page==$part.$parts[$i]) return;
  806. $page = $part.$parts[$i];
  807. if($page == $conf['start']) return;
  808. echo $sep;
  809. if(page_exists($page)){
  810. $title = useHeading('navigation') ? p_get_first_heading($page) : $parts[$i];
  811. tpl_link(wl($page),hsc($title),'title="'.$page.'"');
  812. }else{
  813. tpl_link(wl($page),$parts[$i],'title="'.$page.'" class="wikilink2" rel="nofollow"');
  814. }
  815. return true;
  816. }
  817. /**
  818. * Print info if the user is logged in
  819. * and show full name in that case
  820. *
  821. * Could be enhanced with a profile link in future?
  822. *
  823. * @author Andreas Gohr <andi@splitbrain.org>
  824. */
  825. function tpl_userinfo(){
  826. global $lang;
  827. global $INFO;
  828. if(isset($_SERVER['REMOTE_USER'])){
  829. print $lang['loggedinas'].': '.$INFO['userinfo']['name'].' ('.$_SERVER['REMOTE_USER'].')';
  830. return true;
  831. }
  832. return false;
  833. }
  834. /**
  835. * Print some info about the current page
  836. *
  837. * @author Andreas Gohr <andi@splitbrain.org>
  838. */
  839. function tpl_pageinfo($ret=false){
  840. global $conf;
  841. global $lang;
  842. global $INFO;
  843. global $ID;
  844. // return if we are not allowed to view the page
  845. if (!auth_quickaclcheck($ID)) { return false; }
  846. // prepare date and path
  847. $fn = $INFO['filepath'];
  848. if(!$conf['fullpath']){
  849. if($INFO['rev']){
  850. $fn = str_replace(fullpath($conf['olddir']).'/','',$fn);
  851. }else{
  852. $fn = str_replace(fullpath($conf['datadir']).'/','',$fn);
  853. }
  854. }
  855. $fn = utf8_decodeFN($fn);
  856. $date = dformat($INFO['lastmod']);
  857. // print it
  858. if($INFO['exists']){
  859. $out = '';
  860. $out .= $fn;
  861. $out .= ' &middot; ';
  862. $out .= $lang['lastmod'];
  863. $out .= ': ';
  864. $out .= $date;
  865. if($INFO['editor']){
  866. $out .= ' '.$lang['by'].' ';
  867. $out .= editorinfo($INFO['editor']);
  868. }else{
  869. $out .= ' ('.$lang['external_edit'].')';
  870. }
  871. if($INFO['locked']){
  872. $out .= ' &middot; ';
  873. $out .= $lang['lockedby'];
  874. $out .= ': ';
  875. $out .= editorinfo($INFO['locked']);
  876. }
  877. if($ret){
  878. return $out;
  879. }else{
  880. echo $out;
  881. return true;
  882. }
  883. }
  884. return false;
  885. }
  886. /**
  887. * Prints or returns the name of the given page (current one if none given).
  888. *
  889. * If useheading is enabled this will use the first headline else
  890. * the given ID is used.
  891. *
  892. * @author Andreas Gohr <andi@splitbrain.org>
  893. */
  894. function tpl_pagetitle($id=null, $ret=false){
  895. global $conf;
  896. if(is_null($id)){
  897. global $ID;
  898. $id = $ID;
  899. }
  900. $name = $id;
  901. if (useHeading('navigation')) {
  902. $title = p_get_first_heading($id);
  903. if ($title) $name = $title;
  904. }
  905. if ($ret) {
  906. return hsc($name);
  907. } else {
  908. print hsc($name);
  909. return true;
  910. }
  911. }
  912. /**
  913. * Returns the requested EXIF/IPTC tag from the current image
  914. *
  915. * If $tags is an array all given tags are tried until a
  916. * value is found. If no value is found $alt is returned.
  917. *
  918. * Which texts are known is defined in the functions _exifTagNames
  919. * and _iptcTagNames() in inc/jpeg.php (You need to prepend IPTC
  920. * to the names of the latter one)
  921. *
  922. * Only allowed in: detail.php
  923. *
  924. * @author Andreas Gohr <andi@splitbrain.org>
  925. */
  926. function tpl_img_getTag($tags,$alt='',$src=null){
  927. // Init Exif Reader
  928. global $SRC;
  929. if(is_null($src)) $src = $SRC;
  930. static $meta = null;
  931. if(is_null($meta)) $meta = new JpegMeta($src);
  932. if($meta === false) return $alt;
  933. $info = $meta->getField($tags);
  934. if($info == false) return $alt;
  935. return $info;
  936. }
  937. /**
  938. * Prints the image with a link to the full sized version
  939. *
  940. * Only allowed in: detail.php
  941. */
  942. function tpl_img($maxwidth=0,$maxheight=0){
  943. global $IMG;
  944. $w = tpl_img_getTag('File.Width');
  945. $h = tpl_img_getTag('File.Height');
  946. //resize to given max values
  947. $ratio = 1;
  948. if($w >= $h){
  949. if($maxwidth && $w >= $maxwidth){
  950. $ratio = $maxwidth/$w;
  951. }elseif($maxheight && $h > $maxheight){
  952. $ratio = $maxheight/$h;
  953. }
  954. }else{
  955. if($maxheight && $h >= $maxheight){
  956. $ratio = $maxheight/$h;
  957. }elseif($maxwidth && $w > $maxwidth){
  958. $ratio = $maxwidth/$w;
  959. }
  960. }
  961. if($ratio){
  962. $w = floor($ratio*$w);
  963. $h = floor($ratio*$h);
  964. }
  965. //prepare URLs
  966. $url=ml($IMG,array('cache'=>$_REQUEST['cache']));
  967. $src=ml($IMG,array('cache'=>$_REQUEST['cache'],'w'=>$w,'h'=>$h));
  968. //prepare attributes
  969. $alt=tpl_img_getTag('Simple.Title');
  970. $p = array();
  971. if($w) $p['width'] = $w;
  972. if($h) $p['height'] = $h;
  973. $p['class'] = 'img_detail';
  974. if($alt){
  975. $p['alt'] = $alt;
  976. $p['title'] = $alt;
  977. }else{
  978. $p['alt'] = '';
  979. }
  980. $p = buildAttributes($p);
  981. print '<a href="'.$url.'">';
  982. print '<img src="'.$src.'" '.$p.'/>';
  983. print '</a>';
  984. return true;
  985. }
  986. /**
  987. * This function inserts a 1x1 pixel gif which in reality
  988. * is the indexer function.
  989. *
  990. * Should be called somewhere at the very end of the main.php
  991. * template
  992. */
  993. function tpl_indexerWebBug(){
  994. global $ID;
  995. global $INFO;
  996. if(!$INFO['exists']) return false;
  997. if(isHiddenPage($ID)) return false; //no need to index hidden pages
  998. $p = array();
  999. $p['src'] = DOKU_BASE.'lib/exe/indexer.php?id='.rawurlencode($ID).
  1000. '&'.time();
  1001. $p['width'] = 1;
  1002. $p['height'] = 1;
  1003. $p['alt'] = '';
  1004. $att = buildAttributes($p);
  1005. print "<img $att />";
  1006. return true;
  1007. }
  1008. // configuration methods
  1009. /**
  1010. * tpl_getConf($id)
  1011. *
  1012. * use this function to access template configuration variables
  1013. */
  1014. function tpl_getConf($id){
  1015. global $conf;
  1016. global $tpl_configloaded;
  1017. $tpl = $conf['template'];
  1018. if (!$tpl_configloaded){
  1019. $tconf = tpl_loadConfig();
  1020. if ($tconf !== false){
  1021. foreach ($tconf as $key => $value){
  1022. if (isset($conf['tpl'][$tpl][$key])) continue;
  1023. $conf['tpl'][$tpl][$key] = $value;
  1024. }
  1025. $tpl_configloaded = true;
  1026. }
  1027. }
  1028. return $conf['tpl'][$tpl][$id];
  1029. }
  1030. /**
  1031. * tpl_loadConfig()
  1032. * reads all template configuration variables
  1033. * this function is automatically called by tpl_getConf()
  1034. */
  1035. function tpl_loadConfig(){
  1036. $file = DOKU_TPLINC.'/conf/default.php';
  1037. $conf = array();
  1038. if (!@file_exists($file)) return false;
  1039. // load default config file
  1040. include($file);
  1041. return $conf;
  1042. }
  1043. /**
  1044. * prints the "main content" in the mediamanger popup
  1045. *
  1046. * Depending on the user's actions this may be a list of
  1047. * files in a namespace, the meta editing dialog or
  1048. * a message of referencing pages
  1049. *
  1050. * Only allowed in mediamanager.php
  1051. *
  1052. * @triggers MEDIAMANAGER_CONTENT_OUTPUT
  1053. * @param bool $fromajax - set true when calling this function via ajax
  1054. * @author Andreas Gohr <andi@splitbrain.org>
  1055. */
  1056. function tpl_mediaContent($fromajax=false){
  1057. global $IMG;
  1058. global $AUTH;
  1059. global $INUSE;
  1060. global $NS;
  1061. global $JUMPTO;
  1062. if(is_array($_REQUEST['do'])){
  1063. $do = array_shift(array_keys($_REQUEST['do']));
  1064. }else{
  1065. $do = $_REQUEST['do'];
  1066. }
  1067. if(in_array($do,array('save','cancel'))) $do = '';
  1068. if(!$do){
  1069. if($_REQUEST['edit']){
  1070. $do = 'metaform';
  1071. }elseif(is_array($INUSE)){
  1072. $do = 'filesinuse';
  1073. }else{
  1074. $do = 'filelist';
  1075. }
  1076. }
  1077. // output the content pane, wrapped in an event.
  1078. if(!$fromajax) ptln('<div id="media__content">');
  1079. $data = array( 'do' => $do);
  1080. $evt = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data);
  1081. if ($evt->advise_before()) {
  1082. $do = $data['do'];
  1083. if($do == 'metaform'){
  1084. media_metaform($IMG,$AUTH);
  1085. }elseif($do == 'filesinuse'){
  1086. media_filesinuse($INUSE,$IMG);
  1087. }elseif($do == 'filelist'){
  1088. media_filelist($NS,$AUTH,$JUMPTO);
  1089. }elseif($do == 'searchlist'){
  1090. media_searchlist($_REQUEST['q'],$NS,$AUTH);
  1091. }else{
  1092. msg('Unknown action '.hsc($do),-1);
  1093. }
  1094. }
  1095. $evt->advise_after();
  1096. unset($evt);
  1097. if(!$fromajax) ptln('</div>');
  1098. }
  1099. /**
  1100. * prints the namespace tree in the mediamanger popup
  1101. *
  1102. * Only allowed in mediamanager.php
  1103. *
  1104. * @author Andreas Gohr <andi@splitbrain.org>
  1105. */
  1106. function tpl_mediaTree(){
  1107. global $NS;
  1108. ptln('<div id="media__tree">');
  1109. media_nstree($NS);
  1110. ptln('</div>');
  1111. }
  1112. /**
  1113. * Print a dropdown menu with all DokuWiki actions
  1114. *
  1115. * Note: this will not use any pretty URLs
  1116. *
  1117. * @author Andreas Gohr <andi@splitbrain.org>
  1118. */
  1119. function tpl_actiondropdown($empty='',$button='&gt;'){
  1120. global $ID;
  1121. global $INFO;
  1122. global $REV;
  1123. global $ACT;
  1124. global $conf;
  1125. global $lang;
  1126. global $auth;
  1127. echo '<form method="post" accept-charset="utf-8">'; #FIXME action
  1128. echo '<input type="hidden" name="id" value="'.$ID.'" />';
  1129. if($REV) echo '<input type="hidden" name="rev" value="'.$REV.'" />';
  1130. echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />';
  1131. echo '<select name="do" id="action__selector" class="edit">';
  1132. echo '<option value="">'.$empty.'</option>';
  1133. echo '<optgroup label=" &mdash; ">';
  1134. // 'edit' - most complicated type, we need to decide on current action
  1135. if($ACT == 'show' || $ACT == 'search'){
  1136. if($INFO['writable']){
  1137. if(!empty($INFO['draft'])) {
  1138. echo '<option value="edit">'.$lang['btn_draft'].'</option>';
  1139. } else {
  1140. if($INFO['exists']){
  1141. echo '<option value="edit">'.$lang['btn_edit'].'</option>';
  1142. }else{
  1143. echo '<option value="edit">'.$lang['btn_create'].'</option>';
  1144. }
  1145. }
  1146. }else if(actionOK('source')) { //pseudo action
  1147. echo '<option value="edit">'.$lang['btn_source'].'</option>';
  1148. }
  1149. }else{
  1150. echo '<option value="show">'.$lang['btn_show'].'</option>';
  1151. }
  1152. echo '<option value="revisions">'.$lang['btn_revs'].'</option>';
  1153. if($INFO['ismanager'] && $REV && $INFO['writable'] && actionOK('revert')){
  1154. echo '<option value="revert">'.$lang['btn_revert'].'</option>';
  1155. }
  1156. echo '<option value="backlink">'.$lang['btn_backlink'].'</option>';
  1157. echo '</optgroup>';
  1158. echo '<optgroup label=" &mdash; ">';
  1159. echo '<option value="recent">'.$lang['btn_recent'].'</option>';
  1160. echo '<option value="index">'.$lang['btn_index'].'</option>';
  1161. echo '</optgroup>';
  1162. echo '<optgroup label=" &mdash; ">';
  1163. if($conf['useacl'] && $auth){
  1164. if($_SERVER['REMOTE_USER']){
  1165. echo '<option value="logout">'.$lang['btn_logout'].'</option>';
  1166. }else{
  1167. echo '<option value="login">'.$lang['btn_login'].'</option>';
  1168. }
  1169. }
  1170. if($conf['useacl'] && $auth && $_SERVER['REMOTE_USER'] &&
  1171. $auth->canDo('Profile') && ($ACT!='profile')){
  1172. echo '<option value="profile">'.$lang['btn_profile'].'</option>';
  1173. }
  1174. if($conf['useacl'] && $auth && $ACT == 'show' && $conf['subscribers']){
  1175. if($_SERVER['REMOTE_USER']){
  1176. echo '<option value="subscribe">'.$lang['btn_subscribe'].'</option>';
  1177. }
  1178. }
  1179. if($INFO['ismanager']){
  1180. echo '<option value="admin">'.$lang['btn_admin'].'</option>';
  1181. }
  1182. echo '</optgroup>';
  1183. echo '</select>';
  1184. echo '<input type="submit" value="'.$button.'" id="action__selectorbtn" />';
  1185. echo '</form>';
  1186. }
  1187. /**
  1188. * Print a informational line about the used license
  1189. *
  1190. * @author Andreas Gohr <andi@splitbrain.org>
  1191. * @param string $img - print image? (|button|badge)
  1192. * @param bool $return - when true don't print, but return HTML
  1193. */
  1194. function tpl_license($img='badge',$imgonly=false,$return=false){
  1195. global $license;
  1196. global $conf;
  1197. global $lang;
  1198. if(!$conf['license']) return '';
  1199. if(!is_array($license[$conf['license']])) return '';
  1200. $lic = $license[$conf['license']];
  1201. $out = '<div class="license">';
  1202. if($img){
  1203. $src = license_img($img);
  1204. if($src){
  1205. $out .= '<a href="'.$lic['url'].'" rel="license"';
  1206. if($conf['target']['external']) $out .= ' target="'.$conf['target']['external'].'"';
  1207. $out .= '><img src="'.DOKU_BASE.$src.'" class="medialeft lic'.$img.'" alt="'.$lic['name'].'" /></a> ';
  1208. }
  1209. }
  1210. if(!$imgonly) {
  1211. $out .= $lang['license'];
  1212. $out .= '<a href="'.$lic['url'].'" rel="license" class="urlextern"';
  1213. if(isset($conf['target']['external'])) $out .= ' target="'.$conf['target']['external'].'"';
  1214. $out .= '>'.$lic['name'].'</a>';
  1215. }
  1216. $out .= '</div>';
  1217. if($return) return $out;
  1218. echo $out;
  1219. }
  1220. /**
  1221. * Includes the rendered XHTML of a given page
  1222. *
  1223. * This function is useful to populate sidebars or similar features in a
  1224. * template
  1225. */
  1226. function tpl_include_page($pageid,$print=true){
  1227. global $ID;
  1228. $oldid = $ID;
  1229. $html = p_wiki_xhtml($pageid,'',false);
  1230. $ID = $oldid;
  1231. if(!$print) return $html;
  1232. echo $html;
  1233. }
  1234. /**
  1235. * Display the subscribe form
  1236. *
  1237. * @author Adrian Lang <lang@cosmocode.de>
  1238. */
  1239. function tpl_subscribe() {
  1240. global $INFO;
  1241. global $ID;
  1242. global $lang;
  1243. echo p_locale_xhtml('subscr_form');
  1244. echo '<h2>' . $lang['subscr_m_current_header'] . '</h2>';
  1245. echo '<div class="level2">';
  1246. if ($INFO['subscribed'] === false) {
  1247. echo '<p>' . $lang['subscr_m_not_subscribed'] . '</p>';
  1248. } else {
  1249. echo '<ul>';
  1250. foreach($INFO['subscribed'] as $sub) {
  1251. echo '<li><div class="li">';
  1252. if ($sub['target'] !== $ID) {
  1253. echo '<code class="ns">'.hsc(prettyprint_id($sub['target'])).'</code>';
  1254. } else {
  1255. echo '<code class="page">'.hsc(prettyprint_id($sub['target'])).'</code>';
  1256. }
  1257. $sstl = $lang['subscr_style_'.$sub['style']];
  1258. if(!$sstl) $sstl = hsc($sub['style']);
  1259. echo ' ('.$sstl.') ';
  1260. echo '<a href="'.wl($ID,array('do'=>'subscribe','sub_target'=>$sub['target'],'sub_style'=>$sub['style'],'sub_action'=>'unsubscribe')).'" class="unsubscribe">'.$lang['subscr_m_unsubscribe'].'</a>';
  1261. echo '</div></li>';
  1262. }
  1263. echo '</ul>';
  1264. }
  1265. echo '</div>';
  1266. // Add new subscription form
  1267. echo '<h2>' . $lang['subscr_m_new_header'] . '</h2>';
  1268. echo '<div class="level2">';
  1269. $ns = getNS($ID).':';
  1270. $targets = array(
  1271. $ID => '<code class="page">'.prettyprint_id($ID).'</code>',
  1272. $ns => '<code class="ns">'.prettyprint_id($ns).'</code>',
  1273. );
  1274. $styles = array(
  1275. 'every' => $lang['subscr_style_every'],
  1276. 'digest' => $lang['subscr_style_digest'],
  1277. 'list' => $lang['subscr_style_list'],
  1278. );
  1279. $form = new Doku_Form(array('id' => 'subscribe__form'));
  1280. $form->startFieldset($lang['subscr_m_subscribe']);
  1281. $form->addRadioSet('sub_target', $targets);
  1282. $form->startFieldset($lang['subscr_m_receive']);
  1283. $form->addRadioSet('sub_style', $styles);
  1284. $form->addHidden('sub_action', 'subscribe');
  1285. $form->addHidden('do', 'subscribe');
  1286. $form->addHidden('id', $ID);
  1287. $form->endFieldset();
  1288. $form->addElement(form_makeButton('submit', 'subscribe', $lang['subscr_m_subscribe']));
  1289. html_form('SUBSCRIBE', $form);
  1290. echo '</div>';
  1291. }
  1292. //Setup VIM: ex: et ts=4 enc=utf-8 :