15fc512fbSwikidesign<?php 25fc512fbSwikidesign/** 35fc512fbSwikidesign * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 45fc512fbSwikidesign * @author Esther Brunner <wikidesign@gmail.com> 55fc512fbSwikidesign */ 65fc512fbSwikidesign 75fc512fbSwikidesign// must be run within Dokuwiki 85fc512fbSwikidesignif (!defined('DOKU_INC')) die(); 95fc512fbSwikidesign 105fc512fbSwikidesignif (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 115fc512fbSwikidesignif (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 125fc512fbSwikidesign 135fc512fbSwikidesignclass helper_plugin_discussion extends DokuWiki_Plugin { 145fc512fbSwikidesign 155fc512fbSwikidesign function getInfo(){ 165fc512fbSwikidesign return array( 175fc512fbSwikidesign 'author' => 'Esther Brunner', 185fc512fbSwikidesign 'email' => 'wikidesign@gmail.com', 196046f25cSwikidesign 'date' => '2007-01-05', 205fc512fbSwikidesign 'name' => 'Discussion Plugin (helper class)', 215fc512fbSwikidesign 'desc' => 'Functions to get info about comments to a wiki page', 225fc512fbSwikidesign 'url' => 'http://www.wikidesign/en/plugin/discussion/start', 235fc512fbSwikidesign ); 245fc512fbSwikidesign } 255fc512fbSwikidesign 265fc512fbSwikidesign function getMethods(){ 275fc512fbSwikidesign $result = array(); 285fc512fbSwikidesign $result[] = array( 295fc512fbSwikidesign 'name' => 'th', 305fc512fbSwikidesign 'desc' => 'returns the header of the comments column for pagelist', 315fc512fbSwikidesign 'return' => array('header' => 'string'), 325fc512fbSwikidesign ); 335fc512fbSwikidesign $result[] = array( 345fc512fbSwikidesign 'name' => 'td', 355fc512fbSwikidesign 'desc' => 'returns the link to the discussion section with number of comments', 365fc512fbSwikidesign 'params' => array( 375fc512fbSwikidesign 'id' => 'string', 385fc512fbSwikidesign 'number of comments (optional)' => 'integer'), 395fc512fbSwikidesign 'return' => array('link' => 'string'), 405fc512fbSwikidesign ); 415fc512fbSwikidesign $result[] = array( 425fc512fbSwikidesign 'name' => 'getThreads', 435fc512fbSwikidesign 'desc' => 'returns pages with discussion sections, sorted by recent comments', 445fc512fbSwikidesign 'params' => array( 455fc512fbSwikidesign 'namespace' => 'string', 465fc512fbSwikidesign 'number (optional)' => 'integer'), 475fc512fbSwikidesign 'return' => array('pages' => 'array'), 485fc512fbSwikidesign ); 495fc512fbSwikidesign $result[] = array( 505fc512fbSwikidesign 'name' => 'getComments', 515fc512fbSwikidesign 'desc' => 'returns recently added or edited comments individually', 525fc512fbSwikidesign 'params' => array( 535fc512fbSwikidesign 'namespace' => 'string', 545fc512fbSwikidesign 'number (optional)' => 'integer'), 555fc512fbSwikidesign 'return' => array('pages' => 'array'), 565fc512fbSwikidesign ); 575fc512fbSwikidesign return $result; 585fc512fbSwikidesign } 595fc512fbSwikidesign 605fc512fbSwikidesign /** 615fc512fbSwikidesign * Returns the column header for the Pagelist Plugin 625fc512fbSwikidesign */ 635fc512fbSwikidesign function th(){ 645fc512fbSwikidesign return $this->getLang('discussion'); 655fc512fbSwikidesign } 665fc512fbSwikidesign 675fc512fbSwikidesign /** 685fc512fbSwikidesign * Returns the link to the discussion section of a page 695fc512fbSwikidesign */ 705fc512fbSwikidesign function td($id, $num = NULL){ 71479dd10fSwikidesign $section = '#discussion__section'; 725fc512fbSwikidesign 735fc512fbSwikidesign if (!isset($num)){ 745fc512fbSwikidesign $cfile = metaFN($id, '.comments'); 755fc512fbSwikidesign $comments = unserialize(io_readFile($cfile, false)); 765fc512fbSwikidesign 775fc512fbSwikidesign $num = $comments['number']; 785fc512fbSwikidesign if ((!$comments['status']) || (($comments['status'] == 2) && (!$num))) return ''; 795fc512fbSwikidesign } 805fc512fbSwikidesign 81fbb94835Swikidesign if ($num == 0) $comment = '0 '.$this->getLang('comments'); 82fbb94835Swikidesign elseif ($num == 1) $comment = '1 '.$this->getLang('comment'); 83fbb94835Swikidesign else $comment = $num.' '.$this->getLang('comments'); 845fc512fbSwikidesign 85479dd10fSwikidesign return '<a href="'.wl($id).$section.'" class="wikilink1" title="'.$id.$section.'">'. 865fc512fbSwikidesign $comment.'</a>'; 875fc512fbSwikidesign } 885fc512fbSwikidesign 895fc512fbSwikidesign /** 905fc512fbSwikidesign * Returns an array of pages with discussion sections, sorted by recent comments 915fc512fbSwikidesign */ 92*264b7327Swikidesign function getThreads($ns, $num = NULL, $all = false){ 935fc512fbSwikidesign global $conf; 945fc512fbSwikidesign 955fc512fbSwikidesign require_once(DOKU_INC.'inc/search.php'); 965fc512fbSwikidesign 975fc512fbSwikidesign $dir = $conf['datadir'].($ns ? '/'.str_replace(':', '/', $ns): ''); 985fc512fbSwikidesign 995fc512fbSwikidesign // returns the list of pages in the given namespace and it's subspaces 1005fc512fbSwikidesign $items = array(); 1015fc512fbSwikidesign search($items, $dir, 'search_allpages', ''); 1025fc512fbSwikidesign 1035fc512fbSwikidesign // add pages with comments to result 1045fc512fbSwikidesign $result = array(); 1055fc512fbSwikidesign foreach ($items as $item){ 1065fc512fbSwikidesign $id = ($ns ? $ns.':' : '').$item['id']; 1075fc512fbSwikidesign 1085fc512fbSwikidesign // some checks 1095fc512fbSwikidesign $perm = auth_quickaclcheck($id); 1105fc512fbSwikidesign if ($perm < AUTH_READ) continue; // skip if no permission 1115fc512fbSwikidesign $file = metaFN($id, '.comments'); 1125fc512fbSwikidesign if (!@file_exists($file)) continue; // skip if no comments file 1135fc512fbSwikidesign $data = unserialize(io_readFile($file, false)); 114*264b7327Swikidesign $status = $data['status']; 115fcb1bc77Swikidesign $number = $data['number']; // skip if comments are off or closed without comments 116*264b7327Swikidesign if (!$all && (!$status || (($status == 2) && (!$number)))) continue; 1175fc512fbSwikidesign 1185fc512fbSwikidesign $date = filemtime($file); 1195fc512fbSwikidesign $meta = p_get_metadata($id); 1205fc512fbSwikidesign $result[$date] = array( 1215fc512fbSwikidesign 'id' => $id, 122*264b7327Swikidesign 'file' => $file, 1235fc512fbSwikidesign 'title' => $meta['title'], 1245fc512fbSwikidesign 'date' => $date, 1255fc512fbSwikidesign 'user' => $meta['creator'], 1265fc512fbSwikidesign 'desc' => $meta['description']['abstract'], 127fcb1bc77Swikidesign 'num' => $number, 128fcb1bc77Swikidesign 'comments' => $this->td($id, $number), 129*264b7327Swikidesign 'status' => $status, 1305fc512fbSwikidesign 'perm' => $perm, 1315fc512fbSwikidesign 'exists' => true, 1325fc512fbSwikidesign ); 1335fc512fbSwikidesign } 1345fc512fbSwikidesign 1355fc512fbSwikidesign // finally sort by time of last comment 1365fc512fbSwikidesign krsort($result); 1375fc512fbSwikidesign 1385fc512fbSwikidesign if (is_numeric($num)) $result = array_slice($result, 0, $num); 1395fc512fbSwikidesign 1405fc512fbSwikidesign return $result; 1415fc512fbSwikidesign } 1425fc512fbSwikidesign 1435fc512fbSwikidesign /** 1445fc512fbSwikidesign * Returns an array of recently added comments to a given page or namespace 1455fc512fbSwikidesign */ 1465fc512fbSwikidesign function getComments($ns, $num = NULL){ 1475fc512fbSwikidesign global $conf; 1485fc512fbSwikidesign 1495fc512fbSwikidesign $first = $_REQUEST['first']; 1505fc512fbSwikidesign if (!is_numeric($first)) $first = 0; 1515fc512fbSwikidesign 1525fc512fbSwikidesign if ((!$num) || (!is_numeric($num))) $num = $conf['recent']; 1535fc512fbSwikidesign 1545fc512fbSwikidesign $result = array(); 1555fc512fbSwikidesign $count = 0; 1565fc512fbSwikidesign 1575fc512fbSwikidesign if (!@file_exists($conf['metadir'].'/_comments.changes')) return $result; 1585fc512fbSwikidesign 1595fc512fbSwikidesign // read all recent changes. (kept short) 1605fc512fbSwikidesign $lines = file($conf['metadir'].'/_comments.changes'); 1615fc512fbSwikidesign 1625fc512fbSwikidesign // handle lines 1635fc512fbSwikidesign for ($i = count($lines)-1; $i >= 0; $i--){ 1642cbdac2eSwikidesign $rec = $this->_handleRecentComment($lines[$i], $ns); 1655fc512fbSwikidesign if ($rec !== false) { 1665fc512fbSwikidesign if (--$first >= 0) continue; // skip first entries 1675fc512fbSwikidesign $result[$rec['date']] = $rec; 1685fc512fbSwikidesign $count++; 1695fc512fbSwikidesign // break when we have enough entries 1705fc512fbSwikidesign if ($count >= $num) break; 1715fc512fbSwikidesign } 1725fc512fbSwikidesign } 1735fc512fbSwikidesign 1745fc512fbSwikidesign // finally sort by time of last comment 1755fc512fbSwikidesign krsort($result); 1765fc512fbSwikidesign 1775fc512fbSwikidesign return $result; 1785fc512fbSwikidesign } 1795fc512fbSwikidesign 180*264b7327Swikidesign 181*264b7327Swikidesign /** 182*264b7327Swikidesign * Returns the full comments data for a given wiki page 183*264b7327Swikidesign */ 184*264b7327Swikidesign function getFullComments($thread){ 185*264b7327Swikidesign $id = $thread['id']; 186*264b7327Swikidesign 187*264b7327Swikidesign if (!$thread['file']) $thread['file'] = metaFN($id, '.comments'); 188*264b7327Swikidesign if (!@file_exists($thread['file'])) return false; // no discussion thread at all 189*264b7327Swikidesign 190*264b7327Swikidesign $data = unserialize(io_readFile($thread['file'], false)); 191*264b7327Swikidesign 192*264b7327Swikidesign if (!$data['status']) return false; // comments are turned off 193*264b7327Swikidesign if (!isset($data['comments']) || !$data['number']) return array(); // no comments 194*264b7327Swikidesign 195*264b7327Swikidesign $result = array(); 196*264b7327Swikidesign foreach ($data['comments'] as $cid => $comment){ 197*264b7327Swikidesign $this->_addComment($cid, $data, $result); 198*264b7327Swikidesign } 199*264b7327Swikidesign 200*264b7327Swikidesign return $result; 201*264b7327Swikidesign } 202*264b7327Swikidesign 203*264b7327Swikidesign /** 204*264b7327Swikidesign * Recursive function to add the comment hierarchy to the result 205*264b7327Swikidesign */ 206*264b7327Swikidesign function _addComment($cid, &$data, &$result, $parent = '', $level = 1){ 207*264b7327Swikidesign if (!is_array($data['comments'][$cid])) return; // corrupt datatype 208*264b7327Swikidesign $comment = $data['comments'][$cid]; 209*264b7327Swikidesign if ($comment['parent'] != $parent) return; // answer to another comment 210*264b7327Swikidesign 211*264b7327Swikidesign // okay, add the comment to the result 212*264b7327Swikidesign $comment['id'] = $cid; 213*264b7327Swikidesign $comment['level'] = $level; 214*264b7327Swikidesign $result[] = $comment; 215*264b7327Swikidesign 216*264b7327Swikidesign // check answers to this comment 217*264b7327Swikidesign if (count($comment['replies'])){ 218*264b7327Swikidesign foreach ($comment['replies'] as $rid){ 219*264b7327Swikidesign $this->_addComment($rid, $data, $result, $cid, $level + 1); 220*264b7327Swikidesign } 221*264b7327Swikidesign } 222*264b7327Swikidesign } 223*264b7327Swikidesign 2245fc512fbSwikidesign/* ---------- Changelog function adapted for the Discussion Plugin ---------- */ 2255fc512fbSwikidesign 2265fc512fbSwikidesign /** 2275fc512fbSwikidesign * Internal function used by $this->getComments() 2285fc512fbSwikidesign * 2295fc512fbSwikidesign * don't call directly 2305fc512fbSwikidesign * 2315fc512fbSwikidesign * @see getRecentComments() 2325fc512fbSwikidesign * @author Andreas Gohr <andi@splitbrain.org> 2335fc512fbSwikidesign * @author Ben Coburn <btcoburn@silicodon.net> 2345fc512fbSwikidesign * @author Esther Brunner <wikidesign@gmail.com> 2355fc512fbSwikidesign */ 2365fc512fbSwikidesign function _handleRecentComment($line, $ns){ 2375fc512fbSwikidesign static $seen = array(); //caches seen pages and skip them 2385fc512fbSwikidesign if (empty($line)) return false; //skip empty lines 2395fc512fbSwikidesign 2405fc512fbSwikidesign // split the line into parts 2415fc512fbSwikidesign $recent = parseChangelogLine($line); 2425fc512fbSwikidesign if ($recent === false) return false; 2435fc512fbSwikidesign 2445fc512fbSwikidesign $cid = $recent['extra']; 2455fc512fbSwikidesign $fullcid = $recent['id'].'#'.$recent['extra']; 2465fc512fbSwikidesign 2475fc512fbSwikidesign // skip seen ones 2485fc512fbSwikidesign if (isset($seen[$fullcid])) return false; 2495fc512fbSwikidesign 2505fc512fbSwikidesign // skip 'show comment' log entries 2515fc512fbSwikidesign if ($recent['type'] === 'sc') return false; 2525fc512fbSwikidesign 2535fc512fbSwikidesign // remember in seen to skip additional sights 2545fc512fbSwikidesign $seen[$fullcid] = 1; 2555fc512fbSwikidesign 2565fc512fbSwikidesign // check if it's a hidden page or comment 2575fc512fbSwikidesign if (isHiddenPage($recent['id'])) return false; 2585fc512fbSwikidesign if ($recent['type'] === 'hc') return false; 2595fc512fbSwikidesign 2605fc512fbSwikidesign // filter namespace or id 2615fc512fbSwikidesign if (($ns) && (strpos($recent['id'].':', $ns.':') !== 0)) return false; 2625fc512fbSwikidesign 2635fc512fbSwikidesign // check ACL 2645fc512fbSwikidesign $recent['perm'] = auth_quickaclcheck($recent['id']); 2655fc512fbSwikidesign if ($recent['perm'] < AUTH_READ) return false; 2665fc512fbSwikidesign 2675fc512fbSwikidesign // check existance 2685fc512fbSwikidesign $recent['file'] = wikiFN($recent['id']); 2695fc512fbSwikidesign $recent['exists'] = @file_exists($recent['file']); 2705fc512fbSwikidesign if (!$recent['exists']) return false; 2715fc512fbSwikidesign if ($recent['type'] === 'dc') return false; 2725fc512fbSwikidesign 2735fc512fbSwikidesign // get discussion meta file name 2742cbdac2eSwikidesign $data = unserialize(io_readFile(metaFN($recent['id'], '.comments'), false)); 2755fc512fbSwikidesign 2765fc512fbSwikidesign // check if discussion is turned off 2775fc512fbSwikidesign if ($data['status'] === 0) return false; 2785fc512fbSwikidesign 2795fc512fbSwikidesign // okay, then add some additional info 2806046f25cSwikidesign if (is_array($data['comments'][$cid]['user'])) 2816046f25cSwikidesign $recent['name'] = $data['comments'][$cid]['user']['name']; 2826046f25cSwikidesign else $recent['name'] = $data['comments'][$cid]['name']; 2835fc512fbSwikidesign $recent['desc'] = strip_tags($data['comments'][$cid]['xhtml']); 2845fc512fbSwikidesign 2855fc512fbSwikidesign return $recent; 2865fc512fbSwikidesign } 2875fc512fbSwikidesign 2885fc512fbSwikidesign} 2895fc512fbSwikidesign 2905fc512fbSwikidesign//Setup VIM: ex: et ts=4 enc=utf-8 : 291