DEV: Allow default scope to be configurable per topic. (#15018)

Not exposing this as a plugin API yet as we're testing it out with a
plugin.
This commit is contained in:
Alan Guo Xiang Tan 2021-11-24 16:40:58 +08:00 committed by GitHub
parent 057ef55684
commit a6aff40e4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 5 deletions

View File

@ -79,6 +79,25 @@ class TopicView
@custom_filters || {}
end
# Configure a default scope to be applied to @filtered_posts.
# The registered block is called with @filtered_posts and an instance of
# `TopicView`.
#
# This API should be considered experimental until it is exposed in
# `Plugin::Instance`.
def self.apply_custom_default_scope(&block)
custom_default_scopes << block
end
def self.custom_default_scopes
@custom_default_scopes ||= []
end
# For testing
def self.reset_custom_default_scopes
@custom_default_scopes = nil
end
def initialize(topic_or_topic_id, user = nil, options = {})
@topic = find_topic(topic_or_topic_id)
@user = user
@ -108,7 +127,7 @@ class TopicView
@page = @page.to_i > 1 ? @page.to_i : calculate_page
setup_filtered_posts
@filtered_posts = apply_default_order(@filtered_posts)
@filtered_posts = apply_default_scope(@filtered_posts)
filter_posts(options)
if @posts && !@skip_custom_fields
@ -160,7 +179,7 @@ class TopicView
if is_mega_topic?
nil
else
Gaps.new(filtered_post_ids, apply_default_order(unfiltered_posts).pluck(:id))
Gaps.new(filtered_post_ids, apply_default_scope(unfiltered_posts).pluck(:id))
end
end
end
@ -287,8 +306,10 @@ class TopicView
elsif opts[:post_ids].present?
filter_posts_by_ids(opts[:post_ids])
elsif opts[:filter_post_number].present?
# Only used for megatopics where we do not load the entire post stream
filter_posts_by_post_number(opts[:filter_post_number], opts[:asc])
elsif opts[:best].present?
# Only used for wordpress
filter_best(opts[:best], opts)
else
filter_posts_paged(@page)
@ -738,7 +759,7 @@ class TopicView
:image_upload
)
@posts = apply_default_order(@posts)
@posts = apply_default_scope(@posts)
@posts = filter_post_types(@posts)
@posts = @posts.with_deleted if @guardian.can_see_deleted_posts?(@topic.category)
@posts
@ -762,8 +783,14 @@ class TopicView
result
end
def apply_default_order(scope)
scope.order(sort_order: :asc)
def apply_default_scope(scope)
scope = scope.order(sort_order: :asc)
self.class.custom_default_scopes.each do |block|
scope = block.call(scope, self)
end
scope
end
def setup_filtered_posts

View File

@ -968,4 +968,27 @@ describe TopicView do
expect(topic_view.reviewable_counts.keys).to contain_exactly(reviewable.target_id)
end
end
describe '.apply_custom_default_scope' do
fab!(:post) { Fabricate(:post, topic: topic, created_at: 2.hours.ago) }
fab!(:post_2) { Fabricate(:post, topic: topic, created_at: 1.hour.ago) }
after do
TopicView.reset_custom_default_scopes
end
it 'allows a custom default scope to be configured' do
topic_view = TopicView.new(topic, admin)
expect(topic_view.filtered_post_ids).to eq([post.id, post_2.id])
TopicView.apply_custom_default_scope do |scope, _|
scope.unscope(:order).order("posts.created_at DESC")
end
topic_view = TopicView.new(topic, admin)
expect(topic_view.filtered_post_ids).to eq([post_2.id, post.id])
end
end
end