2015-06-10 14:36:47 -04:00
|
|
|
require_dependency 'pinned_check'
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
class CategoryList
|
|
|
|
include ActiveModel::Serialization
|
|
|
|
|
2013-05-28 21:15:30 -04:00
|
|
|
attr_accessor :categories,
|
|
|
|
:topic_users,
|
|
|
|
:uncategorized,
|
|
|
|
:draft,
|
|
|
|
:draft_key,
|
|
|
|
:draft_sequence
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-10-17 02:44:56 -04:00
|
|
|
def initialize(guardian=nil, options = {})
|
2013-05-28 14:54:00 -04:00
|
|
|
@guardian = guardian || Guardian.new
|
2013-10-17 02:44:56 -04:00
|
|
|
@options = options
|
2013-05-28 14:54:00 -04:00
|
|
|
|
2013-10-17 02:44:56 -04:00
|
|
|
find_relevant_topics unless latest_post_only?
|
2013-05-28 14:54:00 -04:00
|
|
|
find_categories
|
2013-05-28 15:56:46 -04:00
|
|
|
|
|
|
|
prune_empty
|
2013-05-28 14:54:00 -04:00
|
|
|
find_user_data
|
2015-06-10 14:36:47 -04:00
|
|
|
sort_unpinned
|
|
|
|
trim_results
|
2013-05-28 14:54:00 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2013-10-17 02:44:56 -04:00
|
|
|
def latest_post_only?
|
2013-12-11 15:23:41 -05:00
|
|
|
@options[:latest_posts] and latest_posts_count == 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_latest_posts?
|
|
|
|
@options[:latest_posts] and latest_posts_count > 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def latest_posts_count
|
|
|
|
@options[:latest_posts].to_i > 0 ? @options[:latest_posts].to_i : SiteSetting.category_featured_topics
|
2013-10-17 02:44:56 -04:00
|
|
|
end
|
|
|
|
|
2013-05-28 14:54:00 -04:00
|
|
|
# Retrieve a list of all the topics we'll need
|
|
|
|
def find_relevant_topics
|
|
|
|
@topics_by_category_id = {}
|
|
|
|
category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
|
2014-03-12 16:33:05 -04:00
|
|
|
@topics_by_id = {}
|
2013-05-28 14:54:00 -04:00
|
|
|
|
|
|
|
@all_topics = Topic.where(id: category_featured_topics.map(&:topic_id))
|
2014-03-18 14:56:00 -04:00
|
|
|
@all_topics = @all_topics.includes(:last_poster) if include_latest_posts?
|
2013-05-28 14:54:00 -04:00
|
|
|
@all_topics.each do |t|
|
2013-12-11 15:23:41 -05:00
|
|
|
t.include_last_poster = true if include_latest_posts? # hint for serialization
|
2013-05-28 14:54:00 -04:00
|
|
|
@topics_by_id[t.id] = t
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-05-28 14:54:00 -04:00
|
|
|
category_featured_topics.each do |cft|
|
|
|
|
@topics_by_category_id[cft.category_id] ||= []
|
|
|
|
@topics_by_category_id[cft.category_id] << cft.topic_id
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-05-28 14:54:00 -04:00
|
|
|
# Find a list of all categories to associate the topics with
|
|
|
|
def find_categories
|
2014-03-12 16:33:05 -04:00
|
|
|
@categories = Category
|
2014-09-09 09:32:58 -04:00
|
|
|
.includes(:featured_users, :topic_only_relative_url, subcategories: [:topic_only_relative_url])
|
2014-03-12 16:33:05 -04:00
|
|
|
.secured(@guardian)
|
2014-05-21 10:37:37 -04:00
|
|
|
|
2014-07-02 15:10:39 -04:00
|
|
|
if @options[:parent_category_id].present?
|
|
|
|
@categories = @categories.where('categories.parent_category_id = ?', @options[:parent_category_id].to_i)
|
|
|
|
end
|
|
|
|
|
2015-09-02 14:25:18 -04:00
|
|
|
@categories = @categories.where(suppress_from_homepage: false) if @options[:is_homepage]
|
|
|
|
|
2014-05-16 11:33:44 -04:00
|
|
|
if SiteSetting.fixed_category_positions
|
|
|
|
@categories = @categories.order('position ASC').order('id ASC')
|
|
|
|
else
|
|
|
|
@categories = @categories.order('COALESCE(categories.posts_week, 0) DESC')
|
|
|
|
.order('COALESCE(categories.posts_month, 0) DESC')
|
|
|
|
.order('COALESCE(categories.posts_year, 0) DESC')
|
2014-05-21 10:37:37 -04:00
|
|
|
.order('id ASC')
|
2014-05-16 11:33:44 -04:00
|
|
|
end
|
2013-05-28 14:54:00 -04:00
|
|
|
|
2013-10-17 02:44:56 -04:00
|
|
|
if latest_post_only?
|
2015-09-07 12:52:53 -04:00
|
|
|
@categories = @categories.includes(latest_post: { topic: :last_poster })
|
2013-10-17 02:44:56 -04:00
|
|
|
end
|
|
|
|
|
2014-05-16 11:33:44 -04:00
|
|
|
@categories = @categories.to_a
|
2015-09-07 12:52:53 -04:00
|
|
|
|
2015-09-15 08:58:22 -04:00
|
|
|
category_user = {}
|
|
|
|
unless @guardian.anonymous?
|
|
|
|
category_user = Hash[*CategoryUser.where(user: @guardian.user).pluck(:category_id, :notification_level).flatten]
|
|
|
|
end
|
|
|
|
|
2015-09-07 12:52:53 -04:00
|
|
|
allowed_topic_create = Set.new(Category.topic_create_allowed(@guardian).pluck(:id))
|
|
|
|
@categories.each do |category|
|
2015-09-15 08:58:22 -04:00
|
|
|
category.notification_level = category_user[category.id]
|
2015-09-07 12:52:53 -04:00
|
|
|
category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id)
|
2015-09-15 08:58:22 -04:00
|
|
|
category.has_children = category.subcategories.present?
|
2015-09-07 12:52:53 -04:00
|
|
|
end
|
|
|
|
|
2014-07-02 15:10:39 -04:00
|
|
|
if @options[:parent_category_id].blank?
|
|
|
|
subcategories = {}
|
|
|
|
to_delete = Set.new
|
|
|
|
@categories.each do |c|
|
|
|
|
if c.parent_category_id.present?
|
|
|
|
subcategories[c.parent_category_id] ||= []
|
|
|
|
subcategories[c.parent_category_id] << c.id
|
|
|
|
to_delete << c
|
|
|
|
end
|
2013-10-31 18:02:24 -04:00
|
|
|
end
|
|
|
|
|
2014-07-02 15:10:39 -04:00
|
|
|
if subcategories.present?
|
|
|
|
@categories.each do |c|
|
|
|
|
c.subcategory_ids = subcategories[c.id]
|
|
|
|
end
|
|
|
|
@categories.delete_if {|c| to_delete.include?(c) }
|
2013-10-17 02:44:56 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-03-12 16:33:05 -04:00
|
|
|
if latest_post_only?
|
|
|
|
@all_topics = []
|
|
|
|
@categories.each do |c|
|
2014-06-16 15:11:58 -04:00
|
|
|
if c.latest_post && c.latest_post.topic && @guardian.can_see?(c.latest_post.topic)
|
2014-03-12 16:33:05 -04:00
|
|
|
c.displayable_topics = [c.latest_post.topic]
|
|
|
|
topic = c.latest_post.topic
|
|
|
|
topic.include_last_poster = true # hint for serialization
|
|
|
|
@all_topics << topic
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if @topics_by_category_id
|
|
|
|
@categories.each do |c|
|
|
|
|
topics_in_cat = @topics_by_category_id[c.id]
|
|
|
|
if topics_in_cat.present?
|
|
|
|
c.displayable_topics = []
|
|
|
|
topics_in_cat.each do |topic_id|
|
|
|
|
topic = @topics_by_id[topic_id]
|
2014-06-16 15:11:58 -04:00
|
|
|
if topic.present? && @guardian.can_see?(topic)
|
2014-11-17 00:57:52 -05:00
|
|
|
# topic.category is very slow under rails 4.2
|
|
|
|
topic.association(:category).target = c
|
2014-03-12 16:33:05 -04:00
|
|
|
c.displayable_topics << topic
|
|
|
|
end
|
2013-06-02 11:19:37 -04:00
|
|
|
end
|
2013-05-28 14:54:00 -04:00
|
|
|
end
|
|
|
|
end
|
2013-05-07 15:40:18 -04:00
|
|
|
end
|
2013-02-21 10:42:27 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2014-03-12 16:33:05 -04:00
|
|
|
|
2014-01-15 14:11:19 -05:00
|
|
|
# Remove any empty categories unless we can create them (so we can see the controls)
|
2013-05-28 14:54:00 -04:00
|
|
|
def prune_empty
|
2014-01-15 14:11:19 -05:00
|
|
|
if !@guardian.can_create?(Category)
|
2013-05-28 14:54:00 -04:00
|
|
|
# Remove categories with no featured topics unless we have the ability to edit one
|
2014-01-15 14:11:19 -05:00
|
|
|
@categories.delete_if do |c|
|
2013-10-23 19:05:51 -04:00
|
|
|
c.displayable_topics.blank? && c.description.blank?
|
2014-01-15 14:11:19 -05:00
|
|
|
end
|
|
|
|
elsif !SiteSetting.allow_uncategorized_topics
|
|
|
|
# Don't show uncategorized to admins either, if uncategorized topics are not allowed
|
|
|
|
# and there are none.
|
|
|
|
@categories.delete_if do |c|
|
|
|
|
c.uncategorized? && c.displayable_topics.blank?
|
|
|
|
end
|
2013-05-28 14:54:00 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Get forum topic user records if appropriate
|
|
|
|
def find_user_data
|
|
|
|
if @guardian.current_user && @all_topics.present?
|
|
|
|
topic_lookup = TopicUser.lookup_for(@guardian.current_user, @all_topics)
|
|
|
|
|
|
|
|
# Attach some data for serialization to each topic
|
|
|
|
@all_topics.each { |ft| ft.user_data = topic_lookup[ft.id] }
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2015-06-10 14:36:47 -04:00
|
|
|
|
|
|
|
def sort_unpinned
|
|
|
|
if @guardian.current_user && @all_topics.present?
|
|
|
|
# Put unpinned topics at the end of the list
|
|
|
|
@categories.each do |c|
|
|
|
|
next if c.displayable_topics.blank? || c.displayable_topics.size <= latest_posts_count
|
|
|
|
unpinned = []
|
|
|
|
c.displayable_topics.each do |t|
|
|
|
|
unpinned << t if t.pinned_at && PinnedCheck.unpinned?(t, t.user_data)
|
|
|
|
end
|
|
|
|
unless unpinned.empty?
|
|
|
|
c.displayable_topics = (c.displayable_topics - unpinned) + unpinned
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def trim_results
|
|
|
|
@categories.each do |c|
|
|
|
|
next if c.displayable_topics.blank?
|
|
|
|
c.displayable_topics = c.displayable_topics[0,latest_posts_count]
|
|
|
|
end
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|