summaryrefslogtreecommitdiff
path: root/app/controllers/topics_controller.rb
blob: fc60c325ebfe253fc15af9ce09a6cb2df97a2110 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true

class TopicsController < ApplicationController
  before_action :load_forum, only: [:create, :new]
  before_action :load_forum_and_topic, except: [:create, :new]
  before_action :filter_banned_users, only: [:create]

  def show
    authorize! :read, @topic
    @title = "#{@topic.title} - #{@forum.name} - Forums"
    if params[:post_id]
      # Find which page this post is on, and set params[:page] appropriately
      post_to_find = ForumPost.find_by(id: params[:post_id])
      params[:page] = @topic.page_for_post(post_to_find.id) rescue nil
      params[:post_id] = nil
    end
    @topic.increment!(:view_count)

    # Mark topic-related notifications as read, including notifications about
    # creation.
    if current_user
      Notification.mark_all_read(@topic, current_user)
      creation_notice = Notification.find_by(
        actor: @forum, actor_child: @topic
      )
      Notification.mark_read(creation_notice, current_user) if creation_notice
    end

    page = params[:page].to_i
    page = 1 if page < 1

    @posts =
      @topic
      .posts
      .where('topic_position >= ?', 25 * (page - 1))
      .where('topic_position < ?', 25 * page)
      .order(created_at: :asc, id: :asc)
      .includes(:user, topic: :forum)
      .limit(25)
      .to_a

    @posts = Kaminari.paginate_array(@posts, offset: 25 * (page - 1), limit: 25, total_count: @topic.post_count)

    @post = @topic.posts.build
    respond_to do |format|
      format.html
      format.json { render json: @posts }
    end
  end

  def new
    @topic = Topic.new
    @topic.forum = @forum
    @topic.posts.build
    @topic.build_poll
    @title = "New Topic in #{@forum.name}"
    authorize! :create, @topic
    redirect_back flash: { error: 'You need an account to create topics.' } if !current_user
  end

  def create
    @topic = Topic.new
    @topic.forum = @forum
    authorize! :create, @topic
    @topic.user = current_user
    if !current_user
      respond_to do |format|
        flash[:error] = 'Topic creation requires being logged in to an account.'
        format.html { redirect_to(forum_path(@forum)) }
        format.json { render head: :error }
      end
      return
    end
    if @topic.update(topic_params)
      # Create first post
      post = @topic.posts.order(created_at: :asc).first
      post.assign_attributes(request_attributes)
      post.anonymous = @topic.anonymous
      post.topic_position = 0
      if post.user
        inc_user_stat :forum_posts
        post.name_at_post_time = @topic.user.name
      end
      post.save!
      post.update_index(defer: false)
      ForumPost.__elasticsearch__.refresh_index! # nasty hack

      Notification.watch(@topic, current_user) if current_user && current_user.watch_on_new_topic
      # NewTopicLogger.log(@topic) if @forum.access_level == 'normal'
      respond_to do |format|
        format.html { redirect_to short_topic_path(@forum, @topic) }
        format.json { render head: :ok }
      end
    else
      respond_to do |format|
        format.html { render action: 'new', error: 'Whoops, something went wrong - look at the form below for more info' }
        format.json { render json: 'Error creating topic' }
      end
    end
  end

  def show_last_page
    authorize! :read, @topic
    page = @topic.page_for_post(@topic.last_post_id) rescue nil
    if page
      redirect_to url_for(controller: 'topics', action: 'show', forum_id: @forum[:short_name], id: @topic[:slug], page: page.to_s)
    else
      redirect_to short_topic_path(@topic)
    end
  end

  private

  def load_forum
    @forum = Forum.find_by!(short_name: params[:forum_id])
  end

  def load_forum_and_topic
    load_forum
    @topic = @forum.topics.find_by!(slug: params[:id])
  end

  def topic_params
    params.require(:topic).permit(
      :title,
      :anonymous,
      posts_attributes: [:body, :anonymous],
      poll_attributes:  Poll::POLL_ATTRIBUTES
    )
  end
end