annotate app/controllers/wiki_controller.rb @ 8:0c83d98252d9 yuya

* Add custom repo prefix and proper auth realm, remove auth cache (seems like an unwise feature), pass DB handle around, various other bits of tidying
author Chris Cannam
date Thu, 12 Aug 2010 15:31:37 +0100
parents 513646585e45
children 94944d00e43c
rev   line source
Chris@0 1 # redMine - project management software
Chris@0 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
Chris@0 3 #
Chris@0 4 # This program is free software; you can redistribute it and/or
Chris@0 5 # modify it under the terms of the GNU General Public License
Chris@0 6 # as published by the Free Software Foundation; either version 2
Chris@0 7 # of the License, or (at your option) any later version.
Chris@0 8 #
Chris@0 9 # This program is distributed in the hope that it will be useful,
Chris@0 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 12 # GNU General Public License for more details.
Chris@0 13 #
Chris@0 14 # You should have received a copy of the GNU General Public License
Chris@0 15 # along with this program; if not, write to the Free Software
Chris@0 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@0 17
Chris@0 18 require 'diff'
Chris@0 19
Chris@0 20 class WikiController < ApplicationController
Chris@0 21 default_search_scope :wiki_pages
Chris@0 22 before_filter :find_wiki, :authorize
Chris@0 23 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
Chris@0 24
Chris@0 25 verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index }
Chris@0 26
Chris@0 27 helper :attachments
Chris@0 28 include AttachmentsHelper
Chris@0 29 helper :watchers
Chris@0 30
Chris@0 31 # display a page (in editing mode if it doesn't exist)
Chris@0 32 def index
Chris@0 33 page_title = params[:page]
Chris@0 34 @page = @wiki.find_or_new_page(page_title)
Chris@0 35 if @page.new_record?
Chris@0 36 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
Chris@0 37 edit
Chris@0 38 render :action => 'edit'
Chris@0 39 else
Chris@0 40 render_404
Chris@0 41 end
Chris@0 42 return
Chris@0 43 end
Chris@0 44 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
Chris@0 45 # Redirects user to the current version if he's not allowed to view previous versions
Chris@0 46 redirect_to :version => nil
Chris@0 47 return
Chris@0 48 end
Chris@0 49 @content = @page.content_for_version(params[:version])
Chris@0 50 if User.current.allowed_to?(:export_wiki_pages, @project)
Chris@0 51 if params[:format] == 'html'
Chris@0 52 export = render_to_string :action => 'export', :layout => false
Chris@0 53 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
Chris@0 54 return
Chris@0 55 elsif params[:format] == 'txt'
Chris@0 56 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
Chris@0 57 return
Chris@0 58 end
Chris@0 59 end
Chris@0 60 @editable = editable?
Chris@0 61 render :action => 'show'
Chris@0 62 end
Chris@0 63
Chris@0 64 # edit an existing page or a new one
Chris@0 65 def edit
Chris@0 66 @page = @wiki.find_or_new_page(params[:page])
Chris@0 67 return render_403 unless editable?
Chris@0 68 @page.content = WikiContent.new(:page => @page) if @page.new_record?
Chris@0 69
Chris@0 70 @content = @page.content_for_version(params[:version])
Chris@0 71 @content.text = initial_page_content(@page) if @content.text.blank?
Chris@0 72 # don't keep previous comment
Chris@0 73 @content.comments = nil
Chris@0 74 if request.get?
Chris@0 75 # To prevent StaleObjectError exception when reverting to a previous version
Chris@0 76 @content.version = @page.content.version
Chris@0 77 else
Chris@0 78 if !@page.new_record? && @content.text == params[:content][:text]
Chris@0 79 attachments = Attachment.attach_files(@page, params[:attachments])
Chris@0 80 render_attachment_warning_if_needed(@page)
Chris@0 81 # don't save if text wasn't changed
Chris@0 82 redirect_to :action => 'index', :id => @project, :page => @page.title
Chris@0 83 return
Chris@0 84 end
Chris@0 85 #@content.text = params[:content][:text]
Chris@0 86 #@content.comments = params[:content][:comments]
Chris@0 87 @content.attributes = params[:content]
Chris@0 88 @content.author = User.current
Chris@0 89 # if page is new @page.save will also save content, but not if page isn't a new record
Chris@0 90 if (@page.new_record? ? @page.save : @content.save)
Chris@0 91 attachments = Attachment.attach_files(@page, params[:attachments])
Chris@0 92 render_attachment_warning_if_needed(@page)
Chris@0 93 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
Chris@0 94 redirect_to :action => 'index', :id => @project, :page => @page.title
Chris@0 95 end
Chris@0 96 end
Chris@0 97 rescue ActiveRecord::StaleObjectError
Chris@0 98 # Optimistic locking exception
Chris@0 99 flash[:error] = l(:notice_locking_conflict)
Chris@0 100 end
Chris@0 101
Chris@0 102 # rename a page
Chris@0 103 def rename
Chris@0 104 return render_403 unless editable?
Chris@0 105 @page.redirect_existing_links = true
Chris@0 106 # used to display the *original* title if some AR validation errors occur
Chris@0 107 @original_title = @page.pretty_title
Chris@0 108 if request.post? && @page.update_attributes(params[:wiki_page])
Chris@0 109 flash[:notice] = l(:notice_successful_update)
Chris@0 110 redirect_to :action => 'index', :id => @project, :page => @page.title
Chris@0 111 end
Chris@0 112 end
Chris@0 113
Chris@0 114 def protect
Chris@0 115 @page.update_attribute :protected, params[:protected]
Chris@0 116 redirect_to :action => 'index', :id => @project, :page => @page.title
Chris@0 117 end
Chris@0 118
Chris@0 119 # show page history
Chris@0 120 def history
Chris@0 121 @version_count = @page.content.versions.count
Chris@0 122 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
Chris@0 123 # don't load text
Chris@0 124 @versions = @page.content.versions.find :all,
Chris@0 125 :select => "id, author_id, comments, updated_on, version",
Chris@0 126 :order => 'version DESC',
Chris@0 127 :limit => @version_pages.items_per_page + 1,
Chris@0 128 :offset => @version_pages.current.offset
Chris@0 129
Chris@0 130 render :layout => false if request.xhr?
Chris@0 131 end
Chris@0 132
Chris@0 133 def diff
Chris@0 134 @diff = @page.diff(params[:version], params[:version_from])
Chris@0 135 render_404 unless @diff
Chris@0 136 end
Chris@0 137
Chris@0 138 def annotate
Chris@0 139 @annotate = @page.annotate(params[:version])
Chris@0 140 render_404 unless @annotate
Chris@0 141 end
Chris@0 142
Chris@0 143 # Removes a wiki page and its history
Chris@0 144 # Children can be either set as root pages, removed or reassigned to another parent page
Chris@0 145 def destroy
Chris@0 146 return render_403 unless editable?
Chris@0 147
Chris@0 148 @descendants_count = @page.descendants.size
Chris@0 149 if @descendants_count > 0
Chris@0 150 case params[:todo]
Chris@0 151 when 'nullify'
Chris@0 152 # Nothing to do
Chris@0 153 when 'destroy'
Chris@0 154 # Removes all its descendants
Chris@0 155 @page.descendants.each(&:destroy)
Chris@0 156 when 'reassign'
Chris@0 157 # Reassign children to another parent page
Chris@0 158 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
Chris@0 159 return unless reassign_to
Chris@0 160 @page.children.each do |child|
Chris@0 161 child.update_attribute(:parent, reassign_to)
Chris@0 162 end
Chris@0 163 else
Chris@0 164 @reassignable_to = @wiki.pages - @page.self_and_descendants
Chris@0 165 return
Chris@0 166 end
Chris@0 167 end
Chris@0 168 @page.destroy
Chris@0 169 redirect_to :action => 'special', :id => @project, :page => 'Page_index'
Chris@0 170 end
Chris@0 171
Chris@0 172 # display special pages
Chris@0 173 def special
Chris@0 174 page_title = params[:page].downcase
Chris@0 175 case page_title
Chris@0 176 # show pages index, sorted by title
Chris@0 177 when 'page_index', 'date_index'
Chris@0 178 # eager load information about last updates, without loading text
Chris@0 179 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
Chris@0 180 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
Chris@0 181 :order => 'title'
Chris@0 182 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
Chris@0 183 @pages_by_parent_id = @pages.group_by(&:parent_id)
Chris@0 184 # export wiki to a single html file
Chris@0 185 when 'export'
Chris@0 186 if User.current.allowed_to?(:export_wiki_pages, @project)
Chris@0 187 @pages = @wiki.pages.find :all, :order => 'title'
Chris@0 188 export = render_to_string :action => 'export_multiple', :layout => false
Chris@0 189 send_data(export, :type => 'text/html', :filename => "wiki.html")
Chris@0 190 else
Chris@0 191 redirect_to :action => 'index', :id => @project, :page => nil
Chris@0 192 end
Chris@0 193 return
Chris@0 194 else
Chris@0 195 # requested special page doesn't exist, redirect to default page
Chris@0 196 redirect_to :action => 'index', :id => @project, :page => nil
Chris@0 197 return
Chris@0 198 end
Chris@0 199 render :action => "special_#{page_title}"
Chris@0 200 end
Chris@0 201
Chris@0 202 def preview
Chris@0 203 page = @wiki.find_page(params[:page])
Chris@0 204 # page is nil when previewing a new page
Chris@0 205 return render_403 unless page.nil? || editable?(page)
Chris@0 206 if page
Chris@0 207 @attachements = page.attachments
Chris@0 208 @previewed = page.content
Chris@0 209 end
Chris@0 210 @text = params[:content][:text]
Chris@0 211 render :partial => 'common/preview'
Chris@0 212 end
Chris@0 213
Chris@0 214 def add_attachment
Chris@0 215 return render_403 unless editable?
Chris@0 216 attachments = Attachment.attach_files(@page, params[:attachments])
Chris@0 217 render_attachment_warning_if_needed(@page)
Chris@0 218 redirect_to :action => 'index', :page => @page.title
Chris@0 219 end
Chris@0 220
Chris@0 221 private
Chris@0 222
Chris@0 223 def find_wiki
Chris@0 224 @project = Project.find(params[:id])
Chris@0 225 @wiki = @project.wiki
Chris@0 226 render_404 unless @wiki
Chris@0 227 rescue ActiveRecord::RecordNotFound
Chris@0 228 render_404
Chris@0 229 end
Chris@0 230
Chris@0 231 # Finds the requested page and returns a 404 error if it doesn't exist
Chris@0 232 def find_existing_page
Chris@0 233 @page = @wiki.find_page(params[:page])
Chris@0 234 render_404 if @page.nil?
Chris@0 235 end
Chris@0 236
Chris@0 237 # Returns true if the current user is allowed to edit the page, otherwise false
Chris@0 238 def editable?(page = @page)
Chris@0 239 page.editable_by?(User.current)
Chris@0 240 end
Chris@0 241
Chris@0 242 # Returns the default content of a new wiki page
Chris@0 243 def initial_page_content(page)
Chris@0 244 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
Chris@0 245 extend helper unless self.instance_of?(helper)
Chris@0 246 helper.instance_method(:initial_page_content).bind(self).call(page)
Chris@0 247 end
Chris@0 248 end