From 17d999ab1209ac32627263e1b87fcc771bac5846 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 15 Sep 2015 17:21:46 +1000 Subject: [PATCH] FEATURE: search for all posts of users that have a badge with_badge:"badge name" will allow you to search only posts of users with a particular badge --- lib/search.rb | 25 +++++++++++++++++++++++-- spec/components/search_spec.rb | 11 +++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/search.rb b/lib/search.rb index 25840cd6780..adb82a5383e 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -103,6 +103,7 @@ class Search @limit = Search.per_facet term = process_advanced_search!(term) + if term.present? @term = Search.prepare_data(term.to_s) @original_term = PG::Connection.escape_string(@term) @@ -184,6 +185,15 @@ class Search posts.where("posts.post_number = 1") end + advanced_filter(/with_badge:(.*)/) do |posts,match| + badge_id = Badge.where('name ilike ? OR id = ?', match, match.to_i).pluck(:id).first + if badge_id + posts.where('posts.user_id IN (SELECT ub.user_id FROM user_badges ub WHERE ub.badge_id = ?)', badge_id) + else + posts.where("1 = 0") + end + end + advanced_filter(/in:(likes|bookmarks)/) do |posts, match| if @guardian.user post_action_type = PostActionType.types[:like] if match == "likes" @@ -247,12 +257,14 @@ class Search def process_advanced_search!(term) - term.to_s.split(/\s+/).map do |word| + term.to_s.scan(/(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/).to_a.map do |(word,_)| + next if word.blank? found = false Search.advanced_filters.each do |matcher, block| - if word =~ matcher + cleaned = word.gsub(/["']/,"") + if cleaned =~ matcher (@filters ||= []) << [block, $1] found = true end @@ -273,6 +285,9 @@ class Search elsif word == 'order:views' @order = :views nil + elsif word == 'order:likes' + @order = :likes + nil elsif word == 'in:private' @search_pms = true nil @@ -440,6 +455,12 @@ class Search else posts = posts.order("topics.views DESC") end + elsif @order == :likes + if opts[:aggregate_search] + posts = posts.order("MAX(posts.like_count) DESC") + else + posts = posts.order("posts.like_count DESC") + end else posts = posts.order("TS_RANK_CD(TO_TSVECTOR(#{query_locale}, topics.title), #{ts_query}) DESC") diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index a74bffee1b9..335e538b0e0 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -391,6 +391,17 @@ describe Search do expect(Search.execute("user:#{_post.user.username}").posts.length).to eq(1) end + it 'supports with_badge' do + + topic = Fabricate(:topic, created_at: 3.months.ago) + post = Fabricate(:post, raw: 'hi this is a test 123 123', topic: topic) + + badge = Badge.create!(name: "Like a Boss", badge_type_id: 1) + UserBadge.create!(user_id: post.user_id, badge_id: badge.id, granted_at: 1.minute.ago, granted_by_id: -1) + + expect(Search.execute('with_badge:"like a boss"').posts.length).to eq(1) + end + it 'can search numbers correctly, and match exact phrases' do topic = Fabricate(:topic, created_at: 3.months.ago) Fabricate(:post, raw: '3.0 eta is in 2 days horrah', topic: topic)