2013-10-30 15:45:13 -04:00
# Searches for a user by username or full text or name (if enabled in SiteSettings)
2013-02-07 04:34:49 -05:00
class UserSearch
2013-02-07 05:54:55 -05:00
2014-05-13 11:44:06 -04:00
def initialize ( term , opts = { } )
2013-10-30 15:45:13 -04:00
@term = term
2015-11-30 17:03:47 +11:00
@term_like = " #{ term . downcase . gsub ( " _ " , " \\ _ " ) } % "
2014-05-13 11:44:06 -04:00
@topic_id = opts [ :topic_id ]
2015-04-13 20:33:13 +05:30
@topic_allowed_users = opts [ :topic_allowed_users ]
2014-05-13 11:44:06 -04:00
@searching_user = opts [ :searching_user ]
2014-05-15 12:22:35 +10:00
@limit = opts [ :limit ] || 20
2013-10-30 15:45:13 -04:00
end
2013-02-25 19:42:20 +03:00
2015-05-14 14:38:47 +10:00
def scoped_users
2015-11-18 20:57:49 +01:00
users = User . where ( active : true , staged : false )
2015-05-14 14:38:47 +10:00
unless @searching_user && @searching_user . staff?
users = users . not_suspended
end
# Only show users who have access to private topic
if @topic_id && @topic_allowed_users == " true "
topic = Topic . find_by ( id : @topic_id )
if topic . category && topic . category . read_restricted
users = users . includes ( :secure_categories )
. where ( " users.admin = TRUE OR categories.id = ? " , topic . category . id )
. references ( :categories )
end
end
2013-02-07 04:34:49 -05:00
2015-05-14 14:38:47 +10:00
users . limit ( @limit )
end
def filtered_by_term_users
users = scoped_users
2014-08-13 13:30:25 -04:00
2013-10-30 15:45:13 -04:00
if @term . present?
2015-11-30 17:03:47 +11:00
if SiteSetting . enable_names? && @term !~ / [_ \ .-] /
2014-07-05 09:11:41 +10:00
query = Search . ts_query ( @term , " simple " )
2015-11-30 17:03:47 +11:00
2014-07-05 09:11:41 +10:00
users = users . includes ( :user_search_data )
. references ( :user_search_data )
2015-11-04 23:04:37 +01:00
. where ( " user_search_data.search_data @@ #{ query } " )
2014-07-05 09:11:41 +10:00
. order ( User . sql_fragment ( " CASE WHEN username_lower LIKE ? THEN 0 ELSE 1 END ASC " , @term_like ) )
2015-11-30 17:03:47 +11:00
2013-10-30 15:45:13 -04:00
else
users = users . where ( " username_lower LIKE :term_like " , term_like : @term_like )
end
2013-02-07 04:34:49 -05:00
end
2013-02-25 19:42:20 +03:00
2015-05-14 14:38:47 +10:00
users
end
def search_ids
users = Set . new
# 1. exact username matches
if @term . present?
scoped_users . where ( username_lower : @term . downcase )
2015-11-04 23:04:37 +01:00
. limit ( @limit )
2015-05-14 14:38:47 +10:00
. pluck ( :id )
2015-11-04 23:04:37 +01:00
. each { | id | users << id }
2013-02-07 04:34:49 -05:00
2014-05-13 11:44:06 -04:00
end
2015-11-04 23:04:37 +01:00
return users . to_a if users . length > = @limit
2015-04-13 20:33:13 +05:30
2015-05-14 14:38:47 +10:00
# 2. in topic
if @topic_id
2015-11-04 23:04:37 +01:00
filtered_by_term_users . where ( 'users.id IN (SELECT p.user_id FROM posts p WHERE topic_id = ?)' , @topic_id )
2015-05-14 14:38:47 +10:00
. order ( 'last_seen_at DESC' )
. limit ( @limit - users . length )
. pluck ( :id )
2015-11-04 23:04:37 +01:00
. each { | id | users << id }
2015-04-13 20:33:13 +05:30
end
2015-11-04 23:04:37 +01:00
return users . to_a if users . length > = @limit
2015-05-14 14:38:47 +10:00
# 3. global matches
filtered_by_term_users . order ( 'last_seen_at DESC' )
. limit ( @limit - users . length )
. pluck ( :id )
2015-11-04 23:04:37 +01:00
. each { | id | users << id }
2015-05-14 14:38:47 +10:00
users . to_a
end
def search
ids = search_ids
return User . where ( " 0=1 " ) if ids . empty?
User . joins ( " JOIN (SELECT unnest uid, row_number() OVER () AS rn
FROM unnest ( '{#{ids.join(",")}}' :: int [ ] )
) x on uid = users . id " )
. order ( " rn " )
2013-02-07 04:34:49 -05:00
end
2013-10-30 15:45:13 -04:00
2013-02-10 23:37:24 +11:00
end