mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 08:57:10 -06:00
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 :custom_filter_mappings
|
||||
|
||||
def self.register_auth_provider(auth_provider)
|
||||
self.auth_providers << auth_provider
|
||||
end
|
||||
|
@ -239,6 +239,17 @@ class Plugin::Instance
|
||||
DiscoursePluginRegistry.register_editable_group_custom_field(field, self)
|
||||
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:
|
||||
# register_custom_filter_by_status("foobar") do |scope|
|
||||
# scope.where("word_count = 42")
|
||||
|
@ -82,6 +82,11 @@ class TopicsFilter
|
||||
filter_by_number_of_views(min: filter_values)
|
||||
when "views-max"
|
||||
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
|
||||
|
||||
|
@ -212,6 +212,43 @@ RSpec.describe TopicsFilter do
|
||||
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
|
||||
fab!(:category) { Fabricate(:category, name: "category") }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user