FEATURE: ability to register custom filters for posts (#12938)

Allow plugins to extend TopicView to filter posts
This commit is contained in:
Krzysztof Kotlarek 2021-05-10 08:57:58 +10:00 committed by GitHub
parent f337d59ed9
commit a4bd1806d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 0 deletions

View File

@ -208,6 +208,14 @@ class Plugin::Instance
Search.advanced_filter(trigger, &block)
end
# Allows to define TopicView posts filters. Example usage:
# TopicView.advanced_filter do |posts, opts|
# posts.where(wiki: true)
# end
def register_topic_view_posts_filter(trigger, &block)
TopicView.add_custom_filter(trigger, &block)
end
# Allow to eager load additional tables in Search. Useful to avoid N+1 performance problems.
# Example usage:
# register_search_topic_eager_load do |opts|

View File

@ -51,6 +51,15 @@ class TopicView
wpcf.flatten.uniq
end
def self.add_custom_filter(key, &blk)
@custom_filters ||= {}
@custom_filters[key] = blk
end
def self.custom_filters
@custom_filters || {}
end
def initialize(topic_or_topic_id, user = nil, options = {})
@topic = find_topic(topic_or_topic_id)
@user = user
@ -772,6 +781,10 @@ class TopicView
@contains_gaps = true
end
if @filter.present? && @filter != 'summary' && TopicView.custom_filters[@filter].present?
@filtered_posts = TopicView.custom_filters[@filter].call(@filtered_posts, self)
end
if @best.present?
@filtered_posts = @filtered_posts.where('posts.post_type = ?', Post.types[:regular])
@contains_gaps = true

View File

@ -55,6 +55,29 @@ describe TopicView do
end
end
context 'custom filters' do
fab!(:p0) { Fabricate(:post, topic: topic) }
fab!(:p1) { Fabricate(:post, topic: topic, wiki: true) }
it 'allows to register custom filters' do
tv = TopicView.new(topic.id, evil_trout, { filter: 'wiki' })
expect(tv.filter_posts({ filter: "wiki" })).to eq([p0, p1])
TopicView.add_custom_filter("wiki") do |posts, topic_view|
posts.where(wiki: true)
end
tv = TopicView.new(topic.id, evil_trout, { filter: 'wiki' })
expect(tv.filter_posts).to eq([p1])
tv = TopicView.new(topic.id, evil_trout, { filter: 'whatever' })
expect(tv.filter_posts).to eq([p0, p1])
ensure
TopicView.instance_variable_set(:@custom_filters, [])
end
end
context "setup_filtered_posts" do
describe "filters posts with ignored users" do
fab!(:ignored_user) { Fabricate(:ignored_user, user: evil_trout, ignored_user: user) }

View File

@ -2436,6 +2436,29 @@ RSpec.describe TopicsController do
expect(body["post_ids"]).to eq([post2.id])
end
end
describe 'custom filters' do
fab!(:post2) { Fabricate(:post, topic: topic, percent_rank: 0.2) }
fab!(:post3) { Fabricate(:post, topic: topic, percent_rank: 0.5) }
it 'should return the right posts' do
TopicView.add_custom_filter("percent") do |posts, topic_view|
posts.where(percent_rank: 0.5)
end
get "/t/#{topic.id}.json", params: {
post_number: post.post_number,
filter: 'percent'
}
expect(response.status).to eq(200)
body = response.parsed_body
expect(body["post_stream"]["posts"].map { |p| p["id"] }).to eq([post3.id])
ensure
TopicView.instance_variable_set(:@custom_filters, [])
end
end
end
end