From a26562a296ca6bbd39f34029ec8fb8e0069172f2 Mon Sep 17 00:00:00 2001 From: Murtaza Sultani Date: Wed, 19 Nov 2025 09:33:25 +0100 Subject: =?UTF-8?q?Resolve=20"Forum:=20Refaktorierung=20der=20=20Kategorie?= =?UTF-8?q?,=20Topic=20und=20Diskussions=20Metadaten=20sowie=20Behebung=20?= =?UTF-8?q?der=20fehlerhaften=20Anzeige=20ungelesener=20Beitr=C3=A4ge"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #6058 Merge request studip/studip!4613 --- lib/classes/JsonApi/Schemas/Forum/Category.php | 15 +++++----- lib/classes/JsonApi/Schemas/Forum/Discussion.php | 11 ++++---- lib/classes/JsonApi/Schemas/Forum/Topic.php | 13 +++++---- lib/models/Forum/Category.php | 22 +++++++++++++-- lib/models/Forum/Discussion.php | 26 +++++++++++++---- lib/models/Forum/Topic.php | 21 ++++++++++++-- resources/vue/apps/forum/discussions/Show.vue | 2 +- .../components/forum/categories/CategoryItem.vue | 16 +++++------ .../forum/discussions/DiscussionIndex.vue | 8 +++--- .../forum/discussions/DiscussionTimeline.vue | 33 ++++++++-------------- resources/vue/components/forum/posts/Post.vue | 4 +++ .../vue/components/forum/topics/TopicItem.vue | 16 +++++------ resources/vue/store/pinia/forum/ForumPost.js | 9 +++++- 13 files changed, 122 insertions(+), 74 deletions(-) diff --git a/lib/classes/JsonApi/Schemas/Forum/Category.php b/lib/classes/JsonApi/Schemas/Forum/Category.php index 5e3012b..0835937 100644 --- a/lib/classes/JsonApi/Schemas/Forum/Category.php +++ b/lib/classes/JsonApi/Schemas/Forum/Category.php @@ -46,15 +46,16 @@ class Category extends SchemaProvider */ public function getResourceMeta($resource) { - $metaData = $resource->getMetaData(); + $metadata = $resource->getMetadata(); return [ - 'topics-count' => (int) $metaData['topics_count'], - 'discussions-count' => (int) $metaData['discussions_count'], - 'postings-count' => (int) $metaData['postings_count'], - 'user-read-index' => (int) $metaData['user_read_index'], - 'users-count' => (int) $metaData['users_count'], - 'recent-activity' => $metaData['recent_activity'] ? date('c', $metaData['recent_activity']) : '', + 'topics-count' => (int) $metadata['topics_count'], + 'discussions-count' => (int) $metadata['discussions_count'], + 'postings-count' => (int) $metadata['postings_count'], + 'unread-postings-count' => (int) $metadata['unread_postings_count'], + 'user-read-index' => (int) $metadata['user_read_index'], + 'users-count' => (int) $metadata['users_count'], + 'recent-activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : '', ]; } diff --git a/lib/classes/JsonApi/Schemas/Forum/Discussion.php b/lib/classes/JsonApi/Schemas/Forum/Discussion.php index 9252aaa..a8c5c57 100644 --- a/lib/classes/JsonApi/Schemas/Forum/Discussion.php +++ b/lib/classes/JsonApi/Schemas/Forum/Discussion.php @@ -53,13 +53,14 @@ class Discussion extends SchemaProvider */ public function getResourceMeta($resource) { - $metaData = $resource->getMetaData(); + $metadata = $resource->getMetadata(); return [ - 'postings-count' => (int) $metaData['postings_count'], - 'recent-postings-count' => (int) $metaData['recent_postings_count'], - 'user-read-index' => (int) $metaData['user_read_index'], - 'recent-activity' => $metaData['recent_activity'] ? date('c', $metaData['recent_activity']) : '' + 'postings-count' => (int) $metadata['postings_count'], + 'recent-postings-count' => (int) $metadata['recent_postings_count'], + 'unread-postings-count' => (int) $metadata['unread_postings_count'], + 'user-read-index' => (int) $metadata['user_read_index'], + 'recent-activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : '' ]; } diff --git a/lib/classes/JsonApi/Schemas/Forum/Topic.php b/lib/classes/JsonApi/Schemas/Forum/Topic.php index 22a8c83..6a9659b 100644 --- a/lib/classes/JsonApi/Schemas/Forum/Topic.php +++ b/lib/classes/JsonApi/Schemas/Forum/Topic.php @@ -47,14 +47,15 @@ class Topic extends SchemaProvider */ public function getResourceMeta($resource) { - $metaData = $resource->getMetaData(); + $metadata = $resource->getMetadata(); return [ - 'discussions-count' => (int) $metaData['discussions_count'], - 'postings-count' => (int) $metaData['postings_count'], - 'user-read-index' => (int) $metaData['user_read_index'], - 'users-count' => (int) $metaData['users_count'], - 'recent-activity' => $metaData['recent_activity'] ? date('c', $metaData['recent_activity']) : '', + 'discussions-count' => (int) $metadata['discussions_count'], + 'postings-count' => (int) $metadata['postings_count'], + 'unread-postings-count' => (int) $metadata['unread_postings_count'], + 'user-read-index' => (int) $metadata['user_read_index'], + 'users-count' => (int) $metadata['users_count'], + 'recent-activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : '', ]; } diff --git a/lib/models/Forum/Category.php b/lib/models/Forum/Category.php index 6ee52c8..74cd189 100644 --- a/lib/models/Forum/Category.php +++ b/lib/models/Forum/Category.php @@ -56,9 +56,9 @@ class Category extends \SimpleORMap return self::findBySQL("range_id = ? ORDER BY position ASC, mkdate DESC", [$range_id]); } - public function getMetaData(): array + public function getMetadata(): array { - return DBManager::get()->fetchOne( + $metadata= DBManager::get()->fetchOne( "SELECT COUNT(DISTINCT`forum_topics`.`topic_id`) AS 'topics_count', COUNT(DISTINCT `forum_discussions`.`discussion_id`) AS 'discussions_count', @@ -73,7 +73,15 @@ class Category extends \SimpleORMap ON fpr.discussion_id = fd2.discussion_id AND fpr.user_id = :user_id WHERE ft2.category_id = :category_id - ) AS 'user_read_index' + ) AS 'user_read_index', + ( + SELECT + COUNT(DISTINCT fp.posting_id) + FROM forum_postings fp + JOIN `forum_discussions` fd USING (discussion_id) + JOIN `forum_topics` ft USING (topic_id) + WHERE ft.category_id = :category_id AND fp.user_id != :user_id + ) AS 'others_postings_count' FROM `forum_topics` LEFT JOIN `forum_discussions` USING (`topic_id`) LEFT JOIN `forum_postings` USING (`discussion_id`) @@ -83,6 +91,14 @@ class Category extends \SimpleORMap 'user_id' => User::findCurrent()?->user_id ] ); + + return [ + ...$metadata, + 'unread_postings_count' => max( + 0, + $metadata['others_postings_count'] - (int) $metadata['user_read_index'] + ) + ]; } public function transformData(): array diff --git a/lib/models/Forum/Discussion.php b/lib/models/Forum/Discussion.php index de82422..5b8edc5 100644 --- a/lib/models/Forum/Discussion.php +++ b/lib/models/Forum/Discussion.php @@ -240,7 +240,7 @@ class Discussion extends SimpleORMap ]; } - public function getMetaData(int $last_visit = 0): array + public function getMetadata(int $last_visit = 0): array { $user_id = User::findCurrent()?->user_id; @@ -249,7 +249,7 @@ class Discussion extends SimpleORMap $last_visit = object_get_visit($this->topic->range_id, $plugin_id, 'last', '', $user_id); } - return DBManager::get()->fetchOne( + $metadata = DBManager::get()->fetchOne( "SELECT COUNT(`posting_id`) 'postings_count', MAX(`mkdate`) 'recent_activity', @@ -261,10 +261,16 @@ class Discussion extends SimpleORMap ) 'user_read_index', ( SELECT - COUNT(DISTINCT fp.posting_id) - FROM forum_postings fp - WHERE fp.discussion_id = :discussion_id AND fp.mkdate > :last_visit - ) AS 'recent_postings_count' + COUNT(DISTINCT posting_id) + FROM forum_postings + WHERE discussion_id = :discussion_id AND mkdate > :last_visit AND `user_id` != :user_id + ) AS 'recent_postings_count', + ( + SELECT + COUNT(DISTINCT posting_id) + FROM forum_postings + WHERE discussion_id = :discussion_id AND `user_id` != :user_id + ) AS 'others_postings_count' FROM `forum_postings` WHERE `discussion_id` = :discussion_id", [ 'discussion_id' => $this->discussion_id, @@ -272,6 +278,14 @@ class Discussion extends SimpleORMap 'last_visit' => $last_visit ] ); + + return [ + ...$metadata, + 'unread_postings_count' => max( + 0, + $metadata['others_postings_count'] - (int) $metadata['user_read_index'] + ) + ]; } public function onCreate(): void diff --git a/lib/models/Forum/Topic.php b/lib/models/Forum/Topic.php index 2bf4c27..9b5ce7f 100644 --- a/lib/models/Forum/Topic.php +++ b/lib/models/Forum/Topic.php @@ -119,9 +119,9 @@ class Topic extends SimpleORMap ); } - public function getMetaData(): array + public function getMetadata(): array { - return DBManager::get()->fetchOne( + $metadata = DBManager::get()->fetchOne( "SELECT COUNT(DISTINCT `forum_discussions`.`discussion_id`) AS 'discussions_count', COUNT(DISTINCT `forum_postings`.`posting_id`) AS 'postings_count', @@ -135,7 +135,14 @@ class Topic extends SimpleORMap ON fpr.discussion_id = fd2.discussion_id AND fpr.user_id = :user_id WHERE fd2.topic_id = :topic_id - ) AS 'user_read_index' + ) AS 'user_read_index', + ( + SELECT + COUNT(DISTINCT fp.posting_id) + FROM forum_postings fp + JOIN `forum_discussions` fd USING (discussion_id) + WHERE fd.topic_id = :topic_id AND fp.user_id != :user_id + ) AS 'others_postings_count' FROM `forum_discussions` LEFT JOIN `forum_postings` USING (`discussion_id`) WHERE `forum_discussions`.`topic_id` = :topic_id", @@ -144,6 +151,14 @@ class Topic extends SimpleORMap 'user_id' => User::findCurrent()?->user_id ] ); + + return [ + ...$metadata, + 'unread_postings_count' => max( + 0, + $metadata['others_postings_count'] - (int) $metadata['user_read_index'] + ) + ]; } public function transformData(): array diff --git a/resources/vue/apps/forum/discussions/Show.vue b/resources/vue/apps/forum/discussions/Show.vue index 4fa4fad..ca1cabc 100644 --- a/resources/vue/apps/forum/discussions/Show.vue +++ b/resources/vue/apps/forum/discussions/Show.vue @@ -269,7 +269,7 @@ onMounted(async () => { diff --git a/resources/vue/components/forum/categories/CategoryItem.vue b/resources/vue/components/forum/categories/CategoryItem.vue index 72b646b..c761e12 100644 --- a/resources/vue/components/forum/categories/CategoryItem.vue +++ b/resources/vue/components/forum/categories/CategoryItem.vue @@ -87,14 +87,14 @@ const swapCategory = event => { :title="$gettext('Zur Kategorie')"> {{ category.name }} - {{ category.meta.postings_count - category.meta.user_read_index }} + {{ category.meta.unread_postings_count }} @@ -203,14 +203,14 @@ const swapCategory = event => { - {{ category.meta.postings_count - category.meta.user_read_index }} + {{ category.meta.unread_postings_count }}
diff --git a/resources/vue/components/forum/discussions/DiscussionIndex.vue b/resources/vue/components/forum/discussions/DiscussionIndex.vue index 23c2eee..5478489 100644 --- a/resources/vue/components/forum/discussions/DiscussionIndex.vue +++ b/resources/vue/components/forum/discussions/DiscussionIndex.vue @@ -169,14 +169,14 @@ onMounted(() => { {{ discussion.title }}