rows->count() > 0)
diff --git a/core/plugins/groups/forum/assets/css/like.css b/core/plugins/groups/forum/assets/css/like.css
new file mode 100644
index 00000000000..38910761dee
--- /dev/null
+++ b/core/plugins/groups/forum/assets/css/like.css
@@ -0,0 +1,60 @@
+/* Should put this in the comments.less file */
+.comment-body a.like {
+ color: #dadada;
+ margin-right: 5px;
+ font-size:20px;
+}
+
+.comment-body a.like:hover {
+ color: #a6a6a6;
+}
+
+.comment-body a.userLiked {
+ color: red;
+}
+
+.comment-body a.userLiked:hover {
+ color: #ce0202;
+}
+
+.comment-body .likesStat {
+ font-size: 14px;
+ vertical-align:middle;
+ margin-top: 5px;
+ text-decoration: underline;
+}
+
+.comment-body .noLikes {
+ text-decoration: none;
+}
+
+.comment-body .likesStat:hover {
+ cursor: pointer;
+ color: black;
+ text-decoration: underline;
+}
+
+.comment-body .noLikes:hover {
+ cursor: auto;
+ text-decoration: none;
+}
+
+.elementInline {
+ display: inline-flex;
+ float: right;
+ vertical-align:middle;
+}
+
+.whoLikedPost {
+ height: 0;
+ overflow: hidden;
+ transition: height 0.8s ease;
+}
+
+.names {
+ padding: 10px;
+ background-color: #eeeeee;
+ border-radius: 5px;
+ text-align: right;
+ font-size: 12px;
+}
\ No newline at end of file
diff --git a/core/plugins/groups/forum/assets/js/like.js b/core/plugins/groups/forum/assets/js/like.js
new file mode 100644
index 00000000000..2c2fbf017b9
--- /dev/null
+++ b/core/plugins/groups/forum/assets/js/like.js
@@ -0,0 +1,150 @@
+window.addEventListener('DOMContentLoaded', (domEvent) => {
+ // Find all the "like" / stat button
+ const commentSections = document.querySelectorAll('.comment-content')
+ if (commentSections.length) {
+ for(let i = 0; i < commentSections.length;i++) {
+ let likeButton = commentSections[i].querySelector('.like');
+ let likeStatsLink = commentSections[i].querySelector('.likesStat');
+ let whoLikedPostDiv = commentSections[i].querySelector('.whoLikedPost');
+
+ // Make sure all these HTML elements are present before assigning attributes
+ if (likeStatsLink && whoLikedPostDiv && likeButton) {
+ likeStatsLink.onclick = (e) => {
+ e.preventDefault();
+ this.__toggle = !this.__toggle;
+ if(this.__toggle) {
+ whoLikedPostDiv.style.height = `${whoLikedPostDiv.scrollHeight}px`;
+ } else {
+ whoLikedPostDiv.style.height = 0;
+ }
+ }
+
+ likeButton.onclick = (e) => {
+ e.preventDefault();
+
+ let hasHeart = likeButton.classList.contains("userLiked");
+
+ const threadId = likeButton.dataset.thread;
+ const postId = likeButton.dataset.post;
+ const userId = likeButton.dataset.user;
+ const userName = likeButton.dataset.userName;
+ const nameAndId = `${userName}#${userId}`;
+
+ const likesList = likeButton.dataset.likesList;
+ const likeCount = likeButton.dataset.count;
+
+ // console.log(threadId, postId, userId, likeCount, userName, likesList);
+
+ const likesListArray = likesList.split("/");
+
+ if (hasHeart) {
+ removeLike(threadId, postId, userId).then((res) => {
+ if (res.ok) {
+ const newLikeCount = Number(likeCount) - 1;
+ const newLikesString = likesListArray.filter(e => e !== nameAndId).join('/');
+
+ likeButton.dataset.count = `${newLikeCount}`;
+ likeButton.classList.remove("userLiked");
+ likeButton.dataset.likesList = newLikesString;
+ likeStatsLink.innerHTML = (newLikeCount === 0) ? 'No Likes' : `View Likes (${newLikeCount})`;
+
+ if (newLikeCount > 0) {
+ let whoLikedArray = [];
+ const newLikesArray = newLikesString.split("/");
+ for (let i = 0; i < newLikesArray.length; i++) {
+ const nameArray = newLikesArray[i].split('#')
+ const userName = nameArray[0];
+ const userId = nameArray[1];
+ const userProfileUrl = `/members/${userId}/profile`;
+
+ whoLikedArray.push(`
${userName}`);
+ }
+
+ likeStatsLink.classList.remove("noLikes");
+ whoLikedPostDiv.innerHTML = "
" + whoLikedArray.join(', ') + " liked this
";
+ } else {
+ likeStatsLink.classList.add("noLikes");
+ whoLikedPostDiv.innerHTML = "";
+ }
+
+ // console.warn(`Like removed for forum thread '${threadId}' of post '${postId}' for user ${userId}`);
+ }
+ })
+ } else {
+ addLike(threadId, postId, userId).then((res) => {
+ if (res.ok) {
+ const newLikeCount = Number(likeCount) + 1;
+ const newLikesString = [...likesListArray, nameAndId].filter(Boolean).join('/');
+
+ likeButton.dataset.count = `${newLikeCount}`;
+ likeButton.classList.add("userLiked");
+ likeButton.dataset.likesList = newLikesString;
+ likeStatsLink.innerHTML = `View Likes (${newLikeCount})`;
+ likeStatsLink.classList.remove("noLikes");
+
+ let whoLikedArray = [];
+ const newLikesArray = newLikesString.split("/");
+ for (let i = 0; i < newLikesArray.length; i++) {
+ const nameArray = newLikesArray[i].split('#')
+ const userName = nameArray[0];
+ const userId = nameArray[1];
+ const userProfileUrl = `/members/${userId}/profile`;
+
+ whoLikedArray.push(`
${userName}`);
+ }
+
+ whoLikedPostDiv.innerHTML = "
" + whoLikedArray.join(', ') + " liked this
";
+
+ // console.log(`Like recorded for forum thread '${threadId}' of post '${postId}' for user ${userId}`);
+ }
+ })
+ }
+
+ return false;
+ };
+ }
+ }
+ }
+});
+
+const addLike = async (threadId, postId, userId) => {
+ const postUrl = "/api/forum/likes/addLikeToPost";
+ const data = {threadId, postId, userId};
+
+ try {
+ let response = await fetch(postUrl, {
+ method: "POST", headers: {"Content-Type": "application/x-www-form-urlencoded"},
+ body: new URLSearchParams(data) // urlencoded form body
+ });
+
+ if (!response.ok) {
+ window.confirm("Server Error with API");
+ console.error(`Error Code: ${response.status} / Error Message: ${response.statusText}`);
+ }
+
+ return response;
+ } catch (error) {
+ if (error instanceof SyntaxError) {
+ console.error('There was a SyntaxError', error);
+ } else {
+ console.error('There was an error', error);
+ }
+ }
+};
+
+const removeLike = async (threadId, postId, userId) => {
+ const deleteAssertionUrl = "/api/forum/likes/deleteLikeFromPost";
+ const data = {threadId, postId, userId};
+
+ const deleteAssertionResp = await fetch(deleteAssertionUrl, {
+ method: "DELETE", headers: {"Content-Type": "application/x-www-form-urlencoded"},
+ body: new URLSearchParams(data)
+ })
+
+ if (!deleteAssertionResp.ok) {
+ window.confirm("Server Error with API");
+ console.error(`Error Code: ${response.status} / Error Message: ${response.statusText}`);
+ }
+
+ return deleteAssertionResp;
+}
\ No newline at end of file
diff --git a/core/plugins/groups/forum/forum.php b/core/plugins/groups/forum/forum.php
index 9dfb97f3d89..47489389628 100644
--- a/core/plugins/groups/forum/forum.php
+++ b/core/plugins/groups/forum/forum.php
@@ -1246,6 +1246,15 @@ public function threads()
$this->_authorize('thread', $thread->get('id'));
$this->_authorize('post');
+ // Get all the likes of this thread
+ $db = \App::get('db');
+ $queryLikes = "SELECT LIKES.threadId as 'threadId', LIKES.postId as 'postId',
+ LIKES.userId as 'userId', USERS.name as 'userName', USERS.email as 'userEmail'
+ FROM jos_forum_posts_like as LIKES, jos_users AS USERS
+ WHERE LIKES.userId = USERS.id AND LIKES.threadId = " . $thread->get('id');
+ $db->setQuery($queryLikes);
+ $initialLikesList = $db->loadObjectList();
+
// If the access is anything beyond public,
// make sure they're logged in.
if (User::isGuest() && !in_array($thread->get('access'), User::getAuthorisedViewLevels()))
@@ -1280,6 +1289,7 @@ public function threads()
->set('section', $section)
->set('category', $category)
->set('thread', $thread)
+ ->set('likes', $initialLikesList)
->set('filters', $filters)
->setErrors($this->getErrors())
->loadTemplate();
@@ -1505,7 +1515,7 @@ public function savethread()
// Email the group and insert email tokens to allow them to respond to group posts via email
$params = Component::params('com_groups');
- if ($params->get('email_comment_processing') && (isset($moving) && $moving == false))
+ if ($params->get('email_forum_comments') && (isset($moving) && $moving == false))
{
$thread->set('section', $section->get('alias'));
$thread->set('category', $category->get('alias'));
@@ -1552,8 +1562,17 @@ public function savethread()
$unsubscribeToken = $encryptor->buildEmailToken(1, 3, $userID, $this->group->get('gidNumber'));
$unsubscribeLink = rtrim(Request::base(), '/') . '/' . ltrim(Route::url('index.php?option=com_groups&cn=' . $this->group->get('cn') .'&active=forum&action=unsubscribe&t=' . $unsubscribeToken), DS);
- $from['replytoname'] = Lang::txt('PLG_GROUPS_FORUM_REPLYTO') . ' @ ' . Config::get('sitename');
- $from['replytoemail'] = 'hgm-' . $token . '@' . $_SERVER['HTTP_HOST'];
+
+ if(Component::params('com_groups')->get('email_comment_processing'))
+ {
+ $from['replytoname'] = Lang::txt('PLG_GROUPS_FORUM_REPLYTO') . ' @ ' . Config::get('sitename');
+ $from['replytoemail'] = 'hgm-' . $token . '@' . $_SERVER['HTTP_HOST'];
+ }
+ else
+ {
+ $from['replytoname'] = 'noreply';
+ $from['replytoemail'] = 'noreply@' . $_SERVER['HTTP_HOST'];
+ }
}
$msg = array();
diff --git a/core/plugins/groups/forum/language/en-GB/en-GB.plg_groups_forum.ini b/core/plugins/groups/forum/language/en-GB/en-GB.plg_groups_forum.ini
index 978b1cf6ec8..00ac5450a32 100644
--- a/core/plugins/groups/forum/language/en-GB/en-GB.plg_groups_forum.ini
+++ b/core/plugins/groups/forum/language/en-GB/en-GB.plg_groups_forum.ini
@@ -72,7 +72,7 @@ PLG_GROUPS_FORUM_EMAIL_POSTS_DIGEST="digest email"
PLG_GROUPS_FORUM_EMAIL_POSTS_DAILY="Daily"
PLG_GROUPS_FORUM_EMAIL_POSTS_WEEKLY="Weekly"
PLG_GROUPS_FORUM_EMAIL_POSTS_MONTHLY="Monthly"
-PLG_GROUPS_FORUM_EMAIL_POSTS="Email forum posts"
+PLG_GROUPS_FORUM_EMAIL_POSTS="Email forum post notifications"
PLG_GROUPS_FORUM_EMAIL_CATEGORIES="Posts to:"
PLG_GROUPS_FORUM_BY_USER="by %s"
PLG_GROUPS_FORUM_REPORT_ABUSE="Report abuse"
diff --git a/core/plugins/groups/forum/views/email/tmpl/comment_html.php b/core/plugins/groups/forum/views/email/tmpl/comment_html.php
index 446a00dc324..f7daca082f0 100644
--- a/core/plugins/groups/forum/views/email/tmpl/comment_html.php
+++ b/core/plugins/groups/forum/views/email/tmpl/comment_html.php
@@ -15,7 +15,8 @@
$bgcolor = '#f1f1f1';
$bdcolor = '#e1e1e1';
?>
-delimiter) { ?>
+delimiter) {
+ if(Component::params('com_groups')->get('email_comment_processing')) { ?>
+
+
diff --git a/core/plugins/groups/forum/views/email/tmpl/comment_plain.php b/core/plugins/groups/forum/views/email/tmpl/comment_plain.php
index c50642a2048..0d3eb80e011 100644
--- a/core/plugins/groups/forum/views/email/tmpl/comment_plain.php
+++ b/core/plugins/groups/forum/views/email/tmpl/comment_plain.php
@@ -17,7 +17,10 @@
if ($this->delimiter)
{
$message .= $this->delimiter . "\n";
- $message .= Lang::txt('PLG_GROUPS_FORUM_EMAIL_REPLY_ABOVE') . "\n";
+
+ if(Component::params('com_groups')->get('email_comment_processing'))
+ $message .= Lang::txt('PLG_GROUPS_FORUM_EMAIL_REPLY_ABOVE') . "\n";
+
$message .= 'Message from ' . $base . ' / ' . Lang::txt('PLG_GROUPS_FORUM_DETAILS_THREAD', $this->thread->get('id')) . "\n";
}
$message .= ($this->post->get('anonymous')) ? Lang::txt('JANONYMOUS') : $this->post->creator->get('name') . ' (' . $this->post->creator->get('username') . ')';
diff --git a/core/plugins/groups/forum/views/shared/tmpl/_email_settings.php b/core/plugins/groups/forum/views/shared/tmpl/_email_settings.php
index b750cddc9ab..9327e31b269 100644
--- a/core/plugins/groups/forum/views/shared/tmpl/_email_settings.php
+++ b/core/plugins/groups/forum/views/shared/tmpl/_email_settings.php
@@ -7,7 +7,7 @@
$base = $this->base;
-if (Component::params('com_groups')->get('email_comment_processing') && $this->config->get('access-view-section')) : ?>
+if (Component::params('com_groups')->get('email_forum_comments') && $this->config->get('access-view-section')) : ?>
diff --git a/core/plugins/groups/forum/views/threads/tmpl/_comment.php b/core/plugins/groups/forum/views/threads/tmpl/_comment.php
index 73811a2382a..7b347c1f925 100644
--- a/core/plugins/groups/forum/views/threads/tmpl/_comment.php
+++ b/core/plugins/groups/forum/views/threads/tmpl/_comment.php
@@ -7,7 +7,25 @@
defined('_HZEXEC_') or die();
- $this->comment->set('section', $this->filters['section']);
+$this->css('like.css')
+ ->js('like.js');
+
+ $likeArray = $this->like;
+ $countLike = count($likeArray);
+ $currentUserId = User::get('id');
+
+ $userLikesComment = false;
+ $userNameLikesArray = "";
+ foreach ( $likeArray as $likeObj ) {
+ if ( $currentUserId == $likeObj->userId ) {
+ $userLikesComment = true;
+ }
+
+ $userNameLikesArray .= "/" . ($likeObj->userName) . "#" . ($likeObj->userId);
+ }
+ $userNameLikesArray = substr($userNameLikesArray,1);
+
+ $this->comment->set('section', $this->filters['section']);
$this->comment->set('category', $this->category->get('alias'));
$this->config->set('access-edit-post', false);
@@ -60,7 +78,44 @@
-
+
+
+
+
+ ">
+ 0) ? "View Likes (" . $countLike . ")" : "No Likes"; ?>
+
+
+
+
+
+ 0) { ?>
+
+ $userName";
+ }
+ echo join(", ", $links) . " liked this";
+ ?>
+
+
+
+
+