From 4a6e12bf1fc7837699f780674c33cba5f2b1223c Mon Sep 17 00:00:00 2001
From: Jonas Kohl
Date: Thu, 19 Sep 2024 16:32:18 +0200
Subject: Add log messages

---
 src/application/messages/de.msg                    |  9 +++
 src/application/mystic/forum/Database.php          |  9 ++-
 .../mystic/forum/orm/TopicLogMessage.php           | 23 ++++++++
 src/application/views/view_topiclog.php            | 67 ++++++++++++++++++++++
 4 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 src/application/mystic/forum/orm/TopicLogMessage.php
 create mode 100644 src/application/views/view_topiclog.php

(limited to 'src/application')

diff --git a/src/application/messages/de.msg b/src/application/messages/de.msg
index d1b2389..46b48b3 100644
--- a/src/application/messages/de.msg
+++ b/src/application/messages/de.msg
@@ -464,3 +464,12 @@ metadata({
 
 : "Unlock topic"
 = "Thema entsperren"
+
+: "%user% locked this topic"
+= "%user% hat dieses Thema gesperrt"
+
+: "%user% unlocked this topic"
+= "%user% hat dieses Thema entsperrt"
+
+: "%user% changed the title of this topic from %old_title% to %new_title%"
+= "%user% hat den Titel dieses Themas von %old_title% zu %new_title% geƤndert"
diff --git a/src/application/mystic/forum/Database.php b/src/application/mystic/forum/Database.php
index 8ebc36b..7a417be 100644
--- a/src/application/mystic/forum/Database.php
+++ b/src/application/mystic/forum/Database.php
@@ -142,6 +142,7 @@ class Database {
                 return "text";
             case "object":
             case "array":
+                return "jsonb";
             case "iterable":
             case "callable":
             case "mixed":
@@ -241,8 +242,10 @@ class Database {
             return strval($value);
         elseif (is_a($value, \DateTimeInterface::class))
             return $value->format("c");
+        elseif (is_array($value) || is_object($value))
+            return json_encode($value, JSON_UNESCAPED_SLASHES);
         else
-            throw new \RuntimeException("Don't know how to stringify " . is_object($value) ? get_class($value) : gettype($value));
+            throw new \RuntimeException("Don't know how to stringify " . ((is_object($value) && !is_array($value)) ? get_class($value) : gettype($value)));
     }
 
     private static function assignValue(Entity &$entity, array $colProps, ?string $value): void {
@@ -285,7 +288,11 @@ class Database {
                     }
                     break;
                 case "object":
+                    $typedValue = json_decode($value);
+                    break;
                 case "array":
+                    $typedValue = json_decode($value, true);
+                    break;
                 case "iterable":
                 case "callable":
                 case "mixed":
diff --git a/src/application/mystic/forum/orm/TopicLogMessage.php b/src/application/mystic/forum/orm/TopicLogMessage.php
new file mode 100644
index 0000000..1caa3c5
--- /dev/null
+++ b/src/application/mystic/forum/orm/TopicLogMessage.php
@@ -0,0 +1,23 @@
+<?php
+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;
+
+#[Table("public.topic_log")]
+class TopicLogMessage extends Entity {
+    public const TITLE_CHANGED = 200;
+    public const LOCKED = 201;
+    public const UNLOCKED = 202;
+
+    #[PrimaryKey] public string $id;
+    #[References("public.topics", onDelete: References::CASCADE)] public string $topicId;
+    public int $type;
+    public \DateTimeImmutable $postDate;
+    public array $params;
+    #[References("public.users", onDelete: References::SET_NULL)] public ?string $authorId;
+}
diff --git a/src/application/views/view_topiclog.php b/src/application/views/view_topiclog.php
new file mode 100644
index 0000000..be3f78d
--- /dev/null
+++ b/src/application/views/view_topiclog.php
@@ -0,0 +1,67 @@
+<?php
+
+/** @var \mystic\forum\orm\TopicLogMessage $logMessage */
+/** @var ?\mystic\forum\orm\User $postAuthor */
+
+use mystic\forum\orm\TopicLogMessage;
+
+$hide_actions ??= false;
+$hide_pfp ??= false;
+
+$user = "";
+if ($postAuthor === null) {
+    $user = __("(deleted)");
+} else {
+    $user = '<a href="?_action=viewuser&user=' . htmlentities(urlencode($postAuthor->id)) . '">' . htmlentities($postAuthor->displayName) . '</a>';
+}
+
+?>
+<div class="media" id="post-<?= htmlentities($logMessage->id) ?>">
+<div class="media-left hidden-sm hidden-xs">
+    <?php if ($postAuthor): ?>
+        <?php if ($hide_actions): ?>
+            <img class="media-object" alt="<?= __("Profile picture") ?>" src="?_action=profilepicture&amp;user=<?= htmlentities(urlencode($postAuthor->id)) ?>" width="64" height="64">
+        <?php else: ?>
+            <a href="?_action=viewuser&amp;user=<?= htmlentities(urlencode($postAuthor->id)) ?>">
+                <img class="media-object" alt="<?= __("Profile picture") ?>" src="?_action=profilepicture&amp;user=<?= htmlentities(urlencode($postAuthor->id)) ?>" width="64" height="64">
+            </a>
+        <?php endif; ?>
+    <?php else: ?>
+        <div class="media-object" style="width:64px;height:64px"></div>
+    <?php endif; ?>
+</div>
+<div class="media-body">
+    <?php if ($logMessage->type === TopicLogMessage::LOCKED): ?>
+        <div class="well icon-well text-info">
+            <span class="glyphicon glyphicon-lock text-info" aria-hidden="true"></span>
+            <em><?= __("%user% locked this topic", [
+                "user" => $user,
+            ]) ?></em>
+            <br>
+            <small class="_time"><?= $logMessage->postDate->format("c") ?></small>
+        </div>
+    <?php elseif ($logMessage->type === TopicLogMessage::UNLOCKED): ?>
+        <div class="well icon-well text-success">
+            <span class="glyphicon glyphicon-globe text-success" aria-hidden="true"></span>
+            <em><?= __("%user% unlocked this topic", [
+                "user" => $user,
+            ]) ?></em>
+            <br>
+            <small class="_time"><?= $logMessage->postDate->format("c") ?></small>
+        </div>
+    <?php elseif ($logMessage->type === TopicLogMessage::TITLE_CHANGED): ?>
+        <div class="well icon-well text-info">
+            <span class="glyphicon glyphicon-pencil text-info" aria-hidden="true"></span>
+            <em><?= __("%user% changed the title of this topic from %old_title% to %new_title%", [
+                "user" => $user,
+                "old_title" => '<strong>' . htmlentities($logMessage->params["old_value"] ?? __("unknown")) . '</strong>',
+                "new_title" => '<strong>' . htmlentities($logMessage->params["new_value"] ?? __("unknown")) . '</strong>',
+            ]) ?></em>
+            <br>
+            <small class="_time"><?= $logMessage->postDate->format("c") ?></small>
+        </div>
+    <?php else: ?>
+        <?= __("unknown") ?>
+    <?php endif; ?>
+</div>
+</div>
-- 
cgit v1.2.3