To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / app / controllers / .svn / text-base / wiki_controller.rb.svn-base @ 441:cbce1fd3b1b7
History | View | Annotate | Download (9.77 KB)
| 1 | 441:cbce1fd3b1b7 | Chris | # Redmine - project management software |
|---|---|---|---|
| 2 | # Copyright (C) 2006-2011 Jean-Philippe Lang |
||
| 3 | 0:513646585e45 | Chris | # |
| 4 | # This program is free software; you can redistribute it and/or |
||
| 5 | # modify it under the terms of the GNU General Public License |
||
| 6 | # as published by the Free Software Foundation; either version 2 |
||
| 7 | # of the License, or (at your option) any later version. |
||
| 8 | 441:cbce1fd3b1b7 | Chris | # |
| 9 | 0:513646585e45 | Chris | # This program is distributed in the hope that it will be useful, |
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 12 | # GNU General Public License for more details. |
||
| 13 | 441:cbce1fd3b1b7 | Chris | # |
| 14 | 0:513646585e45 | Chris | # You should have received a copy of the GNU General Public License |
| 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. |
||
| 17 | |||
| 18 | require 'diff' |
||
| 19 | |||
| 20 | 37:94944d00e43c | chris | # 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 |
||
| 34 | 0:513646585e45 | Chris | class WikiController < ApplicationController |
| 35 | default_search_scope :wiki_pages |
||
| 36 | before_filter :find_wiki, :authorize |
||
| 37 | 441:cbce1fd3b1b7 | Chris | before_filter :find_existing_or_new_page, :only => [:show, :edit, :update] |
| 38 | 0:513646585e45 | Chris | before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] |
| 39 | |||
| 40 | helper :attachments |
||
| 41 | 441:cbce1fd3b1b7 | Chris | include AttachmentsHelper |
| 42 | 0:513646585e45 | Chris | helper :watchers |
| 43 | 37:94944d00e43c | chris | |
| 44 | # List of pages, sorted alphabetically and by parent (hierarchy) |
||
| 45 | def index |
||
| 46 | 441:cbce1fd3b1b7 | Chris | load_pages_for_index |
| 47 | @pages_by_parent_id = @pages.group_by(&:parent_id) |
||
| 48 | end |
||
| 49 | |||
| 50 | # List of page, by last update |
||
| 51 | def date_index |
||
| 52 | load_pages_for_index |
||
| 53 | @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
|
||
| 54 | 37:94944d00e43c | chris | end |
| 55 | |||
| 56 | 0:513646585e45 | Chris | # display a page (in editing mode if it doesn't exist) |
| 57 | 37:94944d00e43c | chris | def show |
| 58 | 0:513646585e45 | Chris | if @page.new_record? |
| 59 | if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? |
||
| 60 | edit |
||
| 61 | render :action => 'edit' |
||
| 62 | else |
||
| 63 | render_404 |
||
| 64 | end |
||
| 65 | return |
||
| 66 | end |
||
| 67 | if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project) |
||
| 68 | # Redirects user to the current version if he's not allowed to view previous versions |
||
| 69 | redirect_to :version => nil |
||
| 70 | return |
||
| 71 | end |
||
| 72 | @content = @page.content_for_version(params[:version]) |
||
| 73 | if User.current.allowed_to?(:export_wiki_pages, @project) |
||
| 74 | if params[:format] == 'html' |
||
| 75 | export = render_to_string :action => 'export', :layout => false |
||
| 76 | send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
|
||
| 77 | return |
||
| 78 | elsif params[:format] == 'txt' |
||
| 79 | send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
|
||
| 80 | return |
||
| 81 | end |
||
| 82 | end |
||
| 83 | @editable = editable? |
||
| 84 | render :action => 'show' |
||
| 85 | end |
||
| 86 | 441:cbce1fd3b1b7 | Chris | |
| 87 | 0:513646585e45 | Chris | # edit an existing page or a new one |
| 88 | def edit |
||
| 89 | return render_403 unless editable? |
||
| 90 | @page.content = WikiContent.new(:page => @page) if @page.new_record? |
||
| 91 | 441:cbce1fd3b1b7 | Chris | |
| 92 | 0:513646585e45 | Chris | @content = @page.content_for_version(params[:version]) |
| 93 | @content.text = initial_page_content(@page) if @content.text.blank? |
||
| 94 | # don't keep previous comment |
||
| 95 | @content.comments = nil |
||
| 96 | 37:94944d00e43c | chris | |
| 97 | # To prevent StaleObjectError exception when reverting to a previous version |
||
| 98 | @content.version = @page.content.version |
||
| 99 | 0:513646585e45 | Chris | end |
| 100 | 37:94944d00e43c | chris | |
| 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 | return render_403 unless editable? |
||
| 105 | @page.content = WikiContent.new(:page => @page) if @page.new_record? |
||
| 106 | 441:cbce1fd3b1b7 | Chris | |
| 107 | 37:94944d00e43c | chris | @content = @page.content_for_version(params[:version]) |
| 108 | @content.text = initial_page_content(@page) if @content.text.blank? |
||
| 109 | # don't keep previous comment |
||
| 110 | @content.comments = nil |
||
| 111 | |||
| 112 | if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text] |
||
| 113 | attachments = Attachment.attach_files(@page, params[:attachments]) |
||
| 114 | render_attachment_warning_if_needed(@page) |
||
| 115 | # don't save if text wasn't changed |
||
| 116 | redirect_to :action => 'show', :project_id => @project, :id => @page.title |
||
| 117 | return |
||
| 118 | end |
||
| 119 | @content.attributes = params[:content] |
||
| 120 | @content.author = User.current |
||
| 121 | # if page is new @page.save will also save content, but not if page isn't a new record |
||
| 122 | if (@page.new_record? ? @page.save : @content.save) |
||
| 123 | attachments = Attachment.attach_files(@page, params[:attachments]) |
||
| 124 | render_attachment_warning_if_needed(@page) |
||
| 125 | call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
|
||
| 126 | redirect_to :action => 'show', :project_id => @project, :id => @page.title |
||
| 127 | 119:8661b858af72 | Chris | else |
| 128 | render :action => 'edit' |
||
| 129 | 37:94944d00e43c | chris | end |
| 130 | |||
| 131 | rescue ActiveRecord::StaleObjectError |
||
| 132 | # Optimistic locking exception |
||
| 133 | 441:cbce1fd3b1b7 | Chris | flash.now[:error] = l(:notice_locking_conflict) |
| 134 | render :action => 'edit' |
||
| 135 | 37:94944d00e43c | chris | end |
| 136 | |||
| 137 | 0:513646585e45 | Chris | # rename a page |
| 138 | def rename |
||
| 139 | return render_403 unless editable? |
||
| 140 | @page.redirect_existing_links = true |
||
| 141 | # used to display the *original* title if some AR validation errors occur |
||
| 142 | @original_title = @page.pretty_title |
||
| 143 | if request.post? && @page.update_attributes(params[:wiki_page]) |
||
| 144 | flash[:notice] = l(:notice_successful_update) |
||
| 145 | 37:94944d00e43c | chris | redirect_to :action => 'show', :project_id => @project, :id => @page.title |
| 146 | 0:513646585e45 | Chris | end |
| 147 | end |
||
| 148 | 441:cbce1fd3b1b7 | Chris | |
| 149 | verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
|
||
| 150 | 0:513646585e45 | Chris | def protect |
| 151 | @page.update_attribute :protected, params[:protected] |
||
| 152 | 37:94944d00e43c | chris | redirect_to :action => 'show', :project_id => @project, :id => @page.title |
| 153 | 0:513646585e45 | Chris | end |
| 154 | |||
| 155 | # show page history |
||
| 156 | def history |
||
| 157 | @version_count = @page.content.versions.count |
||
| 158 | @version_pages = Paginator.new self, @version_count, per_page_option, params['p'] |
||
| 159 | 441:cbce1fd3b1b7 | Chris | # don't load text |
| 160 | @versions = @page.content.versions.find :all, |
||
| 161 | 0:513646585e45 | Chris | :select => "id, author_id, comments, updated_on, version", |
| 162 | :order => 'version DESC', |
||
| 163 | :limit => @version_pages.items_per_page + 1, |
||
| 164 | :offset => @version_pages.current.offset |
||
| 165 | |||
| 166 | render :layout => false if request.xhr? |
||
| 167 | end |
||
| 168 | 441:cbce1fd3b1b7 | Chris | |
| 169 | 0:513646585e45 | Chris | def diff |
| 170 | @diff = @page.diff(params[:version], params[:version_from]) |
||
| 171 | render_404 unless @diff |
||
| 172 | end |
||
| 173 | 441:cbce1fd3b1b7 | Chris | |
| 174 | 0:513646585e45 | Chris | def annotate |
| 175 | @annotate = @page.annotate(params[:version]) |
||
| 176 | render_404 unless @annotate |
||
| 177 | end |
||
| 178 | 37:94944d00e43c | chris | |
| 179 | verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show }
|
||
| 180 | 0:513646585e45 | Chris | # Removes a wiki page and its history |
| 181 | # Children can be either set as root pages, removed or reassigned to another parent page |
||
| 182 | def destroy |
||
| 183 | return render_403 unless editable? |
||
| 184 | 441:cbce1fd3b1b7 | Chris | |
| 185 | 0:513646585e45 | Chris | @descendants_count = @page.descendants.size |
| 186 | if @descendants_count > 0 |
||
| 187 | case params[:todo] |
||
| 188 | when 'nullify' |
||
| 189 | # Nothing to do |
||
| 190 | when 'destroy' |
||
| 191 | # Removes all its descendants |
||
| 192 | @page.descendants.each(&:destroy) |
||
| 193 | when 'reassign' |
||
| 194 | # Reassign children to another parent page |
||
| 195 | reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i) |
||
| 196 | return unless reassign_to |
||
| 197 | @page.children.each do |child| |
||
| 198 | child.update_attribute(:parent, reassign_to) |
||
| 199 | end |
||
| 200 | else |
||
| 201 | @reassignable_to = @wiki.pages - @page.self_and_descendants |
||
| 202 | return |
||
| 203 | end |
||
| 204 | end |
||
| 205 | @page.destroy |
||
| 206 | 37:94944d00e43c | chris | redirect_to :action => 'index', :project_id => @project |
| 207 | 0:513646585e45 | Chris | end |
| 208 | |||
| 209 | 37:94944d00e43c | chris | # Export wiki to a single html file |
| 210 | def export |
||
| 211 | if User.current.allowed_to?(:export_wiki_pages, @project) |
||
| 212 | @pages = @wiki.pages.find :all, :order => 'title' |
||
| 213 | export = render_to_string :action => 'export_multiple', :layout => false |
||
| 214 | send_data(export, :type => 'text/html', :filename => "wiki.html") |
||
| 215 | 0:513646585e45 | Chris | else |
| 216 | 37:94944d00e43c | chris | redirect_to :action => 'show', :project_id => @project, :id => nil |
| 217 | 0:513646585e45 | Chris | end |
| 218 | 37:94944d00e43c | chris | end |
| 219 | |||
| 220 | 0:513646585e45 | Chris | def preview |
| 221 | 37:94944d00e43c | chris | page = @wiki.find_page(params[:id]) |
| 222 | 0:513646585e45 | Chris | # page is nil when previewing a new page |
| 223 | return render_403 unless page.nil? || editable?(page) |
||
| 224 | if page |
||
| 225 | @attachements = page.attachments |
||
| 226 | @previewed = page.content |
||
| 227 | end |
||
| 228 | @text = params[:content][:text] |
||
| 229 | render :partial => 'common/preview' |
||
| 230 | end |
||
| 231 | |||
| 232 | def add_attachment |
||
| 233 | return render_403 unless editable? |
||
| 234 | attachments = Attachment.attach_files(@page, params[:attachments]) |
||
| 235 | render_attachment_warning_if_needed(@page) |
||
| 236 | 37:94944d00e43c | chris | redirect_to :action => 'show', :id => @page.title, :project_id => @project |
| 237 | 0:513646585e45 | Chris | end |
| 238 | |||
| 239 | private |
||
| 240 | 441:cbce1fd3b1b7 | Chris | |
| 241 | 0:513646585e45 | Chris | def find_wiki |
| 242 | 37:94944d00e43c | chris | @project = Project.find(params[:project_id]) |
| 243 | 0:513646585e45 | Chris | @wiki = @project.wiki |
| 244 | render_404 unless @wiki |
||
| 245 | rescue ActiveRecord::RecordNotFound |
||
| 246 | render_404 |
||
| 247 | end |
||
| 248 | 441:cbce1fd3b1b7 | Chris | |
| 249 | # Finds the requested page or a new page if it doesn't exist |
||
| 250 | def find_existing_or_new_page |
||
| 251 | @page = @wiki.find_or_new_page(params[:id]) |
||
| 252 | if @wiki.page_found_with_redirect? |
||
| 253 | redirect_to params.update(:id => @page.title) |
||
| 254 | end |
||
| 255 | end |
||
| 256 | |||
| 257 | 0:513646585e45 | Chris | # Finds the requested page and returns a 404 error if it doesn't exist |
| 258 | def find_existing_page |
||
| 259 | 37:94944d00e43c | chris | @page = @wiki.find_page(params[:id]) |
| 260 | 441:cbce1fd3b1b7 | Chris | if @page.nil? |
| 261 | render_404 |
||
| 262 | return |
||
| 263 | end |
||
| 264 | if @wiki.page_found_with_redirect? |
||
| 265 | redirect_to params.update(:id => @page.title) |
||
| 266 | end |
||
| 267 | 0:513646585e45 | Chris | end |
| 268 | 441:cbce1fd3b1b7 | Chris | |
| 269 | 0:513646585e45 | Chris | # Returns true if the current user is allowed to edit the page, otherwise false |
| 270 | def editable?(page = @page) |
||
| 271 | page.editable_by?(User.current) |
||
| 272 | end |
||
| 273 | |||
| 274 | # Returns the default content of a new wiki page |
||
| 275 | def initial_page_content(page) |
||
| 276 | helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) |
||
| 277 | extend helper unless self.instance_of?(helper) |
||
| 278 | helper.instance_method(:initial_page_content).bind(self).call(page) |
||
| 279 | end |
||
| 280 | 37:94944d00e43c | chris | |
| 281 | 441:cbce1fd3b1b7 | Chris | def load_pages_for_index |
| 282 | @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
|
||
| 283 | 37:94944d00e43c | chris | end |
| 284 | 0:513646585e45 | Chris | end |