From 803c275bd7506f2a34c4f2e66f7f8528fd64f75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Fri, 26 Apr 2024 12:53:17 +0200 Subject: [PATCH] DEV: add support for adding custom status filter Those can be used in the /filter routes. --- lib/plugin/instance.rb | 8 ++++++++ lib/topics_filter.rb | 12 ++++++++++++ spec/lib/topics_filter_spec.rb | 14 +++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index b12e17d14dd..76ed4548017 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -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") diff --git a/lib/topics_filter.rb b/lib/topics_filter.rb index 5ffa80319f1..4d075d53ac0 100644 --- a/lib/topics_filter.rb +++ b/lib/topics_filter.rb @@ -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 diff --git a/spec/lib/topics_filter_spec.rb b/spec/lib/topics_filter_spec.rb index 54f5b436b07..64247ba74a5 100644 --- a/spec/lib/topics_filter_spec.rb +++ b/spec/lib/topics_filter_spec.rb @@ -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