##// END OF EJS Templates
Ability to delete a version from a wiki page history (#10852)....
Jean-Philippe Lang -
r10493:6cccdce06eff
parent child
Show More
@@ -0,0 +1,68
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
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 #
9 # 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 #
14 # 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 File.expand_path('../../test_helper', __FILE__)
19
20 class WikiContentTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
22
23 def setup
24 end
25
26 def test_destroy
27 v = WikiContent::Version.find(2)
28
29 assert_difference 'WikiContent::Version.count', -1 do
30 v.destroy
31 end
32 end
33
34 def test_destroy_last_version_should_revert_content
35 v = WikiContent::Version.find(3)
36
37 assert_no_difference 'WikiPage.count' do
38 assert_no_difference 'WikiContent.count' do
39 assert_difference 'WikiContent::Version.count', -1 do
40 assert v.destroy
41 end
42 end
43 end
44 c = WikiContent.find(1)
45 v = c.versions.last
46 assert_equal 2, c.version
47 assert_equal v.version, c.version
48 assert_equal v.comments, c.comments
49 assert_equal v.text, c.text
50 assert_equal v.author, c.author
51 assert_equal v.updated_on, c.updated_on
52 end
53
54 def test_destroy_all_versions_should_delete_page
55 WikiContent::Version.find(1).destroy
56 WikiContent::Version.find(2).destroy
57 v = WikiContent::Version.find(3)
58
59 assert_difference 'WikiPage.count', -1 do
60 assert_difference 'WikiContent.count', -1 do
61 assert_difference 'WikiContent::Version.count', -1 do
62 assert v.destroy
63 end
64 end
65 end
66 assert_nil WikiPage.find_by_id(1)
67 end
68 end
@@ -35,7 +35,7 class WikiController < ApplicationController
35 35 default_search_scope :wiki_pages
36 36 before_filter :find_wiki, :authorize
37 37 before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
38 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
38 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
39 39
40 40 helper :attachments
41 41 include AttachmentsHelper
@@ -237,6 +237,14 class WikiController < ApplicationController
237 237 redirect_to :action => 'index', :project_id => @project
238 238 end
239 239
240 def destroy_version
241 return render_403 unless editable?
242
243 @content = @page.content_for_version(params[:version])
244 @content.destroy
245 redirect_to_referer_or :action => 'history', :id => @page.title, :project_id => @project
246 end
247
240 248 # Export wiki to a single pdf or html file
241 249 def export
242 250 @pages = @wiki.pages.all(:order => 'title', :include => [:content, :attachments], :limit => 75)
@@ -147,6 +147,10 module ApplicationHelper
147 147 end
148 148 end
149 149
150 def wiki_page_path(page, options={})
151 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
152 end
153
150 154 def thumbnail_tag(attachment)
151 155 link_to image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment)),
152 156 {:controller => 'attachments', :action => 'show', :id => attachment, :filename => attachment.filename},
@@ -73,6 +73,8 class WikiContent < ActiveRecord::Base
73 73 "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
74 74 "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"}
75 75
76 after_destroy :page_update_after_destroy
77
76 78 def text=(plain)
77 79 case Setting.wiki_compression
78 80 when 'gzip'
@@ -128,5 +130,18 class WikiContent < ActiveRecord::Base
128 130 includes(:author).
129 131 where("wiki_content_id = ? AND version > ?", wiki_content_id, version).first
130 132 end
133
134 private
135
136 # Updates page's content if the latest version is removed
137 # or destroys the page if it was the only version
138 def page_update_after_destroy
139 latest = page.content.versions.reorder("#{self.class.table_name}.version DESC").first
140 if latest && page.content.version != latest.version
141 raise ActiveRecord::Rollback unless page.content.revert_to!(latest)
142 elsif latest.nil?
143 raise ActiveRecord::Rollback unless page.destroy
144 end
145 end
131 146 end
132 147 end
@@ -28,7 +28,10
28 28 <td class="updated_on"><%= format_time(ver.updated_on) %></td>
29 29 <td class="author"><%= link_to_user ver.author %></td>
30 30 <td class="comments"><%=h ver.comments %></td>
31 <td class="buttons"><%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %></td>
31 <td class="buttons">
32 <%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %>
33 <%= delete_link wiki_page_path(@page, :version => ver.version) if User.current.allowed_to?(:delete_wiki_pages, @page.project) && @version_count > 1 %>
34 </td>
32 35 </tr>
33 36 <% line_num += 1 %>
34 37 <% end %>
@@ -160,6 +160,7 RedmineApp::Application.routes.draw do
160 160 end
161 161 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
162 162 get 'wiki/:id/:version', :to => 'wiki#show'
163 delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
163 164 get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
164 165 get 'wiki/:id/:version/diff', :to => 'wiki#diff'
165 166 end
@@ -374,7 +374,7 module ActiveRecord #:nodoc:
374 374 # Clones a model. Used when saving a new version or reverting a model's version.
375 375 def clone_versioned_model(orig_model, new_model)
376 376 self.versioned_attributes.each do |key|
377 new_model.send("#{key}=", orig_model.send(key)) if orig_model.has_attribute?(key)
377 new_model.send("#{key}=", orig_model.send(key)) if orig_model.respond_to?(key)
378 378 end
379 379
380 380 if self.class.columns_hash.include?(self.class.inheritance_column)
@@ -118,7 +118,7 Redmine::AccessControl.map do |map|
118 118 map.project_module :wiki do |map|
119 119 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
120 120 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
121 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
121 map.permission :delete_wiki_pages, {:wiki => [:destroy, :destroy_version]}, :require => :member
122 122 map.permission :view_wiki_pages, {:wiki => [:index, :show, :special, :date_index]}, :read => true
123 123 map.permission :export_wiki_pages, {:wiki => [:export]}, :read => true
124 124 map.permission :view_wiki_edits, {:wiki => [:history, :diff, :annotate]}, :read => true
@@ -499,6 +499,7 class WikiControllerTest < ActionController::TestCase
499 499 end
500 500
501 501 def test_history
502 @request.session[:user_id] = 2
502 503 get :history, :project_id => 'ecookbook', :id => 'CookBook_documentation'
503 504 assert_response :success
504 505 assert_template 'history'
@@ -508,17 +509,24 class WikiControllerTest < ActionController::TestCase
508 509 assert_select "input[type=submit][name=commit]"
509 510 assert_select 'td' do
510 511 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => '2'
511 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate'
512 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate', :text => 'Annotate'
513 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => 'Delete'
512 514 end
513 515 end
514 516
515 517 def test_history_with_one_version
516 get :history, :project_id => 1, :id => 'Another_page'
518 @request.session[:user_id] = 2
519 get :history, :project_id => 'ecookbook', :id => 'Another_page'
517 520 assert_response :success
518 521 assert_template 'history'
519 522 assert_not_nil assigns(:versions)
520 523 assert_equal 1, assigns(:versions).size
521 524 assert_select "input[type=submit][name=commit]", false
525 assert_select 'td' do
526 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => '1'
527 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1/annotate', :text => 'Annotate'
528 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => 'Delete', :count => 0
529 end
522 530 end
523 531
524 532 def test_diff
@@ -681,6 +689,18 class WikiControllerTest < ActionController::TestCase
681 689 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
682 690 end
683 691
692 def test_destroy_version
693 @request.session[:user_id] = 2
694 assert_difference 'WikiContent::Version.count', -1 do
695 assert_no_difference 'WikiContent.count' do
696 assert_no_difference 'WikiPage.count' do
697 delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 2
698 assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation/history'
699 end
700 end
701 end
702 end
703
684 704 def test_index
685 705 get :index, :project_id => 'ecookbook'
686 706 assert_response :success
@@ -39,6 +39,11 class RoutingWikiTest < ActionController::IntegrationTest
39 39 :id => 'CookBook_documentation' }
40 40 )
41 41 assert_routing(
42 { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2" },
43 { :controller => 'wiki', :action => 'show', :project_id => '1',
44 :id => 'CookBook_documentation', :version => '2' }
45 )
46 assert_routing(
42 47 { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2/diff" },
43 48 { :controller => 'wiki', :action => 'diff', :project_id => '1',
44 49 :id => 'CookBook_documentation', :version => '2' }
@@ -117,5 +122,10 class RoutingWikiTest < ActionController::IntegrationTest
117 122 { :controller => 'wiki', :action => 'destroy', :project_id => '22',
118 123 :id => 'ladida' }
119 124 )
125 assert_routing(
126 { :method => 'delete', :path => "/projects/22/wiki/ladida/3" },
127 { :controller => 'wiki', :action => 'destroy_version', :project_id => '22',
128 :id => 'ladida', :version => '3' }
129 )
120 130 end
121 131 end
General Comments 0
You need to be logged in to leave comments. Login now