Add some copyright notices
[gitorious:taladars-gitorious-saltation.git] / app / controllers / comments_controller.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2010 Marko Peltola <marko@markopeltola.com>
4 #   Copyright (C) 2010 Tero Hänninen <tero.j.hanninen@jyu.fi>
5 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
6 #   Copyright (C) 2008 Johan Sørensen <johan@johansorensen.com>
7 #   Copyright (C) 2008 David A. Cuadrado <krawek@gmail.com>
8 #   Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
9 #   Copyright (C) 2009 Fabio Akita <fabio.akita@gmail.com>
10 #
11 #   This program is free software: you can redistribute it and/or modify
12 #   it under the terms of the GNU Affero General Public License as published by
13 #   the Free Software Foundation, either version 3 of the License, or
14 #   (at your option) any later version.
15 #
16 #   This program is distributed in the hope that it will be useful,
17 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
18 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 #   GNU Affero General Public License for more details.
20 #
21 #   You should have received a copy of the GNU Affero General Public License
22 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 #++
24
25 class CommentsController < ApplicationController
26   before_filter :login_required, :only => [:new, :create, :edit, :update, :destroy]
27   before_filter :find_project_and_repository
28   before_filter :require_view_right_to_repository
29   before_filter :find_polymorphic_parent
30   before_filter :comment_should_be_editable, :only => [:edit, :update]
31   renders_in_site_specific_context
32   
33   def index
34     @comments = @repository.comments.find(:all, :include => :user)
35     @merge_request_count = @repository.merge_requests.count_open
36     @atom_auto_discovery_url = project_repository_comments_path(@project, @repository,
37       :format => :atom)
38     respond_to do |format|
39       format.html { }
40       format.atom { }
41     end
42   end
43   
44   def preview
45     @comment = Comment.new(params[:comment])
46     respond_to do |wants|
47       wants.js
48     end
49   end
50   
51   def new
52     @comment = @target.comments.new
53   end
54   
55   def create
56     state = params[:comment].delete(:state)
57     @comment = @target.comments.new(params[:comment])
58     @comment.user = current_user
59     @comment.state = state
60     @comment.project = @project
61     render_or_redirect
62   end
63
64   def edit
65     render :partial => "edit_body"
66   end
67
68   def update
69     @comment.body = params[:comment][:body]
70     @comment.save
71     render :partial => @comment
72   end
73   
74   protected
75   def render_or_redirect
76     if @comment.save
77       comment_was_created
78     else
79       comment_was_invalid
80     end
81   end
82
83
84   def comment_was_created
85     create_new_commented_posted_event
86     add_to_favorites if params[:add_to_favorites]
87     respond_to do |wants|
88       wants.html do
89         flash[:success] = I18n.t "comments_controller.create_success"
90         if @comment.sha1.blank?
91           redirect_to_repository_or_target
92         else
93           redirect_to repo_owner_path(@repository,
94             :project_repository_commit_path, @project, @repository, @comment.sha1)
95         end
96       end
97       wants.js do
98         case @target
99         when Repository
100           commit = @target.git.commit(@comment.sha1)
101           @comments = @target.comments.find_all_by_sha1(@comment.sha1, :include => :user)
102           @diffs = commit.parents.empty? ? [] : commit.diffs.select { |diff|
103             diff.a_path == @comment.path
104           }
105           @file_diff = render_to_string(:partial => "commits/diffs")
106         else
107           @diffs = @target.diffs(range_or_string(@comment.sha1)).select{|d|
108             d.a_path == @comment.path
109           }
110           @file_diff = render_to_string(:partial => "merge_request_versions/comments")
111         end
112         render :json => {
113           "file-diff" => @file_diff,
114           "comment" => render_to_string(:partial => @comment)
115         }, :status => :created
116       end
117     end
118   end
119
120   def add_to_favorites
121     favorite_target.watched_by!(current_user)
122   end
123
124   def favorite_target
125     @target.is_a?(MergeRequest) ? @target : @target.merge_request
126   end
127   
128   def comment_was_invalid
129     respond_to { |wants|
130       wants.html { render :action => "new" }
131       wants.js   { render :nothing => true, :status => :not_acceptable }
132     }
133   end
134   
135   def applies_to_merge_request_version?
136     MergeRequestVersion === @target
137   end
138
139   def range_or_string(str)
140     if match = /^([a-z0-9]*)-([a-z0-9]*)$/.match(str)
141       @sha_range = Range.new(match[1],match[2])
142     else
143       @sha_range = str
144     end
145   end
146
147   def find_repository
148     @repository = @owner.repositories.find_by_name_in_project!(params[:repository_id],
149       @containing_project)
150   end
151
152   def find_polymorphic_parent
153     if params[:merge_request_version_id]
154       @target = MergeRequestVersion.find(params[:merge_request_version_id])
155     elsif params[:merge_request_id]
156       @target = @repository.merge_requests.find_by_sequence_number!(params[:merge_request_id])
157     else
158       @target = @repository
159     end
160   end
161
162   def redirect_to_repository_or_target
163     if @target == @repository
164       redirect_to repo_owner_path(@repository, [@project, @target, :comments])
165     else
166       redirect_to repo_owner_path(@repository, [@project, @repository, @target])
167     end
168   end
169
170   def create_new_commented_posted_event
171     if applies_to_merge_request_version?
172       @project.create_event(Action::COMMENT, @target.merge_request, current_user,
173         @comment.to_param, "MergeRequest")
174       return
175     end
176
177     if @target == @repository
178       @project.create_event(Action::COMMENT, @repository, current_user,
179         @comment.to_param, "Repository")
180     else
181       @project.create_event(Action::COMMENT, @target, current_user,
182         @comment.to_param, "MergeRequest") if @comment.state_change.blank?
183     end
184   end
185
186   def comment_should_be_editable
187     @comment = Comment.find(params[:id])
188     if !@comment.editable_by?(current_user)
189       render :status => :unauthorized, :text => "Sorry mate"
190     end
191   end
192 end