##// END OF EJS Templates
Move wiki page to other project (#5450)....
Jean-Philippe Lang -
r13261:e0a034164f34
parent child
Show More
@@ -0,0 +1,11
1 class AddWikiRedirectsRedirectsToWikiId < ActiveRecord::Migration
2 def self.up
3 add_column :wiki_redirects, :redirects_to_wiki_id, :integer
4 WikiRedirect.update_all "redirects_to_wiki_id = wiki_id"
5 change_column :wiki_redirects, :redirects_to_wiki_id, :integer, :null => false
6 end
7
8 def self.down
9 remove_column :wiki_redirects, :redirects_to_wiki_id
10 end
11 end
@@ -198,9 +198,10 class WikiController < ApplicationController
198 198 @page.redirect_existing_links = true
199 199 # used to display the *original* title if some AR validation errors occur
200 200 @original_title = @page.pretty_title
201 if request.post? && @page.update_attributes(params[:wiki_page])
201 @page.safe_attributes = params[:wiki_page]
202 if request.post? && @page.save
202 203 flash[:notice] = l(:notice_successful_update)
203 redirect_to project_wiki_page_path(@project, @page.title)
204 redirect_to project_wiki_page_path(@page.project, @page.title)
204 205 end
205 206 end
206 207
@@ -344,7 +345,11 private
344 345 end
345 346
346 347 def redirect_to_page(page)
347 redirect_to :action => action_name, :project_id => page.wiki.project, :id => page.title
348 if page.project && page.project.visible?
349 redirect_to :action => action_name, :project_id => page.project, :id => page.title
350 else
351 render_404
352 end
348 353 end
349 354
350 355 # Returns true if the current user is allowed to edit the page, otherwise false
@@ -35,6 +35,16 module WikiHelper
35 35 s
36 36 end
37 37
38 def wiki_page_wiki_options_for_select(page)
39 projects = Project.allowed_to(:rename_wiki_pages).joins(:wiki).preload(:wiki).to_a
40 projects << page.project unless projects.include?(page.project)
41
42 project_tree_options_for_select(projects, :selected => page.project) do |project|
43 wiki_id = project.wiki.try(:id)
44 {:value => wiki_id, :selected => wiki_id == page.wiki_id}
45 end
46 end
47
38 48 def wiki_page_breadcrumb(page)
39 49 breadcrumb(page.ancestors.reverse.collect {|parent|
40 50 link_to(h(parent.pretty_title), {:controller => 'wiki', :action => 'show', :id => parent.title, :project_id => parent.project, :version => nil})
@@ -19,7 +19,7 class Wiki < ActiveRecord::Base
19 19 include Redmine::SafeAttributes
20 20 belongs_to :project
21 21 has_many :pages, lambda {order('title')}, :class_name => 'WikiPage', :dependent => :destroy
22 has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
22 has_many :redirects, :class_name => 'WikiRedirect'
23 23
24 24 acts_as_watchable
25 25
@@ -27,6 +27,8 class Wiki < ActiveRecord::Base
27 27 validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/
28 28 attr_protected :id
29 29
30 before_destroy :delete_redirects
31
30 32 safe_attributes 'start_page'
31 33
32 34 def visible?(user=User.current)
@@ -52,11 +54,11 class Wiki < ActiveRecord::Base
52 54 title = start_page if title.blank?
53 55 title = Wiki.titleize(title)
54 56 page = pages.where("LOWER(title) = LOWER(?)", title).first
55 if !page && !(options[:with_redirect] == false)
57 if page.nil? && options[:with_redirect] != false
56 58 # search for a redirect
57 59 redirect = redirects.where("LOWER(title) = LOWER(?)", title).first
58 60 if redirect
59 page = find_page(redirect.redirects_to, :with_redirect => false)
61 page = redirect.target_page
60 62 @page_found_with_redirect = true
61 63 end
62 64 end
@@ -68,6 +70,12 class Wiki < ActiveRecord::Base
68 70 @page_found_with_redirect
69 71 end
70 72
73 # Deletes all redirects from/to the wiki
74 def delete_redirects
75 WikiRedirect.where(:wiki_id => id).delete_all
76 WikiRedirect.where(:redirects_to_wiki_id => id).delete_all
77 end
78
71 79 # Finds a page by title
72 80 # The given string can be of one of the forms: "title" or "project:title"
73 81 # Examples:
@@ -46,8 +46,9 class WikiPage < ActiveRecord::Base
46 46 attr_protected :id
47 47
48 48 validate :validate_parent_title
49 before_destroy :remove_redirects
50 before_save :handle_redirects
49 before_destroy :delete_redirects
50 before_save :handle_rename_or_move
51 after_save :handle_children_move
51 52
52 53 # eager load information about last updates, without loading text
53 54 scope :with_updated_on, lambda {
@@ -58,7 +59,7 class WikiPage < ActiveRecord::Base
58 59 # Wiki pages that are protected by default
59 60 DEFAULT_PROTECTED_PAGES = %w(sidebar)
60 61
61 safe_attributes 'parent_id', 'parent_title',
62 safe_attributes 'parent_id', 'parent_title', 'title', 'redirect_existing_links', 'wiki_id',
62 63 :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)}
63 64
64 65 def initialize(attributes=nil, *args)
@@ -74,30 +75,67 class WikiPage < ActiveRecord::Base
74 75
75 76 def title=(value)
76 77 value = Wiki.titleize(value)
77 @previous_title = read_attribute(:title) if @previous_title.blank?
78 78 write_attribute(:title, value)
79 79 end
80 80
81 def handle_redirects
82 self.title = Wiki.titleize(title)
83 # Manage redirects if the title has changed
84 if !@previous_title.blank? && (@previous_title != title) && !new_record?
81 def safe_attributes=(attrs, user=User.current)
82 return unless attrs.is_a?(Hash)
83 attrs = attrs.deep_dup
84
85 # Project and Tracker must be set before since new_statuses_allowed_to depends on it.
86 if (w_id = attrs.delete('wiki_id')) && safe_attribute?('wiki_id')
87 if (w = Wiki.find_by_id(w_id)) && w.project && user.allowed_to?(:rename_wiki_pages, w.project)
88 self.wiki = w
89 end
90 end
91
92 super attrs, user
93 end
94
95 # Manages redirects if page is renamed or moved
96 def handle_rename_or_move
97 if !new_record? && (title_changed? || wiki_id_changed?)
85 98 # Update redirects that point to the old title
86 wiki.redirects.where(:redirects_to => @previous_title).each do |r|
99 WikiRedirect.where(:redirects_to => title_was, :redirects_to_wiki_id => wiki_id_was).each do |r|
87 100 r.redirects_to = title
88 r.title == r.redirects_to ? r.destroy : r.save
101 r.redirects_to_wiki_id = wiki_id
102 (r.title == r.redirects_to && r.wiki_id == r.redirects_to_wiki_id) ? r.destroy : r.save
89 103 end
90 104 # Remove redirects for the new title
91 wiki.redirects.where(:title => title).each(&:destroy)
105 WikiRedirect.where(:wiki_id => wiki_id, :title => title).delete_all
92 106 # Create a redirect to the new title
93 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
94 @previous_title = nil
107 unless redirect_existing_links == "0"
108 WikiRedirect.create(
109 :wiki_id => wiki_id_was, :title => title_was,
110 :redirects_to_wiki_id => wiki_id, :redirects_to => title
111 )
112 end
113 end
114 if !new_record? && wiki_id_changed? && parent.present?
115 unless parent.wiki_id == wiki_id
116 self.parent_id = nil
117 end
95 118 end
96 119 end
120 private :handle_rename_or_move
121
122 # Moves child pages if page was moved
123 def handle_children_move
124 if !new_record? && wiki_id_changed?
125 children.each do |child|
126 child.wiki_id = wiki_id
127 child.redirect_existing_links = redirect_existing_links
128 unless child.save
129 WikiPage.where(:id => child.id).update_all :parent_nil => nil
130 end
131 end
132 end
133 end
134 private :handle_children_move
97 135
98 def remove_redirects
99 # Remove redirects to this page
100 wiki.redirects.where(:redirects_to => title).each(&:destroy)
136 # Deletes redirects to this page
137 def delete_redirects
138 WikiRedirect.where(:redirects_to_wiki_id => wiki_id, :redirects_to => title).delete_all
101 139 end
102 140
103 141 def pretty_title
@@ -136,7 +174,7 class WikiPage < ActiveRecord::Base
136 174 end
137 175
138 176 def project
139 wiki.project
177 wiki.try(:project)
140 178 end
141 179
142 180 def text
@@ -196,7 +234,9 class WikiPage < ActiveRecord::Base
196 234 def validate_parent_title
197 235 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
198 236 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
199 errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
237 if parent_id_changed? && parent && (parent.wiki_id != wiki_id)
238 errors.add(:parent_title, :not_same_project)
239 end
200 240 end
201 241 end
202 242
@@ -18,7 +18,22
18 18 class WikiRedirect < ActiveRecord::Base
19 19 belongs_to :wiki
20 20
21 validates_presence_of :title, :redirects_to
21 validates_presence_of :wiki_id, :title, :redirects_to
22 22 validates_length_of :title, :redirects_to, :maximum => 255
23 23 attr_protected :id
24
25 before_save :set_redirects_to_wiki_id
26
27 def target_page
28 wiki = Wiki.find_by_id(redirects_to_wiki_id)
29 if wiki
30 wiki.find_page(redirects_to, :with_redirect => false)
31 end
32 end
33
34 private
35
36 def set_redirects_to_wiki_id
37 self.redirects_to_wiki_id ||= wiki_id
38 end
24 39 end
@@ -16,6 +16,11
16 16 @wiki.pages.includes(:parent).to_a - @page.self_and_descendants,
17 17 @page.parent),
18 18 :label => :field_parent_title %></p>
19
20 <% if @page.safe_attribute? 'wiki_id' %>
21 <p><%= f.select :wiki_id, wiki_page_wiki_options_for_select(@page), :label => :label_project %></p>
22 <% end %>
23
19 24 </div>
20 25 <%= submit_tag l(:button_rename) %>
21 26 <% end %>
@@ -660,6 +660,39 class WikiControllerTest < ActionController::TestCase
660 660 assert_nil WikiPage.find_by_title('Child_1').parent
661 661 end
662 662
663 def test_get_rename_should_show_target_projects_list
664 @request.session[:user_id] = 2
665 project = Project.find(5)
666 project.enable_module! :wiki
667
668 get :rename, :project_id => 1, :id => 'Another_page'
669 assert_response :success
670 assert_template 'rename'
671
672 assert_select 'select[name=?]', 'wiki_page[wiki_id]' do
673 assert_select 'option', 2
674 assert_select 'option[value=?][selected=selected]', '1', :text => /eCookbook/
675 assert_select 'option[value=?]', project.wiki.id.to_s, :text => /#{project.name}/
676 end
677 end
678
679 def test_rename_with_move
680 @request.session[:user_id] = 2
681 project = Project.find(5)
682 project.enable_module! :wiki
683
684 post :rename, :project_id => 1, :id => 'Another_page',
685 :wiki_page => {
686 :wiki_id => project.wiki.id.to_s,
687 :title => 'Another renamed page',
688 :redirect_existing_links => 1
689 }
690 assert_redirected_to '/projects/private-child/wiki/Another_renamed_page'
691
692 page = WikiPage.find(2)
693 assert_equal project.wiki.id, page.wiki_id
694 end
695
663 696 def test_destroy_a_page_without_children_should_not_ask_confirmation
664 697 @request.session[:user_id] = 2
665 698 delete :destroy, :project_id => 1, :id => 'Child_2'
@@ -101,6 +101,26 class WikiPageTest < ActiveSupport::TestCase
101 101 assert page.save
102 102 end
103 103
104 def test_move_child_should_clear_parent
105 parent = WikiPage.create!(:wiki_id => 1, :title => 'Parent')
106 child = WikiPage.create!(:wiki_id => 1, :title => 'Child', :parent => parent)
107
108 child.wiki_id = 2
109 child.save!
110 assert_equal nil, child.reload.parent_id
111 end
112
113 def test_move_parent_should_move_child_page
114 parent = WikiPage.create!(:wiki_id => 1, :title => 'Parent')
115 child = WikiPage.create!(:wiki_id => 1, :title => 'Child', :parent => parent)
116 parent.reload
117
118 parent.wiki_id = 2
119 parent.save!
120 assert_equal 2, child.reload.wiki_id
121 assert_equal parent, child.parent
122 end
123
104 124 def test_destroy
105 125 page = WikiPage.find(1)
106 126 page.destroy
@@ -25,15 +25,38 class WikiRedirectTest < ActiveSupport::TestCase
25 25 @original = WikiPage.create(:wiki => @wiki, :title => 'Original title')
26 26 end
27 27
28 def test_create_redirect
28 def test_create_redirect_on_rename
29 29 @original.title = 'New title'
30 assert @original.save
31 @original.reload
30 @original.save!
32 31
33 assert_equal 'New_title', @original.title
34 assert @wiki.redirects.find_by_title('Original_title')
35 assert @wiki.find_page('Original title')
36 assert @wiki.find_page('ORIGINAL title')
32 redirect = @wiki.redirects.find_by_title('Original_title')
33 assert_not_nil redirect
34 assert_equal 1, redirect.redirects_to_wiki_id
35 assert_equal 'New_title', redirect.redirects_to
36 assert_equal @original, redirect.target_page
37 end
38
39 def test_create_redirect_on_move
40 @original.wiki_id = 2
41 @original.save!
42
43 redirect = @wiki.redirects.find_by_title('Original_title')
44 assert_not_nil redirect
45 assert_equal 2, redirect.redirects_to_wiki_id
46 assert_equal 'Original_title', redirect.redirects_to
47 assert_equal @original, redirect.target_page
48 end
49
50 def test_create_redirect_on_rename_and_move
51 @original.title = 'New title'
52 @original.wiki_id = 2
53 @original.save!
54
55 redirect = @wiki.redirects.find_by_title('Original_title')
56 assert_not_nil redirect
57 assert_equal 2, redirect.redirects_to_wiki_id
58 assert_equal 'New_title', redirect.redirects_to
59 assert_equal @original, redirect.target_page
37 60 end
38 61
39 62 def test_update_redirect
@@ -97,4 +97,18 class WikiTest < ActiveSupport::TestCase
97 97 assert_kind_of WikiPage, @wiki.sidebar
98 98 assert_equal 'Sidebar', @wiki.sidebar.title
99 99 end
100
101 def test_destroy_should_remove_redirects_from_the_wiki
102 WikiRedirect.create!(:wiki_id => 1, :title => 'Foo', :redirects_to_wiki_id => 2, :redirects_to => 'Bar')
103
104 Wiki.find(1).destroy
105 assert_equal 0, WikiRedirect.where(:wiki_id => 1).count
106 end
107
108 def test_destroy_should_remove_redirects_to_the_wiki
109 WikiRedirect.create!(:wiki_id => 2, :title => 'Foo', :redirects_to_wiki_id => 1, :redirects_to => 'Bar')
110
111 Wiki.find(1).destroy
112 assert_equal 0, WikiRedirect.where(:redirects_to_wiki_id => 1).count
113 end
100 114 end
General Comments 0
You need to be logged in to leave comments. Login now