messages_controller.rb 4.76 KB
Newer Older
1
# Redmine - project management software
jplang's avatar
jplang committed
2
# Copyright (C) 2006-2016  Jean-Philippe Lang
jplang's avatar
jplang committed
3 4 5 6 7
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
8
#
jplang's avatar
jplang committed
9 10 11 12
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
13
#
jplang's avatar
jplang committed
14 15 16 17 18
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

class MessagesController < ApplicationController
19
  menu_item :boards
jplang's avatar
jplang committed
20
  default_search_scope :messages
21 22 23 24
  before_action :find_board, :only => [:new, :preview]
  before_action :find_attachments, :only => [:preview]
  before_action :find_message, :except => [:new, :preview]
  before_action :authorize, :except => [:preview, :edit, :destroy]
jplang's avatar
jplang committed
25

jplang's avatar
jplang committed
26
  helper :boards
27
  helper :watchers
28
  helper :attachments
29
  include AttachmentsHelper
30

31
  REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)
32

jplang's avatar
jplang committed
33
  # Show a topic and its replies
jplang's avatar
jplang committed
34
  def show
35 36 37
    page = params[:page]
    # Find the page of the requested reply
    if params[:r] && page.nil?
38
      offset = @topic.children.where("#{Message.table_name}.id < ?", params[:r].to_i).count
39 40
      page = 1 + offset / REPLIES_PER_PAGE
    end
41

42
    @reply_count = @topic.children.count
jplang's avatar
jplang committed
43
    @reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
jplang's avatar
jplang committed
44 45
    @replies =  @topic.children.
      includes(:author, :attachments, {:board => :project}).
jplang's avatar
jplang committed
46
      reorder("#{Message.table_name}.created_on ASC, #{Message.table_name}.id ASC").
47
      limit(@reply_pages.per_page).
jplang's avatar
jplang committed
48
      offset(@reply_pages.offset).
jplang's avatar
jplang committed
49
      to_a
50

jplang's avatar
jplang committed
51 52 53
    @reply = Message.new(:subject => "RE: #{@message.subject}")
    render :action => "show", :layout => false if request.xhr?
  end
54

jplang's avatar
jplang committed
55
  # Create a new topic
jplang's avatar
jplang committed
56
  def new
57
    @message = Message.new
58
    @message.author = User.current
jplang's avatar
jplang committed
59
    @message.board = @board
60
    @message.safe_attributes = params[:message]
61 62 63 64 65
    if request.post?
      @message.save_attachments(params[:attachments])
      if @message.save
        call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
        render_attachment_warning_if_needed(@message)
jplang's avatar
jplang committed
66
        redirect_to board_message_path(@board, @message)
67
      end
jplang's avatar
jplang committed
68 69 70
    end
  end

jplang's avatar
jplang committed
71
  # Reply to a topic
jplang's avatar
jplang committed
72
  def reply
73
    @reply = Message.new
74
    @reply.author = User.current
jplang's avatar
jplang committed
75
    @reply.board = @board
76
    @reply.safe_attributes = params[:reply]
jplang's avatar
jplang committed
77
    @topic.children << @reply
78
    if !@reply.new_record?
edavis10's avatar
edavis10 committed
79
      call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
80
      attachments = Attachment.attach_files(@reply, params[:attachments])
81
      render_attachment_warning_if_needed(@reply)
82
    end
jplang's avatar
jplang committed
83
    redirect_to board_message_path(@board, @topic, :r => @reply)
jplang's avatar
jplang committed
84 85 86 87
  end

  # Edit a message
  def edit
88
    (render_403; return false) unless @message.editable_by?(User.current)
89 90
    @message.safe_attributes = params[:message]
    if request.post? && @message.save
91
      attachments = Attachment.attach_files(@message, params[:attachments])
92
      render_attachment_warning_if_needed(@message)
jplang's avatar
jplang committed
93
      flash[:notice] = l(:notice_successful_update)
94
      @message.reload
jplang's avatar
jplang committed
95
      redirect_to board_message_path(@message.board, @message.root, :r => (@message.parent_id && @message.id))
jplang's avatar
jplang committed
96 97
    end
  end
98

jplang's avatar
jplang committed
99 100
  # Delete a messages
  def destroy
101
    (render_403; return false) unless @message.destroyable_by?(User.current)
jplang's avatar
jplang committed
102
    r = @message.to_param
jplang's avatar
jplang committed
103
    @message.destroy
jplang's avatar
jplang committed
104 105 106 107 108
    if @message.parent
      redirect_to board_message_path(@board, @message.parent, :r => r)
    else
      redirect_to project_board_path(@project, @board)
    end
jplang's avatar
jplang committed
109
  end
110

111
  def quote
jplang's avatar
jplang committed
112 113 114 115
    @subject = @message.subject
    @subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')

    @content = "#{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
116
    @content << @message.content.to_s.strip.gsub(%r{<pre>(.*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
117
  end
118

jplang's avatar
jplang committed
119 120 121
  def preview
    message = @board.messages.find_by_id(params[:id])
    @text = (params[:message] || params[:reply])[:content]
122
    @previewed = message
jplang's avatar
jplang committed
123 124
    render :partial => 'common/preview'
  end
125

jplang's avatar
jplang committed
126
private
jplang's avatar
jplang committed
127
  def find_message
128
    return unless find_board
129
    @message = @board.messages.includes(:parent).find(params[:id])
jplang's avatar
jplang committed
130 131 132 133
    @topic = @message.root
  rescue ActiveRecord::RecordNotFound
    render_404
  end
134

jplang's avatar
jplang committed
135
  def find_board
136
    @board = Board.includes(:project).find(params[:board_id])
jplang's avatar
jplang committed
137 138 139
    @project = @board.project
  rescue ActiveRecord::RecordNotFound
    render_404
140
    nil
jplang's avatar
jplang committed
141 142
  end
end