FEATURE: allow plugins to register custom topic list filters

This commit is contained in:
Sam 2017-02-15 15:25:43 -05:00
parent 9c51e3e8e7
commit 74d4209d24
3 changed files with 79 additions and 46 deletions

View File

@ -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

View File

@ -9,7 +9,10 @@ require_dependency 'topic_query_sql'
require_dependency 'avatar_lookup' require_dependency 'avatar_lookup'
class TopicQuery class TopicQuery
VALID_OPTIONS = %i(except_topic_ids
def self.valid_options
@valid_options ||=
%i(except_topic_ids
exclude_category_ids exclude_category_ids
limit limit
page page
@ -33,6 +36,8 @@ class TopicQuery
filter filter
group_name group_name
q) 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

View File

@ -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