133 lines
4.2 KiB
Ruby
133 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module KnowledgeExplorer
|
|
class Query
|
|
def initialize(user = nil, filters = {})
|
|
@user = user
|
|
@filters = filters
|
|
@limit = 30
|
|
end
|
|
|
|
def self.categories
|
|
SiteSetting.knowledge_explorer_categories.split('|')
|
|
end
|
|
|
|
def self.tags
|
|
SiteSetting.knowledge_explorer_tags.split('|')
|
|
end
|
|
|
|
def list
|
|
# query for topics matching selected categories & tags
|
|
tq = TopicQuery.new(@user)
|
|
results = tq.latest_results(no_definitions: true, limit: false)
|
|
results = results.left_outer_joins(:tags)
|
|
results = results.where('category_id IN (?)', Query.categories).or(results.where('tags.name IN (?)', Query.tags))
|
|
|
|
# filter results by selected category
|
|
if @filters[:category].present?
|
|
results = results.where('category_id IN (?)', @filters[:category].split('|'))
|
|
end
|
|
|
|
# filter results by selected tags
|
|
if @filters[:tags].present?
|
|
tag_filters = @filters[:tags].split('|')
|
|
tags_count = tag_filters.length
|
|
tag_filters = Tag.where_name(tag_filters).pluck(:id) unless Integer === tag_filters[0]
|
|
|
|
if tags_count == tag_filters.length
|
|
tag_filters.each_with_index do |tag, index|
|
|
sql_alias = ['t', index].join
|
|
results = results.joins("INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}")
|
|
end
|
|
else
|
|
results = results.none # don't return any results unless all tags exist in the database
|
|
end
|
|
end
|
|
|
|
# filter results by search term
|
|
if @filters[:search_term].present?
|
|
results = results.where('lower(title) LIKE ?', "%#{@filters[:search_term].downcase}%")
|
|
end
|
|
|
|
tags = tag_count(results)
|
|
categories = categories_count(results)
|
|
|
|
results_length = results.length
|
|
|
|
if @filters[:page]
|
|
offset = @filters[:page].to_i * @limit
|
|
page_range = offset + @limit
|
|
end_of_list = true if page_range > results_length
|
|
else
|
|
offset = 0
|
|
page_range = @limit
|
|
end
|
|
|
|
results = results[offset...page_range]
|
|
|
|
# assemble the object
|
|
topic_query = tq.create_list(:knowledge_explorer, { unordered: true }, results)
|
|
|
|
topic_list = TopicListSerializer.new(topic_query, scope: Guardian.new(@user)).as_json
|
|
|
|
if end_of_list.nil?
|
|
topic_list['load_more_url'] = load_more_url
|
|
else
|
|
topic_list['load_more_url'] = nil
|
|
end
|
|
|
|
{ tags: tags, categories: categories, topics: topic_list }
|
|
end
|
|
|
|
def tag_count(results)
|
|
tags = []
|
|
|
|
results.each do |topic|
|
|
topic.tags.each do |tag|
|
|
active = @filters[:tags].include?(tag.name) if @filters[:tags]
|
|
if tags.none? { |item| item[:id].to_s == tag.name }
|
|
tags << { id: tag.name, count: 1, active: active || false }
|
|
else
|
|
tag_index = tags.index(tags.find { |item| item[:id].to_s == tag.name })
|
|
tags[tag_index][:count] += 1
|
|
end
|
|
end
|
|
end
|
|
|
|
tags.sort_by { |tag| [tag[:active] ? 0 : 1, -tag[:count]] }
|
|
end
|
|
|
|
def categories_count(results)
|
|
categories = []
|
|
|
|
results.each do |topic|
|
|
active = @filters[:category].include?(topic.category_id.to_s) if @filters[:category]
|
|
if categories.none? { |item| item[:id] == topic.category_id }
|
|
categories << { id: topic.category_id, count: 1, active: active || false }
|
|
else
|
|
category_index = categories.index(categories.find { |item| item[:id] == topic.category_id })
|
|
categories[category_index][:count] += 1
|
|
end
|
|
end
|
|
|
|
categories.sort_by { |category| [category[:active] ? 0 : 1, -category[:count]] }
|
|
end
|
|
|
|
def load_more_url
|
|
filters = []
|
|
|
|
filters.push("tags=#{@filters[:tags]}") if @filters[:tags].present?
|
|
filters.push("category=#{@filters[:category]}") if @filters[:category].present?
|
|
filters.push("search=#{@filters[:search_term]}") if @filters[:search_term].present?
|
|
|
|
if @filters[:page].present?
|
|
filters.push("page=#{@filters[:page].to_i + 1}")
|
|
else
|
|
filters.push('page=1')
|
|
end
|
|
|
|
"/knowledge-explorer.json?#{filters.join('&')}"
|
|
end
|
|
end
|
|
end
|