discourse/app/models/user_search.rb

57 lines
2.0 KiB
Ruby

# Searches for a user by username or full text or name (if enabled in SiteSettings)
class UserSearch
def initialize(term, opts={})
@term = term
@term_like = "#{term.downcase}%"
@topic_id = opts[:topic_id]
@topic_allowed_users = opts[:topic_allowed_users]
@searching_user = opts[:searching_user]
@limit = opts[:limit] || 20
end
def search
users = User.order(User.sql_fragment("CASE WHEN username_lower = ? THEN 0 ELSE 1 END ASC", @term.downcase))
users = users.where(active: true)
if @term.present?
if SiteSetting.enable_names?
query = Search.ts_query(@term, "simple")
users = users.includes(:user_search_data)
.references(:user_search_data)
.where("username_lower LIKE :term_like OR user_search_data.search_data @@ #{query}",
term: @term, term_like: @term_like)
.order(User.sql_fragment("CASE WHEN username_lower LIKE ? THEN 0 ELSE 1 END ASC", @term_like))
else
users = users.where("username_lower LIKE :term_like", term_like: @term_like)
end
end
if @topic_id
users = users.joins(User.sql_fragment("LEFT JOIN (SELECT DISTINCT p.user_id FROM POSTS p WHERE topic_id = ?) s ON s.user_id = users.id", @topic_id))
.order("CASE WHEN s.user_id IS NULL THEN 0 ELSE 1 END DESC")
end
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"
allowed_user_ids = []
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
users.order("CASE WHEN last_seen_at IS NULL THEN 0 ELSE 1 END DESC, last_seen_at DESC, username ASC")
.limit(@limit)
end
end