From 539723f8ffd6506fe3db24ed880471251b287c61 Mon Sep 17 00:00:00 2001 From: Tim Lange Date: Wed, 1 May 2019 04:31:13 +0200 Subject: [PATCH] FEATURE: Added unlisted topics option to advanced search (#7447) --- .../components/search-advanced-options.js.es6 | 32 ++++++++++++------- config/locales/client.en.yml | 1 + lib/search.rb | 10 +++++- spec/components/search_spec.rb | 19 +++++++++++ 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 index cbe6564d19..939d5fca1b 100644 --- a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 +++ b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 @@ -28,6 +28,17 @@ const REGEXP_POST_TIME_WHEN = /^(before|after)/gi; const IN_OPTIONS_MAPPING = { images: "with" }; +const DEFAULT_STATUS_OPTIONS = [ + { name: I18n.t("search.advanced.statuses.open"), value: "open" }, + { name: I18n.t("search.advanced.statuses.closed"), value: "closed" }, + { name: I18n.t("search.advanced.statuses.archived"), value: "archived" }, + { name: I18n.t("search.advanced.statuses.noreplies"), value: "noreplies" }, + { + name: I18n.t("search.advanced.statuses.single_user"), + value: "single_user" + } +]; + export default Ember.Component.extend({ classNames: ["search-advanced-options"], @@ -47,17 +58,6 @@ export default Ember.Component.extend({ { name: I18n.t("search.advanced.filters.images"), value: "images" } ], - statusOptions: [ - { name: I18n.t("search.advanced.statuses.open"), value: "open" }, - { name: I18n.t("search.advanced.statuses.closed"), value: "closed" }, - { name: I18n.t("search.advanced.statuses.archived"), value: "archived" }, - { name: I18n.t("search.advanced.statuses.noreplies"), value: "noreplies" }, - { - name: I18n.t("search.advanced.statuses.single_user"), - value: "single_user" - } - ], - postTimeOptions: [ { name: I18n.t("search.advanced.post.time.before"), value: "before" }, { name: I18n.t("search.advanced.post.time.after"), value: "after" } @@ -102,10 +102,20 @@ export default Ember.Component.extend({ days: "" } }, + statusOptions: DEFAULT_STATUS_OPTIONS, inOptions: this.currentUser ? this.inOptionsForUsers.concat(this.inOptionsForAll) : this.inOptionsForAll }); + + if (this.currentUser.get("staff")) { + this.setProperties({ + statusOptions: DEFAULT_STATUS_OPTIONS.concat({ + name: I18n.t("search.advanced.statuses.unlisted"), + value: "unlisted" + }) + }); + } }, _update() { diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 63f6b116c7..329a858571 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1772,6 +1772,7 @@ en: archived: are archived noreplies: have zero replies single_user: contain a single user + unlisted: are unlisted post: count: label: Minimum Post Count diff --git a/lib/search.rb b/lib/search.rb index fbc1e8c12e..c7e691d62d 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -280,6 +280,14 @@ class Search posts.where("topics.participant_count = 1") end + advanced_filter(/^status:unlisted$/) do |posts| + if @guardian.is_staff? + posts.where("NOT topics.visible") + else + posts.where("1=0") + end + end + advanced_filter(/^posts_count:(\d+)$/) do |posts, match| posts.where("topics.posts_count = ?", match.to_i) end @@ -737,7 +745,7 @@ class Search is_topic_search = @search_context.present? && @search_context.is_a?(Topic) - posts = posts.where("topics.visible") unless is_topic_search + posts = posts.where("topics.visible") if !is_topic_search && !@guardian.is_staff? if opts[:private_messages] || (is_topic_search && @search_context.private_message?) posts = posts.where("topics.archetype = ?", Archetype.private_message) diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index 7b23bb8417..24f2b49391 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -1130,6 +1130,25 @@ describe Search do .to eq([post7.id, post8.id]) end + it "can search for unlisted topics as staff" do + topic1 = Fabricate(:topic, visible: false) + post = Fabricate(:post, raw: 'Testing post', topic: topic1) + topic2 = Fabricate(:topic) + Fabricate(:post, raw: 'Testing post', topic: topic2) + + results = Search.execute('Testing post status:unlisted', guardian: Guardian.new(Fabricate(:moderator))) + expect(results.posts.length).to eq(1) + expect(results.posts.first.id).to eq(post.id) + end + + it "unlisted topics can't be found using search for non-staff" do + topic = Fabricate(:topic, visible: false) + Fabricate(:post, raw: 'Testing post', topic: topic) + + results = Search.execute('Testing post', guardian: Guardian.new(Fabricate(:user))) + expect(results.posts.length).to eq(0) + end + end it "can find posts which contains filetypes" do