Mercurial > hg > soundsoftware-site
comparison app/controllers/wiki_controller.rb @ 37:94944d00e43c
* Update to SVN trunk rev 4411
author | Chris Cannam <chris.cannam@soundsoftware.ac.uk> |
---|---|
date | Fri, 19 Nov 2010 13:24:41 +0000 |
parents | 513646585e45 |
children | af80e5618e9b |
comparison
equal
deleted
inserted
replaced
22:40f7cfd4df19 | 37:94944d00e43c |
---|---|
15 # along with this program; if not, write to the Free Software | 15 # along with this program; if not, write to the Free Software |
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | 17 |
18 require 'diff' | 18 require 'diff' |
19 | 19 |
20 # The WikiController follows the Rails REST controller pattern but with | |
21 # a few differences | |
22 # | |
23 # * index - shows a list of WikiPages grouped by page or date | |
24 # * new - not used | |
25 # * create - not used | |
26 # * show - will also show the form for creating a new wiki page | |
27 # * edit - used to edit an existing or new page | |
28 # * update - used to save a wiki page update to the database, including new pages | |
29 # * destroy - normal | |
30 # | |
31 # Other member and collection methods are also used | |
32 # | |
33 # TODO: still being worked on | |
20 class WikiController < ApplicationController | 34 class WikiController < ApplicationController |
21 default_search_scope :wiki_pages | 35 default_search_scope :wiki_pages |
22 before_filter :find_wiki, :authorize | 36 before_filter :find_wiki, :authorize |
23 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] | 37 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] |
24 | 38 |
25 verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index } | 39 verify :method => :post, :only => [:protect], :redirect_to => { :action => :show } |
26 | 40 |
27 helper :attachments | 41 helper :attachments |
28 include AttachmentsHelper | 42 include AttachmentsHelper |
29 helper :watchers | 43 helper :watchers |
30 | 44 |
45 # List of pages, sorted alphabetically and by parent (hierarchy) | |
46 def index | |
47 load_pages_grouped_by_date_without_content | |
48 end | |
49 | |
31 # display a page (in editing mode if it doesn't exist) | 50 # display a page (in editing mode if it doesn't exist) |
32 def index | 51 def show |
33 page_title = params[:page] | 52 page_title = params[:id] |
34 @page = @wiki.find_or_new_page(page_title) | 53 @page = @wiki.find_or_new_page(page_title) |
35 if @page.new_record? | 54 if @page.new_record? |
36 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? | 55 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? |
37 edit | 56 edit |
38 render :action => 'edit' | 57 render :action => 'edit' |
61 render :action => 'show' | 80 render :action => 'show' |
62 end | 81 end |
63 | 82 |
64 # edit an existing page or a new one | 83 # edit an existing page or a new one |
65 def edit | 84 def edit |
66 @page = @wiki.find_or_new_page(params[:page]) | 85 @page = @wiki.find_or_new_page(params[:id]) |
67 return render_403 unless editable? | 86 return render_403 unless editable? |
68 @page.content = WikiContent.new(:page => @page) if @page.new_record? | 87 @page.content = WikiContent.new(:page => @page) if @page.new_record? |
69 | 88 |
70 @content = @page.content_for_version(params[:version]) | 89 @content = @page.content_for_version(params[:version]) |
71 @content.text = initial_page_content(@page) if @content.text.blank? | 90 @content.text = initial_page_content(@page) if @content.text.blank? |
72 # don't keep previous comment | 91 # don't keep previous comment |
73 @content.comments = nil | 92 @content.comments = nil |
74 if request.get? | 93 |
75 # To prevent StaleObjectError exception when reverting to a previous version | 94 # To prevent StaleObjectError exception when reverting to a previous version |
76 @content.version = @page.content.version | 95 @content.version = @page.content.version |
77 else | |
78 if !@page.new_record? && @content.text == params[:content][:text] | |
79 attachments = Attachment.attach_files(@page, params[:attachments]) | |
80 render_attachment_warning_if_needed(@page) | |
81 # don't save if text wasn't changed | |
82 redirect_to :action => 'index', :id => @project, :page => @page.title | |
83 return | |
84 end | |
85 #@content.text = params[:content][:text] | |
86 #@content.comments = params[:content][:comments] | |
87 @content.attributes = params[:content] | |
88 @content.author = User.current | |
89 # if page is new @page.save will also save content, but not if page isn't a new record | |
90 if (@page.new_record? ? @page.save : @content.save) | |
91 attachments = Attachment.attach_files(@page, params[:attachments]) | |
92 render_attachment_warning_if_needed(@page) | |
93 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) | |
94 redirect_to :action => 'index', :id => @project, :page => @page.title | |
95 end | |
96 end | |
97 rescue ActiveRecord::StaleObjectError | 96 rescue ActiveRecord::StaleObjectError |
98 # Optimistic locking exception | 97 # Optimistic locking exception |
99 flash[:error] = l(:notice_locking_conflict) | 98 flash[:error] = l(:notice_locking_conflict) |
100 end | 99 end |
101 | 100 |
101 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } | |
102 # Creates a new page or updates an existing one | |
103 def update | |
104 @page = @wiki.find_or_new_page(params[:id]) | |
105 return render_403 unless editable? | |
106 @page.content = WikiContent.new(:page => @page) if @page.new_record? | |
107 | |
108 @content = @page.content_for_version(params[:version]) | |
109 @content.text = initial_page_content(@page) if @content.text.blank? | |
110 # don't keep previous comment | |
111 @content.comments = nil | |
112 | |
113 if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text] | |
114 attachments = Attachment.attach_files(@page, params[:attachments]) | |
115 render_attachment_warning_if_needed(@page) | |
116 # don't save if text wasn't changed | |
117 redirect_to :action => 'show', :project_id => @project, :id => @page.title | |
118 return | |
119 end | |
120 @content.attributes = params[:content] | |
121 @content.author = User.current | |
122 # if page is new @page.save will also save content, but not if page isn't a new record | |
123 if (@page.new_record? ? @page.save : @content.save) | |
124 attachments = Attachment.attach_files(@page, params[:attachments]) | |
125 render_attachment_warning_if_needed(@page) | |
126 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) | |
127 redirect_to :action => 'show', :project_id => @project, :id => @page.title | |
128 end | |
129 | |
130 rescue ActiveRecord::StaleObjectError | |
131 # Optimistic locking exception | |
132 flash[:error] = l(:notice_locking_conflict) | |
133 end | |
134 | |
102 # rename a page | 135 # rename a page |
103 def rename | 136 def rename |
104 return render_403 unless editable? | 137 return render_403 unless editable? |
105 @page.redirect_existing_links = true | 138 @page.redirect_existing_links = true |
106 # used to display the *original* title if some AR validation errors occur | 139 # used to display the *original* title if some AR validation errors occur |
107 @original_title = @page.pretty_title | 140 @original_title = @page.pretty_title |
108 if request.post? && @page.update_attributes(params[:wiki_page]) | 141 if request.post? && @page.update_attributes(params[:wiki_page]) |
109 flash[:notice] = l(:notice_successful_update) | 142 flash[:notice] = l(:notice_successful_update) |
110 redirect_to :action => 'index', :id => @project, :page => @page.title | 143 redirect_to :action => 'show', :project_id => @project, :id => @page.title |
111 end | 144 end |
112 end | 145 end |
113 | 146 |
114 def protect | 147 def protect |
115 @page.update_attribute :protected, params[:protected] | 148 @page.update_attribute :protected, params[:protected] |
116 redirect_to :action => 'index', :id => @project, :page => @page.title | 149 redirect_to :action => 'show', :project_id => @project, :id => @page.title |
117 end | 150 end |
118 | 151 |
119 # show page history | 152 # show page history |
120 def history | 153 def history |
121 @version_count = @page.content.versions.count | 154 @version_count = @page.content.versions.count |
137 | 170 |
138 def annotate | 171 def annotate |
139 @annotate = @page.annotate(params[:version]) | 172 @annotate = @page.annotate(params[:version]) |
140 render_404 unless @annotate | 173 render_404 unless @annotate |
141 end | 174 end |
142 | 175 |
176 verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show } | |
143 # Removes a wiki page and its history | 177 # Removes a wiki page and its history |
144 # Children can be either set as root pages, removed or reassigned to another parent page | 178 # Children can be either set as root pages, removed or reassigned to another parent page |
145 def destroy | 179 def destroy |
146 return render_403 unless editable? | 180 return render_403 unless editable? |
147 | 181 |
164 @reassignable_to = @wiki.pages - @page.self_and_descendants | 198 @reassignable_to = @wiki.pages - @page.self_and_descendants |
165 return | 199 return |
166 end | 200 end |
167 end | 201 end |
168 @page.destroy | 202 @page.destroy |
169 redirect_to :action => 'special', :id => @project, :page => 'Page_index' | 203 redirect_to :action => 'index', :project_id => @project |
170 end | 204 end |
171 | 205 |
172 # display special pages | 206 # Export wiki to a single html file |
173 def special | 207 def export |
174 page_title = params[:page].downcase | 208 if User.current.allowed_to?(:export_wiki_pages, @project) |
175 case page_title | 209 @pages = @wiki.pages.find :all, :order => 'title' |
176 # show pages index, sorted by title | 210 export = render_to_string :action => 'export_multiple', :layout => false |
177 when 'page_index', 'date_index' | 211 send_data(export, :type => 'text/html', :filename => "wiki.html") |
178 # eager load information about last updates, without loading text | |
179 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", | |
180 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", | |
181 :order => 'title' | |
182 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} | |
183 @pages_by_parent_id = @pages.group_by(&:parent_id) | |
184 # export wiki to a single html file | |
185 when 'export' | |
186 if User.current.allowed_to?(:export_wiki_pages, @project) | |
187 @pages = @wiki.pages.find :all, :order => 'title' | |
188 export = render_to_string :action => 'export_multiple', :layout => false | |
189 send_data(export, :type => 'text/html', :filename => "wiki.html") | |
190 else | |
191 redirect_to :action => 'index', :id => @project, :page => nil | |
192 end | |
193 return | |
194 else | 212 else |
195 # requested special page doesn't exist, redirect to default page | 213 redirect_to :action => 'show', :project_id => @project, :id => nil |
196 redirect_to :action => 'index', :id => @project, :page => nil | 214 end |
197 return | 215 end |
198 end | 216 |
199 render :action => "special_#{page_title}" | 217 def date_index |
218 load_pages_grouped_by_date_without_content | |
200 end | 219 end |
201 | 220 |
202 def preview | 221 def preview |
203 page = @wiki.find_page(params[:page]) | 222 page = @wiki.find_page(params[:id]) |
204 # page is nil when previewing a new page | 223 # page is nil when previewing a new page |
205 return render_403 unless page.nil? || editable?(page) | 224 return render_403 unless page.nil? || editable?(page) |
206 if page | 225 if page |
207 @attachements = page.attachments | 226 @attachements = page.attachments |
208 @previewed = page.content | 227 @previewed = page.content |
213 | 232 |
214 def add_attachment | 233 def add_attachment |
215 return render_403 unless editable? | 234 return render_403 unless editable? |
216 attachments = Attachment.attach_files(@page, params[:attachments]) | 235 attachments = Attachment.attach_files(@page, params[:attachments]) |
217 render_attachment_warning_if_needed(@page) | 236 render_attachment_warning_if_needed(@page) |
218 redirect_to :action => 'index', :page => @page.title | 237 redirect_to :action => 'show', :id => @page.title, :project_id => @project |
219 end | 238 end |
220 | 239 |
221 private | 240 private |
222 | 241 |
223 def find_wiki | 242 def find_wiki |
224 @project = Project.find(params[:id]) | 243 @project = Project.find(params[:project_id]) |
225 @wiki = @project.wiki | 244 @wiki = @project.wiki |
226 render_404 unless @wiki | 245 render_404 unless @wiki |
227 rescue ActiveRecord::RecordNotFound | 246 rescue ActiveRecord::RecordNotFound |
228 render_404 | 247 render_404 |
229 end | 248 end |
230 | 249 |
231 # Finds the requested page and returns a 404 error if it doesn't exist | 250 # Finds the requested page and returns a 404 error if it doesn't exist |
232 def find_existing_page | 251 def find_existing_page |
233 @page = @wiki.find_page(params[:page]) | 252 @page = @wiki.find_page(params[:id]) |
234 render_404 if @page.nil? | 253 render_404 if @page.nil? |
235 end | 254 end |
236 | 255 |
237 # Returns true if the current user is allowed to edit the page, otherwise false | 256 # Returns true if the current user is allowed to edit the page, otherwise false |
238 def editable?(page = @page) | 257 def editable?(page = @page) |
243 def initial_page_content(page) | 262 def initial_page_content(page) |
244 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) | 263 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) |
245 extend helper unless self.instance_of?(helper) | 264 extend helper unless self.instance_of?(helper) |
246 helper.instance_method(:initial_page_content).bind(self).call(page) | 265 helper.instance_method(:initial_page_content).bind(self).call(page) |
247 end | 266 end |
267 | |
268 # eager load information about last updates, without loading text | |
269 def load_pages_grouped_by_date_without_content | |
270 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", | |
271 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", | |
272 :order => 'title' | |
273 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} | |
274 @pages_by_parent_id = @pages.group_by(&:parent_id) | |
275 end | |
276 | |
248 end | 277 end |