From 8fa8eaa1f9d7668fe46de54c4dc98299065f0d4a Mon Sep 17 00:00:00 2001 From: flashwave Date: Sat, 15 Dec 2018 23:15:35 +0100 Subject: [PATCH] Improved handling of soft deleted comments. --- assets/less/classes/comment.less | 13 +++++++--- public/comments.php | 42 ++++++++++++++++++++++++++++++++ src/audit_log.php | 2 ++ src/comments.php | 29 +++++++++------------- templates/_layout/comments.twig | 21 ++++++++-------- 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/assets/less/classes/comment.less b/assets/less/classes/comment.less index 58f76c73..ece5b87e 100644 --- a/assets/less/classes/comment.less +++ b/assets/less/classes/comment.less @@ -13,6 +13,15 @@ display: none; } + &--deleted > &__container { + opacity: .5; + transition: opacity .2s; + + &:hover { + opacity: .9; + } + } + &__container { display: flex; margin-bottom: 3px; @@ -123,10 +132,6 @@ font: 12px/20px @mio-font-regular; margin-right: 1px; } - - &--deleted { - font-style: italic; - } } &__user { diff --git a/public/comments.php b/public/comments.php index 5debc482..8699fd65 100644 --- a/public/comments.php +++ b/public/comments.php @@ -114,6 +114,48 @@ switch ($_GET['m'] ?? null) { ]); break; + case 'restore': + if (!$commentPerms['can_delete_any']) { + echo render_info_or_json($isXHR, "You're not allowed to restore deleted comments.", 403); + break; + } + + $comment = (int)($_GET['c'] ?? 0); + $commentInfo = comments_post_get($comment, false); + + if (!$commentInfo) { + echo render_info_or_json($isXHR, "This comment doesn't exist.", 400); + break; + } + + $currentUserId = user_session_current('user_id', 0); + + if ($commentInfo['comment_deleted'] === null) { + echo render_info_or_json($isXHR, "This comment isn't in a deleted state.", 400); + break; + } + + if (!comments_post_delete($comment, false)) { + echo render_info_or_json($isXHR, 'Failed to restore comment.', 500); + break; + } + + audit_log(MSZ_AUDIT_COMMENT_ENTRY_RESTORE, $currentUserId, [ + $comment, + (int)($commentInfo['user_id'] ?? 0), + $commentInfo['username'] ?? '(Deleted User)', + ]); + + if ($redirect) { + header('Location: ' . $redirect . '#comment-' . $comment); + break; + } + + echo json_encode([ + 'id' => $comment, + ]); + break; + case 'create': if (!$commentPerms['can_comment']) { echo render_info_or_json($isXHR, "You're not allowed to post comments.", 403); diff --git a/src/audit_log.php b/src/audit_log.php index ab32f0db..0debf19c 100644 --- a/src/audit_log.php +++ b/src/audit_log.php @@ -14,6 +14,7 @@ define('MSZ_AUDIT_CHANGELOG_ACTION_CREATE', 'CHANGELOG_ACTION_CREATE'); define('MSZ_AUDIT_CHANGELOG_ACTION_EDIT', 'CHANGELOG_ACTION_EDIT'); define('MSZ_AUDIT_COMMENT_ENTRY_DELETE', 'COMMENT_ENTRY_DELETE'); define('MSZ_AUDIT_COMMENT_ENTRY_DELETE_MOD', 'COMMENT_ENTRY_DELETE_MOD'); +define('MSZ_AUDIT_COMMENT_ENTRY_RESTORE', 'COMMENT_ENTRY_RESTORE'); define('MSZ_AUDIT_NEWS_POST_CREATE', 'NEWS_POST_CREATE'); define('MSZ_AUDIT_NEWS_POST_EDIT', 'NEWS_POST_EDIT'); define('MSZ_AUDIT_NEWS_CATEGORY_CREATE', 'NEWS_CATEGORY_CREATE'); @@ -36,6 +37,7 @@ define('MSZ_AUDIT_LOG_STRINGS', [ MSZ_AUDIT_CHANGELOG_ACTION_EDIT => 'Edited changelog action #%d.', MSZ_AUDIT_COMMENT_ENTRY_DELETE => 'Deleted comment #%d.', MSZ_AUDIT_COMMENT_ENTRY_DELETE_MOD => 'Deleted comment #%d by user #%d %s.', + MSZ_AUDIT_COMMENT_ENTRY_RESTORE => 'Restored comment #%d by user #%d %s.', MSZ_AUDIT_NEWS_POST_CREATE => 'Created news post #%d.', MSZ_AUDIT_NEWS_POST_EDIT => 'Edited news post #%d.', MSZ_AUDIT_NEWS_CATEGORY_CREATE => 'Created news category #%d.', diff --git a/src/comments.php b/src/comments.php index 5a9f4d46..0e831404 100644 --- a/src/comments.php +++ b/src/comments.php @@ -213,29 +213,22 @@ define('MSZ_COMMENTS_CATEGORY_QUERY', ' LEFT JOIN `msz_roles` as r ON r.`role_id` = u.`display_role` WHERE p.`category_id` = :category - AND p.`comment_deleted` IS NULL - %s - ORDER BY p.`comment_pinned` DESC, p.`comment_id` %s + %1$s + ORDER BY p.`comment_deleted` ASC, p.`comment_pinned` DESC, p.`comment_id` %2$s '); -define('MSZ_COMMENTS_CATEGORY_QUERY_ROOT', sprintf( - MSZ_COMMENTS_CATEGORY_QUERY, - 'AND p.`comment_reply_to` IS NULL', - 'DESC' -)); -define('MSZ_COMMENTS_CATEGORY_QUERY_REPLIES', sprintf( - MSZ_COMMENTS_CATEGORY_QUERY, - 'AND p.`comment_reply_to` = :parent', - 'ASC' -)); -// heavily recursive +// The $parent param should never be used outside of this function itself and should always remain the last of the list. function comments_category_get(int $category, int $user, ?int $parent = null): array { - if ($parent !== null) { - $getComments = db_prepare(MSZ_COMMENTS_CATEGORY_QUERY_REPLIES); + $isParent = $parent === null; + $getComments = db_prepare(sprintf( + MSZ_COMMENTS_CATEGORY_QUERY, + $isParent ? 'AND p.`comment_reply_to` IS NULL' : 'AND p.`comment_reply_to` = :parent', + $isParent ? 'DESC' : 'ASC' + )); + + if (!$isParent) { $getComments->bindValue('parent', $parent); - } else { - $getComments = db_prepare(MSZ_COMMENTS_CATEGORY_QUERY_ROOT); } $getComments->bindValue('user', $user); diff --git a/templates/_layout/comments.twig b/templates/_layout/comments.twig index c50b4718..6e035f9f 100644 --- a/templates/_layout/comments.twig +++ b/templates/_layout/comments.twig @@ -42,8 +42,8 @@ {% macro comments_entry(comment, indent, category, user, perms) %} {% from '_layout/input.twig' import input_checkbox_raw %} - {% if comment.comment_deleted is null or comment.comment_replies|length > 0 %} -
+ {% if perms.can_delete_any or (comment.comment_deleted is null or comment.comment_replies|length > 0) %} +