misuzu/public-legacy/forum/topic.php

337 lines
12 KiB
PHP
Raw Normal View History

2022-09-13 13:14:49 +00:00
<?php
namespace Misuzu;
2023-08-28 01:17:34 +00:00
use stdClass;
use RuntimeException;
2022-09-13 13:14:49 +00:00
$postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
$topicId = !empty($_GET['t']) && is_string($_GET['t']) ? (int)$_GET['t'] : 0;
2023-08-28 01:17:34 +00:00
$categoryId = null;
2022-09-13 13:14:49 +00:00
$moderationMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$submissionConfirmed = !empty($_GET['confirm']) && is_string($_GET['confirm']) && $_GET['confirm'] === '1';
$currentUser = $msz->authInfo->userInfo;
2023-08-28 01:17:34 +00:00
$currentUserId = $currentUser === null ? '0' : $currentUser->getId();
2022-09-13 13:14:49 +00:00
if($topicId < 1 && $postId > 0) {
2023-08-28 01:17:34 +00:00
try {
$postInfo = $msz->forumCtx->posts->getPost(postId: $postId);
2023-08-28 01:17:34 +00:00
} catch(RuntimeException $ex) {
Template::throwError(404);
2023-08-28 01:17:34 +00:00
}
$categoryId = (int)$postInfo->categoryId;
$perms = $msz->authInfo->getPerms('forum', $postInfo->categoryId);
2023-08-30 22:37:21 +00:00
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
2022-09-13 13:14:49 +00:00
if($postInfo->deleted && !$canDeleteAny)
Template::throwError(404);
2023-08-28 01:17:34 +00:00
$topicId = $postInfo->topicId;
$preceedingPostCount = $msz->forumCtx->posts->countPosts(
2023-08-28 01:17:34 +00:00
topicInfo: $topicId,
upToPostInfo: $postInfo,
deleted: $canDeleteAny ? null : false
);
2022-09-13 13:14:49 +00:00
}
2023-08-28 01:17:34 +00:00
try {
$topicIsNuked = $topicIsDeleted = $canDeleteAny = false;
$topicInfo = $msz->forumCtx->topics->getTopic(topicId: $topicId);
2023-08-28 01:17:34 +00:00
} catch(RuntimeException $ex) {
$topicIsNuked = true;
}
2022-09-13 13:14:49 +00:00
2023-08-28 01:17:34 +00:00
if(!$topicIsNuked) {
$topicIsDeleted = $topicInfo->deleted;
2022-09-13 13:14:49 +00:00
if($categoryId !== (int)$topicInfo->categoryId) {
$categoryId = (int)$topicInfo->categoryId;
$perms = $msz->authInfo->getPerms('forum', $topicInfo->categoryId);
2023-08-28 01:17:34 +00:00
}
2022-09-13 13:14:49 +00:00
if($msz->usersCtx->hasActiveBan($currentUser))
2023-08-30 22:37:21 +00:00
$perms = $perms->apply(fn($calc) => $calc & (Perm::F_CATEGORY_LIST | Perm::F_CATEGORY_VIEW));
2023-08-28 01:17:34 +00:00
2023-08-30 22:37:21 +00:00
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
2023-08-28 01:17:34 +00:00
}
if($topicIsNuked || $topicIsDeleted) {
if($msz->forumCtx->topicRedirects->hasTopicRedirect($topicId)) {
$topicRedirectInfo = $msz->forumCtx->topicRedirects->getTopicRedirect($topicId);
Template::set('topic_redir_info', $topicRedirectInfo);
if($topicIsNuked || !$canDeleteAny) {
header('Location: ' . $topicRedirectInfo->linkTarget);
return;
}
}
if(empty($topicRedirectInfo))
Template::throwError(404);
2022-09-13 13:14:49 +00:00
}
if(!$perms->check(Perm::F_CATEGORY_VIEW))
Template::throwError(403);
2022-09-13 13:14:49 +00:00
2023-08-28 01:17:34 +00:00
// Maximum amount of posts a topic may contain to still be deletable by the author
// this should be in the config
$deletePostThreshold = 1;
$categoryInfo = $msz->forumCtx->categories->getCategory(topicInfo: $topicInfo);
$topicIsLocked = $topicInfo->locked;
$topicIsArchived = $categoryInfo->archived;
$topicPostsTotal = $topicInfo->totalPostsCount;
2022-09-13 13:14:49 +00:00
$topicIsFrozen = $topicIsArchived || $topicIsDeleted;
2023-08-30 22:37:21 +00:00
$canDeleteOwn = !$topicIsFrozen && !$topicIsLocked && $perms->check(Perm::F_POST_DELETE_OWN);
$canBumpTopic = !$topicIsFrozen && $perms->check(Perm::F_TOPIC_BUMP);
$canLockTopic = !$topicIsFrozen && $perms->check(Perm::F_TOPIC_LOCK);
2022-09-13 13:14:49 +00:00
$canNukeOrRestore = $canDeleteAny && $topicIsDeleted;
$canDelete = !$topicIsDeleted && (
$canDeleteAny || (
$topicPostsTotal > 0
2023-08-28 01:17:34 +00:00
&& $topicPostsTotal <= $deletePostThreshold
2022-09-13 13:14:49 +00:00
&& $canDeleteOwn
&& $topicInfo->userId === (string)$currentUserId
2022-09-13 13:14:49 +00:00
)
);
$validModerationModes = [
'delete', 'restore', 'nuke',
'bump', 'lock', 'unlock',
];
if(in_array($moderationMode, $validModerationModes, true)) {
if(!CSRF::validateRequest())
Template::displayInfo("Couldn't verify this request, please refresh the page and try again.", 403);
2022-09-13 13:14:49 +00:00
if(!$msz->authInfo->isLoggedIn)
Template::displayInfo('You must be logged in to manage posts.', 401);
2022-09-13 13:14:49 +00:00
if($msz->usersCtx->hasActiveBan($currentUser))
Template::displayInfo('You have been banned, check your profile for more information.', 403);
2022-09-13 13:14:49 +00:00
switch($moderationMode) {
case 'delete':
2023-08-28 01:17:34 +00:00
if($canDeleteAny) {
if($topicInfo->deleted)
Template::displayInfo('This topic has already been marked as deleted.', 404);
2023-08-28 01:17:34 +00:00
} else {
if($topicInfo->deleted)
Template::throwError(404);
2023-08-28 01:17:34 +00:00
if(!$canDeleteOwn)
Template::displayInfo("You aren't allowed to delete topics.", 403);
2023-08-28 01:17:34 +00:00
if($topicInfo->userId !== $currentUser->getId())
Template::displayInfo('You can only delete your own topics.', 403);
2023-08-28 01:17:34 +00:00
// topics may only be deleted within a day of creation, this should be a config value
$deleteTimeFrame = 60 * 60 * 24;
if($topicInfo->createdTime < time() - $deleteTimeFrame)
Template::displayInfo('This topic has existed for too long. Ask a moderator to remove if it absolutely necessary.', 403);
2023-08-28 01:17:34 +00:00
// deleted posts are intentionally included
$topicPostCount = $msz->forumCtx->posts->countPosts(topicInfo: $topicInfo);
if($topicPostCount > $deletePostThreshold)
Template::displayInfo('This topic already has replies, you may no longer delete it. Ask a moderator to remove if it absolutely necessary.', 403);
2022-09-13 13:14:49 +00:00
}
2023-01-02 23:12:23 +00:00
if(!isset($_GET['confirm'])) {
Template::render('forum.confirm', [
'title' => 'Confirm topic deletion',
'class' => 'far fa-trash-alt',
'message' => sprintf('You are about to delete topic #%d. Are you sure about that?', $topicInfo->id),
2023-01-02 23:12:23 +00:00
'params' => [
't' => $topicInfo->id,
2023-01-02 23:12:23 +00:00
'm' => 'delete',
],
]);
break;
} elseif(!$submissionConfirmed) {
Tools::redirect($msz->urls->format(
2023-01-02 23:12:23 +00:00
'forum-topic',
['topic' => $topicInfo->id]
2023-09-08 20:40:48 +00:00
));
2023-01-02 23:12:23 +00:00
break;
2022-09-13 13:14:49 +00:00
}
$msz->forumCtx->topics->deleteTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_DELETE', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
Tools::redirect($msz->urls->format('forum-category', [
'forum' => $categoryInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
case 'restore':
if(!$canNukeOrRestore)
Template::throwError(403);
2022-09-13 13:14:49 +00:00
2023-01-02 23:12:23 +00:00
if(!isset($_GET['confirm'])) {
Template::render('forum.confirm', [
'title' => 'Confirm topic restore',
'class' => 'fas fa-magic',
'message' => sprintf('You are about to restore topic #%d. Are you sure about that?', $topicInfo->id),
2023-01-02 23:12:23 +00:00
'params' => [
't' => $topicInfo->id,
2023-01-02 23:12:23 +00:00
'm' => 'restore',
],
]);
break;
} elseif(!$submissionConfirmed) {
Tools::redirect($msz->urls->format('forum-topic', [
'topic' => $topicInfo->id,
2023-09-08 20:40:48 +00:00
]));
2023-01-02 23:12:23 +00:00
break;
2022-09-13 13:14:49 +00:00
}
$msz->forumCtx->topics->restoreTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_RESTORE', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
Tools::redirect($msz->urls->format('forum-category', [
'forum' => $categoryInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
case 'nuke':
if(!$canNukeOrRestore)
Template::throwError(403);
2022-09-13 13:14:49 +00:00
2023-01-02 23:12:23 +00:00
if(!isset($_GET['confirm'])) {
Template::render('forum.confirm', [
'title' => 'Confirm topic nuke',
'class' => 'fas fa-radiation',
'message' => sprintf('You are about to PERMANENTLY DELETE topic #%d. Are you sure about that?', $topicInfo->id),
2023-01-02 23:12:23 +00:00
'params' => [
't' => $topicInfo->id,
2023-01-02 23:12:23 +00:00
'm' => 'nuke',
],
]);
break;
} elseif(!$submissionConfirmed) {
Tools::redirect($msz->urls->format('forum-topic', [
'topic' => $topicInfo->id,
2023-09-08 20:40:48 +00:00
]));
2023-01-02 23:12:23 +00:00
break;
2022-09-13 13:14:49 +00:00
}
$msz->forumCtx->topics->nukeTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_NUKE', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
Tools::redirect($msz->urls->format('forum-category', [
'forum' => $categoryInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
case 'bump':
2023-08-28 01:17:34 +00:00
if($canBumpTopic) {
$msz->forumCtx->topics->bumpTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_BUMP', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
}
Tools::redirect($msz->urls->format('forum-topic', [
'topic' => $topicInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
case 'lock':
2023-08-28 01:17:34 +00:00
if($canLockTopic && !$topicIsLocked) {
$msz->forumCtx->topics->lockTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_LOCK', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
}
Tools::redirect($msz->urls->format('forum-topic', [
'topic' => $topicInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
case 'unlock':
2023-08-28 01:17:34 +00:00
if($canLockTopic && $topicIsLocked) {
$msz->forumCtx->topics->unlockTopic($topicInfo->id);
$msz->createAuditLog('FORUM_TOPIC_UNLOCK', [$topicInfo->id]);
2022-09-13 13:14:49 +00:00
}
Tools::redirect($msz->urls->format('forum-topic', [
'topic' => $topicInfo->id,
2023-09-08 20:40:48 +00:00
]));
2022-09-13 13:14:49 +00:00
break;
}
return;
}
$topicPosts = $topicInfo->postsCount;
2023-08-28 01:17:34 +00:00
if($canDeleteAny)
$topicPosts += $topicInfo->deletedPostsCount;
2022-09-13 13:14:49 +00:00
2023-08-28 01:17:34 +00:00
$topicPagination = new Pagination($topicPosts, 10, 'page');
2022-09-13 13:14:49 +00:00
2023-08-28 01:17:34 +00:00
if(isset($preceedingPostCount))
$topicPagination->setPage(floor($preceedingPostCount / $topicPagination->getRange()), true);
2022-09-13 13:14:49 +00:00
if(!$topicPagination->hasValidOffset())
Template::throwError(404);
2022-09-13 13:14:49 +00:00
$postInfos = $msz->forumCtx->posts->getPosts(
2023-08-28 01:17:34 +00:00
topicInfo: $topicInfo,
2023-08-30 22:37:21 +00:00
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false,
2023-08-28 01:17:34 +00:00
pagination: $topicPagination,
2022-09-13 13:14:49 +00:00
);
if(empty($postInfos))
Template::throwError(404);
2022-09-13 13:14:49 +00:00
try {
$originalPostInfo = $msz->forumCtx->posts->getPost(topicInfo: $topicInfo);
} catch(RuntimeException $ex) {
Template::throwError(404);
}
2023-08-28 01:17:34 +00:00
$posts = [];
foreach($postInfos as $postInfo) {
$posts[] = $post = new stdClass;
$post->info = $postInfo;
if($postInfo->userId !== null) {
$post->user = $msz->usersCtx->getUserInfo($postInfo->userId);
$post->colour = $msz->usersCtx->getUserColour($post->user);
$post->postsCount = $msz->forumCtx->countTotalUserPosts($post->user);
2023-08-28 01:17:34 +00:00
}
$post->isOriginalPost = $originalPostInfo->id == $postInfo->id;
$post->isOriginalPoster = $originalPostInfo->userId !== null && $postInfo->userId !== null
&& $originalPostInfo->userId === $postInfo->userId;
2023-08-28 01:17:34 +00:00
}
2023-08-30 22:37:21 +00:00
$canReply = !$topicIsArchived && !$topicIsLocked && !$topicIsDeleted && $perms->check(Perm::F_POST_CREATE);
2022-09-13 13:14:49 +00:00
if(!$msz->forumCtx->topics->checkUserHasReadTopic($currentUser, $topicInfo))
$msz->forumCtx->topics->incrementTopicViews($topicInfo);
2023-08-28 01:17:34 +00:00
$msz->forumCtx->topics->updateUserReadTopic($currentUser, $topicInfo);
2023-08-28 01:17:34 +00:00
2023-08-30 22:37:21 +00:00
$perms = $perms->checkMany([
'can_create_post' => Perm::F_POST_CREATE,
'can_edit_post' => Perm::F_POST_EDIT_OWN,
'can_edit_any_post' => Perm::F_POST_EDIT_ANY,
'can_delete_post' => Perm::F_POST_DELETE_OWN,
'can_delete_any_post' => Perm::F_POST_DELETE_ANY,
2023-08-28 01:17:34 +00:00
]);
2022-09-13 13:14:49 +00:00
Template::render('forum.topic', [
'topic_breadcrumbs' => iterator_to_array($msz->forumCtx->categories->getCategoryAncestry($topicInfo)),
'global_accent_colour' => $msz->forumCtx->categories->getCategoryColour($topicInfo),
2023-08-28 01:17:34 +00:00
'topic_info' => $topicInfo,
'category_info' => $categoryInfo,
2022-09-13 13:14:49 +00:00
'topic_posts' => $posts,
'can_reply' => $canReply,
'topic_pagination' => $topicPagination,
'topic_can_delete' => $canDelete,
'topic_can_nuke_or_restore' => $canNukeOrRestore,
'topic_can_bump' => $canBumpTopic,
'topic_can_lock' => $canLockTopic,
2023-08-28 01:17:34 +00:00
'topic_user_id' => $currentUserId,
'topic_perms' => $perms,
2022-09-13 13:14:49 +00:00
]);