| [ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * HTML output functions 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9 if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/'); 10 if(!defined('NL')) define('NL',"\n"); 11 require_once (DOKU_INC.'inc/parserutils.php'); 12 require_once (DOKU_INC.'inc/form.php'); 13 14 /** 15 * Convenience function to quickly build a wikilink 16 * 17 * @author Andreas Gohr <andi@splitbrain.org> 18 */ 19 function html_wikilink($id,$name=NULL,$search=''){ 20 static $xhtml_renderer = NULL; 21 if(is_null($xhtml_renderer)){ 22 require_once (DOKU_INC.'inc/parser/xhtml.php'); 23 $xhtml_renderer = new Doku_Renderer_xhtml(); 24 } 25 26 return $xhtml_renderer->internallink($id,$name,$search,true,'navigation'); 27 } 28 29 /** 30 * Helps building long attribute lists 31 * 32 * @author Andreas Gohr <andi@splitbrain.org> 33 */ 34 function html_attbuild($attributes){ 35 $ret = ''; 36 foreach ( $attributes as $key => $value ) { 37 $ret .= $key.'="'.formtext($value).'" '; 38 } 39 return trim($ret); 40 } 41 42 /** 43 * The loginform 44 * 45 * @author Andreas Gohr <andi@splitbrain.org> 46 */ 47 function html_login(){ 48 global $lang; 49 global $conf; 50 global $ID; 51 global $auth; 52 53 print p_locale_xhtml('login'); 54 print '<div class="centeralign">'.NL; 55 $form = new Doku_Form('dw__login'); 56 $form->startFieldset($lang['btn_login']); 57 $form->addHidden('id', $ID); 58 $form->addHidden('do', 'login'); 59 $form->addElement(form_makeTextField('u', ((!$_REQUEST['http_credentials']) ? $_REQUEST['u'] : ''), $lang['user'], 'focus__this', 'block')); 60 $form->addElement(form_makePasswordField('p', $lang['pass'], '', 'block')); 61 if($conf['rememberme']) { 62 $form->addElement(form_makeCheckboxField('r', '1', $lang['remember'], 'remember__me', 'simple')); 63 } 64 $form->addElement(form_makeButton('submit', '', $lang['btn_login'])); 65 $form->endFieldset(); 66 html_form('login', $form); 67 68 if($auth && $auth->canDo('addUser') && actionOK('register')){ 69 print '<p>'; 70 print $lang['reghere']; 71 print ': <a href="'.wl($ID,'do=register').'" rel="nofollow" class="wikilink1">'.$lang['register'].'</a>'; 72 print '</p>'; 73 } 74 75 if ($auth && $auth->canDo('modPass') && actionOK('resendpwd')) { 76 print '<p>'; 77 print $lang['pwdforget']; 78 print ': <a href="'.wl($ID,'do=resendpwd').'" rel="nofollow" class="wikilink1">'.$lang['btn_resendpwd'].'</a>'; 79 print '</p>'; 80 } 81 print '</div>'.NL; 82 } 83 84 /** 85 * prints a section editing button 86 * used as a callback in html_secedit 87 * 88 * @author Andreas Gohr <andi@splitbrain.org> 89 */ 90 function html_secedit_button($matches){ 91 global $ID; 92 global $INFO; 93 94 $section = $matches[2]; 95 $name = $matches[1]; 96 97 $secedit = ''; 98 $secedit .= '<div class="secedit">'; 99 $secedit .= html_btn('secedit',$ID,'', 100 array('do' => 'edit', 101 'lines' => "$section", 102 'rev' => $INFO['lastmod']), 103 'post', $name); 104 $secedit .= '</div>'; 105 return $secedit; 106 } 107 108 /** 109 * inserts section edit buttons if wanted or removes the markers 110 * 111 * @author Andreas Gohr <andi@splitbrain.org> 112 */ 113 function html_secedit($text,$show=true){ 114 global $INFO; 115 116 if($INFO['writable'] && $show && !$INFO['rev']){ 117 $text = preg_replace_callback('#<!-- SECTION "(.*?)" \[(\d+-\d*)\] -->#', 118 'html_secedit_button', $text); 119 }else{ 120 $text = preg_replace('#<!-- SECTION "(.*?)" \[(\d+-\d*)\] -->#','',$text); 121 } 122 123 return $text; 124 } 125 126 /** 127 * Just the back to top button (in its own form) 128 * 129 * @author Andreas Gohr <andi@splitbrain.org> 130 */ 131 function html_topbtn(){ 132 global $lang; 133 134 $ret = ''; 135 $ret = '<a class="nolink" href="#dokuwiki__top"><input type="button" class="button" value="'.$lang['btn_top'].'" onclick="window.scrollTo(0, 0)" title="'.$lang['btn_top'].'" /></a>'; 136 137 return $ret; 138 } 139 140 /** 141 * Displays a button (using its own form) 142 * If tooltip exists, the access key tooltip is replaced. 143 * 144 * @author Andreas Gohr <andi@splitbrain.org> 145 */ 146 function html_btn($name,$id,$akey,$params,$method='get',$tooltip=''){ 147 global $conf; 148 global $lang; 149 150 $label = $lang['btn_'.$name]; 151 152 $ret = ''; 153 $tip = ''; 154 155 //filter id (without urlencoding) 156 $id = idfilter($id,false); 157 158 //make nice URLs even for buttons 159 if($conf['userewrite'] == 2){ 160 $script = DOKU_BASE.DOKU_SCRIPT.'/'.$id; 161 }elseif($conf['userewrite']){ 162 $script = DOKU_BASE.$id; 163 }else{ 164 $script = DOKU_BASE.DOKU_SCRIPT; 165 $params['id'] = $id; 166 } 167 168 $ret .= '<form class="button btn_'.$name.'" method="'.$method.'" action="'.$script.'"><div class="no">'; 169 170 if(is_array($params)){ 171 reset($params); 172 while (list($key, $val) = each($params)) { 173 $ret .= '<input type="hidden" name="'.$key.'" '; 174 $ret .= 'value="'.htmlspecialchars($val).'" />'; 175 } 176 } 177 178 if ($tooltip!='') { 179 $tip = htmlspecialchars($tooltip); 180 }else{ 181 $tip = htmlspecialchars($label); 182 } 183 184 $ret .= '<input type="submit" value="'.htmlspecialchars($label).'" class="button" '; 185 if($akey){ 186 $tip .= ' ['.strtoupper($akey).']'; 187 $ret .= 'accesskey="'.htmlspecialchars($label).' '.$akey.'" '; 188 } 189 $ret .= 'title="'.$tip.'" '; 190 $ret .= '/>'; 191 $ret .= '</div></form>'; 192 193 return $ret; 194 } 195 196 /** 197 * show a wiki page 198 * 199 * @author Andreas Gohr <andi@splitbrain.org> 200 */ 201 function html_show($txt=''){ 202 global $ID; 203 global $REV; 204 global $HIGH; 205 global $INFO; 206 //disable section editing for old revisions or in preview 207 if($txt || $REV){ 208 $secedit = false; 209 }else{ 210 $secedit = true; 211 } 212 213 if ($txt){ 214 //PreviewHeader 215 echo '<br id="scroll__here" />'; 216 echo p_locale_xhtml('preview'); 217 echo '<div class="preview">'; 218 $html = html_secedit(p_render('xhtml',p_get_instructions($txt),$info),$secedit); 219 if($INFO['prependTOC']) $html = tpl_toc(true).$html; 220 echo $html; 221 echo '<div class="clearer"></div>'; 222 echo '</div>'; 223 224 }else{ 225 if ($REV) print p_locale_xhtml('showrev'); 226 $html = p_wiki_xhtml($ID,$REV,true); 227 $html = html_secedit($html,$secedit); 228 if($INFO['prependTOC']) $html = tpl_toc(true).$html; 229 $html = html_hilight($html,$HIGH); 230 echo $html; 231 } 232 } 233 234 /** 235 * ask the user about how to handle an exisiting draft 236 * 237 * @author Andreas Gohr <andi@splitbrain.org> 238 */ 239 function html_draft(){ 240 global $INFO; 241 global $ID; 242 global $lang; 243 global $conf; 244 $draft = unserialize(io_readFile($INFO['draft'],false)); 245 $text = cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true)); 246 247 print p_locale_xhtml('draft'); 248 $form = new Doku_Form('dw__editform'); 249 $form->addHidden('id', $ID); 250 $form->addHidden('date', $draft['date']); 251 $form->addElement(form_makeWikiText($text, array('readonly'=>'readonly'))); 252 $form->addElement(form_makeOpenTag('div', array('id'=>'draft__status'))); 253 $form->addElement($lang['draftdate'].' '. strftime($conf['dformat'],filemtime($INFO['draft']))); 254 $form->addElement(form_makeCloseTag('div')); 255 $form->addElement(form_makeButton('submit', 'recover', $lang['btn_recover'], array('tabindex'=>'1'))); 256 $form->addElement(form_makeButton('submit', 'draftdel', $lang['btn_draftdel'], array('tabindex'=>'2'))); 257 $form->addElement(form_makeButton('submit', 'show', $lang['btn_cancel'], array('tabindex'=>'3'))); 258 html_form('draft', $form); 259 } 260 261 /** 262 * Highlights searchqueries in HTML code 263 * 264 * @author Andreas Gohr <andi@splitbrain.org> 265 * @author Harry Fuecks <hfuecks@gmail.com> 266 */ 267 function html_hilight($html,$phrases){ 268 $regex = join('|',array_map('preg_quote_cb',array_filter((array) $phrases))); 269 270 if ($regex === '') return $html; 271 $html = preg_replace_callback("/((<[^>]*)|$regex)/ui",'html_hilight_callback',$html); 272 return $html; 273 } 274 275 /** 276 * Callback used by html_hilight() 277 * 278 * @author Harry Fuecks <hfuecks@gmail.com> 279 */ 280 function html_hilight_callback($m) { 281 $hlight = unslash($m[0]); 282 if ( !isset($m[2])) { 283 $hlight = '<span class="search_hit">'.$hlight.'</span>'; 284 } 285 return $hlight; 286 } 287 288 /** 289 * Run a search and display the result 290 * 291 * @author Andreas Gohr <andi@splitbrain.org> 292 */ 293 function html_search(){ 294 require_once (DOKU_INC.'inc/search.php'); 295 require_once (DOKU_INC.'inc/fulltext.php'); 296 global $conf; 297 global $QUERY; 298 global $ID; 299 global $lang; 300 301 print p_locale_xhtml('searchpage'); 302 flush(); 303 304 //check if search is restricted to namespace 305 if(preg_match('/([^@]*)@([^@]*)/',$QUERY,$match)) { 306 $id = cleanID($match[1]); 307 if(empty($id)) { 308 print '<div class="nothing">'.$lang['nothingfound'].'</div>'; 309 flush(); 310 return; 311 } 312 } else { 313 $id = cleanID($QUERY); 314 } 315 316 //show progressbar 317 print '<div class="centeralign" id="dw__loading">'.NL; 318 print '<script type="text/javascript" charset="utf-8"><!--//--><![CDATA[//><!--'.NL; 319 print 'showLoadBar();'.NL; 320 print '//--><!]]></script>'.NL; 321 print '<br /></div>'.NL; 322 flush(); 323 324 //do quick pagesearch 325 $data = array(); 326 327 $data = ft_pageLookup($id); 328 if(count($data)){ 329 print '<div class="search_quickresult">'; 330 print '<h3>'.$lang['quickhits'].':</h3>'; 331 print '<ul class="search_quickhits">'; 332 foreach($data as $id){ 333 print '<li> '; 334 $ns = getNS($id); 335 if($ns){ 336 $name = shorten(noNS($id), ' ('.$ns.')',30); 337 }else{ 338 $name = $id; 339 } 340 print html_wikilink(':'.$id,$name); 341 print '</li> '; 342 } 343 print '</ul> '; 344 //clear float (see http://www.complexspiral.com/publications/containing-floats/) 345 print '<div class="clearer"> </div>'; 346 print '</div>'; 347 } 348 flush(); 349 350 //do fulltext search 351 $data = ft_pageSearch($QUERY,$regex); 352 if(count($data)){ 353 $num = 1; 354 foreach($data as $id => $cnt){ 355 print '<div class="search_result">'; 356 print html_wikilink(':'.$id,useHeading('navigation')?NULL:$id,$regex); 357 print ': <span class="search_cnt">'.$cnt.' '.$lang['hits'].'</span><br />'; 358 if($num < 15){ // create snippets for the first number of matches only #FIXME add to conf ? 359 print '<div class="search_snippet">'.ft_snippet($id,$regex).'</div>'; 360 } 361 print '</div>'; 362 flush(); 363 $num++; 364 } 365 }else{ 366 print '<div class="nothing">'.$lang['nothingfound'].'</div>'; 367 } 368 369 //hide progressbar 370 print '<script type="text/javascript" charset="utf-8"><!--//--><![CDATA[//><!--'.NL; 371 print 'hideLoadBar("dw__loading");'.NL; 372 print '//--><!]]></script>'.NL; 373 flush(); 374 } 375 376 /** 377 * Display error on locked pages 378 * 379 * @author Andreas Gohr <andi@splitbrain.org> 380 */ 381 function html_locked(){ 382 global $ID; 383 global $conf; 384 global $lang; 385 global $INFO; 386 387 $locktime = filemtime(wikiLockFN($ID)); 388 $expire = @strftime($conf['dformat'], $locktime + $conf['locktime'] ); 389 $min = round(($conf['locktime'] - (time() - $locktime) )/60); 390 391 print p_locale_xhtml('locked'); 392 print '<ul>'; 393 print '<li><div class="li"><strong>'.$lang['lockedby'].':</strong> '.$INFO['locked'].'</div></li>'; 394 print '<li><div class="li"><strong>'.$lang['lockexpire'].':</strong> '.$expire.' ('.$min.' min)</div></li>'; 395 print '</ul>'; 396 } 397 398 /** 399 * list old revisions 400 * 401 * @author Andreas Gohr <andi@splitbrain.org> 402 * @author Ben Coburn <btcoburn@silicodon.net> 403 */ 404 function html_revisions($first=0){ 405 global $ID; 406 global $INFO; 407 global $conf; 408 global $lang; 409 /* we need to get one additionally log entry to be able to 410 * decide if this is the last page or is there another one. 411 * see html_recent() 412 */ 413 $revisions = getRevisions($ID, $first, $conf['recent']+1); 414 if(count($revisions)==0 && $first!=0){ 415 $first=0; 416 $revisions = getRevisions($ID, $first, $conf['recent']+1);; 417 } 418 $hasNext = false; 419 if (count($revisions)>$conf['recent']) { 420 $hasNext = true; 421 array_pop($revisions); // remove extra log entry 422 } 423 424 $date = @strftime($conf['dformat'],$INFO['lastmod']); 425 426 print p_locale_xhtml('revisions'); 427 428 $form = new Doku_Form('page__revisions', wl($ID)); 429 $form->addElement(form_makeOpenTag('ul')); 430 if($INFO['exists'] && $first==0){ 431 if (isset($INFO['meta']) && isset($INFO['meta']['last_change']) && $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) 432 $form->addElement(form_makeOpenTag('li', array('class' => 'minor'))); 433 else 434 $form->addElement(form_makeOpenTag('li')); 435 $form->addElement(form_makeOpenTag('div', array('class' => 'li'))); 436 $form->addElement(form_makeTag('input', array( 437 'type' => 'checkbox', 438 'name' => 'rev2[]', 439 'value' => 'current'))); 440 441 $form->addElement(form_makeOpenTag('span', array('class' => 'date'))); 442 $form->addElement($date); 443 $form->addElement(form_makeCloseTag('span')); 444 445 $form->addElement(form_makeTag('img', array( 446 'src' => DOKU_BASE.'lib/images/blank.gif', 447 'width' => '15', 448 'height' => '11', 449 'alt' => ''))); 450 451 $form->addElement(form_makeOpenTag('a', array( 452 'class' => 'wikilink1', 453 'href' => wl($ID)))); 454 $form->addElement($ID); 455 $form->addElement(form_makeCloseTag('a')); 456 457 $form->addElement(form_makeOpenTag('span', array('class' => 'sum'))); 458 $form->addElement(' – '); 459 $form->addElement(htmlspecialchars($INFO['sum'])); 460 $form->addElement(form_makeCloseTag('span')); 461 462 $form->addElement(form_makeOpenTag('span', array('class' => 'user'))); 463 $form->addElement((empty($INFO['editor']))?('('.$lang['external_edit'].')'):editorinfo($INFO['editor'])); 464 $form->addElement(form_makeCloseTag('span')); 465 466 $form->addElement('('.$lang['current'].')'); 467 $form->addElement(form_makeCloseTag('div')); 468 $form->addElement(form_makeCloseTag('li')); 469 } 470 471 foreach($revisions as $rev){ 472 $date = strftime($conf['dformat'],$rev); 473 $info = getRevisionInfo($ID,$rev,true); 474 $exists = page_exists($ID,$rev); 475 476 if ($info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) 477 $form->addElement(form_makeOpenTag('li', array('class' => 'minor'))); 478 else 479 $form->addElement(form_makeOpenTag('li')); 480 $form->addElement(form_makeOpenTag('div', array('class' => 'li'))); 481 if($exists){ 482 $form->addElement(form_makeTag('input', array( 483 'type' => 'checkbox', 484 'name' => 'rev2[]', 485 'value' => $rev))); 486 }else{ 487 $form->addElement(form_makeTag('img', array( 488 'src' => DOKU_BASE.'lib/images/blank.gif', 489 'width' => 14, 490 'height' => 11, 491 'alt' => ''))); 492 } 493 494 $form->addElement(form_makeOpenTag('span', array('class' => 'date'))); 495 $form->addElement($date); 496 $form->addElement(form_makeCloseTag('span')); 497 498 if($exists){ 499 $form->addElement(form_makeOpenTag('a', array('href' => wl(