', 10);
ptln('
', 10);
ptln('
', 10);
echo html_buildlist($comments, 'admin_discussion', [$this, 'commentItem'], [$this, 'liComment']);
$this->actionButtons();
}
$this->browseDiscussionLinks($isMore, $first, $num);
}
/**
* Returns an array of pages with discussion sections, sorted by recent comments
*
* @return array
*/
protected function getThreads()
{
global $conf;
// returns the list of pages in the given namespace and it's subspaces
$items = [];
search($items, $conf['datadir'], 'search_allpages', []);
// add pages with comments to result
$result = [];
foreach ($items as $item) {
$id = $item['id'];
// some checks
$file = metaFN($id, '.comments');
if (!@file_exists($file)) continue; // skip if no comments file
$date = filemtime($file);
$result[] = [
'id' => $id,
'file' => $file,
'date' => $date,
];
}
// finally sort by time of last comment
usort($result, ['admin_plugin_discussion', 'threadCmp']);
return $result;
}
/**
* Callback for comparison of thread data.
*
* Used for sorting threads in descending order by date of last comment.
* If this date happens to be equal for the compared threads, page id
* is used as second comparison attribute.
*
* @param array $a
* @param array $b
* @return int
*/
protected function threadCmp($a, $b)
{
if ($a['date'] == $b['date']) {
return strcmp($a['id'], $b['id']);
}
if ($a['date'] < $b['date']) {
return 1;
} else {
return -1;
}
}
/**
* Outputs header, page ID and status of a discussion thread
*
* @param array $thread
* @return bool
*/
protected function threadHead($thread)
{
$id = $thread['id'];
$labels = [
0 => $this->getLang('off'),
1 => $this->getLang('open'),
2 => $this->getLang('closed')
];
$title = p_get_metadata($id, 'title');
if (!$title) {
$title = $id;
}
ptln('
' . hsc($title) . '
', 6);
ptln('
', 6);
ptln('
', 6);
ptln('
' . $id . ' ', 8);
return true;
}
/**
* Returns the full comments data for a given wiki page
*
* @param array $thread by reference with:
* 'id' => string,
* 'file' => string file location of .comments metadata file
* 'status' => int
* 'number' => int number of visible comments
*
* @return array|bool
*/
protected function getComments(&$thread)
{
$id = $thread['id'];
if (!$thread['file']) {
$thread['file'] = metaFN($id, '.comments');
}
if (!@file_exists($thread['file'])) return false; // no discussion thread at all
$data = unserialize(io_readFile($thread['file'], false));
$thread['status'] = $data['status'];
$thread['number'] = $data['number'];
if (empty($data['status'])) return false; // comments are turned off
if (empty($data['comments'])) return false; // no comments
$result = [];
foreach ($data['comments'] as $cid => $comment) {
$this->addComment($cid, $data, $result);
}
if (empty($result)) {
return false;
} else {
return $result;
}
}
/**
* Recursive function to add the comment hierarchy to the result
*
* @param string $cid comment id of current comment
* @param array $data array with all comments by reference
* @param array $result array with all comments by reference enhanced with level
* @param string $parent comment id of parent or empty
* @param int $level level of current comment, higher is deeper
*/
protected function addComment($cid, &$data, &$result, $parent = '', $level = 1)
{
if (!isset($data['comments'][$cid]) || !is_array($data['comments'][$cid])) return; // corrupt datatype
$comment = $data['comments'][$cid];
// handle only replies to given parent comment
if ($comment['parent'] != $parent) return;
// okay, add the comment to the result
$comment['id'] = $cid;
$comment['level'] = $level;
$result[] = $comment;
// check answers to this comment
if (count($comment['replies'])) {
foreach ($comment['replies'] as $rid) {
$this->addComment($rid, $data, $result, $cid, $level + 1);
}
}
}
/**
* Returns html of checkbox and info about a comment item
*
* @param array $comment array with comment data
* @return string html of checkbox and info
*/
public function commentItem($comment)
{
global $conf;
// prepare variables
if (is_array($comment['user'])) { // new format
$name = $comment['user']['name'];
$mail = $comment['user']['mail'];
} else { // old format
$name = $comment['name'];
$mail = $comment['mail'];
}
if (is_array($comment['date'])) { // new format
$created = $comment['date']['created'];
} else { // old format
$created = $comment['date'];
}
$abstract = preg_replace('/\s+?/', ' ', strip_tags($comment['xhtml']));
if (PhpString::strlen($abstract) > 160) {
$abstract = PhpString::substr($abstract, 0, 160) . '...';
}
return '
' .
$this->email($mail, $name, 'email') . ', ' . strftime($conf['dformat'], $created) . ': ' .
'
' . $abstract . '';
}
/**
* Returns html of list item openings tag
*
* @param array $comment
* @return string
*/
public function liComment($comment)
{
$showclass = ($comment['show'] ? '' : ' hidden');
return '
', 10); // class="no"
ptln('', 8);
ptln('
', 6); // class="level2"
}
/**
* Displays links to older newer discussions
*
* @param bool $isMore whether there are more pages needed
* @param int $first first entry on this page
* @param int $num number of entries per page
*/
protected function browseDiscussionLinks($isMore, $first, $num)
{
global $ID;
if ($first == 0 && !$isMore) return;
$params = ['do' => 'admin', 'page' => 'discussion'];
$last = $first + $num;
ptln('', 8);
$return = '';
if ($first > 0) {
$first -= $num;
if ($first < 0) {
$first = 0;
}
$params['first'] = $first;
ptln('
', 8);
$return = '<< ' . $this->getLang('newer') . '';
if ($isMore) {
$return .= ' | ';
} else {
ptln($return, 10);
ptln('
', 8);
}
} elseif ($isMore) {
ptln('
', 8);
}
if ($isMore) {
$params['first'] = $last;
$return .= '' . $this->getLang('older') . ' >>';
ptln($return, 10);
ptln('
', 8);
}
ptln('
', 6); // class="level1"
}
/**
* Changes the status of a comment section
*
* @param int $new 0=disabled, 1=enabled, 2=closed
*/
protected function changeStatus($new)
{
global $ID;
// get discussion meta file name
$file = metaFN($ID, '.comments');
$data = unserialize(io_readFile($file, false));
$old = $data['status'];
if ($old == $new) {
return;
}
// save the comment metadata file
$data['status'] = $new;
io_saveFile($file, serialize($data));
// look for ~~DISCUSSION~~ command in page file and change it accordingly
$patterns = ['~~DISCUSSION:off\2~~', '~~DISCUSSION\2~~', '~~DISCUSSION:closed\2~~'];
$replace = $patterns[$new];
$wiki = preg_replace('/~~DISCUSSION([\w:]*)(\|?.*?)~~/', $replace, rawWiki($ID));
saveWikiText($ID, $wiki, $this->getLang('statuschanged'), true);
}
}