1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Esther Brunner <wikidesign@gmail.com> 5 */ 6 7// must be run within Dokuwiki 8if(!defined('DOKU_INC')) die(); 9 10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 11require_once(DOKU_PLUGIN.'action.php'); 12 13if (!defined('NL')) define('NL',"\n"); 14 15class action_plugin_discussion extends DokuWiki_Action_Plugin{ 16 17 /** 18 * Return some info 19 */ 20 function getInfo(){ 21 return array( 22 'author' => 'Esther Brunner', 23 'email' => 'wikidesign@gmail.com', 24 'date' => '2006-11-06', 25 'name' => 'Discussion Plugin', 26 'desc' => 'Enables discussion features', 27 'url' => 'http://wiki:splitbrain.org/plugin:discussion', 28 ); 29 } 30 31 /** 32 * Register the eventhandlers 33 */ 34 function register(&$contr){ 35 $contr->register_hook( 36 'ACTION_ACT_PREPROCESS', 37 'BEFORE', 38 $this, 39 'handle_act_preprocess', 40 array() 41 ); 42 $contr->register_hook( 43 'TPL_ACT_RENDER', 44 'AFTER', 45 $this, 46 'comments', 47 array() 48 ); 49 } 50 51 /** 52 * Main function; dispatches the comment actions 53 */ 54 function comments(&$event, $param){ 55 if ($event->data != 'show') return; // nothing to do for us 56 57 $cid = $_REQUEST['cid']; 58 59 switch ($_REQUEST['comment']){ 60 61 case 'add': 62 $comment = array( 63 'user' => $_REQUEST['user'], 64 'name' => $_REQUEST['name'], 65 'mail' => $_REQUEST['mail'], 66 'url' => $_REQUEST['url'], 67 'address' => $_REQUEST['address'], 68 'date' => $_REQUEST['date'], 69 'raw' => cleanText($_REQUEST['text']) 70 ); 71 $repl = $_REQUEST['reply']; 72 $this->_add($comment, $repl); 73 break; 74 75 case 'edit': 76 $this->_show(NULL, $cid); 77 break; 78 79 case 'save': 80 $raw = cleanText($_REQUEST['text']); 81 $this->_save($cid, $raw); 82 break; 83 84 case 'toogle': 85 $this->_save($cid, '', true); 86 break; 87 88 default: // 'show' => $this->_show(), 'reply' => $this->_show($cid) 89 $this->_show($cid); 90 } 91 } 92 93 /** 94 * Shows all comments of the current page 95 */ 96 function _show($reply = NULL, $edit = NULL){ 97 global $ID; 98 99 // get discussion meta file name 100 $file = metaFN($ID, '.comments'); 101 102 if (!file_exists($file)) return true; // no comments at all 103 104 $data = unserialize(io_readFile($file, false)); 105 106 if ($data['status'] == 0) return true; // comments are off 107 108 // section title 109 $title = $this->getLang('discussion'); 110 $secid = cleanID($title); 111 echo '<h2><a name="'.$secid.'" id="'.$secid.'">'.$title.'</a></h2>'; 112 echo '<div class="level2">'; 113 114 // now display the comments 115 if (isset($data['comments'])){ 116 foreach ($data['comments'] as $key => $value){ 117 if ($key == $edit) $this->_form($value['raw'], 'save', $edit); // edit form 118 else $this->_print($key, $data, '', $reply); 119 } 120 } 121 122 // comment form 123 if (($data['status'] == 1) && !$reply && !$edit) $this->_form(''); 124 125 echo '</div>'; 126 127 return true; 128 } 129 130 /** 131 * Adds a new comment and then displays all comments 132 */ 133 function _add($comment, $parent){ 134 global $ID; 135 global $TEXT; 136 137 $otxt = $TEXT; // set $TEXT to comment text for wordblock check 138 $TEXT = $comment['raw']; 139 140 // spamcheck against the DokuWiki blacklist 141 if (checkwordblock()){ 142 msg($this->getLang('wordblock'), -1); 143 $this->_show(); 144 return false; 145 } 146 147 $TEXT = $otxt; // restore global $TEXT 148 149 // get discussion meta file name 150 $file = metaFN($ID, '.comments'); 151 152 $data = array(); 153 $data = unserialize(io_readFile($file, false)); 154 155 if ($data['status'] != 1) return false; // comments off or closed 156 if ((!$this->getConf('allowguests')) 157 && ($comment['user'] != $_SERVER['REMOTE_USER'])) 158 return false; // guest comments not allowed 159 160 if ($comment['date']) $date = strtotime($comment['date']); 161 else $date = time(); 162 if ($date == -1) $date = time(); 163 $cid = md5($comment['user'].$date); // create a unique id 164 165 if (!is_array($data['comments'][$parent])) $parent = NULL; // invalid parent comment 166 167 // render the comment 168 $xhtml = $this->_render($comment['raw']); 169 170 // fill in the new comment 171 $data['comments'][$cid] = array( 172 'user' => htmlspecialchars($comment['user']), 173 'name' => htmlspecialchars($comment['name']), 174 'mail' => htmlspecialchars($comment['mail']), 175 'date' => $date, 176 'show' => true, 177 'raw' => trim($comment['raw']), 178 'xhtml' => $xhtml, 179 'parent' => $parent, 180 'replies' => array() 181 ); 182 if ($comment['url']) 183 $data['comments'][$cid]['url'] = htmlspecialchars($comment['url']); 184 if ($comment['address']) 185 $data['comments'][$cid]['address'] = htmlspecialchars($comment['address']); 186 187 // update parent comment 188 if ($parent) $data['comments'][$parent]['replies'][] = $cid; 189 190 // update the number of comments 191 $data['number']++; 192 193 // save the comment metadata file 194 io_saveFile($file, serialize($data)); 195 $this->_addLogEntry($date, $ID, 'cc', '', $cid); 196 197 // notify subscribers of the page 198 $this->_notify($data['comments'][$cid]); 199 200 $this->_show(); 201 return true; 202 } 203 204 /** 205 * Saves the comment with the given ID and then displays all comments 206 */ 207 function _save($cid, $raw, $toogle = false){ 208 global $ID; 209 global $TEXT; 210 global $INFO; 211 212 $otxt = $TEXT; // set $TEXT to comment text for wordblock check 213 $TEXT = $raw; 214 215 // spamcheck against the DokuWiki blacklist 216 if (checkwordblock()){ 217 msg($this->getLang('wordblock'), -1); 218 $this->_show(); 219 return false; 220 } 221 222 $TEXT = $otxt; // restore global $TEXT 223 224 // get discussion meta file name 225 $file = metaFN($ID, '.comments'); 226 227 $data = array(); 228 $data = unserialize(io_readFile($file, false)); 229 230 // someone else was trying to edit our comment -> abort 231 if (($data['comments'][$cid]['user'] != $_SERVER['REMOTE_USER']) 232 && ($INFO['perm'] != AUTH_ADMIN)) return false; 233 234 $date = time(); 235 236 if ($toogle){ // toogle visibility 237 $now = $data['comments'][$cid]['show']; 238 $data['comments'][$cid]['show'] = !$now; 239 $data['number'] = $this->_count($data); 240 241 $type = ($data['comments'][$cid]['show'] ? 'sc' : 'hc'); 242 243 } elseif (!$raw){ // remove the comment 244 unset($data['comments'][$cid]); 245 $data['number'] = $this->_count($data); 246 247 $type = 'dc'; 248 249 } else { // save changed comment 250 $xhtml = $this->_render($raw); 251 252 // now change the comment's content 253 $data['comments'][$cid]['edited'] = $date; 254 $data['comments'][$cid]['raw'] = trim($raw); 255 $data['comments'][$cid]['xhtml'] = $xhtml; 256 257 $type = 'ec'; 258 } 259 260 // save the comment metadata file 261 io_saveFile($file, serialize($data)); 262 $this->_addLogEntry($date, $ID, $type, '', $cid); 263 264 $this->_show(); 265 return true; 266 } 267 268 /** 269 * Prints an individual comment 270 */ 271 function _print($cid, &$data, $parent = '', $reply = '', $visible = true){ 272 global $conf; 273 global $lang; 274 global $ID; 275 global $INFO; 276 277 $comment = $data['comments'][$cid]; 278 279 if (!is_array($comment)) return false; // corrupt datatype 280 281 if ($comment['parent'] != $parent) return true; // reply to an other comment 282 283 if (!$comment['show']){ // comment hidden 284 if ($INFO['perm'] == AUTH_ADMIN) echo '<div class="comment_hidden">'.NL; 285 else return true; 286 } 287 288 // comment head with date and user data 289 echo '<div class="comment_head">'.NL; 290 echo '<a name="comment__'.$cid.'" id="comment__'.$cid.'">'.NL; 291 292 // show gravatar image 293 if ($this->getConf('usegravatar')){ 294 $default = DOKU_URL.'lib/plugins/discussion/images/default.gif'; 295 $size = $this->getConf('gravatar_size'); 296 if ($comment['mail']) $src = ml('http://www.gravatar.com/avatar.php?'. 297 'gravatar_id='.md5($comment['mail']). 298 '&default='.urlencode($default). 299 '&size='.$size. 300 '&rating='.$this->getConf('gravatar_rating')); 301 else $src = $default; 302 $title = ($comment['name'] ? $comment['name'] : obfuscate($comment['mail'])); 303 echo '<img src="'.$src.'" class="medialeft" title="'.$title.'"'. 304 ' alt="'.$title.'" width="'.$size.'" height="'.$size.'" />'.NL; 305 } 306 307 echo '</a>'.NL; 308 if ($this->getConf('linkemail') && $comment['mail']){ 309 echo $this->email($comment['email'], $comment['name']); 310 } elseif ($comment['url']){ 311 echo $this->external_link($comment['url'], $comment['name'], 'urlextern'); 312 } else { 313 echo $comment['name']; 314 } 315 if ($comment['address']) echo ', '.htmlentities($comment['address']); 316 echo ', '.date($conf['dformat'], $comment['date']); 317 if ($comment['edited']) echo ' ('.date($conf['dformat'], $comment['edited']).')'; 318 echo ':'.NL; 319 echo '</div>'.NL; // class="comment_head" 320 321 // main comment content 322 echo '<div class="comment_body">'.NL; 323 echo $comment['xhtml'].NL; 324 echo '</div>'.NL; // class="comment_body" 325 326 327 if ($visible){ 328 // show hide/show toogle button? 329 echo '<div class="comment_buttons">'.NL; 330 if ($INFO['perm'] == AUTH_ADMIN){ 331 if (!$comment['show']) $label = $this->getLang('btn_show'); 332 else $label = $this->getLang('btn_hide'); 333 334 $this->_button($cid, $label, 'toogle'); 335 } 336 337 // show reply button? 338 if (($data['status'] == 1) && !$reply && $comment['show']) 339 $this->_button($cid, $this->getLang('btn_reply'), 'reply'); 340 341 // show edit button? 342 if ((($comment['user'] == $_SERVER['REMOTE_USER']) && ($comment['user'] != '')) 343 || ($INFO['perm'] == AUTH_ADMIN)) 344 $this->_button($cid, $lang['btn_secedit'], 'edit'); 345 echo '</div>'.NL; // class="comment_buttons" 346 } 347 348 // replies to this comment entry? 349 if (count($comment['replies'])){ 350 echo '<div class="comment_replies">'.NL; 351 $visible = ($comment['show'] && $visible); 352 foreach ($comment['replies'] as $rid){ 353 $this->_print($rid, $data, $cid, $reply, $visible); 354 } 355 echo '</div>'.NL; // class="comment_replies" 356 } 357 358 if (!$comment['show']) echo '</div>'.NL; // class="comment_hidden" 359 360 // reply form 361 if ($reply == $cid){ 362 echo '<div class="comment_replies">'.NL; 363 $this->_form('', 'add', $cid); 364 echo '</div>'.NL; // class="comment_replies" 365 } 366 } 367 368 /** 369 * Outputs the comment form 370 */ 371 function _form($raw = '', $act = 'add', $cid = NULL){ 372 global $lang; 373 global $conf; 374 global $ID; 375 global $INFO; 376 377 // not for unregistered users when guest comments aren't allowed 378 if (!$_SERVER['REMOTE_USER'] && !$this->getConf('allowguests')) return false; 379 380 ?> 381 <div class="comment_form"> 382 <form id="discussion__comment_form" method="post" action="<?php echo script() ?>" accept-charset="<?php echo $lang['encoding'] ?>" onsubmit="return validate(this);"> 383 <div class="no"> 384 <input type="hidden" name="id" value="<?php echo $ID ?>" /> 385 <input type="hidden" name="do" value="show" /> 386 <input type="hidden" name="comment" value="<?php echo $act ?>" /> 387 <?php 388 389 // for adding a comment 390 if ($act == 'add'){ 391 ?> 392 <input type="hidden" name="reply" value="<?php echo $cid ?>" /> 393 <?php 394 // for registered user 395 if ($conf['useacl'] && $_SERVER['REMOTE_USER']){ 396 ?> 397 <input type="hidden" name="user" value="<?php echo $_SERVER['REMOTE_USER'] ?>" /> 398 <input type="hidden" name="name" value="<?php echo $INFO['userinfo']['name'] ?>" /> 399 <input type="hidden" name="mail" value="<?php echo $INFO['userinfo']['mail'] ?>" /> 400 <?php 401 // for guest: show name and e-mail entry fields 402 } else { 403 ?> 404 <input type="hidden" name="user" value="<?php echo clientIP() ?>" /> 405 <div class="comment_name"> 406 <label class="block" for="discussion__comment_name"> 407 <span><?php echo $lang['fullname'] ?>:</span> 408 <input type="text" class="edit" name="name" id="discussion__comment_name" size="50" tabindex="1" /> 409 </label> 410 </div> 411 <div class="comment_mail"> 412 <label class="block" for="discussion__comment_mail"> 413 <span><?php echo $lang['email'] ?>:</span> 414 <input type="text" class="edit" name="mail" id="discussion__comment_mail" size="50" tabindex="2" /> 415 </label> 416 </div> 417 <?php 418 } 419 420 // allow entering an URL 421 if ($this->getConf('urlfield')){ 422 ?> 423 <div class="comment_url"> 424 <label class="block" for="discussion__comment_url"> 425 <span><?php echo $this->getLang('url') ?>:</span> 426 <input type="text" class="edit" name="url" id="discussion__comment_url" size="50" tabindex="3" /> 427 </label> 428 </div> 429 <?php 430 } 431 432 // allow entering an address 433 if ($this->getConf('addressfield')){ 434 ?> 435 <div class="comment_address"> 436 <label class="block" for="discussion__comment_address"> 437 <span><?php echo $this->getLang('address') ?>:</span> 438 <input type="text" class="edit" name="address" id="discussion__comment_address" size="50" tabindex="4" /> 439 </label> 440 </div> 441 <?php 442 } 443 444 // allow setting the comment date 445 if ($this->getConf('datefield') && ($INFO['perm'] == AUTH_ADMIN)){ 446 ?> 447 <div class="comment_date"> 448 <label class="block" for="discussion__comment_date"> 449 <span><?php echo $this->getLang('date') ?>:</span> 450 <input type="text" class="edit" name="date" id="discussion__comment_date" size="50" /> 451 </label> 452 </div> 453 <?php 454 } 455 456 // for saving a comment 457 } else { 458 ?> 459 <input type="hidden" name="cid" value="<?php echo $cid ?>" /> 460 <?php 461 } 462 ?> 463 <div class="comment_text"> 464 <textarea class="edit" name="text" cols="80" rows="10" id="discussion__comment_text" tabindex="5"><?php echo $raw ?></textarea> 465 </div> 466 <input class="button" type="submit" name="submit" value="<?php echo $lang['btn_save'] ?>" tabindex="6" /> 467 </div> 468 </form> 469 </div> 470 <?php 471 if ($this->getConf('usecocomment')) echo $this->_coComment(); 472 } 473 474 /** 475 * Adds a javascript to interact with coComments 476 */ 477 function _coComment(){ 478 global $ID; 479 global $conf; 480 global $INFO; 481 482 $user = $_SERVER['REMOTE_USER']; 483 484 ?> 485 <script type="text/javascript"><!--//--><![CDATA[//><!-- 486 var blogTool = "DokuWiki"; 487 var blogURL = "<?php echo DOKU_URL ?>"; 488 var blogTitle = "<?php echo $conf['title'] ?>"; 489 var postURL = "<?php echo wl($ID, '', true) ?>"; 490 var postTitle = "<?php echo tpl_pagetitle($ID, true) ?>"; 491 <?php 492 if ($user){ 493 ?> 494 var commentAuthor = "<?php echo $INFO['userinfo']['name'] ?>"; 495 <?php 496 } else { 497 ?> 498 var commentAuthorFieldName = "name"; 499 <?php 500 } 501 ?> 502 var commentAuthorLoggedIn = <?php echo ($user ? 'true' : 'false') ?>; 503 var commentFormID = "discussion__comment_form"; 504 var commentTextFieldName = "text"; 505 var commentButtonName = "submit"; 506 var cocomment_force = false; 507 //--><!]]></script> 508 <script type="text/javascript" src="http://www.cocomment.com/js/cocomment.js"> 509 </script> 510 <?php 511 } 512 513 /** 514 * General button function 515 */ 516 function _button($cid, $label, $act){ 517 global $ID; 518 519 ?> 520 <form class="button" method="post" action="<?php echo script() ?>"> 521 <div class="no"> 522 <input type="hidden" name="id" value="<?php echo $ID ?>" /> 523 <input type="hidden" name="do" value="show" /> 524 <input type="hidden" name="comment" value="<?php echo $act ?>" /> 525 <input type="hidden" name="cid" value="<?php echo $cid ?>" /> 526 <input type="submit" value="<?php echo $label ?>" class="button" title="<?php echo $label ?>" /> 527 </div> 528 </form> 529 <?php 530 return true; 531 } 532 533 /** 534 * Adds an entry to the comments changelog 535 * 536 * @author Esther Brunner <wikidesign@gmail.com> 537 * @author Ben Coburn <btcoburn@silicodon.net> 538 */ 539 function _addLogEntry($date, $id, $type = 'cc', $summary = '', $extra = ''){ 540 global $conf; 541 542 $changelog = $conf['metadir'].'/_comments.changes'; 543 544 if(!$date) $date = time(); //use current time if none supplied 545 $remote = $_SERVER['REMOTE_ADDR']; 546 $user = $_SERVER['REMOTE_USER']; 547 548 $strip = array("\t", "\n"); 549 $logline = array( 550 'date' => $date, 551 'ip' => $remote, 552 'type' => str_replace($strip, '', $type), 553 'id' => $id, 554 'user' => $user, 555 'sum' => str_replace($strip, '', $summary), 556 'extra' => str_replace($strip, '', $extra) 557 ); 558 559 // add changelog line 560 $logline = implode("\t", $logline)."\n"; 561 io_saveFile($changelog, $logline, true); //global changelog cache 562 $this->_trimRecentCommentsLog($changelog); 563 } 564 565 /** 566 * Trims the recent comments cache to the last $conf['changes_days'] recent 567 * changes or $conf['recent'] items, which ever is larger. 568 * The trimming is only done once a day. 569 * 570 * @author Ben Coburn <btcoburn@silicodon.net> 571 */ 572 function _trimRecentCommentsLog($changelog){ 573 global $conf; 574 575 if (@file_exists($changelog) && 576 (filectime($changelog) + 86400) < time() && 577 !@file_exists($changelog.'_tmp')){ 578 579 io_lock($changelog); 580 $lines = file($changelog); 581 if (count($lines)<$conf['recent']) { 582 // nothing to trim 583 io_unlock($changelog); 584 return true; 585 } 586 587 io_saveFile($changelog.'_tmp', ''); // presave tmp as 2nd lock 588 $trim_time = time() - $conf['recent_days']*86400; 589 $out_lines = array(); 590 591 for ($i=0; $i<count($lines); $i++) { 592 $log = parseChangelogLine($lines[$i]); 593 if ($log === false) continue; // discard junk 594 if ($log['date'] < $trim_time) { 595 $old_lines[$log['date'].".$i"] = $lines[$i]; // keep old lines for now (append .$i to prevent key collisions) 596 } else { 597 $out_lines[$log['date'].".$i"] = $lines[$i]; // definitely keep these lines 598 } 599 } 600 601 // sort the final result, it shouldn't be necessary, 602 // however the extra robustness in making the changelog cache self-correcting is worth it 603 ksort($out_lines); 604 $extra = $conf['recent'] - count($out_lines); // do we need extra lines do bring us up to minimum 605 if ($extra > 0) { 606 ksort($old_lines); 607 $out_lines = array_merge(array_slice($old_lines,-$extra),$out_lines); 608 } 609 610 // save trimmed changelog 611 io_saveFile($changelog.'_tmp', implode('', $out_lines)); 612 @unlink($changelog); 613 if (!rename($changelog.'_tmp', $changelog)) { 614 // rename failed so try another way... 615 io_unlock($changelog); 616 io_saveFile($changelog, implode('', $out_lines)); 617 @unlink($changelog.'_tmp'); 618 } else { 619 io_unlock($changelog); 620 } 621 return true; 622 } 623 } 624 625 /** 626 * Sends a notify mail on new comment 627 * 628 * @param array $comment data array of the new comment 629 * 630 * @author Andreas Gohr <andi@splitbrain.org> 631 * @author Esther Brunner <wikidesign@gmail.com> 632 */ 633 function _notify($comment){ 634 global $conf; 635 global $ID; 636 637 if (!$conf['subscribers']) return; //subscribers enabled? 638 $bcc = subscriber_addresslist($ID); 639 if (empty($bcc)) return; 640 $to = ''; 641 $text = io_readFile($this->localFN('subscribermail')); 642 643 $text = str_replace('@PAGE@', $ID, $text); 644 $text = str_replace('@TITLE@', $conf['title'], $text); 645 $text = str_replace('@DATE@', date($conf['dformat'], $comment['date']), $text); 646 $text = str_replace('@NAME@', $comment['name'], $text); 647 $text = str_replace('@TEXT@', $comment['raw'], $text); 648 $text = str_replace('@UNSUBSCRIBE@', wl($ID, 'do=unsubscribe', true, '&'), $text); 649 $text = str_replace('@DOKUWIKIURL@', DOKU_URL, $text); 650 651 $subject = '['.$conf['title'].'] '.$this->getLang('mail_newcomment'); 652 653 mail_send($to, $subject, $text, $conf['mailfrom'], '', $bcc); 654 } 655 656 /** 657 * Counts the number of visible comments 658 */ 659 function _count($data){ 660 $number = 0; 661 foreach ($data['comments'] as $cid => $comment){ 662 if ($comment['parent']) continue; 663 if (!$comment['show']) continue; 664 $number++; 665 $rids = $comment['replies']; 666 if (count($rids)) $number = $number + $this->_countReplies($data, $rids); 667 } 668 return $number; 669 } 670 671 function _countReplies(&$data, $rids){ 672 $number = 0; 673 foreach ($rids as $rid){ 674 if (!$data['comments'][$rid]['show']) continue; 675 $number++; 676 $rids = $data['comments'][$rid]['replies']; 677 if (count($rids)) $number = $number + $this->_countReplies($data, $rids); 678 } 679 return $number; 680 } 681 682 /** 683 * Renders the comment text 684 */ 685 function _render($raw){ 686 if ($this->getConf('wikisyntaxok')){ 687 $xhtml = $this->render($raw); 688 } else { // wiki syntax not allowed -> just encode special chars 689 $xhtml = htmlspecialchars(trim($raw)); 690 } 691 return $xhtml; 692 } 693 694 /** 695 * Checks if 'newthread' was given as action, if so we 696 * do handle the event our self and no further checking takes place 697 */ 698 function handle_act_preprocess(&$event, $param){ 699 if ($event->data != 'newthread') return; // nothing to do for us 700 701 global $ACT; 702 global $ID; 703 704 // we can handle it -> prevent others 705 $event->stopPropagation(); 706 $event->preventDefault(); 707 708 $ns = $_REQUEST['ns']; 709 $title = str_replace(':', '', $_REQUEST['title']); 710 $id = ($ns ? $ns.':' : '').cleanID($title); 711 712 // check if we are allowed to create this file 713 if (auth_quickaclcheck($id) >= AUTH_CREATE){ 714 $back = $ID; 715 $ID = $id; 716 $file = wikiFN($ID); 717 718 //check if locked by anyone - if not lock for my self 719 if (checklock($ID)){ 720 $ACT = 'locked'; 721 } else { 722 lock($ID); 723 } 724 725 // prepare the new thread file with default stuff 726 if (!@file_exists($file)){ 727 global $TEXT; 728 global $INFO; 729 global $conf; 730 731 $TEXT = pageTemplate(array($ns.':'.$title)); 732 if (!$TEXT) $TEXT = "<- [[:$back]]\n\n====== $title ======\n\n". 733 "{{gravatar>".$INFO['userinfo']['mail']." }} ". 734 "//".$INFO['userinfo']['name'].", ". 735 date($conf['dformat']).": //\n\n\n\n". 736 "~~DISCUSSION~~\n"; 737 $ACT = 'preview'; 738 } else { 739 $ACT = 'edit'; 740 } 741 } else { 742 $ACT = 'show'; 743 } 744 } 745 746} 747 748//Setup VIM: ex: et ts=4 enc=utf-8 : 749