2015-01-08 16:44:27 -05:00
require_dependency 'topic_list_responder'
2013-02-05 14:16:51 -05:00
class ListController < ApplicationController
2015-01-08 16:44:27 -05:00
include TopicListResponder
2013-02-05 14:16:51 -05:00
2014-01-17 23:52:06 +01:00
skip_before_filter :check_xhr
@@categories = [
# filtered topics lists
2014-02-03 16:08:00 +01:00
Discourse . filters . map { | f | " category_ #{ f } " . to_sym } ,
Discourse . filters . map { | f | " category_none_ #{ f } " . to_sym } ,
Discourse . filters . map { | f | " parent_category_category_ #{ f } " . to_sym } ,
Discourse . filters . map { | f | " parent_category_category_none_ #{ f } " . to_sym } ,
# top summaries
:category_top ,
:category_none_top ,
:parent_category_category_top ,
2014-01-17 23:52:06 +01:00
# top pages (ie. with a period)
2014-02-03 16:08:00 +01:00
TopTopic . periods . map { | p | " category_top_ #{ p } " . to_sym } ,
TopTopic . periods . map { | p | " category_none_top_ #{ p } " . to_sym } ,
TopTopic . periods . map { | p | " parent_category_category_top_ #{ p } " . to_sym } ,
2014-01-17 23:52:06 +01:00
# category feeds
:category_feed ,
] . flatten
before_filter :set_category , only : @@categories
2014-01-14 01:02:14 +01:00
before_filter :ensure_logged_in , except : [
:topics_by ,
# anonymous filters
2014-01-17 23:52:06 +01:00
Discourse . anonymous_filters ,
Discourse . anonymous_filters . map { | f | " #{ f } _feed " . to_sym } ,
2014-04-04 10:05:40 -07:00
# anonymous categorized filters
Discourse . anonymous_filters . map { | f | " category_ #{ f } " . to_sym } ,
Discourse . anonymous_filters . map { | f | " category_none_ #{ f } " . to_sym } ,
Discourse . anonymous_filters . map { | f | " parent_category_category_ #{ f } " . to_sym } ,
Discourse . anonymous_filters . map { | f | " parent_category_category_none_ #{ f } " . to_sym } ,
# category feeds
:category_feed ,
# top summaries
2014-01-17 23:52:06 +01:00
:top ,
2014-04-04 10:05:40 -07:00
:category_top ,
:category_none_top ,
:parent_category_category_top ,
# top pages (ie. with a period)
TopTopic . periods . map { | p | " top_ #{ p } " . to_sym } ,
TopTopic . periods . map { | p | " category_top_ #{ p } " . to_sym } ,
TopTopic . periods . map { | p | " category_none_top_ #{ p } " . to_sym } ,
TopTopic . periods . map { | p | " parent_category_category_top_ #{ p } " . to_sym } ,
2014-01-14 01:02:14 +01:00
] . flatten
2013-02-05 14:16:51 -05:00
# Create our filters
2015-03-30 11:40:44 -04:00
Discourse . filters . each_with_index do | filter , idx |
2014-01-17 23:52:06 +01:00
define_method ( filter ) do | options = nil |
2013-06-19 19:11:14 -07:00
list_opts = build_topic_list_options
2014-01-17 23:52:06 +01:00
list_opts . merge! ( options ) if options
2013-08-24 19:38:02 +02:00
user = list_target_user
2014-02-11 10:06:20 +11:00
if filter == :latest && params [ :category ] . blank?
list_opts [ :no_definitions ] = true
end
2013-08-22 09:18:54 +10:00
list = TopicQuery . new ( user , list_opts ) . public_send ( " list_ #{ filter } " )
2015-02-13 19:34:22 +08:00
list . more_topics_url = construct_url_with ( :next , list_opts )
list . prev_topics_url = construct_url_with ( :prev , list_opts )
2013-12-24 00:50:36 +01:00
if Discourse . anonymous_filters . include? ( filter )
2013-10-11 18:35:12 +02:00
@description = SiteSetting . site_description
@rss = filter
2014-10-30 14:26:35 -04:00
2015-03-30 11:40:44 -04:00
# Note the first is the default and we don't add a title
2015-06-08 12:07:35 -04:00
if ( filter . to_s != current_homepage ) && use_crawler_layout?
2015-07-29 15:39:20 +02:00
filter_title = I18n . t ( " js.filters. #{ filter . to_s } .title " , count : 0 )
2014-10-30 14:26:35 -04:00
if list_opts [ :category ]
@title = I18n . t ( 'js.filters.with_category' , filter : filter_title , category : Category . find ( list_opts [ :category ] ) . name )
else
@title = I18n . t ( 'js.filters.with_topics' , filter : filter_title )
end
end
2013-10-11 18:35:12 +02:00
end
2014-10-30 14:26:35 -04:00
2015-01-08 16:44:27 -05:00
respond_with_list ( list )
2013-02-07 16:45:24 +01:00
end
2014-01-17 23:52:06 +01:00
2014-02-03 16:08:00 +01:00
define_method ( " category_ #{ filter } " ) do
2015-02-25 20:46:45 +05:30
canonical_url " #{ Discourse . base_url } #{ @category . url } "
2014-01-17 23:52:06 +01:00
self . send ( filter , { category : @category . id } )
end
2014-02-03 16:08:00 +01:00
define_method ( " category_none_ #{ filter } " ) do
2014-01-17 23:52:06 +01:00
self . send ( filter , { category : @category . id , no_subcategories : true } )
end
2014-02-03 16:08:00 +01:00
define_method ( " parent_category_category_ #{ filter } " ) do
2015-02-25 20:46:45 +05:30
canonical_url " #{ Discourse . base_url } #{ @category . url } "
2014-02-03 16:08:00 +01:00
self . send ( filter , { category : @category . id } )
end
define_method ( " parent_category_category_none_ #{ filter } " ) do
self . send ( filter , { category : @category . id } )
end
2013-02-05 14:16:51 -05:00
end
2014-09-11 15:30:10 -04:00
Discourse . feed_filters . each do | filter |
2013-07-05 16:49:06 -04:00
define_method ( " #{ filter } _feed " ) do
2013-10-16 16:39:18 +11:00
discourse_expires_in 1 . minute
2014-05-05 09:33:19 -07:00
@title = " #{ SiteSetting . title } - #{ I18n . t ( " rss_description. #{ filter } " ) } "
2013-10-16 16:39:18 +11:00
@link = " #{ Discourse . base_url } / #{ filter } "
@description = I18n . t ( " rss_description. #{ filter } " )
@atom_link = " #{ Discourse . base_url } / #{ filter } .rss "
2014-08-27 12:42:54 -04:00
@topic_list = TopicQuery . new ( nil , order : 'created' ) . public_send ( " list_ #{ filter } " )
2013-12-24 00:50:36 +01:00
2013-10-16 16:39:18 +11:00
render 'list' , formats : [ :rss ]
2013-07-05 16:49:06 -04:00
end
end
2013-10-19 18:51:17 +05:30
[ :topics_by , :private_messages , :private_messages_sent , :private_messages_unread ] . each do | action |
define_method ( " #{ action } " ) do
list_opts = build_topic_list_options
target_user = fetch_user_from_params
guardian . ensure_can_see_private_messages! ( target_user . id ) unless action == :topics_by
list = generate_list_for ( action . to_s , target_user , list_opts )
url_prefix = " topics " unless action == :topics_by
2015-02-13 19:34:22 +08:00
list . more_topics_url = url_for ( construct_url_with ( :next , list_opts , url_prefix ) )
list . prev_topics_url = url_for ( construct_url_with ( :prev , list_opts , url_prefix ) )
2015-01-08 16:44:27 -05:00
respond_with_list ( list )
2013-10-19 18:51:17 +05:30
end
2013-08-30 12:32:05 -04:00
end
2013-02-27 19:36:12 -08:00
def category_feed
guardian . ensure_can_see! ( @category )
2013-10-16 16:39:18 +11:00
discourse_expires_in 1 . minute
@title = @category . name
2015-02-05 13:22:28 +05:30
@link = " #{ Discourse . base_url } #{ @category . url } "
2013-10-16 16:39:18 +11:00
@description = " #{ I18n . t ( 'topics_in_category' , category : @category . name ) } #{ @category . description } "
2015-02-05 13:22:28 +05:30
@atom_link = " #{ Discourse . base_url } #{ @category . url } .rss "
2013-10-16 16:39:18 +11:00
@topic_list = TopicQuery . new . list_new_in_category ( @category )
2014-01-17 23:52:06 +01:00
2013-10-16 16:39:18 +11:00
render 'list' , formats : [ :rss ]
2013-02-27 19:36:12 -08:00
end
2014-11-24 23:10:33 +05:30
2014-08-28 14:34:31 -04:00
def top ( options = nil )
options || = { }
period = ListController . best_period_for ( current_user . try ( :previous_visit_at ) , options [ :category ] )
send ( " top_ #{ period } " , options )
2013-12-24 00:50:36 +01:00
end
2014-02-03 16:08:00 +01:00
def category_top
2014-08-28 14:34:31 -04:00
top ( { category : @category . id } )
2014-01-17 23:52:06 +01:00
end
2014-02-03 16:08:00 +01:00
def category_none_top
2014-08-28 14:34:31 -04:00
top ( { category : @category . id , no_subcategories : true } )
2014-01-17 23:52:06 +01:00
end
2014-02-03 16:08:00 +01:00
def parent_category_category_top
2014-08-28 14:34:31 -04:00
top ( { category : @category . id } )
2014-02-03 16:08:00 +01:00
end
2014-01-14 01:02:14 +01:00
TopTopic . periods . each do | period |
2014-01-17 23:52:06 +01:00
define_method ( " top_ #{ period } " ) do | options = nil |
top_options = build_topic_list_options
top_options . merge! ( options ) if options
top_options [ :per_page ] = SiteSetting . topics_per_period_in_top_page
2014-01-14 01:02:14 +01:00
user = list_target_user
2014-05-07 19:04:39 +02:00
list = TopicQuery . new ( user , top_options ) . list_top_for ( period )
2014-08-28 14:34:31 -04:00
list . for_period = period
2015-02-13 19:34:22 +08:00
list . more_topics_url = construct_url_with ( :next , top_options )
list . prev_topics_url = construct_url_with ( :prev , top_options )
2014-10-30 14:26:35 -04:00
if use_crawler_layout?
@title = I18n . t ( " js.filters.top. #{ period } .title " )
end
2015-01-08 16:44:27 -05:00
respond_with_list ( list )
2014-01-14 01:02:14 +01:00
end
2014-02-03 16:08:00 +01:00
define_method ( " category_top_ #{ period } " ) do
2014-01-17 23:52:06 +01:00
self . send ( " top_ #{ period } " , { category : @category . id } )
end
2013-02-05 14:16:51 -05:00
2014-02-03 16:08:00 +01:00
define_method ( " category_none_top_ #{ period } " ) do
2014-01-17 23:52:06 +01:00
self . send ( " top_ #{ period } " , { category : @category . id , no_subcategories : true } )
end
2014-02-03 16:08:00 +01:00
2014-08-28 14:34:31 -04:00
define_method ( " parent_category_category_top_ #{ period } " ) do
2014-02-03 16:08:00 +01:00
self . send ( " top_ #{ period } " , { category : @category . id } )
end
2013-12-13 17:18:28 -05:00
end
2014-01-17 23:52:06 +01:00
protected
2014-02-03 16:08:00 +01:00
def next_page_params ( opts = nil )
2014-02-25 12:15:20 -05:00
page_params ( opts ) . merge ( page : params [ :page ] . to_i + 1 )
end
def prev_page_params ( opts = nil )
2014-03-03 12:56:37 -05:00
pg = params [ :page ] . to_i
if pg > 1
page_params ( opts ) . merge ( page : pg - 1 )
else
page_params ( opts ) . merge ( page : nil )
end
2014-02-25 12:15:20 -05:00
end
private
def page_params ( opts = nil )
2014-02-03 16:08:00 +01:00
opts || = { }
2014-02-25 12:15:20 -05:00
route_params = { format : 'json' }
2014-03-24 13:36:23 -04:00
route_params [ :category ] = @category . slug_for_url if @category
route_params [ :parent_category ] = @category . parent_category . slug_for_url if @category && @category . parent_category
2014-04-16 12:05:54 -04:00
route_params [ :order ] = opts [ :order ] if opts [ :order ] . present?
route_params [ :ascending ] = opts [ :ascending ] if opts [ :ascending ] . present?
2013-11-14 12:35:18 -05:00
route_params
2013-02-05 14:16:51 -05:00
end
2013-06-19 19:11:14 -07:00
def set_category
2014-01-17 04:38:08 +01:00
slug_or_id = params . fetch ( :category )
parent_slug_or_id = params [ :parent_category ]
2013-10-23 14:40:39 -04:00
parent_category_id = nil
2014-01-17 15:32:23 +01:00
if parent_slug_or_id . present?
2014-02-08 14:10:48 -08:00
parent_category_id = Category . query_parent_category ( parent_slug_or_id )
2015-05-07 11:00:51 +10:00
raise Discourse :: NotFound if parent_category_id . blank?
2013-10-23 14:40:39 -04:00
end
2014-02-08 14:10:48 -08:00
@category = Category . query_category ( slug_or_id , parent_category_id )
2015-05-07 11:00:51 +10:00
raise Discourse :: NotFound if ! @category
2014-02-08 14:10:48 -08:00
2015-08-14 10:00:07 +08:00
@description_meta = @category . description_text
2014-02-05 15:33:52 -05:00
guardian . ensure_can_see! ( @category )
2013-06-19 19:11:14 -07:00
end
def build_topic_list_options
# exclude_category = 1. from params / 2. parsed from top menu / 3. nil
2014-01-17 04:38:08 +01:00
options = {
2013-06-19 19:11:14 -07:00
page : params [ :page ] ,
topic_ids : param_to_integer_list ( :topic_ids ) ,
2014-02-03 16:08:00 +01:00
exclude_category : ( params [ :exclude_category ] || select_menu_item . try ( :filter ) ) ,
2013-11-11 19:35:57 -05:00
category : params [ :category ] ,
2014-04-16 12:05:54 -04:00
order : params [ :order ] ,
ascending : params [ :ascending ] ,
2014-06-05 15:30:24 +02:00
min_posts : params [ :min_posts ] ,
max_posts : params [ :max_posts ] ,
2014-05-16 00:31:45 +10:00
status : params [ :status ] ,
2015-01-07 18:20:10 +11:00
filter : params [ :filter ] ,
2014-07-17 09:29:09 +10:00
state : params [ :state ] ,
2015-06-22 18:09:08 +10:00
search : params [ :search ] ,
q : params [ :q ]
2013-06-19 19:11:14 -07:00
}
2014-01-17 04:38:08 +01:00
options [ :no_subcategories ] = true if params [ :no_subcategories ] == 'true'
2014-12-15 11:54:26 -05:00
options [ :slow_platform ] = true if slow_platform?
2014-01-17 04:38:08 +01:00
options
2013-06-19 19:11:14 -07:00
end
2013-08-24 19:38:02 +02:00
2014-02-03 16:08:00 +01:00
def select_menu_item
menu_item = SiteSetting . top_menu_items . select do | mu |
( mu . has_specific_category? && mu . specific_category == @category . try ( :slug ) ) ||
action_name == mu . name ||
( action_name . include? ( " top " ) && mu . name == " top " )
end . first
menu_item = nil if menu_item . try ( :has_specific_category? ) && menu_item . specific_category == @category . try ( :slug )
menu_item
end
2013-08-24 19:38:02 +02:00
def list_target_user
if params [ :user_id ] && guardian . is_staff?
User . find ( params [ :user_id ] . to_i )
else
current_user
end
end
2013-10-19 18:51:17 +05:30
def generate_list_for ( action , target_user , opts )
2013-11-14 12:35:18 -05:00
TopicQuery . new ( current_user , opts ) . send ( " list_ #{ action } " , target_user )
2013-10-19 18:51:17 +05:30
end
2015-02-13 19:34:22 +08:00
def construct_url_with ( action , opts , url_prefix = nil )
2014-02-03 16:08:00 +01:00
method = url_prefix . blank? ? " #{ action_name } _path " : " #{ url_prefix } _ #{ action_name } _path "
2015-02-13 19:34:22 +08:00
url = if action == :prev
public_send ( method , opts . merge ( prev_page_params ( opts ) ) )
else # :next
public_send ( method , opts . merge ( next_page_params ( opts ) ) )
end
url . sub ( '.json?' , '?' )
2014-02-25 12:15:20 -05:00
end
2014-01-16 00:49:58 +01:00
def generate_top_lists ( options )
2014-02-06 11:39:43 +01:00
top = TopLists . new
2014-01-16 00:49:58 +01:00
options [ :per_page ] = SiteSetting . topics_per_period_in_top_summary
2014-01-14 01:02:14 +01:00
topic_query = TopicQuery . new ( current_user , options )
2014-01-15 21:45:28 +01:00
2014-08-20 17:37:28 -04:00
periods = [ ListController . best_period_for ( current_user . try ( :previous_visit_at ) , options [ :category ] ) ]
2014-01-14 01:02:14 +01:00
2014-02-06 11:39:43 +01:00
periods . each { | period | top . send ( " #{ period } = " , topic_query . list_top_for ( period ) ) }
2013-12-24 00:50:36 +01:00
top
end
2014-05-14 11:49:50 +02:00
def self . best_period_for ( previous_visit_at , category_id = nil )
best_periods_for ( previous_visit_at ) . each do | period |
top_topics = TopTopic . where ( " #{ period } _score > 0 " )
if category_id
top_topics = top_topics . joins ( :topic ) . where ( " topics.category_id = ? " , category_id )
end
return period if top_topics . count > = SiteSetting . topics_per_period_in_top_page
2014-05-07 19:04:39 +02:00
end
# default period is yearly
:yearly
end
def self . best_periods_for ( date )
2014-01-16 01:36:32 +01:00
date || = 1 . year . ago
2014-05-07 19:04:39 +02:00
periods = [ ]
periods << :daily if date > 8 . days . ago
periods << :weekly if date > 35 . days . ago
periods << :monthly if date > 180 . days . ago
periods << :yearly
periods
2014-01-14 01:02:14 +01:00
end
2013-02-05 14:16:51 -05:00
end