diff options
| author | Murtaza Sultani <sultani@data-quest.de> | 2025-07-10 14:59:43 +0200 |
|---|---|---|
| committer | Murtaza Sultani <sultani@data-quest.de> | 2025-07-10 14:59:43 +0200 |
| commit | a83b19699faac0b537c03493e4ce1f84a944c206 (patch) | |
| tree | 50333ea471665a5166066a737a01e0940e88e5c1 | |
| parent | 3496fc0bd4cab0e7f097acae17ad2a7f6553c1e9 (diff) | |
Resolve "Forum 3: Letzte Aktivität wird falsch gezählt"
Closes #5707 and #5708
Merge request studip/studip!4339
36 files changed, 230 insertions, 164 deletions
diff --git a/app/controllers/course/forum/categories.php b/app/controllers/course/forum/categories.php index 2ff5dc6..3b5cfd4 100644 --- a/app/controllers/course/forum/categories.php +++ b/app/controllers/course/forum/categories.php @@ -40,7 +40,7 @@ class Course_Forum_CategoriesController extends Forum\ForumBaseController 'metadata' => [ 'postings_count' => (int) $category->metadata['postings_count'], 'users_count' => (int) $category->metadata['users_count'], - 'recent_activity' => date('c', $category->metadata['recent_activity']) + 'recent_activity' => $category->metadata['recent_activity'] ? date('c', $category->metadata['recent_activity']) : null ] ]) ); diff --git a/app/controllers/course/forum/discussions.php b/app/controllers/course/forum/discussions.php index 213f567..decff73 100644 --- a/app/controllers/course/forum/discussions.php +++ b/app/controllers/course/forum/discussions.php @@ -43,7 +43,7 @@ class Course_Forum_DiscussionsController extends Forum\ForumBaseController 'metadata' => [ 'postings_count' => (int) $metadata['postings_count'], 'users_count' => (int) $metadata['users_count'], - 'recent_activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : '' + 'recent_activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : null ] ]) ); diff --git a/app/controllers/course/forum/search.php b/app/controllers/course/forum/search.php index 84172fb..9e811e3 100644 --- a/app/controllers/course/forum/search.php +++ b/app/controllers/course/forum/search.php @@ -64,14 +64,14 @@ class Course_Forum_SearchController extends Forum\ForumBaseController $query = [ "SELECT - discussions.discussion_id, - COUNT(DISTINCT postings.posting_id) AS 'postings_count' - FROM `forum_discussions` AS `discussions` - LEFT JOIN `forum_postings` AS `postings` USING(`discussion_id`) - LEFT JOIN `tags_relations` ON (`tags_relations`.`range_id` = `discussions`.`discussion_id` AND `range_type` = 'forum') - WHERE `postings`.`range_id` = :course_id ", + discussions.*, + MAX(postings.mkdate) AS latest_post_date + FROM forum_discussions AS discussions + LEFT JOIN forum_postings AS postings USING(discussion_id) + LEFT JOIN tags_relations ON (tags_relations.range_id = discussions.discussion_id AND range_type = 'forum') + WHERE postings.range_id = :range_id ", [ - 'course_id' => $this->course_id + 'range_id' => $this->course_id ] ]; @@ -117,18 +117,16 @@ class Course_Forum_SearchController extends Forum\ForumBaseController default => "" }; - $result = DBManager::get()->fetchAll( - $query[0]." GROUP BY discussions.discussion_id", - $query[1] + $discussions = DBManager::get()->fetchAll( + $query[0]." GROUP BY discussions.discussion_id ORDER BY latest_post_date DESC", + $query[1], + ForumDiscussion::buildExisting(...) ); - $discussions = ForumDiscussion::findBySQL("discussion_id IN (:discussion_ids)", ['discussion_ids' => array_column($result, 'discussion_id')]); - - - return array_map(function (ForumDiscussion $discussion) use ($result) { - $postings_count = array_find($result, fn($item) => $item['discussion_id'] === $discussion->discussion_id)['postings_count']; + return array_map(function (ForumDiscussion $discussion) { $members = array_map(fn(ForumMember $member) => $member->toRawArray(), $discussion->members); $tags = array_map(fn(ForumTag $tag) => $tag->toRawArray(), $discussion->tags); + $metadata = $discussion->getMetaData(); return [ 'id' => $discussion->discussion_id, @@ -150,8 +148,8 @@ class Course_Forum_SearchController extends Forum\ForumBaseController 'members' => $members, 'tags' => $tags, 'meta' => [ - 'postings_count' => (int) $postings_count, - 'recent_activity' => $discussion->metadata['recent_activity'] ? date('c', $discussion->metadata['recent_activity']) : null, + 'postings_count' => (int) $metadata['postings_count'], + 'recent_activity' => $metadata['recent_activity'] ? date('c', $metadata['recent_activity']) : null, ] ]; }, $discussions); diff --git a/lib/classes/JsonApi/Routes/Forum/ForumCategoryIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumCategoryIndex.php index 9e8375c..c70df2b 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumCategoryIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumCategoryIndex.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -18,7 +19,8 @@ class ForumCategoryIndex extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - if (!$course = \Course::find($args['course_id'])) { + $course = Course::find($args['course_id']); + if (!$course) { throw new RecordNotFoundException(); } @@ -27,7 +29,7 @@ class ForumCategoryIndex extends JsonApiController throw new AuthorizationFailedException(); } - $categories = ForumCategory::findBySQL("range_id = ? ORDER BY position ASC, mkdate DESC", [$course->id]); + $categories = ForumCategory::getCourseCategories($course->id); return $this->getPaginatedContentResponse( array_slice($categories, ...$this->getOffsetAndLimit()), diff --git a/lib/classes/JsonApi/Routes/Forum/ForumCategoryShow.php b/lib/classes/JsonApi/Routes/Forum/ForumCategoryShow.php index 46bba9d..e85d49d 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumCategoryShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumCategoryShow.php @@ -1,6 +1,8 @@ <?php namespace JsonApi\Routes\Forum; +use Course; +use Forum\ForumCategory; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -16,13 +18,13 @@ class ForumCategoryShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $category = \Forum\ForumCategory::find($args['category_id']); - + $category = ForumCategory::find($args['category_id']); if (!$category) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($category->range_id)) { + $course = Course::find($category->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumCategoryTopics.php b/lib/classes/JsonApi/Routes/Forum/ForumCategoryTopics.php index f597c52..88a212c 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumCategoryTopics.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumCategoryTopics.php @@ -1,7 +1,7 @@ <?php namespace JsonApi\Routes\Forum; -use JsonApi\Errors\BadRequestException; +use Course; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; @@ -9,8 +9,6 @@ use Psr\Http\Message\ResponseInterface as Response; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\JsonApiController; use Forum\ForumCategory; -use Forum\ForumSubscription; -use Forum\ForumTopic; class ForumCategoryTopics extends JsonApiController { @@ -21,13 +19,13 @@ class ForumCategoryTopics extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $category = \Forum\ForumCategory::find($args['category_id']); - + $category = ForumCategory::find($args['category_id']); if (!$category) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($category->range_id)) { + $course = Course::find($category->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumCategoryUpdateSort.php b/lib/classes/JsonApi/Routes/Forum/ForumCategoryUpdateSort.php index 3e2c597..b8e41f0 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumCategoryUpdateSort.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumCategoryUpdateSort.php @@ -1,8 +1,9 @@ <?php namespace JsonApi\Routes\Forum; +use CoreForum; +use Course; use JsonApi\Errors\RecordNotFoundException; -use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; use JsonApi\Errors\AuthorizationFailedException; @@ -19,11 +20,12 @@ class ForumCategoryUpdateSort extends JsonApiController $json = $this->validate($request); $course_id = self::arrayGet($json, 'data.relationships.range.data.id'); - if (!$course = \Course::find($course_id)) { + $course = Course::find($course_id); + if (!$course) { throw new RecordNotFoundException(); } - if (!\CoreForum::isModerator($course->id)) { + if (!CoreForum::isModerator($course->id)) { throw new AuthorizationFailedException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumConfigIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumConfigIndex.php index d3be0ce..973dd12 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumConfigIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumConfigIndex.php @@ -2,6 +2,7 @@ namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -13,7 +14,8 @@ class ForumConfigIndex extends JsonApiController { public function __invoke(Request $request, Response $response, $args) { - if (!$course = \Course::find($args['course_id'])) { + $course = Course::find($args['course_id']); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php index c8e8477..a9ef436 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -8,7 +9,6 @@ use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; use JsonApi\JsonApiController; use Forum\ForumDiscussion; -use Forum\ForumPosting; class ForumDiscussionIndex extends JsonApiController { @@ -25,7 +25,8 @@ class ForumDiscussionIndex extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - if (!$course = \Course::find($args['course_id'])) { + $course = Course::find($args['course_id']); + if (!$course) { throw new RecordNotFoundException(); } @@ -37,20 +38,7 @@ class ForumDiscussionIndex extends JsonApiController $filtering = $this->getQueryParameters()->getFilteringParameters() ?: []; $last_visit = $filtering['last-visit'] ?? 0; - if ($last_visit) { - $recent_posts = ForumPosting::getRecentPosts($course->id, $last_visit); - $discussions = ForumDiscussion::findBySQL( - "discussion_id IN (:discussion_ids)", - [ - 'discussion_ids' => array_column($recent_posts, 'discussion_id') - ] - ); - } else { - $discussions = ForumDiscussion::findBySQL( - "JOIN forum_topics USING(topic_id) WHERE forum_topics.range_id = :course_id ORDER BY position ASC, mkdate DESC", - ['course_id' => $course->id] - ); - } + $discussions = ForumDiscussion::getCourseDiscussions($course->id, $last_visit); return $this->getPaginatedContentResponse( array_slice($discussions, ...$this->getOffsetAndLimit()), diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionPostings.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionPostings.php index 320344d..a33c808 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionPostings.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionPostings.php @@ -1,6 +1,8 @@ <?php namespace JsonApi\Routes\Forum; +use Course; +use Forum\ForumDiscussion; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -24,13 +26,13 @@ class ForumDiscussionPostings extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $discussion = \Forum\ForumDiscussion::find($args['discussion_id']); - + $discussion = ForumDiscussion::find($args['discussion_id']); if (!$discussion) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($discussion->range_id)) { + $course = Course::find($discussion->range_id); + if (!$course) { throw new RecordNotFoundException(); } @@ -39,12 +41,12 @@ class ForumDiscussionPostings extends JsonApiController throw new AuthorizationFailedException(); } - $postings = ForumPosting::findBySQL("discussion_id = :discussion_id ORDER BY mkdate ASC", ['discussion_id' => $discussion->discussion_id]); + $postings = $discussion->postings ?? \SimpleORMapCollection::createFromArray([]); ForumPostingRead::updateUserReadPoint($user->user_id, $discussion->discussion_id, count($postings)); return $this->getPaginatedContentResponse( - array_slice($postings, ...$this->getOffsetAndLimit()), + $postings->limit(...$this->getOffsetAndLimit()), count($postings) ); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionShow.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionShow.php index 784a181..077a910 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionShow.php @@ -1,6 +1,8 @@ <?php namespace JsonApi\Routes\Forum; +use Course; +use Forum\ForumDiscussion; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -19,13 +21,13 @@ class ForumDiscussionShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $discussion = \Forum\ForumDiscussion::find($args['discussion_id']); - + $discussion = ForumDiscussion::find($args['discussion_id']); if (!$discussion) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($discussion->range_id)) { + $course = Course::find($discussion->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeDiscussions.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeDiscussions.php index 162f23a..469903a 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeDiscussions.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeDiscussions.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Forum\ForumDiscussionType; use JsonApi\Errors\RecordNotFoundException; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -15,16 +16,15 @@ class ForumDiscussionTypeDiscussions extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $discussion_type = \Forum\ForumDiscussionType::find($args['type_id']); - - if (!$discussion_type) { + $discussionType = ForumDiscussionType::find($args['type_id']); + if (!$discussionType) { throw new RecordNotFoundException(); } - $discussions = $discussion_type->discussions ?? \SimpleORMapCollection::createFromArray([]); + $discussions = $discussionType->discussions; return $this->getPaginatedContentResponse( - $discussions->limit(...$this->getOffsetAndLimit()), + array_slice($discussions, ...$this->getOffsetAndLimit()), count($discussions) ); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeIndex.php index b6a9999..75f9750 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeIndex.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Forum\ForumDiscussionType; use JsonApi\Errors\BadRequestException; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -15,7 +16,7 @@ class ForumDiscussionTypeIndex extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $discussion_types = \Forum\ForumDiscussionType::findBySQL('1'); + $discussion_types = ForumDiscussionType::findBySQL('1'); return $this->getPaginatedContentResponse( array_slice($discussion_types, ...$this->getOffsetAndLimit()), diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeShow.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeShow.php index 66ff9e5..a3e37d9 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionTypeShow.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Forum\ForumDiscussionType; use JsonApi\Errors\RecordNotFoundException; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -14,8 +15,7 @@ class ForumDiscussionTypeShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $discussion_type = \Forum\ForumDiscussionType::find($args['type_id']); - + $discussion_type = ForumDiscussionType::find($args['type_id']); if (!$discussion_type) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionShow.php b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionShow.php index a6a0299..0df6931 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionShow.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Forum\ForumPostingReaction; use JsonApi\Errors\RecordNotFoundException; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -15,8 +16,7 @@ class ForumPostingReactionShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $posting_reaction = \Forum\ForumPostingReaction::find($args['reaction_id']); - + $posting_reaction = ForumPostingReaction::find($args['reaction_id']); if (!$posting_reaction) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionStore.php b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionStore.php index 58b7a8b..cb8fc85 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionStore.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactionStore.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\BadRequestException; use JsonApi\Errors\RecordNotFoundException; @@ -26,12 +27,12 @@ class ForumPostingReactionStore extends JsonApiController $user = $this->getUser($request); $posting = ForumPosting::find(self::arrayGet($json, 'data.relationships.posting.data.id')); - if (!$posting) { throw new BadRequestException(); } - if (!$course = \Course::find($posting->range_id)) { + $course = Course::find($posting->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactions.php b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactions.php index d5dde95..dfdc0ab 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumPostingReactions.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumPostingReactions.php @@ -1,12 +1,15 @@ <?php namespace JsonApi\Routes\Forum; +use Course; +use Forum\ForumPosting; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; use JsonApi\JsonApiController; +use SimpleORMapCollection; class ForumPostingReactions extends JsonApiController { @@ -18,13 +21,13 @@ class ForumPostingReactions extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $posting = \Forum\ForumPosting::find($args['posting_id']); - + $posting = ForumPosting::find($args['posting_id']); if (!$posting) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($posting->range_id)) { + $course = Course::find($posting->range_id); + if (!$course) { throw new RecordNotFoundException(); } @@ -33,7 +36,7 @@ class ForumPostingReactions extends JsonApiController throw new AuthorizationFailedException(); } - $reactions = $posting->reactions ?? \SimpleORMapCollection::createFromArray([]); + $reactions = $posting->reactions ?? SimpleORMapCollection::createFromArray([]); return $this->getPaginatedContentResponse( $reactions->limit(...$this->getOffsetAndLimit()), diff --git a/lib/classes/JsonApi/Routes/Forum/ForumPostingShow.php b/lib/classes/JsonApi/Routes/Forum/ForumPostingShow.php index ec64bb6..8d29654 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumPostingShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumPostingShow.php @@ -1,6 +1,8 @@ <?php namespace JsonApi\Routes\Forum; +use Course; +use Forum\ForumPosting; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -20,13 +22,13 @@ class ForumPostingShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $posting = \Forum\ForumPosting::find($args['posting_id']); - + $posting = ForumPosting::find($args['posting_id']); if (!$posting) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($posting->range_id)) { + $course = Course::find($posting->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumPostingStore.php b/lib/classes/JsonApi/Routes/Forum/ForumPostingStore.php index b6ecf6e..d32d75e 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumPostingStore.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumPostingStore.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; @@ -34,7 +35,7 @@ class ForumPostingStore extends JsonApiController $user = $this->getUser($request); $discussion = ForumDiscussion::find(self::arrayGet($json, 'data.relationships.discussion.data.id')); - $course = \Course::find($discussion->range_id); + $course = Course::find($discussion->range_id); if (!$discussion || !$course) { throw new RecordNotFoundException(); diff --git a/lib/classes/JsonApi/Routes/Forum/ForumSubscriptionIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumSubscriptionIndex.php index 5771d19..015f959 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumSubscriptionIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumSubscriptionIndex.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -20,7 +21,8 @@ class ForumSubscriptionIndex extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - if (!$course = \Course::find($args['course_id'])) { + $course = Course::find($args['course_id']); + if (!$course) { throw new RecordNotFoundException(); } @@ -29,13 +31,7 @@ class ForumSubscriptionIndex extends JsonApiController throw new AuthorizationFailedException(); } - $subscriptions = ForumSubscription::findBySQL( - "range_id = :course_id AND user_id = :user_id ORDER BY mkdate DESC", - [ - 'course_id' => $course->id, - 'user_id' => $user->user_id - ] - ); + $subscriptions = ForumSubscription::getUserSubscriptions($course->id, $user->user_id); return $this->getPaginatedContentResponse( array_slice($subscriptions, ...$this->getOffsetAndLimit()), diff --git a/lib/classes/JsonApi/Routes/Forum/ForumTopicDiscussions.php b/lib/classes/JsonApi/Routes/Forum/ForumTopicDiscussions.php index 68bd09a..d2cbb70 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumTopicDiscussions.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumTopicDiscussions.php @@ -1,16 +1,14 @@ <?php namespace JsonApi\Routes\Forum; -use JsonApi\Errors\BadRequestException; +use Course; +use Forum\ForumTopic; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\JsonApiController; -use Forum\ForumCategory; -use Forum\ForumSubscription; -use Forum\ForumTopic; class ForumTopicDiscussions extends JsonApiController { @@ -25,13 +23,13 @@ class ForumTopicDiscussions extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - $topic = \Forum\ForumTopic::find($args['topic_id']); - + $topic = ForumTopic::find($args['topic_id']); if (!$topic) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($topic->range_id)) { + $course = Course::find($topic->range_id); + if (!$course) { throw new RecordNotFoundException(); } @@ -40,10 +38,10 @@ class ForumTopicDiscussions extends JsonApiController throw new AuthorizationFailedException(); } - $discussions = $topic->discussions ?? \SimpleORMapCollection::createFromArray([]); + $discussions = $topic->discussions; return $this->getPaginatedContentResponse( - $discussions->limit(...$this->getOffsetAndLimit()), + array_slice($discussions, ...$this->getOffsetAndLimit()), count($discussions) ); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumTopicIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumTopicIndex.php index 0379bfa..8be3018 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumTopicIndex.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumTopicIndex.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\RecordNotFoundException; use JsonApi\Routes\Courses\Authority as CourseAuthority; @@ -19,7 +20,8 @@ class ForumTopicIndex extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - if (!$course = \Course::find($args['course_id'])) { + $course = Course::find($args['course_id']); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumTopicShow.php b/lib/classes/JsonApi/Routes/Forum/ForumTopicShow.php index d4170df..99dd427 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumTopicShow.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumTopicShow.php @@ -1,6 +1,7 @@ <?php namespace JsonApi\Routes\Forum; +use Course; use JsonApi\Routes\Courses\Authority as CourseAuthority; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -15,11 +16,13 @@ class ForumTopicShow extends JsonApiController public function __invoke(Request $request, Response $response, $args) { - if (!$topic = ForumTopic::find($args['topic_id'])) { + $topic = ForumTopic::find($args['topic_id']); + if (!$topic) { throw new RecordNotFoundException(); } - if (!$course = \Course::find($topic->range_id)) { + $course = Course::find($topic->range_id); + if (!$course) { throw new RecordNotFoundException(); } diff --git a/lib/classes/JsonApi/Routes/Forum/ForumTopicUpdateSort.php b/lib/classes/JsonApi/Routes/Forum/ForumTopicUpdateSort.php index 4926487..8f9e93b 100644 --- a/lib/classes/JsonApi/Routes/Forum/ForumTopicUpdateSort.php +++ b/lib/classes/JsonApi/Routes/Forum/ForumTopicUpdateSort.php @@ -1,6 +1,8 @@ <?php namespace JsonApi\Routes\Forum; +use CoreForum; +use Course; use JsonApi\Errors\RecordNotFoundException; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; @@ -18,11 +20,12 @@ class ForumTopicUpdateSort extends JsonApiController $json = $this->validate($request); $course_id = self::arrayGet($json, 'data.relationships.range.data.id'); - if (!$course = \Course::find($course_id)) { + $course = Course::find($course_id); + if (!$course) { throw new RecordNotFoundException(); } - if (!\CoreForum::isModerator($course->id)) { + if (!CoreForum::isModerator($course->id)) { throw new AuthorizationFailedException(); } diff --git a/lib/classes/JsonApi/Schemas/Forum/ForumCategory.php b/lib/classes/JsonApi/Schemas/Forum/ForumCategory.php index 551201a..b75e82b 100644 --- a/lib/classes/JsonApi/Schemas/Forum/ForumCategory.php +++ b/lib/classes/JsonApi/Schemas/Forum/ForumCategory.php @@ -40,7 +40,6 @@ class ForumCategory extends SchemaProvider 'topics-count' => (int) $metaData['topics_count'], 'discussions-count' => (int) $metaData['discussions_count'], 'postings-count' => (int) $metaData['postings_count'], - 'recent-postings-count' => (int) $metaData['recent_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/ForumTopic.php b/lib/classes/JsonApi/Schemas/Forum/ForumTopic.php index 1d310c2..88461a1 100644 --- a/lib/classes/JsonApi/Schemas/Forum/ForumTopic.php +++ b/lib/classes/JsonApi/Schemas/Forum/ForumTopic.php @@ -56,7 +56,6 @@ class ForumTopic extends SchemaProvider return [ 'discussions-count' => (int) $metaData['discussions_count'], 'postings-count' => (int) $metaData['postings_count'], - 'recent-postings-count' => (int) $metaData['recent_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/ForumCategory.php b/lib/models/Forum/ForumCategory.php index 1ec94f6..de90cab 100644 --- a/lib/models/Forum/ForumCategory.php +++ b/lib/models/Forum/ForumCategory.php @@ -2,6 +2,7 @@ namespace Forum; use DBManager; +use User; /** * @property string $category_id @@ -21,6 +22,7 @@ class ForumCategory extends \SimpleORMap protected static function configure($config = []) { $config['db_table'] = 'forum_categories'; + $config['has_many']['topics'] = [ 'class_name' => ForumTopic::class, 'foreign_key' => 'category_id', @@ -35,18 +37,16 @@ class ForumCategory extends \SimpleORMap parent::configure($config); } - public function getMetaData(): array + /** + * @return self[] + */ + public static function getCourseCategories($course_id): array { - $user_id = \User::findCurrent()->user_id; - $object_user_visit = \ObjectUserVisit::findOneBySQL( - "object_id = :object_id AND plugin_id = :plugin_id AND user_id = :user_id", - [ - 'object_id' => $this->range_id, - 'plugin_id' => \PluginEngine::getPlugin(\CoreForum::class)->getPluginId(), - 'user_id' => $user_id, - ] - ); + return self::findBySQL("range_id = ? ORDER BY position ASC, mkdate DESC", [$course_id]); + } + public function getMetaData(): array + { return DBManager::get()->fetchOne( "SELECT COUNT(DISTINCT`forum_topics`.`topic_id`) AS 'topics_count', @@ -62,23 +62,14 @@ class ForumCategory 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', - ( - SELECT - COUNT(DISTINCT fp.posting_id) - FROM forum_topics ft - JOIN forum_discussions fd USING(topic_id) - JOIN forum_postings fp ON fp.discussion_id = fd.discussion_id AND fp.mkdate > :last_visit - WHERE ft.category_id = :category_id - ) AS 'recent_postings_count' + ) AS 'user_read_index' FROM `forum_topics` LEFT JOIN `forum_discussions` USING (`topic_id`) LEFT JOIN `forum_postings` USING (`discussion_id`) WHERE `forum_topics`.`category_id` = :category_id", [ 'category_id' => $this->category_id, - 'user_id' => $user_id, - 'last_visit' => $object_user_visit->last_visitdate ?? 0 + 'user_id' => User::findCurrent()->user_id ] ); } diff --git a/lib/models/Forum/ForumDiscussion.php b/lib/models/Forum/ForumDiscussion.php index c1d8240..51225bc 100644 --- a/lib/models/Forum/ForumDiscussion.php +++ b/lib/models/Forum/ForumDiscussion.php @@ -1,12 +1,12 @@ <?php namespace Forum; +use User; use DBManager; use SimpleORMap; -use Forum\Service\DiscussionNotification; use Forum\DTO\ForumMember; use Forum\DTO\ForumTag; -use User; +use Forum\Service\DiscussionNotification; /** * @property string $discussion_id @@ -49,7 +49,8 @@ class ForumDiscussion extends SimpleORMap $config['has_many']['postings'] = [ 'class_name' => ForumPosting::class, 'foreign_key' => 'discussion_id', - 'assoc_foreign_key' => 'discussion_id' + 'assoc_foreign_key' => 'discussion_id', + 'order_by' => 'ORDER BY mkdate', ]; $config['has_many']['subscribers'] = [ @@ -71,6 +72,34 @@ class ForumDiscussion extends SimpleORMap parent::configure($config); } + /** + * @return self[] + */ + public static function getCourseDiscussions($course_id, $last_visit = 0): array + { + $query = [ + "SELECT + discussions.*, + MAX(postings.mkdate) AS latest_post_date + FROM forum_discussions AS discussions + JOIN forum_postings as postings USING (discussion_id) + JOIN forum_topics AS topics USING (topic_id) + WHERE topics.range_id = :range_id", + ['range_id' => $course_id] + ]; + + if ($last_visit) { + $query[0] .= " AND postings.mkdate > :last_visit"; + $query[1]["last_visit"] = $last_visit; + } + + return \DBManager::get()->fetchAll( + $query[0]." GROUP BY discussions.discussion_id ORDER BY latest_post_date DESC", + $query[1], + self::buildExisting(...) + ); + } + public function getTags(): array { return DBManager::get()->fetchAll( @@ -149,17 +178,14 @@ class ForumDiscussion extends SimpleORMap ]; } - public function getMetaData(): array + public function getMetaData(int $last_visit = 0): array { $user_id = \User::findCurrent()->user_id; - $object_user_visit = \ObjectUserVisit::findOneBySQL( - "object_id = :object_id AND plugin_id = :plugin_id AND user_id = :user_id", - [ - 'object_id' => $this->topic->range_id, - 'plugin_id' => \PluginEngine::getPlugin(\CoreForum::class)->getPluginId(), - 'user_id' => $user_id, - ] - ); + + if (!$last_visit) { + $plugin_id = \PluginEngine::getPlugin(\CoreForum::class)->getPluginId(); + $last_visit = object_get_visit($this->topic->range_id, $plugin_id, 'last', '', $user_id); + } return DBManager::get()->fetchOne( "SELECT @@ -181,7 +207,7 @@ class ForumDiscussion extends SimpleORMap [ 'discussion_id' => $this->discussion_id, 'user_id' => $user_id, - 'last_visit' => $object_user_visit->last_visitdate ?? 0 + 'last_visit' => $last_visit ] ); } diff --git a/lib/models/Forum/ForumDiscussionType.php b/lib/models/Forum/ForumDiscussionType.php index fe44add..e3914b5 100644 --- a/lib/models/Forum/ForumDiscussionType.php +++ b/lib/models/Forum/ForumDiscussionType.php @@ -2,6 +2,7 @@ namespace Forum; +use DBManager; use SimpleORMap; /** @@ -33,4 +34,23 @@ class ForumDiscussionType extends SimpleORMap { return self::findBySQL("TRUE ORDER BY `mkdate` DESC"); } + + /** + * @return ForumDiscussion[] + */ + public function getDiscussions(): array + { + return DBManager::get()->fetchAll( + "SELECT + discussions.*, + MAX(postings.mkdate) AS latest_post_date + FROM forum_discussions AS discussions + JOIN forum_postings as postings USING (discussion_id) + WHERE discussions.type_id = :type_id + GROUP BY discussions.discussion_id + ORDER BY discussions.sticky DESC, latest_post_date DESC", + ['type_id' => $this->type_id], + ForumDiscussion::buildExisting(...) + ); + } } diff --git a/lib/models/Forum/ForumSubscription.php b/lib/models/Forum/ForumSubscription.php index a805975..fc044a4 100644 --- a/lib/models/Forum/ForumSubscription.php +++ b/lib/models/Forum/ForumSubscription.php @@ -43,6 +43,17 @@ class ForumSubscription extends SimpleORMap parent::configure($config); } + public static function getUserSubscriptions($course_id, $user_id) + { + return self::findBySQL( + "range_id = :range_id AND user_id = :user_id ORDER BY mkdate DESC", + [ + 'range_id' => $course_id, + 'user_id' => $user_id + ] + ); + } + public function getSubjectObject(): ForumDiscussion | ForumTopic { return match ($this->subject) { diff --git a/lib/models/Forum/ForumTopic.php b/lib/models/Forum/ForumTopic.php index accae17..4d7bf69 100644 --- a/lib/models/Forum/ForumTopic.php +++ b/lib/models/Forum/ForumTopic.php @@ -36,6 +36,7 @@ class ForumTopic extends SimpleORMap $config['has_many']['discussions'] = [ 'class_name' => ForumDiscussion::class, 'foreign_key' => 'topic_id', + 'assoc_func' => 'getDiscussions', 'assoc_foreign_key' => 'topic_id', ]; @@ -46,6 +47,9 @@ class ForumTopic extends SimpleORMap parent::configure($config); } + /** + * @return self[] + */ public static function getCourseTopics($course_id): array { return self::findBySQL( @@ -85,18 +89,27 @@ class ForumTopic extends SimpleORMap return array_values($unique_users); } - public function getMetaData(): array + /** + * @return ForumDiscussion[] + */ + public function getDiscussions(): array { - $user_id = User::findCurrent()->user_id; - $object_user_visit = \ObjectUserVisit::findOneBySQL( - "object_id = :object_id AND plugin_id = :plugin_id AND user_id = :user_id", - [ - 'object_id' => $this->range_id, - 'plugin_id' => \PluginEngine::getPlugin(\CoreForum::class)->getPluginId(), - 'user_id' => $user_id, - ] + return DBManager::get()->fetchAll( + "SELECT + discussions.*, + MAX(postings.mkdate) AS latest_post_date + FROM forum_discussions AS discussions + JOIN forum_postings as postings USING (discussion_id) + WHERE discussions.topic_id = :topic_id + GROUP BY discussions.discussion_id + ORDER BY discussions.sticky DESC, latest_post_date DESC", + ['topic_id' => $this->topic_id], + ForumDiscussion::buildExisting(...) ); + } + public function getMetaData(): array + { return DBManager::get()->fetchOne( "SELECT COUNT(DISTINCT `forum_discussions`.`discussion_id`) AS 'discussions_count', @@ -111,22 +124,13 @@ class ForumTopic 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', - ( - SELECT - COUNT(DISTINCT fp.posting_id) - FROM forum_topics ft - JOIN forum_discussions fd USING(topic_id) - JOIN forum_postings fp ON fp.discussion_id = fd.discussion_id AND fp.mkdate > :last_visit - WHERE ft.topic_id = :topic_id - ) AS 'recent_postings_count' + ) AS 'user_read_index' FROM `forum_discussions` LEFT JOIN `forum_postings` USING (`discussion_id`) WHERE `forum_discussions`.`topic_id` = :topic_id", [ 'topic_id' => $this->topic_id, - 'user_id' => $user_id, - 'last_visit' => $object_user_visit->last_visitdate ?? 0 + 'user_id' => User::findCurrent()->user_id ] ); } diff --git a/resources/vue/apps/forum/categories/Show.vue b/resources/vue/apps/forum/categories/Show.vue index 29cbec1..2445646 100644 --- a/resources/vue/apps/forum/categories/Show.vue +++ b/resources/vue/apps/forum/categories/Show.vue @@ -77,7 +77,7 @@ onMounted(async () => { <small>{{ metadata.users_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Anzahl der Beiträge')" :aria-label="$gettext('Anzahl der Beiträge')" role="group"> - <StudipIcon shape="forum" :size="15" role="info" aria-hidden="true" /> + <StudipIcon shape="reply" :size="15" role="info" aria-hidden="true" /> <small>{{ metadata.postings_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Letzte Aktivität')" :aria-label="$gettext('Letzte Aktivität')" role="group"> diff --git a/resources/vue/apps/forum/discussions/Index.vue b/resources/vue/apps/forum/discussions/Index.vue index 2f8632c..07f7ee2 100644 --- a/resources/vue/apps/forum/discussions/Index.vue +++ b/resources/vue/apps/forum/discussions/Index.vue @@ -65,7 +65,7 @@ onMounted(async () => { <small>{{ metadata.users_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Anzahl der Beiträge')" :aria-label="$gettext('Anzahl der Beiträge')" role="group"> - <StudipIcon shape="forum" role="info" :size="15" aria-hidden="true"/> + <StudipIcon shape="reply" role="info" :size="15" aria-hidden="true"/> <small>{{ metadata.postings_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Letzte Aktivität')" :aria-label="$gettext('Letzte Aktivität')" role="group"> diff --git a/resources/vue/apps/forum/recent/Index.vue b/resources/vue/apps/forum/recent/Index.vue index 3817432..f615eb8 100644 --- a/resources/vue/apps/forum/recent/Index.vue +++ b/resources/vue/apps/forum/recent/Index.vue @@ -53,7 +53,7 @@ onMounted(async () => { <template> <ForumApp class="use-utility-classes"> - <DiscussionIndex :discussions="discussions" :withActions="false" :isLoading="isLoading"> + <DiscussionIndex :discussions="discussions" :withActions="false" :isLoading="isLoading" redirect="recent"> <template #pagination> <tfoot v-if="pagination && pagination.total > pagination.limit"> <tr> diff --git a/resources/vue/apps/forum/topics/Show.vue b/resources/vue/apps/forum/topics/Show.vue index a5f15d1..3d9adf3 100644 --- a/resources/vue/apps/forum/topics/Show.vue +++ b/resources/vue/apps/forum/topics/Show.vue @@ -85,7 +85,7 @@ onMounted(async () => { <small>{{ metadata.users_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Anzahl der Beiträge')" :aria-label="$gettext('Anzahl der Beiträge')" role="group"> - <StudipIcon shape="forum" role="info" :size="15" aria-hidden="true"/> + <StudipIcon shape="reply" role="info" :size="15" aria-hidden="true"/> <small>{{ metadata.postings_count }}</small> </span> <span class="inline-flex gap-5 items-center" :title="$gettext('Letzte Aktivität')" :aria-label="$gettext('Letzte Aktivität')" role="group"> diff --git a/resources/vue/components/forum/discussions/DiscussionIndex.vue b/resources/vue/components/forum/discussions/DiscussionIndex.vue index 9c6c952..266e1b7 100644 --- a/resources/vue/components/forum/discussions/DiscussionIndex.vue +++ b/resources/vue/components/forum/discussions/DiscussionIndex.vue @@ -169,15 +169,25 @@ onMounted(() => { :title="$gettext('Zur Diskussion')"> <h3 class="title-with-actions_title line-clamp-2 m-0">{{ discussion.title }}</h3> <span - v-if="discussion.meta.postings_count > discussion.meta.user_read_index" + v-if="redirect !== 'recent' && discussion.meta.postings_count > discussion.meta.user_read_index" class="unread-items-badge" role="status" aria-live="polite" - :aria-label="$gettext('Sie haben %{count} ungelesene Beiträge', {count: discussion.meta.postings_count - discussion.meta.user_read_index})" - :title="$gettext('Sie haben %{count} ungelesene Beiträge', {count: discussion.meta.postings_count - discussion.meta.user_read_index})" + :aria-label="$gettext('Sie haben %{count} ungelesene Beiträge.', {count: discussion.meta.postings_count - discussion.meta.user_read_index})" + :title="$gettext('Sie haben %{count} ungelesene Beiträge.', {count: discussion.meta.postings_count - discussion.meta.user_read_index})" > {{ discussion.meta.postings_count - discussion.meta.user_read_index }} </span> + <span + v-if="redirect === 'recent' && discussion.meta.recent_postings_count" + class="unread-items-badge" + role="status" + aria-live="polite" + :aria-label="$gettext('%{count} neue Beiträge seit Ihrem letzten Besuch.', {count: discussion.meta.recent_postings_count})" + :title="$gettext('%{count} neue Beiträge seit Ihrem letzten Besuch.', {count: discussion.meta.recent_postings_count})" + > + {{ discussion.meta.recent_postings_count }} + </span> </a> </div> <div class="title-with-actions__actions-xs"> @@ -221,7 +231,7 @@ onMounted(() => { <dt>{{ $gettext('Anzahl der Beitrage') }}</dt> <dd class="inline-flex gap-5 items-center"> - <StudipIcon shape="forum" :size="15" role="info" /> + <StudipIcon shape="reply" :size="15" role="info" /> {{ discussion.meta.postings_count }} </dd> |
