DEV: add support for adding custom status filter

Those can be used in the /filter routes.
This commit is contained in:
Régis Hanol 2024-04-26 12:53:17 +02:00
parent 351d212e8a
commit 803c275bd7
3 changed files with 33 additions and 1 deletions

View File

@ -236,6 +236,14 @@ class Plugin::Instance
DiscoursePluginRegistry.register_editable_group_custom_field(field, self)
end
# Allows to define custom "status:" filter. Example usage:
# register_custom_filter_by_status("foobar") do |scope|
# scope.where("word_count = 42")
# end
def register_custom_filter_by_status(status, &block)
TopicsFilter.add_filter_by_status(status, &block)
end
# Allows to define custom search order. Example usage:
# Search.advanced_order(:chars) do |posts|
# posts.reorder("(SELECT LENGTH(raw) FROM posts WHERE posts.topic_id = subquery.topic_id) DESC")

View File

@ -86,6 +86,14 @@ class TopicsFilter
@scope
end
def self.add_filter_by_status(status, &blk)
(@custom_status_filters ||= {})[status] = blk
end
def self.custom_status_filters
@custom_status_filters || {}
end
def filter_status(status:, category_id: nil)
case status
when "open"
@ -106,6 +114,10 @@ class TopicsFilter
end
when "public"
@scope = @scope.joins(:category).where("NOT categories.read_restricted")
else
if custom_filter = TopicsFilter.custom_status_filters[status]
@scope = custom_filter.call(@scope)
end
end
@scope

View File

@ -617,6 +617,18 @@ RSpec.describe TopicsFilter do
fab!(:closed_topic) { Fabricate(:topic, closed: true) }
fab!(:archived_topic) { Fabricate(:topic, archived: true) }
fab!(:deleted_topic_id) { Fabricate(:topic, deleted_at: Time.zone.now).id }
fab!(:foobar_topic) { Fabricate(:topic, closed: true, word_count: 42) }
it "supports custom status filters" do
TopicsFilter.add_filter_by_status("foobar") { |scope| scope.where("word_count = 42") }
expect(
TopicsFilter
.new(guardian: Guardian.new)
.filter_from_query_string("status:foobar")
.pluck(:id),
).to contain_exactly(foobar_topic.id)
end
it "should only return topics that have not been closed or archived when query string is `status:open`" do
expect(
@ -642,7 +654,7 @@ RSpec.describe TopicsFilter do
.new(guardian: Guardian.new)
.filter_from_query_string("status:deleted")
.pluck(:id),
).to contain_exactly(topic.id, closed_topic.id, archived_topic.id)
).to contain_exactly(topic.id, closed_topic.id, archived_topic.id, foobar_topic.id)
end
it "should only return topics that have been archived when query string is `status:archived`" do