['onPluginsInitialized', 0]
];
}
/**
* Add the comment form information to the page header dynamically
*
* Used by Form plugin >= 2.0
*/
public function onFormPageHeaderProcessed(Event $event)
{
$header = $event['header'];
if ($this->enable) {
if (!isset($header->form)) {
$header->form = $this->grav['config']->get('plugins.comments.form');
}
}
$event->header = $header;
}
public function onTwigSiteVariables() {
$this->grav['twig']->enable_comments_plugin = $this->enable;
$this->grav['twig']->comments = $this->fetchComments();
$this->grav['twig']->recentComments = $this->getRecentComments();
if ($this->config->get('plugins.comments.built_in_css')) {
$this->grav['assets']
->addCss('plugin://comments/assets/comments.css');
}
$this->grav['assets']
->add('jquery', 101)
->addJs('plugin://comments/assets/comments.js');
}
/**
* Determine if the plugin should be enabled based on the enable_on_routes and disable_on_routes config options
*/
private function calculateEnable() {
$uri = $this->grav['uri'];
$disable_on_routes = (array) $this->config->get('plugins.comments.disable_on_routes');
$enable_on_routes = (array) $this->config->get('plugins.comments.enable_on_routes');
$callback = $this->config->get('plugins.comments.ajax_callback');
$path = $uri->path();
if ($callback === $path) {
$this->enable = true;
return;
}
if (!in_array($path, $disable_on_routes)) {
if (in_array($path, $enable_on_routes)) {
$this->enable = true;
} else {
foreach($enable_on_routes as $route) {
if (Utils::startsWith($path, $route)) {
$this->enable = true;
break;
}
}
}
}
}
/**
* Frontend side initialization
*/
private function initializeFrontend()
{
$this->calculateEnable();
$this->enable([
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
]);
if ($this->enable) {
$this->enable([
'onPageInitialized' => ['onPageInitialized', 0],
'onFormProcessed' => ['onFormProcessed', 0],
'onFormPageHeaderProcessed' => ['onFormPageHeaderProcessed', 0],
'onTwigSiteVariables' => ['onTwigSiteVariables', 0]
]);
}
$cache = $this->grav['cache'];
$uri = $this->grav['uri'];
//init cache id
$this->comments_cache_id = md5('comments-data' . $cache->getKey() . '-' . $uri->url());
}
/**
* Admin side initialization
*/
private function initializeAdmin()
{
/** @var Uri $uri */
$uri = $this->grav['uri'];
$this->enable([
'onTwigTemplatePaths' => ['onTwigAdminTemplatePaths', 0],
'onAdminMenu' => ['onAdminMenu', 0],
'onAdminTaskExecute' => ['onAdminTaskExecute', 0],
'onAdminAfterSave' => ['onAdminAfterSave', 0],
'onAdminAfterDelete' => ['onAdminAfterDelete', 0],
'onDataTypeExcludeFromDataManagerPluginHook' => ['onDataTypeExcludeFromDataManagerPluginHook', 0],
]);
if (strpos($uri->path(), $this->config->get('plugins.admin.route') . '/' . $this->route) === false) {
return;
}
$page = $this->grav['uri']->param('page');
$comments = $this->getLastComments($page);
if ($page > 0) {
echo json_encode($comments);
exit();
}
$this->grav['twig']->comments = $comments;
$this->grav['twig']->pages = $this->fetchPages();
}
/**
*/
public function onPluginsInitialized()
{
if ('/recent' === $this->grav['uri']->path()) {
//TODO TEST
echo PAGES_DIR;
echo "
";
$test = $this->getRecentComments(25);
var_dump($test[0]);
echo '
';
var_dump($test[1]);
echo '
';
var_dump($test[2]);
echo '
';
exit();
}
if ($this->isAdmin()) {
$this->initializeAdmin();
} else {
$this->initializeFrontend();
}
}
/**
* Handle ajax call.
*/
public function onPageInitialized()
{
$is_ajax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
//$callback = $this->config->get('plugins.comments.ajax_callback');
// Process comment if required
if ($is_ajax) {// || $callback === $this->grav['uri']->path()
$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING);
switch ($action) {
case 'addComment':
case '':
case null:
// try to add the comment
$result = $this->addCommentAjax(true);
echo json_encode([
'status' => $result[0],
'message' => $result[1],
'data' => $result[2],
]);
break;
case 'delete':
// try to delete the comment
$result = $this->deleteComment(true);
echo json_encode([
'status' => $result[0],
'message' => $result[1],
'data' => $result[2],
]);
break;
default:
//request unknown, present error page
//Set a 400 (bad request) response code.
http_response_code(400);
echo 'request malformed - action unknown';
break;
}
exit(); //prevents the page frontend from beeing displayed.
}
}
/**
* Validate ajax input before deleting comment
*
* @return boolean[]|string[]|array[][]
*/
private function deleteComment()
{
$language = $this->grav['language'];
if (!$this->grav['user']->authorize('admin.super')) {
http_response_code(403);
return [false, 'access forbidden', [0, 0]];
}
$id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);
$nonce = filter_input(INPUT_POST, 'nonce', FILTER_SANITIZE_STRING);
// ensure both values are sent
if (is_null($id) || is_null($nonce)) {
// Set a 400 (bad request) response code and exit.
http_response_code(400);
return [false, 'request malformed - missing parameter(s)', [0, 0]];
}
if (!Utils::verifyNonce($nonce, 'comments')) {
http_response_code(403);
return [false, 'Invalid security nonce', [0, $nonce]];
}
$lang = $this->grav['language']->getLanguage();
$path = $this->grav['page']->path();
$route = $this->grav['page']->route();
$data = $this->removeComment($route, $path, $id, $lang);
if ($data[0]) {
return [true, $language->translate('PLUGIN_COMMENTS.DELETE_SUCCESS'), $data[1]];
} else {
http_response_code(403); //forbidden
return [false, $language->translate('PLUGIN_COMMENTS.DELETE_FAIL'), $data[1]];
}
}
/**
* Validate ajax input before adding comment
*
* @return boolean[]|string[]|array[][]
*/
private function addCommentAjax()
{
$language = $this->grav['language'];
if (!$_SERVER["REQUEST_METHOD"] == "POST") {
// Not a POST request, set a 403 (forbidden) response code.
http_response_code(403);
return [false, 'There was a problem with your submission, please try again.', [0, 0]];
}
// get and filter the data
if (!isset($_POST['data']) || !is_array($_POST['data'])) {
// Set a 400 (bad request) response code and exit.
http_response_code(400);
return [false, 'missing data', [0, 0]];
}
$input = array();
$input['parent_id'] = filter_input(INPUT_POST, 'parentID', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
$input['name'] = isset($_POST['data']['name']) ? filter_var($_POST['data']['name'], FILTER_SANITIZE_STRING) : null;
$input['email'] = isset($_POST['data']['email']) ? filter_var($_POST['data']['email'], FILTER_SANITIZE_EMAIL) : null;
$input['text'] = isset($_POST['data']['text']) ? filter_var($_POST['data']['text'], FILTER_SANITIZE_STRING) : null;
$input['date'] = isset($_POST['data']['date']) ? filter_var($_POST['data']['date'], FILTER_SANITIZE_STRING) : null;
$input['title'] = isset($_POST['data']['title']) ? filter_var($_POST['data']['title'], FILTER_SANITIZE_STRING) : null;
$input['lang'] = isset($_POST['data']['lang']) ? filter_var($_POST['data']['lang'], FILTER_SANITIZE_STRING) : null;
$input['path'] = isset($_POST['data']['path']) ? filter_var($_POST['data']['path'], FILTER_SANITIZE_STRING) : null;
$input['form-name'] = filter_input(INPUT_POST, 'form-name', FILTER_SANITIZE_STRING);
$input['form-nonce'] = filter_input(INPUT_POST, 'form-nonce', FILTER_SANITIZE_STRING);
if (!Utils::verifyNonce($input['form-nonce'], 'comments')) {
http_response_code(403);
return [false, 'Invalid security nonce', [0, $input['form-nonce']]];
}
// ensure both values are sent
if (is_null($input['title']) || is_null($input['text'])) {
// Set a 400 (bad request) response code and exit.
http_response_code(400);
return [false, 'missing either text or title', [0, 0]];
//return [false, $language->translate('PLUGIN_COMMENTS.FAIL'), $data];
}
// sanity checks for parents
if ($input['parent_id'] < 0) {
$input['parent_id'] = 0;
} elseif ($input['parent_id'] > 999 ) { //TODO: Change to 'exists in list of comment ids
$input['parent_id'] = 0;
}
$lang = $this->grav['language']->getLanguage();
$path = $this->grav['page']->path();
$route = $this->grav['page']->route();
$user = $this->grav['user']->authenticated ? $this->grav['user']->username : '';
$isAdmin = $this->grav['user']->authorize('admin.login');
$comment = $this->saveComment($route, $path, $input['parent_id'], $lang, $input['text'], $input['name'], $input['email'], $input['title'], $user, $isAdmin);
//$comments = $this->fetchComments();
$data = array(
'parent_id' => $comment['parent'],
'id' => $comment['id'],
'text' => $comment['text'],
'title' => $comment['title'],
'name' => $comment['author'],
'date' => $comment['date'],
'hash' => md5(strtolower(trim($comment['email']))),
'authenticated' => !empty($comment['user']),
'isAdmin' => !empty($comment['isAdmin']),
'ADD_REPLY' => $language->translate('PLUGIN_COMMENTS.ADD_REPLY'),
'REPLY' => $language->translate('PLUGIN_COMMENTS.REPLY'),
'WRITTEN_ON' => $language->translate('PLUGIN_COMMENTS.WRITTEN_ON'),
'BY' => $language->translate('PLUGIN_COMMENTS.BY'),
);
return [true, $language->translate('PLUGIN_COMMENTS.SUCCESS'), $data];
}
/**
* Handle form processing instructions.
*
* @param Event $event
*/
private function removeComment($route, $path, $id, $lang)
{
$entry_removed = false;
$message = '';
$date = time();//date('D, d M Y H:i:s', time());
/******************************/
/** store comments with page **/
/******************************/
$localfilename = $path . '/comments.yaml';
$localfile = CompiledYamlFile::instance($localfilename);
if (file_exists($localfilename)) {
$data = $localfile->content();
if(isset($data['comments']) && is_array($data['comments'])) {
foreach($data['comments'] as $key => $comment) {
if(!empty($comment['parent_id']) && $comment['parent_id'] == $id) {
//hit an existing comment that is a reply to comment selected for deletion.
//deletion of "parent" comment not allowed to preserve integrity of nested comments.
//TODO: Alternatively allow it to mark parent comments as deleted
// and make sure (via Comment class / setCommentLevels) that children are
// filtered out from fetch regardless of their own deletion state.
$data['comments'][$key] = array_merge(array('deleted' => ''), $comment);
//set date after merge
//reason: could be possible that "deleted" already exists (e.g. false or '') in $comment which would overwrite the first (newly added) occurence
$data['comments'][$key]['deleted'] = $date;
//no need to look further as ids are supposed to be unique.
$localfile->save($data);
$entry_removed = false;
$reply_id = empty($comment['id']) ? '' : $comment['id'];
$message = "Found active reply ($reply_id) for selected comment ($id).";
return [$entry_removed, $message];
break;
}
}
foreach($data['comments'] as $key => $comment) {
if(!empty($comment['id']) && $comment['id'] == $id) {
//add deleted as first item in array (better readability in file)
$data['comments'][$key] = array_merge(array('deleted' => ''), $comment);
//set date after merge
//reason: could be possible that "deleted" already exists (e.g. false or '') in $comment which would overwrite the first (newly added) occurence
$data['comments'][$key]['deleted'] = $date;
//no need to look further as ids are supposed to be unique.
$localfile->save($data);
$entry_removed = true;
$message = "Deleted comment ($id) via path ($path)";
break;
}
}
}
} else {
//nothing
}
/**********************************/
/** store comments in index file **/
/**********************************/
$indexfilename = DATA_DIR . 'comments/index.yaml';
$indexfile = CompiledYamlFile::instance($indexfilename);
if (file_exists($indexfilename)) {
$dataIndex = $indexfile->content();
if(isset($dataIndex['comments']) && is_array($dataIndex['comments'])) {
foreach($dataIndex['comments'] as $key => $comment) {
if(!empty($comment['page']) && !empty($comment['id']) && $comment['page'] == $route && $comment['id'] == $id) {
//add deleted as first item in array (better readability in file)
$dataIndex['comments'][$key] = array_merge(array('deleted' => ''), $comment);
//set date after merge
//reason: could be possible that "deleted" already exists (e.g. false or '') in $comment which would overwrite the first (newly added) occurence
$dataIndex['comments'][$key]['deleted'] = $date;
//no need to look further as ids are supposed to be unique.
$indexfile->save($dataIndex);
break;
}
}
}
} else {
//nothing
}
//clear cache
$this->grav['cache']->delete($this->comments_cache_id);
return [$entry_removed, $message];
}
/**
* Handle form processing instructions.
*
* @param Event $event
*/
private function saveComment($route, $path, $parent_id, $lang, $text, $name, $email, $title, $user = "", $isAdmin = false)
{
$date = date('D, d M Y H:i:s', time());
/******************************/
/** store comments with page **/
/******************************/
$localfilename = $path . '/comments.yaml';
$localfile = CompiledYamlFile::instance($localfilename);
if (file_exists($localfilename)) {
$data = $localfile->content();
$data['autoincrement']++;
} else {
$data = array(
'autoincrement' => 1,
'comments' => array()
);
}
$localid = $data['autoincrement'];
$newComment = [
'id' => $data['autoincrement'],
'parent' => $parent_id,
'lang' => $lang,
'title' => $title,
'text' => $text,
'date' => $date,
'author' => $name,
'email' => $email,
'user' => $user,
'isAdmin' => !empty($isAdmin),
];
$data['comments'][] = $newComment;
$localfile->save($data);
/**********************************/
/** store comments in index file **/
/**********************************/
$indexfilename = DATA_DIR . 'comments/index.yaml';
$indexfile = CompiledYamlFile::instance($indexfilename);
if (file_exists($indexfilename)) {
$dataIndex = $indexfile->content();
} else {
$dataIndex = array(
'comments' => array()
);
}
$dataIndex['comments'][] = [
'page' => $route,
'id' => $localid,
'parent' => $parent_id,
'lang' => $lang,
'title' => $title,
'text' => $text,
'date' => $date,
'author' => $name,
'email' => $email
];
$indexfile->save($dataIndex);
//clear cache
$this->grav['cache']->delete($this->comments_cache_id);
return $newComment;
}
/**
* Handle form processing instructions.
*
* @param Event $event
*/
public function onFormProcessed(Event $event)
{
$form = $event['form'];
$action = $event['action'];
$params = $event['params'];
if (!$this->active) {
return;
}
switch ($action) {
case 'addComment':
$post = isset($_POST['data']) ? $_POST['data'] : [];
$lang = filter_var(urldecode($post['lang']), FILTER_SANITIZE_STRING);
$path = filter_var(urldecode($post['path']), FILTER_SANITIZE_STRING);
$text = filter_var(urldecode($post['text']), FILTER_SANITIZE_STRING);
$name = filter_var(urldecode($post['name']), FILTER_SANITIZE_STRING);
$email = filter_var(urldecode($post['email']), FILTER_SANITIZE_STRING);
$title = filter_var(urldecode($post['title']), FILTER_SANITIZE_STRING);
$parent_id = 0;
$username = '';
$isAdmin = false;
if (isset($this->grav['user'])) {
$user = $this->grav['user'];
if ($user->authenticated) {
$name = $user->fullname;
$email = $user->email;
}
$username = $this->grav['user']->authenticated ? $this->grav['user']->username : '';
$isAdmin = $this->grav['user']->authorize('admin.login');
}
/** @var Language $language */
$lang = $this->grav['language']->getLanguage();
$path = $this->grav['page']->path();
$route = $this->grav['page']->route();
$this->saveComment($route, $path, $parent_id, $lang, $text, $name, $email, $title, $username, $isAdmin);
break;
}
}
private function getRecentComments($limit = 10) {
//TODO
/*
//init cache id
$cache = $this->grav['cache'];
$comments_cache_id = md5('comments-data' . $cache->getKey() . '-' . $uri->url());
$uri = $this->grav['uri'];
//search in cache
if ($comments = $cache->fetch($comments_cache_id)) {
return $comments;
}
$comments = $this->getDataFromFilename($filename)['comments'];
$comments = $this->setCommentLevels($comments);
//save to cache if enabled
$cache->save($this->comments_cache_id, $comments);
*/
$path = PAGES_DIR;
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
$itrFilter = new \RecursiveIteratorIterator($dirItr, \RecursiveIteratorIterator::SELF_FIRST);
$filesItr = new \RegexIterator($itrFilter, '/^.+comments\.yaml$/i');
$files = array();
$global_stats = array(
'active_entries' => 0,
'deleted_entries' => 0,
'active_comments' => 0,
'deleted_comments' => 0,
'active_replies' => 0,
'deleted_replies' => 0,
'pages_with_active_entries' => 0,
);
$page_stats = array();
$comments = array();
foreach ($filesItr as $filepath => $file) {
if ($file->isDir()) {
// this should never trigger as we are looking vor yamls only
} else {
$page_stats[$filepath] = array(
'active_entries' => 0,
'deleted_entries' => 0,
'active_comments' => 0,
'deleted_comments' => 0,
'active_replies' => 0,
'deleted_replies' => 0,
'latest_active_entry' => 0,
);
$localfile = CompiledYamlFile::instance($filepath);
$localcomments = $localfile->content();
if (!empty($localcomments['comments']) && is_array($localcomments['comments'])) {
foreach ($localcomments['comments'] as $comment) {
if (!empty($comment['deleted'])) {
empty($comment['parent']) ? $page_stats[$filepath]['deleted_comments']++ : $page_stats[$filepath]['deleted_replies']++;
empty($comment['parent']) ? $global_stats['deleted_comments']++ : $global_stats['deleted_replies']++;
$page_stats[$filepath]['deleted_entries']++;
$global_stats['deleted_entries']++;
} else {
empty($comment['parent']) ? $page_stats[$filepath]['active_comments']++ : $page_stats[$filepath]['active_replies']++;
empty($comment['parent']) ? $global_stats['active_comments']++ : $global_stats['active_replies']++;
$page_stats[$filepath]['active_entries']++;
$global_stats['active_entries']++;
//use unix timestamp for comparing and sorting
if(is_int($comment['date'])) {
$time = $comment['date'];
} else {
$time = \DateTime::createFromFormat('D, d M Y H:i:s', $comment['date'])->getTimestamp();
}
if (empty($page_stats[$filepath]['latest_active_entry']) || $page_stats[$filepath]['latest_active_entry'] < $time) {
$page_stats[$filepath]['latest_active_entry'] = $time;
}
$comments[] = array_merge(array(
'path' => $filepath,
'time' => $time,
), $comment);
}
}
}
if (!empty($page_stats[$filepath]['latest_active_entry'])) {
$global_stats['pages_with_active_entries']++;
}
}
}
usort($comments, function($a, $b) {
if ($a['time'] === $b['time']) return 0;
if ($a['time'] < $b['time']) return 1;
return -1;
});
if (!empty($limit) && $limit > 0 && $limit < count($comments)) {
return [$global_stats, $page_stats, array_slice($comments, 0, $limit)];
} else {
return [$global_stats, $page_stats, $comments];
}
}
private function getFilesOrderedByModifiedDate($path = '') {
$files = [];
if (!$path) {
$path = DATA_DIR . 'comments';
}
if (!file_exists($path)) {
Folder::mkdir($path);
}
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
$filterItr = new RecursiveFolderFilterIterator($dirItr);
$itr = new \RecursiveIteratorIterator($filterItr, \RecursiveIteratorIterator::SELF_FIRST);
$itrItr = new \RecursiveIteratorIterator($dirItr, \RecursiveIteratorIterator::SELF_FIRST);
$filesItr = new \RegexIterator($itrItr, '/^.+\.yaml$/i');
// Collect files if modified in the last 7 days
foreach ($filesItr as $filepath => $file) {
$modifiedDate = $file->getMTime();
$sevenDaysAgo = time() - (7 * 24 * 60 * 60);
if ($modifiedDate < $sevenDaysAgo) {
continue;
}
$files[] = (object)array(
"modifiedDate" => $modifiedDate,
"fileName" => $file->getFilename(),
"filePath" => $filepath,
"data" => Yaml::parse(file_get_contents($filepath))
);
}
// Traverse folders and recurse
foreach ($itr as $file) {
if ($file->isDir()) {
$this->getFilesOrderedByModifiedDate($file->getPath() . '/' . $file->getFilename());
}
}
// Order files by last modified date
usort($files, function($a, $b) {
return !($a->modifiedDate > $b->modifiedDate);
});
return $files;
}
private function getLastComments($page = 0) {
$number = 30;
$files = [];
$files = $this->getFilesOrderedByModifiedDate();
$comments = [];
foreach($files as $file) {
$data = Yaml::parse(file_get_contents($file->filePath));
for ($i = 0; $i < count($data['comments']); $i++) {
$commentTimestamp = \DateTime::createFromFormat('D, d M Y H:i:s', $data['comments'][$i]['date'])->getTimestamp();
$data['comments'][$i]['pageTitle'] = $data['title'];
$data['comments'][$i]['filePath'] = $file->filePath;
$data['comments'][$i]['timestamp'] = $commentTimestamp;
}
if (count($data['comments'])) {
$comments = array_merge($comments, $data['comments']);
}
}
// Order comments by date
usort($comments, function($a, $b) {
return !($a['timestamp'] > $b['timestamp']);
});
$totalAvailable = count($comments);
$comments = array_slice($comments, $page * $number, $number);
$totalRetrieved = count($comments);
return (object)array(
"comments" => $comments,
"page" => $page,
"totalAvailable" => $totalAvailable,
"totalRetrieved" => $totalRetrieved
);
}
/**
* Return the comments associated to the current route
*/
private function fetchComments() {
$cache = $this->grav['cache'];
//search in cache
if ($comments = $cache->fetch($this->comments_cache_id)) {
return $comments;
}
$lang = $this->grav['language']->getLanguage();
$filename = $lang ? '/' . $lang : '';
$filename .= $this->grav['uri']->path() . '.yaml';
$comments = $this->getDataFromFilename($filename)['comments'];
$comments = $this->setCommentLevels($comments);
//save to cache if enabled
$cache->save($this->comments_cache_id, $comments);
return $comments;
}
/**
* Return the latest commented pages
*/
private function setCommentLevels($comments) {
if(!is_array($comments)) {
return $comments;
}
$levelsflat = array();
foreach($comments as $key => $comment) {
if(!empty($comment['deleted'])) {
//if field "deleted" exists and is filled with a true value then ignore the comment completely.
//TODO: This only works on this position as long as it is forbidden to delete comments that have active replies (children).
// Otherwise implement that children get the deleted flag recursively or are ignored via Comment class.
} else {
$levelsflat[$comment['id']]['parent'] = $comment['parent'];
$levelsflat[$comment['id']]['class'] = new Comment($comment['id'], $comments[$key]);
}
}
//get starting points (entries without valid parent = root element)
$leveltree = array();
foreach($levelsflat as $id => $parent) {
$parent_id = $parent['parent'];
if(!isset($levelsflat[$parent_id])){
$leveltree[$id] = $levelsflat[$id]['class'];
} else {
$currentParent = $levelsflat[$parent_id]['class'];
$currentChild = $levelsflat[$id]['class'];
$levelsflat[$id]['class']->setParent($currentParent);
$levelsflat[$parent_id]['class']->addSubComment($currentChild);
}
}
//youngest comments first (DESC date), only root comments. Keep replies in ASC date order.
//as long as comments are not editable, it is sufficient to reverse order from comment file
$leveltree = array_reverse($leveltree, true);
//reset comment values to nested order
$comments = array();
foreach($leveltree as $id => $comment) {
$comments = array_merge($comments, $comment->getContent());
}
return $comments;
}
/**
* Return the latest commented pages
*/
private function fetchPages() {
$files = [];
$files = $this->getFilesOrderedByModifiedDate();
$pages = [];
foreach($files as $file) {
$pages[] = [
'title' => $file->data['title'],
'commentsCount' => count($file->data['comments']),
'lastCommentDate' => date('D, d M Y H:i:s', $file->modifiedDate)
];
}
return $pages;
}
/**
* Given a data file route, return the YAML content already parsed
*/
private function getDataFromFilename($fileRoute) {
//Single item details
//$fileInstance = CompiledYamlFile::instance(DATA_DIR . 'comments/' . $fileRoute);
//Use comment file in page folder
$fileInstance = CompiledYamlFile::instance($this->grav['page']->path() . '/comments.yaml');
if (!$fileInstance->content()) {
//Item not found
return;
}
return $fileInstance->content();
}
/**
* Add templates directory to twig lookup paths.
*/
public function onTwigTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
/**
* Add plugin templates path
*/
public function onTwigAdminTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/admin/templates';
}
/**
* Handle the Reindex task from the admin
*
* @param Event $e
*/
public function onAdminTaskExecute(Event $e)
{
if ($e['method'] == 'taskReindexComments') {
$controller = $e['controller'];
header('Content-type: application/json');
if (!$controller->authorizeTask('reindexComments', ['admin.configuration', 'admin.super'])) {
$json_response = [
'status' => 'error',
'message' => ' Index not created',
'details' => 'Insufficient permissions to reindex the comments index file.'
];
echo json_encode($json_response);
exit;
}
/*TODO // disable warnings
error_reporting(1);
// capture content
ob_start();
$this->gtnt->createIndex();
ob_get_clean();
list($status, $msg) = $this->getIndexCount();
$json_response = [
'status' => $status ? 'success' : 'error',
'message' => ' ' . $msg
];
echo json_encode($json_response);
*/ exit;
}
}
/**
* Perform an 'add' or 'update' for comment data as needed
*
* @param $event
* @return bool
*/
public function onAdminAfterSave($event)
{
$obj = $event['object'];
if ($obj instanceof Page) {
//nothing to do
//save means, the page changed, but still exists
}
return true;
}
/**
* Perform an 'add' or 'update' for comment data as needed
*
* @param $event
* @return bool
*/
public function onAdminAfterDelete($event)
{
$obj = $event['object'];
if ($obj instanceof Page) {
//TODO $this->deleteComment($obj);
}
return true;
}
/**
* Add navigation item to the admin plugin
*/
public function onAdminMenu()
{
$this->grav['twig']->plugins_hooked_nav['PLUGIN_COMMENTS.COMMENTS'] = ['route' => $this->route, 'icon' => 'fa-file-text'];
$options = [
'authorize' => 'taskReindexComments',
'hint' => 'reindexes the comments index',
'class' => 'comments-reindex',
'icon' => 'fa-file-text'
];
$this->grav['twig']->plugins_quick_tray['PLUGIN_COMMENTS.COMMENTS'] = $options;
}
/**
* Exclude comments from the Data Manager plugin
*/
public function onDataTypeExcludeFromDataManagerPluginHook()
{
$this->grav['admin']->dataTypesExcludedFromDataManagerPlugin[] = 'comments';
}
}