diff --git a/lib/topics_filter.rb b/lib/topics_filter.rb index 66dafa633a9..d2eb32b791e 100644 --- a/lib/topics_filter.rb +++ b/lib/topics_filter.rb @@ -549,14 +549,21 @@ class TopicsFilter def order_by(values:) values.each do |value| + # If the order by value is not recognized, check if it is a custom filter. match_data = value.match(ORDER_BY_REGEXP) - if match_data && column_name = ORDER_BY_MAPPINGS.dig(match_data[:order_by], :column) if scope = ORDER_BY_MAPPINGS.dig(match_data[:order_by], :scope) @scope = instance_exec(&scope) end @scope = @scope.order("#{column_name} #{match_data[:asc] ? "ASC" : "DESC"}") + else + match_data = value.match /^(?.*?)(?:-(?asc))?$/ + key = "order:#{match_data[:column]}" + if custom_match = + DiscoursePluginRegistry.custom_filter_mappings.find { |hash| hash.key?(key) } + @scope = custom_match[key].call(@scope, match_data[:asc].nil? ? "DESC" : "ASC") + end end end end diff --git a/spec/lib/topics_filter_spec.rb b/spec/lib/topics_filter_spec.rb index ef9f665853c..5adf404903f 100644 --- a/spec/lib/topics_filter_spec.rb +++ b/spec/lib/topics_filter_spec.rb @@ -1349,6 +1349,13 @@ RSpec.describe TopicsFilter do end describe "ordering topics filter" do + before do + Plugin::Instance.new.add_filter_custom_filter( + "order:wrongly", + &->(scope) { scope.order("wrongly") } + ) + end + # Requires the fabrication of `topic`, `topic2` and `topic3` such that the order of the topics is `topic2`, `topic1`, `topic3` # when ordered by the given filter in descending order. shared_examples "ordering topics filters" do |order, order_description| @@ -1500,6 +1507,38 @@ RSpec.describe TopicsFilter do end end end + + context "for DiscoursePluginRegistry.custom_filter_mappings" do + describe "when extending order:{col}" do + fab!(:earlier_topic) { Fabricate(:topic, bumped_at: 2.hours.ago) } + fab!(:now_topic) { Fabricate(:topic, bumped_at: Time.now) } + + before_all do + Plugin::Instance.new.add_filter_custom_filter( + "order:bumped", + &->(scope, value) { scope.order("bumped_at #{value}") } + ) + end + + it "applies ASC order correctly" do + expect( + TopicsFilter + .new(guardian: Guardian.new) + .filter_from_query_string("order:bumped-asc") + .pluck(:id), + ).to eq([earlier_topic.id, now_topic.id]) + end + + it "applies default order correctly" do + expect( + TopicsFilter + .new(guardian: Guardian.new) + .filter_from_query_string("order:bumped") + .pluck(:id), + ).to eq([now_topic.id, earlier_topic.id]) + end + end + end end end end