aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2025-07-25 12:25:37 +0200
committerMurtaza Sultani <sultani@data-quest.de>2025-07-25 12:25:37 +0200
commitd83a8347ed60b06b360827dc8a1026a70815a483 (patch)
tree358db42c7c3f35dc6c599c36b91baee0b8039a79 /lib
parent1d51d3baf430da6b4573b42aae5f0db9cea838c1 (diff)
Resolve "Forumsuche ohne Reload"
Closes #5747 Merge request studip/studip!4388
Diffstat (limited to 'lib')
-rw-r--r--lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php65
-rw-r--r--lib/models/Forum/ForumDiscussion.php54
2 files changed, 112 insertions, 7 deletions
diff --git a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php
index 140a502..83af8ac 100644
--- a/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php
+++ b/lib/classes/JsonApi/Routes/Forum/ForumDiscussionIndex.php
@@ -12,7 +12,17 @@ use Forum\ForumDiscussion;
class ForumDiscussionIndex extends JsonApiController
{
protected $allowedPagingParameters = ['offset', 'limit'];
- protected $allowedFilteringParameters = ['last-visit'];
+ protected $allowedFilteringParameters = [
+ 'last-visit',
+ 'keyword',
+ 'begin',
+ 'end',
+ 'topic-ids',
+ 'type-ids',
+ 'tag-ids',
+ 'user-ids',
+ 'status'
+ ];
protected $allowedIncludePaths = [
\JsonApi\Schemas\Forum\ForumCategory::REL_TOPICS,
\JsonApi\Schemas\Forum\ForumDiscussion::REL_CATEGORY,
@@ -35,14 +45,61 @@ class ForumDiscussionIndex extends JsonApiController
throw new AuthorizationFailedException();
}
- $filtering = $this->getQueryParameters()->getFilteringParameters() ?: [];
- $last_visit = $filtering['last-visit'] ?? 0;
+ $filters = $this->getFilter();
+ if ($filters) {
+ $_SESSION['forum'][$range->id]['search_filter'] = $filters;
+ }
- $discussions = ForumDiscussion::getCourseDiscussions($range->id, $last_visit);
+ $discussions = ForumDiscussion::getCourseDiscussions($range->id, $filters);
return $this->getPaginatedContentResponse(
array_slice($discussions, ...$this->getOffsetAndLimit()),
count($discussions)
);
}
+
+ private function getFilter(): array
+ {
+ $filtering = $this->getQueryParameters()->getFilteringParameters() ?: [];
+
+ $discussion_filter = [];
+
+ if (isset($filtering['last-visit'])) {
+ $discussion_filter['last_visit'] = (int) $filtering['last-visit'];
+ }
+
+ if (isset($filtering['keyword'])) {
+ $discussion_filter['keyword'] = $filtering['keyword'];
+ }
+
+ if (isset($filtering['status'])) {
+ $discussion_filter['status'] = (int) $filtering['status'];
+ }
+
+ if (isset($filtering['begin'])) {
+ $discussion_filter['begin'] = (int) $filtering['begin'];
+ }
+
+ if (isset($filtering['end'])) {
+ $discussion_filter['end'] = (int) $filtering['end'];
+ }
+
+ if (isset($filtering['topic-ids'])) {
+ $discussion_filter['topic_ids'] = explode(',', $filtering['topic-ids']);
+ }
+
+ if (isset($filtering['type-ids'])) {
+ $discussion_filter['type_ids'] = explode(',', $filtering['type-ids']);
+ }
+
+ if (isset($filtering['tag-ids'])) {
+ $discussion_filter['tag_ids'] = explode(',', $filtering['tag-ids']);
+ }
+
+ if (isset($filtering['user-ids'])) {
+ $discussion_filter['user_ids'] = explode(',', $filtering['user-ids']);
+ }
+
+ return $discussion_filter;
+ }
}
diff --git a/lib/models/Forum/ForumDiscussion.php b/lib/models/Forum/ForumDiscussion.php
index ce648fa..0dae82e 100644
--- a/lib/models/Forum/ForumDiscussion.php
+++ b/lib/models/Forum/ForumDiscussion.php
@@ -80,9 +80,12 @@ class ForumDiscussion extends SimpleORMap
}
/**
+ * @param string $range_id course_id or institute_id.
+ * @param array $filter Optional: filters to apply.
+ *
* @return self[]
*/
- public static function getCourseDiscussions($range_id, $last_visit = 0): array
+ public static function getCourseDiscussions(string $range_id, array $filter = []): array
{
$query = [
"SELECT
@@ -91,13 +94,58 @@ class ForumDiscussion extends SimpleORMap
FROM forum_discussions AS discussions
JOIN forum_postings as postings USING (discussion_id)
JOIN forum_topics AS topics USING (topic_id)
+ LEFT JOIN tags_relations ON (tags_relations.range_id = discussions.discussion_id AND range_type = 'forum')
WHERE topics.range_id = :range_id",
['range_id' => $range_id]
];
- if ($last_visit) {
+ if (isset($filter['last_visit'])) {
$query[0] .= " AND postings.mkdate > :last_visit";
- $query[1]["last_visit"] = $last_visit;
+ $query[1]["last_visit"] = $filter['last_visit'];
+ }
+
+ if (isset($filter['keyword'])) {
+ $keyword = $filter['keyword'];
+ $query[0] .= " AND (discussions.title LIKE :keyword OR postings.content LIKE :keyword)";
+ $query[1]["keyword"] = "%$keyword%";
+ }
+
+ if (isset($filter['begin'])) {
+ $query[0] .= " AND postings.mkdate >= :begin";
+ $query[1]['begin'] = $filter['begin'];
+ }
+
+ if (isset($filter['end'])) {
+ $query[0] .= " AND postings.mkdate <= :end";
+ $query[1]['end'] = $filter['end'];
+ }
+
+ if (isset($filter['topic_ids'])) {
+ $query[0] .= " AND discussions.topic_id IN (:topic_ids)";
+ $query[1]['topic_ids'] = $filter['topic_ids'];
+ }
+
+ if (isset($filter['type_ids'])) {
+ $query[0] .= " AND discussions.type_id IN (:type_ids)";
+ $query[1]['type_ids'] = $filter['type_ids'];
+ }
+
+ if (isset($filter['tag_ids'])) {
+ $query[0] .= " AND tags_relations.tag_id IN (:tag_ids)";
+ $query[1]['tag_ids'] = $filter['tag_ids'];
+ }
+
+ if (isset($filter['user_ids'])) {
+ $query[0] .= " AND postings.user_id IN (:user_ids)";
+ $query[1]['user_ids'] = $filter['user_ids'];
+ }
+
+ if (isset($filter['status'])) {
+ $query[0] .= match ($filter['status']) {
+ 2 => " AND discussions.closed_at IS NULL", // opens
+ 3 => " AND discussions.closed_at IS NOT NULL", // closed
+ default => ""
+ };
}
return \DBManager::get()->fetchAll(