mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
FEATURE: allow plugins to register custom topic list filters
This commit is contained in:
@ -277,27 +277,15 @@ class ListController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build_topic_list_options
|
def build_topic_list_options
|
||||||
options = {
|
options = {}
|
||||||
page: params[:page],
|
TopicQuery.valid_options.each do |key|
|
||||||
topic_ids: param_to_integer_list(:topic_ids),
|
options[key] = params[key]
|
||||||
exclude_category_ids: params[:exclude_category_ids],
|
end
|
||||||
category: params[:category],
|
|
||||||
order: params[:order],
|
# hacky columns get special handling
|
||||||
ascending: params[:ascending],
|
options[:topic_ids] = param_to_integer_list(:topic_ids)
|
||||||
min_posts: params[:min_posts],
|
options[:no_subcategories] = options[:no_subcategories] == 'true'
|
||||||
max_posts: params[:max_posts],
|
options[:slow_platform] = slow_platform?
|
||||||
status: params[:status],
|
|
||||||
filter: params[:filter],
|
|
||||||
state: params[:state],
|
|
||||||
search: params[:search],
|
|
||||||
q: params[:q],
|
|
||||||
group_name: params[:group_name],
|
|
||||||
tags: params[:tags],
|
|
||||||
match_all_tags: params[:match_all_tags],
|
|
||||||
no_tags: params[:no_tags]
|
|
||||||
}
|
|
||||||
options[:no_subcategories] = true if params[:no_subcategories] == 'true'
|
|
||||||
options[:slow_platform] = true if slow_platform?
|
|
||||||
|
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
@ -9,30 +9,35 @@ require_dependency 'topic_query_sql'
|
|||||||
require_dependency 'avatar_lookup'
|
require_dependency 'avatar_lookup'
|
||||||
|
|
||||||
class TopicQuery
|
class TopicQuery
|
||||||
VALID_OPTIONS = %i(except_topic_ids
|
|
||||||
exclude_category_ids
|
def self.valid_options
|
||||||
limit
|
@valid_options ||=
|
||||||
page
|
%i(except_topic_ids
|
||||||
per_page
|
exclude_category_ids
|
||||||
min_posts
|
limit
|
||||||
max_posts
|
page
|
||||||
topic_ids
|
per_page
|
||||||
visible
|
min_posts
|
||||||
category
|
max_posts
|
||||||
tags
|
topic_ids
|
||||||
match_all_tags
|
visible
|
||||||
no_tags
|
category
|
||||||
order
|
tags
|
||||||
ascending
|
match_all_tags
|
||||||
no_subcategories
|
no_tags
|
||||||
no_definitions
|
order
|
||||||
status
|
ascending
|
||||||
state
|
no_subcategories
|
||||||
search
|
no_definitions
|
||||||
slow_platform
|
status
|
||||||
filter
|
state
|
||||||
group_name
|
search
|
||||||
q)
|
slow_platform
|
||||||
|
filter
|
||||||
|
group_name
|
||||||
|
q)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# Maps `order` to a columns in `topics`
|
# Maps `order` to a columns in `topics`
|
||||||
SORTABLE_MAPPING = {
|
SORTABLE_MAPPING = {
|
||||||
@ -49,8 +54,31 @@ class TopicQuery
|
|||||||
cattr_accessor :results_filter_callbacks
|
cattr_accessor :results_filter_callbacks
|
||||||
self.results_filter_callbacks = []
|
self.results_filter_callbacks = []
|
||||||
|
|
||||||
|
attr_accessor :options, :user, :guardian
|
||||||
|
|
||||||
|
def self.add_custom_filter(key, &blk)
|
||||||
|
@custom_filters ||= {}
|
||||||
|
valid_options << key
|
||||||
|
@custom_filters[key] = blk
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove_custom_filter(key)
|
||||||
|
@custom_filters.delete(key)
|
||||||
|
valid_options.delete(key)
|
||||||
|
@custom_filters = nil if @custom_filters.length == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.apply_custom_filters(results, topic_query)
|
||||||
|
if @custom_filters
|
||||||
|
@custom_filters.each do |key,filter|
|
||||||
|
results = filter.call(results, topic_query)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
results
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(user=nil, options={})
|
def initialize(user=nil, options={})
|
||||||
options.assert_valid_keys(VALID_OPTIONS)
|
options.assert_valid_keys(TopicQuery.valid_options)
|
||||||
@options = options.dup
|
@options = options.dup
|
||||||
@user = user
|
@user = user
|
||||||
@guardian = Guardian.new(@user)
|
@guardian = Guardian.new(@user)
|
||||||
@ -589,6 +617,8 @@ class TopicQuery
|
|||||||
result = result.where('topics.posts_count <= ?', options[:max_posts]) if options[:max_posts].present?
|
result = result.where('topics.posts_count <= ?', options[:max_posts]) if options[:max_posts].present?
|
||||||
result = result.where('topics.posts_count >= ?', options[:min_posts]) if options[:min_posts].present?
|
result = result.where('topics.posts_count >= ?', options[:min_posts]) if options[:min_posts].present?
|
||||||
|
|
||||||
|
result = TopicQuery.apply_custom_filters(result,self)
|
||||||
|
|
||||||
@guardian.filter_allowed_categories(result)
|
@guardian.filter_allowed_categories(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,6 +40,21 @@ describe TopicQuery do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "custom filters" do
|
||||||
|
it "allows custom filters to be applied" do
|
||||||
|
topic1 = Fabricate(:topic)
|
||||||
|
_topic2 = Fabricate(:topic)
|
||||||
|
|
||||||
|
TopicQuery.add_custom_filter(:only_topic_id) do |results, topic_query|
|
||||||
|
results = results.where('topics.id = ?', topic_query.options[:only_topic_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(TopicQuery.new(nil, {only_topic_id: topic1.id}).list_latest.topics.map(&:id)).to eq([topic1.id])
|
||||||
|
|
||||||
|
TopicQuery.remove_custom_filter(:only_topic_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "list_topics_by" do
|
context "list_topics_by" do
|
||||||
|
|
||||||
it "allows users to view their own invisible topics" do
|
it "allows users to view their own invisible topics" do
|
||||||
|
Reference in New Issue
Block a user