DEV: Add include_pms option to TopicQuery (#10647)

DEV: Add include_pms option to TopicQuery (#10647)

This is intended for use by plugins which are building their own topic lists, and want to include PMs alongside regular topics (e.g. discourse-assign). It does not get used directly in core.

diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index 73aa372..a9ae978 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -70,7 +70,8 @@ class TopicQuery
          visible
          guardian
          no_definitions
-         destination_category_id)
+         destination_category_id
+         include_pms)
   end
 
   # Maps `order` to a columns in `topics`
@@ -724,7 +725,15 @@ class TopicQuery
     end
 
     result = apply_ordering(result, options)
-    result = result.listable_topics
+
+    all_listable_topics = @guardian.filter_allowed_categories(Topic.unscoped.listable_topics)
+
+    if options[:include_pms]
+      all_pm_topics = Topic.unscoped.private_messages_for_user(@user)
+      result = result.merge(all_listable_topics.or(all_pm_topics))
+    else
+      result = result.merge(all_listable_topics)
+    end
 
     # Don't include the category topics if excluded
     if options[:no_definitions]
@@ -851,7 +860,7 @@ class TopicQuery
 
     result = TopicQuery.apply_custom_filters(result, self)
 
-    @guardian.filter_allowed_categories(result)
+    result
   end
 
   def remove_muted_topics(list, user)
diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb
index f1ee856..31ade88 100644
--- a/spec/components/topic_query_spec.rb
+++ b/spec/components/topic_query_spec.rb
@@ -9,7 +9,7 @@ describe TopicQuery do
   #  it indeed happens first, but is not obvious later in the tests we depend on the user being
   #  created so early otherwise finding new topics does not work
   #  we should remove the let! here and use freeze time to communicate how the clock moves
-  let!(:user) { Fabricate(:coding_horror) }
+  let!(:user) { Fabricate(:user) }
 
   fab!(:creator) { Fabricate(:user) }
   let(:topic_query) { TopicQuery.new(user) }
@@ -162,6 +162,18 @@ describe TopicQuery do
     end
   end
 
+  describe 'include_pms option' do
+    it "includes users own pms in regular topic lists" do
+      topic = Fabricate(:topic)
+      own_pm = Fabricate(:private_message_topic, user: user)
+      other_pm = Fabricate(:private_message_topic, user: Fabricate(:user))
+
+      expect(TopicQuery.new(user).list_latest.topics).to contain_exactly(topic)
+      expect(TopicQuery.new(admin).list_latest.topics).to contain_exactly(topic)
+      expect(TopicQuery.new(user, include_pms: true).list_latest.topics).to contain_exactly(topic, own_pm)
+    end
+  end
+
   context 'category filter' do
     let(:category) { Fabricate(:category_with_definition) }
     let(:diff_category) { Fabricate(:category_with_definition, name: "Different Category") }
diff --git a/spec/fabricators/topic_fabricator.rb b/spec/fabricators/topic_fabricator.rb
index 3bcee07..b65cd48 100644
--- a/spec/fabricators/topic_fabricator.rb
+++ b/spec/fabricators/topic_fabricator.rb
@@ -21,11 +21,12 @@ Fabricator(:banner_topic, from: :topic) do
 end
 
 Fabricator(:private_message_topic, from: :topic) do
+  transient :recipient
   category_id { nil }
   title { sequence(:title) { |i| "This is a private message #{i}" } }
   archetype "private_message"
   topic_allowed_users { |t| [
     Fabricate.build(:topic_allowed_user, user: t[:user]),
-    Fabricate.build(:topic_allowed_user, user: Fabricate(:coding_horror))
+    Fabricate.build(:topic_allowed_user, user: t[:recipient] || Fabricate(:user))
   ]}
 end
diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb
index 17346ce..72d1583 100644
--- a/spec/models/topic_spec.rb
+++ b/spec/models/topic_spec.rb
@@ -894,9 +894,9 @@ describe Topic do
   end
 
   context 'private message' do
-    let(:coding_horror) { User.find_by(username: "CodingHorror") }
+    let(:coding_horror) { Fabricate(:coding_horror) }
     fab!(:evil_trout) { Fabricate(:evil_trout) }
-    let(:topic) { Fabricate(:private_message_topic) }
+    let(:topic) { Fabricate(:private_message_topic, recipient: coding_horror) }
 
     it "should integrate correctly" do
       expect(Guardian.new(topic.user).can_see?(topic)).to eq(true)

GitHub sha: 66eda8c9

This commit appears in #10647 which was approved by tgxworld. It was merged by davidtaylorhq.