DEV: Support adding a custom filter on `/filter` (#27927)
# Context Currently there is no way to add a custom filter to the experimental `/filter` endpoint. While you can implement a custom `status:` there is no way to include the user's input in a custom query. # PR This PR adds the ability to implement a custom filter. eg. `CUSTOM_FILTER:foo` - Add `add_filter_custom_filter` for extension - Add specs
This commit is contained in:
parent
6dd09b0868
commit
b3e0e920ed
|
@ -127,6 +127,8 @@ class DiscoursePluginRegistry
|
||||||
|
|
||||||
define_filtered_register :flag_applies_to_types
|
define_filtered_register :flag_applies_to_types
|
||||||
|
|
||||||
|
define_filtered_register :custom_filter_mappings
|
||||||
|
|
||||||
def self.register_auth_provider(auth_provider)
|
def self.register_auth_provider(auth_provider)
|
||||||
self.auth_providers << auth_provider
|
self.auth_providers << auth_provider
|
||||||
end
|
end
|
||||||
|
|
|
@ -239,6 +239,17 @@ class Plugin::Instance
|
||||||
DiscoursePluginRegistry.register_editable_group_custom_field(field, self)
|
DiscoursePluginRegistry.register_editable_group_custom_field(field, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allows to define custom filter utilizing the user's input.
|
||||||
|
# Ensure proper input sanitization before using it in a query.
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# add_filter_custom_filter("word_count") do |scope, value|
|
||||||
|
# scope.where(word_count: value)
|
||||||
|
# end
|
||||||
|
def add_filter_custom_filter(name, &block)
|
||||||
|
DiscoursePluginRegistry.register_custom_filter_mapping({ name => block }, self)
|
||||||
|
end
|
||||||
|
|
||||||
# Allows to define custom "status:" filter. Example usage:
|
# Allows to define custom "status:" filter. Example usage:
|
||||||
# register_custom_filter_by_status("foobar") do |scope|
|
# register_custom_filter_by_status("foobar") do |scope|
|
||||||
# scope.where("word_count = 42")
|
# scope.where("word_count = 42")
|
||||||
|
|
|
@ -82,6 +82,11 @@ class TopicsFilter
|
||||||
filter_by_number_of_views(min: filter_values)
|
filter_by_number_of_views(min: filter_values)
|
||||||
when "views-max"
|
when "views-max"
|
||||||
filter_by_number_of_views(max: filter_values)
|
filter_by_number_of_views(max: filter_values)
|
||||||
|
else
|
||||||
|
if custom_filter =
|
||||||
|
DiscoursePluginRegistry.custom_filter_mappings.find { |hash| hash.key?(filter) }
|
||||||
|
@scope = custom_filter[filter].call(@scope, filter_values)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -212,6 +212,43 @@ RSpec.describe TopicsFilter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when filtering with custom filters" do
|
||||||
|
fab!(:topic)
|
||||||
|
fab!(:word_count_topic) { Fabricate(:topic, word_count: 42) }
|
||||||
|
fab!(:word_count_topic_2) { Fabricate(:topic, word_count: 42) }
|
||||||
|
|
||||||
|
let(:word_count_block) { Proc.new { |scope, value| scope.where(word_count: value) } }
|
||||||
|
let(:id_block) { Proc.new { |scope, value| scope.where(id: value) } }
|
||||||
|
let(:plugin) { Plugin::Instance.new }
|
||||||
|
|
||||||
|
it "supports a custom filter" do
|
||||||
|
plugin.add_filter_custom_filter("word_count", &word_count_block)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
TopicsFilter
|
||||||
|
.new(guardian: Guardian.new)
|
||||||
|
.filter_from_query_string("word_count:42")
|
||||||
|
.pluck(:id),
|
||||||
|
).to contain_exactly(word_count_topic.id, word_count_topic_2.id)
|
||||||
|
ensure
|
||||||
|
DiscoursePluginRegistry.reset_register!(:custom_filter_mappings)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "supports multiple custom filters" do
|
||||||
|
plugin.add_filter_custom_filter("word_count", &word_count_block)
|
||||||
|
plugin.add_filter_custom_filter("id", &id_block)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
TopicsFilter
|
||||||
|
.new(guardian: Guardian.new)
|
||||||
|
.filter_from_query_string("word_count:42 id:#{word_count_topic.id}")
|
||||||
|
.pluck(:id),
|
||||||
|
).to contain_exactly(word_count_topic.id)
|
||||||
|
ensure
|
||||||
|
DiscoursePluginRegistry.reset_register!(:custom_filter_mappings)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "when filtering by categories" do
|
describe "when filtering by categories" do
|
||||||
fab!(:category) { Fabricate(:category, name: "category") }
|
fab!(:category) { Fabricate(:category, name: "category") }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue