summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Kohl <git@jonaskohl.de>2024-09-19 14:19:35 +0200
committerJonas Kohl <git@jonaskohl.de>2024-09-19 14:19:35 +0200
commit95bfdb59b6a1e04e474551c23c7caef619c79839 (patch)
tree0fe7bf17c5767df5084dac05c61b4167781b9b1b
parentd7faf7053803aaa9eb8ae85a864ea1b2cccaa586 (diff)
Topic locking
-rw-r--r--src/application/messages/de.msg9
-rw-r--r--src/application/mystic/forum/orm/Topic.php2
-rw-r--r--src/application/views/view_post.php3
-rw-r--r--src/application/views/view_search_results.php4
-rw-r--r--src/application/views/view_topic_locked.php4
-rw-r--r--src/application/views/view_topic_start.php31
-rw-r--r--src/application/views/view_topics.php7
-rw-r--r--src/application/views/view_user.php4
-rw-r--r--src/index.php94
9 files changed, 153 insertions, 5 deletions
diff --git a/src/application/messages/de.msg b/src/application/messages/de.msg
index c2d8416..d1b2389 100644
--- a/src/application/messages/de.msg
+++ b/src/application/messages/de.msg
@@ -455,3 +455,12 @@ metadata({
: "Failed to send verification email"
= "Konnte Bestätigungsmail nicht versenden"
+
+: "This topic has been locked"
+= "Dieses Thema wurde gesperrt"
+
+: "Lock topic"
+= "Thema sperren"
+
+: "Unlock topic"
+= "Thema entsperren"
diff --git a/src/application/mystic/forum/orm/Topic.php b/src/application/mystic/forum/orm/Topic.php
index 421f5ec..cfd0c78 100644
--- a/src/application/mystic/forum/orm/Topic.php
+++ b/src/application/mystic/forum/orm/Topic.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace mystic\forum\orm;
+use mystic\forum\attributes\DefaultValue;
use mystic\forum\attributes\PrimaryKey;
use mystic\forum\attributes\References;
use mystic\forum\attributes\Table;
@@ -13,4 +14,5 @@ class Topic extends Entity {
public string $title;
public \DateTimeImmutable $creationDate;
#[References("public.users", onDelete: References::SET_NULL)] public ?string $createdBy;
+ #[DefaultValue("false")] public bool $isLocked;
}
diff --git a/src/application/views/view_post.php b/src/application/views/view_post.php
index 62b2d18..0f86896 100644
--- a/src/application/views/view_post.php
+++ b/src/application/views/view_post.php
@@ -5,6 +5,7 @@ use mystic\forum\orm\Attachment;
/** @var mystic\forum\orm\Post $post */
/** @var mystic\forum\orm\User $postAuthor */
+/** @var mystic\forum\orm\Topic $topic */
$isImage = fn(string $m) => str_starts_with($m, "image/") || str_starts_with($m, "video/");
@@ -16,6 +17,8 @@ $canReply = $GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_
$canEdit = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?->hasPermission(UserPermissions::EDIT_OWN_POST))
|| ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::EDIT_OTHER_POST));
+$canEdit = $canEdit && !$topic->isLocked;
+
$canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))
|| ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::DELETE_OTHER_POST));
diff --git a/src/application/views/view_search_results.php b/src/application/views/view_search_results.php
index e21fbb8..914d2b2 100644
--- a/src/application/views/view_search_results.php
+++ b/src/application/views/view_search_results.php
@@ -20,7 +20,9 @@ use mystic\forum\utils\StringUtils;
<span class="text-muted"><?= __("posted by %author% on %post_date% in %topic%", [
"author" => '<em>' . htmlentities($users[$post->authorId]?->displayName ?? __("unknown")) . '</em>',
"post_date" => '<span class="_time">' . htmlentities($post->postDate->format("c")) . '</span>',
- "topic" => '<em>' . htmlentities($topics[$post->topicId]?->title ?? "unknown") . '</em>',
+ "topic" => '<em>'
+ . ($topics[$post->topicId]?->isLocked ? '<span class="glyphicon glyphicon-lock text-muted" aria-hidden="true"></span> ' : '')
+ . htmlentities($topics[$post->topicId]?->title ?? "unknown") . '</em>',
]) ?></span>
</a>
<?php endforeach; ?>
diff --git a/src/application/views/view_topic_locked.php b/src/application/views/view_topic_locked.php
new file mode 100644
index 0000000..ac59fcb
--- /dev/null
+++ b/src/application/views/view_topic_locked.php
@@ -0,0 +1,4 @@
+<div class="well icon-well text-warning margin-top-4x">
+ <span class="glyphicon glyphicon-lock text-warning" aria-hidden="true"></span>
+ <em><?= __("This topic has been locked") ?></em>
+</div>
diff --git a/src/application/views/view_topic_start.php b/src/application/views/view_topic_start.php
index da8c0cd..fe85afa 100644
--- a/src/application/views/view_topic_start.php
+++ b/src/application/views/view_topic_start.php
@@ -1,5 +1,6 @@
<?php
use mystic\forum\orm\UserPermissions;
+use mystic\forum\utils\RequestUtils;
$canReply = $GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_POST) ?? false;
@@ -111,17 +112,45 @@ $canDelete = ($GLOBALS["currentUser"]?->id === $topicAuthor->id && $topicAuthor-
</script>
<?php endif; ?>
+<?php
+if (($_formError = RequestUtils::getAndClearFormError("updatetopic")) !== null) {
+ _view("alert_error", ["message" => $_formError]);
+}
+
+if (($_formError = RequestUtils::getAndClearFormError("locktopic")) !== null) {
+ _view("alert_error", ["message" => $_formError]);
+}
+?>
+
<div class="page-header margin-top-0 clearfix">
<div id="displayHeading">
<div role="heading" class="h1 seamless-inline">
+ <?php if ($topic->isLocked): ?>
+ <span class="glyphicon glyphicon-lock text-muted" aria-hidden="true"></span>
+ <?php endif; ?>
<?= htmlentities($topic->title) ?>
<div class="pull-right text-normal">
- <?php if ($canEdit): ?>
+ <?php if ($canEdit && !$topic->isLocked): ?>
<button id="btn-edit-title" class="btn btn-default js-only"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> <?= __("Edit title") ?></button>
<?php endif; ?>
<?php if ($canReply): ?>
<button id="btn-reply" class="btn btn-default js-only"><span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> <?= __("Reply") ?></button>
<?php endif; ?>
+ <?php if ($canEdit): ?>
+ <?php if ($topic->isLocked): ?>
+ <form action="?_action=locktopic" method="post" class="seamless-inline">
+ <input type="hidden" name="topic" value="<?= htmlentities($topic->id) ?>">
+ <input type="hidden" name="locked" value="false">
+ <button type="submit" class="btn btn-success"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> <?= __("Unlock topic") ?></button>
+ </form>
+ <?php else: ?>
+ <form action="?_action=locktopic" method="post" class="seamless-inline">
+ <input type="hidden" name="topic" value="<?= htmlentities($topic->id) ?>">
+ <input type="hidden" name="locked" value="true">
+ <button type="submit" class="btn btn-warning"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> <?= __("Lock topic") ?></button>
+ </form>
+ <?php endif; ?>
+ <?php endif; ?>
<?php if ($canDelete): ?>
<form action="?_action=deletetopic" method="post" class="seamless-inline">
<input type="hidden" name="topic" value="<?= htmlentities($topic->id) ?>">
diff --git a/src/application/views/view_topics.php b/src/application/views/view_topics.php
index 291fbdc..a762f8c 100644
--- a/src/application/views/view_topics.php
+++ b/src/application/views/view_topics.php
@@ -12,7 +12,12 @@ if ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_TOPIC)):
<div class="list-group">
<?php /** @var Topic $topic */ foreach ($topics as $topic): ?>
<a class="list-group-item" href="?_action=viewtopic&amp;topic=<?= htmlentities(urlencode($topic->id)) ?>">
- <h4 class="list-group-item-heading"><?= htmlentities($topic->title) ?></h4>
+ <h4 class="list-group-item-heading">
+ <?php if ($topic->isLocked): ?>
+ <span class="glyphicon glyphicon-lock text-muted" aria-hidden="true"></span>
+ <?php endif; ?>
+ <?= htmlentities($topic->title) ?>
+ </h4>
<p class="list-group-item-text _time"><?= htmlentities($topic->creationDate->format("c")) ?></p>
</a>
<?php endforeach; ?>
diff --git a/src/application/views/view_user.php b/src/application/views/view_user.php
index d3ebe04..5c89411 100644
--- a/src/application/views/view_user.php
+++ b/src/application/views/view_user.php
@@ -59,7 +59,9 @@ $emailPending = $isOwnProfile && $user->pendingEmail !== null;
<?= htmlentities(StringUtils::truncate(strip_tags(renderPost($post->content)), 100)) ?><br>
<span class="text-muted"><?= __("posted on %post_date% in %topic%", [
"post_date" => '<span class="_time">' . htmlentities($post->postDate->format("c")) . '</span>',
- "topic" => '<em>' . htmlentities($topics[$post->topicId]?->title ?? "unknown") . '</em>',
+ "topic" => '<em>' .
+ ($topics[$post->topicId]?->isLocked ? '<span class="glyphicon glyphicon-lock text-muted" aria-hidden="true"></span> ' : '') .
+ htmlentities($topics[$post->topicId]?->title ?? "unknown") . '</em>',
]) ?></span>
</a>
<?php endforeach; ?>
diff --git a/src/index.php b/src/index.php
index d651400..cc9e99d 100644
--- a/src/index.php
+++ b/src/index.php
@@ -572,6 +572,12 @@ if ($_action === "auth") {
msg_error("You need to be logged in to add new posts!");
exit;
}
+
+ if ($topic->isLocked) {
+ http_response_code(403);
+ msg_error("This topic is locked!");
+ exit;
+ }
$attachments = reArrayFiles($_FILES["files"]);
@@ -658,12 +664,15 @@ if ($_action === "auth") {
"postAuthor" => $postAuthor,
"topicAuthor" => $topicAuthor,
"attachments" => $attachments,
+ "topic" => $topic,
]);
}
_view("view_topic_end");
- if ($currentUser) {
+ if ($topic->isLocked) {
+ _view("view_topic_locked");
+ } elseif ($currentUser) {
_view("form_addpost");
} else {
_view("view_logintoreply");
@@ -709,6 +718,7 @@ if ($_action === "auth") {
$topic->id = $db->generateId();
$topic->title = $title;
$topic->creationDate = new DateTimeImmutable();
+ $topic->isLocked = false;
$db->insert($topic);
@@ -1169,6 +1179,12 @@ if ($_action === "auth") {
if (!$db->fetch($topicAuthor))
$topicAuthor = null;
+ $topic = new Topic();
+ $topic->id = $post->topicId;
+
+ if (!$db->fetch($topic))
+ $topic = null;
+
$canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))
|| ($currentUser->hasPermission(UserPermissions::DELETE_OTHER_POST));
@@ -1217,6 +1233,7 @@ if ($_action === "auth") {
"postAuthor" => $topicAuthor,
"topicAuthor" => null,
"attachments" => $attachments,
+ "topic" => $topic,
]);
_view("template_end", [...getThemeAndLangInfo()]);
}
@@ -1251,6 +1268,18 @@ if ($_action === "auth") {
$canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::EDIT_OWN_POST))
|| ($currentUser->hasPermission(UserPermissions::EDIT_OTHER_POST));
+ $topic = new Topic();
+ $topic->id = $post->topicId;
+
+ if (!$db->fetch($topic))
+ $topic = null;
+
+ if ($topic->isLocked) {
+ http_response_code(403);
+ msg_error(__("This topic has been locked"));
+ exit;
+ }
+
if (!$canEdit) {
http_response_code(403);
msg_error(__("You don't have permission to edit this post"));
@@ -1360,6 +1389,12 @@ if ($_action === "auth") {
if (!$db->fetch($topicAuthor))
$topicAuthor = null;
+ if ($topic->isLocked) {
+ http_response_code(403);
+ msg_error(__("This topic has been locked"));
+ exit;
+ }
+
$canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::EDIT_OWN_TOPIC))
|| ($currentUser->hasPermission(UserPermissions::EDIT_OTHER_TOPIC));
@@ -1378,6 +1413,63 @@ if ($_action === "auth") {
}
header("Location: ./?_action=viewtopic&topic=" . urlencode($topicId));
+} elseif ($_action === "locktopic") {
+ RequestUtils::ensureRequestMethod("POST");
+ $topicId = $_POST["topic"] ?? null;
+ if ($topicId === null) {
+ http_response_code(400);
+ msg_error(__("Missing topic id"));
+ exit;
+ }
+ RequestUtils::setFormErrorDestination($dest = "Location: ./?_action=viewtopic&topic=" . urlencode($topicId));
+
+ if (!$currentUser) {
+ http_response_code(403);
+ msg_error(__("You need to be logged in to lock topics!"));
+ exit;
+ }
+
+ $formId = "locktopic";
+ $locked = RequestUtils::getRequiredField("locked", $formId);
+ if ($locked === "true") {
+ $locked = true;
+ } elseif ($locked === "false") {
+ $locked = false;
+ } else RequestUtils::triggerFormError("Invalid value", $formId);
+
+ $topic = new Topic();
+ $topic->id = $topicId;
+
+ if (!$db->fetch($topic)) {
+ http_response_code(404);
+ msg_error(__("No topic exists with this id"));
+ exit;
+ }
+
+ $topicAuthor = new User();
+ $topicAuthor->id = $topic->createdBy;
+
+ if (!$db->fetch($topicAuthor))
+ $topicAuthor = null;
+
+ $canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::EDIT_OWN_TOPIC))
+ || ($currentUser->hasPermission(UserPermissions::EDIT_OTHER_TOPIC));
+
+ if (!$canEdit) {
+ http_response_code(403);
+ msg_error(__("You don't have permission to lock or unlock this topic"));
+ exit;
+ }
+
+ $topic->isLocked = $locked;
+
+ if (!$db->update($topic)) {
+ http_response_code(500);
+ msg_error(__("Failed to lock or unlock topic"));
+ exit;
+ }
+
+ header($dest);
} elseif ($_action === "search") {
$query = $_GET["query"] ?? null;
if ($query !== null) {