ordered searching to match SQL clauses, moved role&badge filtering to User.search

This commit is contained in:
MrYummy
2017-06-02 19:14:28 +02:00
parent 0d5d69ac6e
commit 887263d28e
5 changed files with 56 additions and 91 deletions

View File

@@ -67,45 +67,42 @@ class Forumthread < ActiveRecord::Base
end
def self.filter (user, title, content, reply, label, author, query, forum)
userid = user.try(:id).to_i
role = user.try(:role).to_i
order_phrase = query || [title, content, reply].select(&:present?).join(" ")
user_id = user.try(:id).to_i
role_value = user.try(:role).to_i
can_read = "COALESCE(forum_role_read.value, 0) <= ? AND COALESCE(forumgroup_role_read.value, 0) <= ?"
# A user can view sticky threads in write-only forums without read permissions.
sticky_can_write = "sticky = true AND (COALESCE(forum_role_write.value, 0) <= ? AND COALESCE(forumgroup_role_write.value, 0) <= ?)"
match = "MATCH (title, forumthreads.content) AGAINST (?) OR MATCH (threadreplies.content) AGAINST (?)"
can_read = "COALESCE(forum_role_read.value, 0) <= ? AND COALESCE(forumgroup_role_read.value, 0) <= ?"
sticky_can_write = "sticky = true AND (COALESCE(forum_role_write.value, 0) <= ? OR COALESCE(forumgroup_role_write.value, 0) <= ?)"
threads = forum.try(:forumthreads) || Forumthread
threads = forum.try(:forumthreads) || Forumthread
threads = threads.where("forumthreads.user_author_id = ? OR (#{can_read}) OR (#{sticky_can_write})", userid, role, role, role, role)
.joins("LEFT JOIN threadreplies ON forumthreads.id = threadreplies.forumthread_id")
.joins(forum: :forumgroup)
.joins("LEFT JOIN roles as forum_role_read ON forums.role_read_id = forum_role_read.id")
.joins("LEFT JOIN roles as forum_role_write ON forums.role_write_id = forum_role_write.id")
.joins("LEFT JOIN roles as forumgroup_role_read ON forumgroups.role_read_id = forumgroup_role_read.id")
.joins("LEFT JOIN roles as forumgroup_role_write ON forumgroups.role_write_id = forumgroup_role_write.id")
threads = threads.select("forumthreads.*", "(MATCH (title, forumthreads.content) AGAINST (#{Forumthread.sanitize(order_phrase)})) AS relevance", "(MATCH (threadreplies.content) AGAINST (#{Forumthread.sanitize(order_phrase)})) AS reply_rel")
if [content, title, reply, label, author, query].any?
label_o = Label.find_by(name: label)
if label_o
threads = threads.where(label: label_o)
elsif label.try(:downcase) == "no label"
threads = threads.where(label: nil)
threads = threads.joins(forum: :forumgroup)
.joins("LEFT JOIN threadreplies ON forumthreads.id = threadreplies.forumthread_id")
.joins("LEFT JOIN roles as forum_role_read ON forums.role_read_id = forum_role_read.id")
.joins("LEFT JOIN roles as forum_role_write ON forums.role_write_id = forum_role_write.id")
.joins("LEFT JOIN roles as forumgroup_role_read ON forumgroups.role_read_id = forumgroup_role_read.id")
.joins("LEFT JOIN roles as forumgroup_role_write ON forumgroups.role_write_id = forumgroup_role_write.id")
threads = threads.where("forumthreads.user_author_id = ? OR (#{can_read}) OR (#{sticky_can_write})", user_id, role_value, role_value, role_value, role_value)
if query
threads = threads.where("#{match}", query[0..99], query[0..99])
elsif [title, content, reply].any?
threads = threads.where("MATCH (title) AGAINST (?)", title[0..99]) if title
threads = threads.where("MATCH (forumthreads.content) AGAINST (?)", content[0..99]) if content
threads = threads.where("MATCH (threadreplies.content) AGAINST (?)", reply[0..99]) if reply
end
if label.try(:downcase) == "no label"
threads = threads.where(label: nil)
elsif l = Label.find_by(name: label) && label
threads = threads.where(label: l)
end
threads = threads.where(user_author: author) if author
if query
threads = threads.where("MATCH (title, forumthreads.content) AGAINST (?) OR MATCH (threadreplies.content) AGAINST (?)", query, query)
elsif [title, content, reply].any?
query = [title, content, reply].select(&:present?).join(" ")
threads = threads.where("MATCH (title) AGAINST (?)", title) if title
threads = threads.where("MATCH (forumthreads.content) AGAINST (?)", content) if content
threads = threads.where("MATCH (threadreplies.content) AGAINST (?)", reply) if reply
threads = threads.group("threadreplies.id", "forumthreads.id")
threads = threads.order("(MATCH (title, forumthreads.content) AGAINST ('#{query}')) DESC")
end
end
threads = threads.group("forumthreads.id")
threads = threads.order("sticky desc", "threadreplies.created_at desc", "forumthreads.created_at desc") if threads.order_values.empty?
threads
order_phrase.presence ? threads.order("GREATEST(relevance, reply_rel) DESC") : threads.order("sticky desc", "threadreplies.created_at DESC", "forumthreads.created_at DESC")
end
end

View File

@@ -175,7 +175,19 @@ class User < ActiveRecord::Base
self.email_token ||= SecureRandom.hex(16)
end
def self.search (users, search)
return users.where("users.name like ? OR ign like ?", "%#{User.send(:sanitize_sql_like, search)}%", "%#{User.send(:sanitize_sql_like, search)}%")
def self.search (search, role, badge)
if role
if role.downcase == "staff"
users = User.joins(:role).where("roles.value >= ?", Role.get(:mod).to_i)
elsif r = Role.get(role)
users = User.joins(:role).where(role: r)
else
end
elsif badge && b = Badge.get(badge)
users = User.joins(:badge).where(badge: b)
else
users = User.joins(:role).where.not(id: User.first.id) #Remove first user
end
return users.where("users.name like ? OR ign like ?", "%#{User.send(:sanitize_sql_like, search.to_s)}%", "%#{User.send(:sanitize_sql_like, search.to_s)}%")
end
end