2013-02-05 14:16:51 -05:00
|
|
|
require_dependency 'topic_view'
|
|
|
|
require_dependency 'promotion'
|
|
|
|
|
|
|
|
class TopicsController < ApplicationController
|
|
|
|
|
|
|
|
# Avatar is an image request, not XHR
|
2013-02-07 10:45:24 -05:00
|
|
|
before_filter :ensure_logged_in, only: [:timings,
|
|
|
|
:destroy_timings,
|
|
|
|
:update,
|
|
|
|
:star,
|
|
|
|
:destroy,
|
|
|
|
:status,
|
|
|
|
:invite,
|
|
|
|
:mute,
|
|
|
|
:unmute,
|
2013-02-05 14:16:51 -05:00
|
|
|
:set_notifications,
|
2013-03-06 15:17:07 -05:00
|
|
|
:move_posts,
|
2013-05-16 15:55:14 -04:00
|
|
|
:merge_topic,
|
2013-05-07 14:25:41 -04:00
|
|
|
:clear_pin,
|
|
|
|
:autoclose]
|
2013-03-06 15:17:07 -05:00
|
|
|
|
2013-02-10 13:50:26 -05:00
|
|
|
before_filter :consider_user_for_promotion, only: :show
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-05-29 18:01:25 -04:00
|
|
|
skip_before_filter :check_xhr, only: [:avatar, :show, :feed, :redirect_to_show]
|
2013-03-23 11:02:59 -04:00
|
|
|
caches_action :avatar, cache_path: Proc.new {|c| "#{c.params[:post_number]}-#{c.params[:topic_id]}" }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-05-29 18:01:25 -04:00
|
|
|
def redirect_to_show
|
|
|
|
topic_query = ((num = params[:id].to_i) > 0 and num.to_s == params[:id].to_s) ? Topic.where(id: num) : Topic.where(slug: params[:id])
|
|
|
|
topic = topic_query.includes(:category).first
|
|
|
|
raise Discourse::NotFound unless topic
|
|
|
|
redirect_to topic.relative_url
|
|
|
|
end
|
|
|
|
|
2013-02-10 13:50:26 -05:00
|
|
|
def show
|
2013-05-19 20:29:49 -04:00
|
|
|
opts = params.slice(:username_filters, :best_of, :page, :post_number, :posts_before, :posts_after, :best)
|
|
|
|
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)
|
|
|
|
|
2013-05-22 01:04:30 -04:00
|
|
|
raise Discourse::NotFound if @topic_view.posts.blank? && !(opts[:best].to_i > 0)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
anonymous_etag(@topic_view.topic) do
|
2013-03-04 19:42:44 -05:00
|
|
|
redirect_to_correct_topic && return if slugs_do_not_match
|
2013-02-07 10:45:24 -05:00
|
|
|
View.create_for(@topic_view.topic, request.remote_ip, current_user)
|
2013-02-10 13:50:26 -05:00
|
|
|
track_visit_to_topic
|
|
|
|
perform_show_response
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2013-02-13 06:04:43 -05:00
|
|
|
|
|
|
|
canonical_url @topic_view.canonical_path
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def destroy_timings
|
|
|
|
PostTiming.destroy_for(current_user.id, params[:topic_id].to_i)
|
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
|
|
|
def update
|
|
|
|
topic = Topic.where(id: params[:topic_id]).first
|
2013-02-07 10:45:24 -05:00
|
|
|
guardian.ensure_can_edit!(topic)
|
2013-02-05 14:16:51 -05:00
|
|
|
topic.title = params[:title] if params[:title].present?
|
|
|
|
|
|
|
|
# TODO: we may need smarter rules about converting archetypes
|
2013-02-07 10:45:24 -05:00
|
|
|
if current_user.admin?
|
2013-02-05 14:16:51 -05:00
|
|
|
topic.archetype = "regular" if params[:archetype] == 'regular'
|
|
|
|
end
|
|
|
|
|
2013-05-31 15:22:34 -04:00
|
|
|
success = false
|
2013-02-05 14:16:51 -05:00
|
|
|
Topic.transaction do
|
2013-05-31 15:22:34 -04:00
|
|
|
success = topic.save
|
|
|
|
topic.change_category(params[:category]) if success
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-04-10 05:00:50 -04:00
|
|
|
# this is used to return the title to the client as it may have been
|
|
|
|
# changed by "TextCleaner"
|
2013-05-31 15:22:34 -04:00
|
|
|
if success
|
|
|
|
render_serialized(topic, BasicTopicSerializer)
|
|
|
|
else
|
|
|
|
render_json_error(topic)
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-03-14 14:45:29 -04:00
|
|
|
def similar_to
|
2013-06-06 03:14:32 -04:00
|
|
|
params.require(:title)
|
|
|
|
params.require(:raw)
|
2013-03-14 14:45:29 -04:00
|
|
|
title, raw = params[:title], params[:raw]
|
|
|
|
|
|
|
|
raise Discourse::InvalidParameters.new(:title) if title.length < SiteSetting.min_title_similar_length
|
|
|
|
raise Discourse::InvalidParameters.new(:raw) if raw.length < SiteSetting.min_body_similar_length
|
|
|
|
|
|
|
|
topics = Topic.similar_to(title, raw)
|
|
|
|
render_serialized(topics, BasicTopicSerializer)
|
|
|
|
end
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
def status
|
2013-06-06 03:14:32 -04:00
|
|
|
params.require(:status)
|
|
|
|
params.require(:enabled)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
raise Discourse::InvalidParameters.new(:status) unless %w(visible closed pinned archived).include?(params[:status])
|
|
|
|
@topic = Topic.where(id: params[:topic_id].to_i).first
|
|
|
|
guardian.ensure_can_moderate!(@topic)
|
|
|
|
@topic.update_status(params[:status], (params[:enabled] == 'true'), current_user)
|
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
|
|
|
def star
|
|
|
|
@topic = Topic.where(id: params[:topic_id].to_i).first
|
|
|
|
guardian.ensure_can_see!(@topic)
|
|
|
|
|
|
|
|
@topic.toggle_star(current_user, params[:starred] == 'true')
|
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
2013-02-07 10:45:24 -05:00
|
|
|
def mute
|
2013-02-05 14:16:51 -05:00
|
|
|
toggle_mute(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
def unmute
|
|
|
|
toggle_mute(false)
|
|
|
|
end
|
|
|
|
|
2013-05-07 14:25:41 -04:00
|
|
|
def autoclose
|
2013-06-06 03:14:32 -04:00
|
|
|
raise Discourse::InvalidParameters.new(:auto_close_days) unless params.has_key?(:auto_close_days)
|
2013-05-07 14:25:41 -04:00
|
|
|
@topic = Topic.where(id: params[:topic_id].to_i).first
|
|
|
|
guardian.ensure_can_moderate!(@topic)
|
|
|
|
@topic.auto_close_days = params[:auto_close_days]
|
|
|
|
@topic.auto_close_user = current_user
|
|
|
|
@topic.save
|
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
def destroy
|
|
|
|
topic = Topic.where(id: params[:id]).first
|
|
|
|
guardian.ensure_can_delete!(topic)
|
2013-05-07 00:39:01 -04:00
|
|
|
topic.trash!
|
2013-02-05 14:16:51 -05:00
|
|
|
render nothing: true
|
|
|
|
end
|
2013-02-07 10:45:24 -05:00
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
def excerpt
|
2013-02-07 10:45:24 -05:00
|
|
|
render nothing: true
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def invite
|
2013-06-06 03:14:32 -04:00
|
|
|
params.require(:user)
|
2013-02-05 14:16:51 -05:00
|
|
|
topic = Topic.where(id: params[:topic_id]).first
|
|
|
|
guardian.ensure_can_invite_to!(topic)
|
|
|
|
|
2013-02-07 10:45:24 -05:00
|
|
|
if topic.invite(current_user, params[:user])
|
2013-02-05 14:16:51 -05:00
|
|
|
render json: success_json
|
|
|
|
else
|
|
|
|
render json: failed_json, status: 422
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def set_notifications
|
|
|
|
topic = Topic.find(params[:topic_id].to_i)
|
|
|
|
TopicUser.change(current_user, topic.id, notification_level: params[:notification_level].to_i)
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
2013-05-16 15:55:14 -04:00
|
|
|
def merge_topic
|
2013-06-06 03:14:32 -04:00
|
|
|
params.require(:destination_topic_id)
|
2013-05-16 15:55:14 -04:00
|
|
|
|
|
|
|
topic = Topic.where(id: params[:topic_id]).first
|
|
|
|
guardian.ensure_can_move_posts!(topic)
|
|
|
|
|
|
|
|
dest_topic = topic.move_posts(current_user, topic.posts.pluck(:id), destination_topic_id: params[:destination_topic_id].to_i)
|
|
|
|
if dest_topic.present?
|
|
|
|
render json: {success: true, url: dest_topic.relative_url}
|
|
|
|
else
|
|
|
|
render json: {success: false}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
def move_posts
|
2013-06-06 03:14:32 -04:00
|
|
|
params.require(:post_ids)
|
2013-05-08 13:33:58 -04:00
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
topic = Topic.where(id: params[:topic_id]).first
|
|
|
|
guardian.ensure_can_move_posts!(topic)
|
|
|
|
|
2013-05-08 13:33:58 -04:00
|
|
|
args = {}
|
|
|
|
args[:title] = params[:title] if params[:title].present?
|
|
|
|
args[:destination_topic_id] = params[:destination_topic_id].to_i if params[:destination_topic_id].present?
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-05-08 13:33:58 -04:00
|
|
|
dest_topic = topic.move_posts(current_user, params[:post_ids].map {|p| p.to_i}, args)
|
|
|
|
if dest_topic.present?
|
|
|
|
render json: {success: true, url: dest_topic.relative_url}
|
2013-02-05 14:16:51 -05:00
|
|
|
else
|
|
|
|
render json: {success: false}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-06 15:17:07 -05:00
|
|
|
def clear_pin
|
|
|
|
topic = Topic.where(id: params[:topic_id].to_i).first
|
|
|
|
guardian.ensure_can_see!(topic)
|
|
|
|
topic.clear_pin_for(current_user)
|
|
|
|
render nothing: true
|
|
|
|
end
|
2013-02-25 18:38:11 -05:00
|
|
|
|
2013-03-06 15:17:07 -05:00
|
|
|
def timings
|
2013-02-25 02:42:42 -05:00
|
|
|
PostTiming.process_timings(
|
2013-03-06 15:17:07 -05:00
|
|
|
current_user,
|
|
|
|
params[:topic_id].to_i,
|
|
|
|
params[:topic_time].to_i,
|
|
|
|
(params[:timings] || []).map{|post_number, t| [post_number.to_i, t.to_i]}
|
2013-02-25 02:42:42 -05:00
|
|
|
)
|
2013-02-05 14:16:51 -05:00
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
2013-02-21 13:20:00 -05:00
|
|
|
def feed
|
|
|
|
@topic_view = TopicView.new(params[:topic_id])
|
2013-03-01 16:56:14 -05:00
|
|
|
anonymous_etag(@topic_view.topic) do
|
|
|
|
render 'topics/show', formats: [:rss]
|
|
|
|
end
|
2013-02-21 13:20:00 -05:00
|
|
|
end
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
private
|
|
|
|
|
2013-02-10 13:50:26 -05:00
|
|
|
def toggle_mute(v)
|
|
|
|
@topic = Topic.where(id: params[:topic_id].to_i).first
|
|
|
|
guardian.ensure_can_see!(@topic)
|
|
|
|
|
2013-05-24 02:06:38 -04:00
|
|
|
@topic.toggle_mute(current_user)
|
2013-02-10 13:50:26 -05:00
|
|
|
render nothing: true
|
|
|
|
end
|
|
|
|
|
|
|
|
def consider_user_for_promotion
|
|
|
|
Promotion.new(current_user).review if current_user.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def slugs_do_not_match
|
|
|
|
params[:slug] && @topic_view.topic.slug != params[:slug]
|
|
|
|
end
|
|
|
|
|
|
|
|
def redirect_to_correct_topic
|
|
|
|
fullpath = request.fullpath
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-02-10 13:50:26 -05:00
|
|
|
split = fullpath.split('/')
|
|
|
|
split[2] = @topic_view.topic.slug
|
|
|
|
|
|
|
|
redirect_to split.join('/'), status: 301
|
|
|
|
end
|
|
|
|
|
|
|
|
def track_visit_to_topic
|
|
|
|
return unless should_track_visit_to_topic?
|
|
|
|
TopicUser.track_visit! @topic_view.topic, current_user
|
|
|
|
@topic_view.draft = Draft.get(current_user, @topic_view.draft_key, @topic_view.draft_sequence)
|
|
|
|
end
|
|
|
|
|
|
|
|
def should_track_visit_to_topic?
|
|
|
|
(!request.xhr? || params[:track_visit]) && current_user
|
|
|
|
end
|
|
|
|
|
|
|
|
def perform_show_response
|
|
|
|
topic_view_serializer = TopicViewSerializer.new(@topic_view, scope: guardian, root: false)
|
|
|
|
respond_to do |format|
|
|
|
|
format.html do
|
|
|
|
store_preloaded("topic_#{@topic_view.topic.id}", MultiJson.dump(topic_view_serializer))
|
|
|
|
end
|
|
|
|
|
|
|
|
format.json do
|
|
|
|
render_json_dump(topic_view_serializer)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|