15fc512fbSwikidesign<?php 25fc512fbSwikidesign/** 35fc512fbSwikidesign * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 45fc512fbSwikidesign * @author Esther Brunner <wikidesign@gmail.com> 55fc512fbSwikidesign */ 65fc512fbSwikidesign 7e7ac9adaSGerrit Uitslag/** 8e7ac9adaSGerrit Uitslag * Class helper_plugin_discussion 9e7ac9adaSGerrit Uitslag */ 105fc512fbSwikidesignclass helper_plugin_discussion extends DokuWiki_Plugin { 115fc512fbSwikidesign 12e7ac9adaSGerrit Uitslag /** 13e7ac9adaSGerrit Uitslag * @return array 14e7ac9adaSGerrit Uitslag */ 15*f3535bedSGerrit Uitslag public function getMethods() { 165fc512fbSwikidesign $result = array(); 175fc512fbSwikidesign $result[] = array( 185fc512fbSwikidesign 'name' => 'th', 195fc512fbSwikidesign 'desc' => 'returns the header of the comments column for pagelist', 205fc512fbSwikidesign 'return' => array('header' => 'string'), 215fc512fbSwikidesign ); 225fc512fbSwikidesign $result[] = array( 235fc512fbSwikidesign 'name' => 'td', 245fc512fbSwikidesign 'desc' => 'returns the link to the discussion section with number of comments', 255fc512fbSwikidesign 'params' => array( 265fc512fbSwikidesign 'id' => 'string', 275fc512fbSwikidesign 'number of comments (optional)' => 'integer'), 285fc512fbSwikidesign 'return' => array('link' => 'string'), 295fc512fbSwikidesign ); 305fc512fbSwikidesign $result[] = array( 315fc512fbSwikidesign 'name' => 'getThreads', 325fc512fbSwikidesign 'desc' => 'returns pages with discussion sections, sorted by recent comments', 335fc512fbSwikidesign 'params' => array( 345fc512fbSwikidesign 'namespace' => 'string', 355fc512fbSwikidesign 'number (optional)' => 'integer'), 365fc512fbSwikidesign 'return' => array('pages' => 'array'), 375fc512fbSwikidesign ); 385fc512fbSwikidesign $result[] = array( 395fc512fbSwikidesign 'name' => 'getComments', 405fc512fbSwikidesign 'desc' => 'returns recently added or edited comments individually', 415fc512fbSwikidesign 'params' => array( 425fc512fbSwikidesign 'namespace' => 'string', 435fc512fbSwikidesign 'number (optional)' => 'integer'), 445fc512fbSwikidesign 'return' => array('pages' => 'array'), 455fc512fbSwikidesign ); 46*f3535bedSGerrit Uitslag $result[] = array( 47*f3535bedSGerrit Uitslag 'name' => 'isDiscussionModerator', 48*f3535bedSGerrit Uitslag 'desc' => 'check if current user is member of moderator groups', 49*f3535bedSGerrit Uitslag 'params' => array(), 50*f3535bedSGerrit Uitslag 'return' => array('isModerator' => 'boolean') 51*f3535bedSGerrit Uitslag ); 525fc512fbSwikidesign return $result; 535fc512fbSwikidesign } 545fc512fbSwikidesign 555fc512fbSwikidesign /** 565fc512fbSwikidesign * Returns the column header for the Pagelist Plugin 57e7ac9adaSGerrit Uitslag * 58e7ac9adaSGerrit Uitslag * @return string 595fc512fbSwikidesign */ 60*f3535bedSGerrit Uitslag public function th() { 615fc512fbSwikidesign return $this->getLang('discussion'); 625fc512fbSwikidesign } 635fc512fbSwikidesign 645fc512fbSwikidesign /** 655fc512fbSwikidesign * Returns the link to the discussion section of a page 66e7ac9adaSGerrit Uitslag * 67e7ac9adaSGerrit Uitslag * @param string $id 68e7ac9adaSGerrit Uitslag * @param null|int $num 69e7ac9adaSGerrit Uitslag * @return string 705fc512fbSwikidesign */ 71*f3535bedSGerrit Uitslag public function td($id, $num = null) { 72479dd10fSwikidesign $section = '#discussion__section'; 735fc512fbSwikidesign 745fc512fbSwikidesign if (!isset($num)) { 755fc512fbSwikidesign $cfile = metaFN($id, '.comments'); 765fc512fbSwikidesign $comments = unserialize(io_readFile($cfile, false)); 775fc512fbSwikidesign 785fc512fbSwikidesign $num = $comments['number']; 795fc512fbSwikidesign if ((!$comments['status']) || (($comments['status'] == 2) && (!$num))) return ''; 805fc512fbSwikidesign } 815fc512fbSwikidesign 824cded5e1SGerrit Uitslag if ($num == 0) { 834cded5e1SGerrit Uitslag $comment = '0 '.$this->getLang('nocomments'); 844cded5e1SGerrit Uitslag } elseif ($num == 1) { 854cded5e1SGerrit Uitslag $comment = '1 '.$this->getLang('comment'); 864cded5e1SGerrit Uitslag } else { 874cded5e1SGerrit Uitslag $comment = $num.' '.$this->getLang('comments'); 884cded5e1SGerrit Uitslag } 895fc512fbSwikidesign 90479dd10fSwikidesign return '<a href="'.wl($id).$section.'" class="wikilink1" title="'.$id.$section.'">'. 915fc512fbSwikidesign $comment.'</a>'; 925fc512fbSwikidesign } 935fc512fbSwikidesign 945fc512fbSwikidesign /** 955fc512fbSwikidesign * Returns an array of pages with discussion sections, sorted by recent comments 964cded5e1SGerrit Uitslag * Note: also used for content by Feed Plugin 97e7ac9adaSGerrit Uitslag * 98e7ac9adaSGerrit Uitslag * @param string $ns 99e7ac9adaSGerrit Uitslag * @param null|int $num 100e7ac9adaSGerrit Uitslag * @param string|bool $skipEmpty 101e7ac9adaSGerrit Uitslag * @return array 1025fc512fbSwikidesign */ 103*f3535bedSGerrit Uitslag public function getThreads($ns, $num = null, $skipEmpty = false) { 1045fc512fbSwikidesign global $conf; 1055fc512fbSwikidesign 1065fc512fbSwikidesign require_once(DOKU_INC.'inc/search.php'); 1075fc512fbSwikidesign 10893bbea85SMichael Hamann $dir = $conf['datadir'].utf8_encodeFN(($ns ? '/'.str_replace(':', '/', $ns): '')); 1095fc512fbSwikidesign 1105fc512fbSwikidesign // returns the list of pages in the given namespace and it's subspaces 1115fc512fbSwikidesign $items = array(); 1125d76f934SMichael Hamann search($items, $dir, 'search_allpages', array()); 1135fc512fbSwikidesign 1145fc512fbSwikidesign // add pages with comments to result 1155fc512fbSwikidesign $result = array(); 1165fc512fbSwikidesign foreach ($items as $item) { 1175fc512fbSwikidesign $id = ($ns ? $ns.':' : '').$item['id']; 1185fc512fbSwikidesign 1195fc512fbSwikidesign // some checks 1205fc512fbSwikidesign $perm = auth_quickaclcheck($id); 1215fc512fbSwikidesign if ($perm < AUTH_READ) continue; // skip if no permission 1225fc512fbSwikidesign $file = metaFN($id, '.comments'); 1235fc512fbSwikidesign if (!@file_exists($file)) continue; // skip if no comments file 1245fc512fbSwikidesign $data = unserialize(io_readFile($file, false)); 125264b7327Swikidesign $status = $data['status']; 1265644a1afSlupo49 $number = $data['number']; 1275644a1afSlupo49 1285644a1afSlupo49 if (!$status || (($status == 2) && (!$number))) continue; // skip if comments are off or closed without comments 1295644a1afSlupo49 if($skipEmpty == 'y' && $number == 0) continue; // skip if discussion is empty and flag is set 1305fc512fbSwikidesign 1315fc512fbSwikidesign $date = filemtime($file); 1325fc512fbSwikidesign $meta = p_get_metadata($id); 133ae836b78SMichael Hamann $result[$date.'_'.$id] = array( 1345fc512fbSwikidesign 'id' => $id, 135264b7327Swikidesign 'file' => $file, 1365fc512fbSwikidesign 'title' => $meta['title'], 1375fc512fbSwikidesign 'date' => $date, 1385fc512fbSwikidesign 'user' => $meta['creator'], 1395fc512fbSwikidesign 'desc' => $meta['description']['abstract'], 140fcb1bc77Swikidesign 'num' => $number, 141fcb1bc77Swikidesign 'comments' => $this->td($id, $number), 142264b7327Swikidesign 'status' => $status, 1435fc512fbSwikidesign 'perm' => $perm, 1445fc512fbSwikidesign 'exists' => true, 14573f66a3cSwikidesign 'anchor' => 'discussion__section', 1465fc512fbSwikidesign ); 1475fc512fbSwikidesign } 1485fc512fbSwikidesign 1495fc512fbSwikidesign // finally sort by time of last comment 1505fc512fbSwikidesign krsort($result); 1515fc512fbSwikidesign 1525fc512fbSwikidesign if (is_numeric($num)) $result = array_slice($result, 0, $num); 1535fc512fbSwikidesign 1545fc512fbSwikidesign return $result; 1555fc512fbSwikidesign } 1565fc512fbSwikidesign 1575fc512fbSwikidesign /** 1585fc512fbSwikidesign * Returns an array of recently added comments to a given page or namespace 1594cded5e1SGerrit Uitslag * Note: also used for content by Feed Plugin 160e7ac9adaSGerrit Uitslag * 161e7ac9adaSGerrit Uitslag * @param string $ns 162e7ac9adaSGerrit Uitslag * @param int|null $num 163e7ac9adaSGerrit Uitslag * @return array 1645fc512fbSwikidesign */ 165*f3535bedSGerrit Uitslag public function getComments($ns, $num = NULL) { 1665fc512fbSwikidesign global $conf; 1675fc512fbSwikidesign 1685fc512fbSwikidesign $first = $_REQUEST['first']; 1695fc512fbSwikidesign if (!is_numeric($first)) $first = 0; 1705fc512fbSwikidesign 1715fc512fbSwikidesign if ((!$num) || (!is_numeric($num))) $num = $conf['recent']; 1725fc512fbSwikidesign 1735fc512fbSwikidesign $result = array(); 1745fc512fbSwikidesign $count = 0; 1755fc512fbSwikidesign 1765fc512fbSwikidesign if (!@file_exists($conf['metadir'].'/_comments.changes')) return $result; 1775fc512fbSwikidesign 1785fc512fbSwikidesign // read all recent changes. (kept short) 1795fc512fbSwikidesign $lines = file($conf['metadir'].'/_comments.changes'); 1805fc512fbSwikidesign 18155e1d144SMichael Hamann $seen = array(); //caches seen pages in order to skip them 1825fc512fbSwikidesign // handle lines 18355e1d144SMichael Hamann $line_num = count($lines); 18455e1d144SMichael Hamann for ($i = ($line_num - 1); $i >= 0; $i--) { 18555e1d144SMichael Hamann $rec = $this->_handleRecentComment($lines[$i], $ns, $seen); 1865fc512fbSwikidesign if ($rec !== false) { 1875fc512fbSwikidesign if (--$first >= 0) continue; // skip first entries 1885fc512fbSwikidesign $result[$rec['date']] = $rec; 1895fc512fbSwikidesign $count++; 1905fc512fbSwikidesign // break when we have enough entries 1915fc512fbSwikidesign if ($count >= $num) break; 1925fc512fbSwikidesign } 1935fc512fbSwikidesign } 1945fc512fbSwikidesign 1955fc512fbSwikidesign // finally sort by time of last comment 1965fc512fbSwikidesign krsort($result); 1975fc512fbSwikidesign 1985fc512fbSwikidesign return $result; 1995fc512fbSwikidesign } 2005fc512fbSwikidesign 2015fc512fbSwikidesign /* ---------- Changelog function adapted for the Discussion Plugin ---------- */ 2025fc512fbSwikidesign 2035fc512fbSwikidesign /** 2045fc512fbSwikidesign * Internal function used by $this->getComments() 2055fc512fbSwikidesign * 2065fc512fbSwikidesign * don't call directly 2075fc512fbSwikidesign * 2085fc512fbSwikidesign * @see getRecentComments() 2095fc512fbSwikidesign * @author Andreas Gohr <andi@splitbrain.org> 2105fc512fbSwikidesign * @author Ben Coburn <btcoburn@silicodon.net> 2115fc512fbSwikidesign * @author Esther Brunner <wikidesign@gmail.com> 212e7ac9adaSGerrit Uitslag * 213e7ac9adaSGerrit Uitslag * @param string $line 214e7ac9adaSGerrit Uitslag * @param string $ns 215e7ac9adaSGerrit Uitslag * @param array $seen 216e7ac9adaSGerrit Uitslag * @return array|bool 2175fc512fbSwikidesign */ 218*f3535bedSGerrit Uitslag protected function _handleRecentComment($line, $ns, &$seen) { 2195fc512fbSwikidesign if (empty($line)) return false; //skip empty lines 2205fc512fbSwikidesign 2215fc512fbSwikidesign // split the line into parts 2225fc512fbSwikidesign $recent = parseChangelogLine($line); 2235fc512fbSwikidesign if ($recent === false) return false; 2245fc512fbSwikidesign 2255fc512fbSwikidesign $cid = $recent['extra']; 2265fc512fbSwikidesign $fullcid = $recent['id'].'#'.$recent['extra']; 2275fc512fbSwikidesign 2285fc512fbSwikidesign // skip seen ones 2295fc512fbSwikidesign if (isset($seen[$fullcid])) return false; 2305fc512fbSwikidesign 2315fc512fbSwikidesign // skip 'show comment' log entries 2325fc512fbSwikidesign if ($recent['type'] === 'sc') return false; 2335fc512fbSwikidesign 2345fc512fbSwikidesign // remember in seen to skip additional sights 2355fc512fbSwikidesign $seen[$fullcid] = 1; 2365fc512fbSwikidesign 2375fc512fbSwikidesign // check if it's a hidden page or comment 2385fc512fbSwikidesign if (isHiddenPage($recent['id'])) return false; 2395fc512fbSwikidesign if ($recent['type'] === 'hc') return false; 2405fc512fbSwikidesign 2415fc512fbSwikidesign // filter namespace or id 2425fc512fbSwikidesign if (($ns) && (strpos($recent['id'].':', $ns.':') !== 0)) return false; 2435fc512fbSwikidesign 2445fc512fbSwikidesign // check ACL 2455fc512fbSwikidesign $recent['perm'] = auth_quickaclcheck($recent['id']); 2465fc512fbSwikidesign if ($recent['perm'] < AUTH_READ) return false; 2475fc512fbSwikidesign 2485fc512fbSwikidesign // check existance 2495fc512fbSwikidesign $recent['file'] = wikiFN($recent['id']); 2505fc512fbSwikidesign $recent['exists'] = @file_exists($recent['file']); 2515fc512fbSwikidesign if (!$recent['exists']) return false; 2525fc512fbSwikidesign if ($recent['type'] === 'dc') return false; 2535fc512fbSwikidesign 2545fc512fbSwikidesign // get discussion meta file name 2552cbdac2eSwikidesign $data = unserialize(io_readFile(metaFN($recent['id'], '.comments'), false)); 2565fc512fbSwikidesign 2575fc512fbSwikidesign // check if discussion is turned off 2585fc512fbSwikidesign if ($data['status'] === 0) return false; 2595fc512fbSwikidesign 2604dd9b9e2SMichael Hamann $parent_id = $cid; 2614dd9b9e2SMichael Hamann // Check for the comment and all parents if they exist and are visible. 2624dd9b9e2SMichael Hamann do { 2634dd9b9e2SMichael Hamann $tcid = $parent_id; 2644dd9b9e2SMichael Hamann 26555e1d144SMichael Hamann // check if the comment still exists 2664dd9b9e2SMichael Hamann if (!isset($data['comments'][$tcid])) return false; 2674dd9b9e2SMichael Hamann // check if the comment is visible 2684dd9b9e2SMichael Hamann if ($data['comments'][$tcid]['show'] != 1) return false; 2694dd9b9e2SMichael Hamann 2704dd9b9e2SMichael Hamann $parent_id = $data['comments'][$tcid]['parent']; 2714dd9b9e2SMichael Hamann } while ($parent_id && $parent_id != $tcid); 27255e1d144SMichael Hamann 2735fc512fbSwikidesign // okay, then add some additional info 2744cded5e1SGerrit Uitslag if (is_array($data['comments'][$cid]['user'])) { 2756046f25cSwikidesign $recent['name'] = $data['comments'][$cid]['user']['name']; 2764cded5e1SGerrit Uitslag } else { 2774cded5e1SGerrit Uitslag $recent['name'] = $data['comments'][$cid]['name']; 2784cded5e1SGerrit Uitslag } 2795fc512fbSwikidesign $recent['desc'] = strip_tags($data['comments'][$cid]['xhtml']); 280d8092064SMichael Hamann $recent['anchor'] = 'comment_'.$cid; 2815fc512fbSwikidesign 2825fc512fbSwikidesign return $recent; 2835fc512fbSwikidesign } 284e6b2f142Slupo49 285e7ac9adaSGerrit Uitslag /** 286e7ac9adaSGerrit Uitslag * @return bool 287e7ac9adaSGerrit Uitslag */ 288*f3535bedSGerrit Uitslag public function isDiscussionModerator() { 289e6b2f142Slupo49 global $USERINFO; 290e6b2f142Slupo49 $groups = trim($this->getConf('moderatorgroups')); 291e6b2f142Slupo49 292e6b2f142Slupo49 if(auth_ismanager()) return true; 293e6b2f142Slupo49 // Check if user is member of the moderator groups 294e6b2f142Slupo49 if(!empty($groups) && auth_isMember($groups, $_SERVER['REMOTE_USER'], (array)$USERINFO['grps'])) return true; 295e6b2f142Slupo49 296e6b2f142Slupo49 return false; 297e6b2f142Slupo49 } 2985fc512fbSwikidesign} 299530693fbSMichael Klier// vim:ts=4:sw=4:et:enc=utf-8: 300