##// 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 @page.redirect_existing_links = true
198 @page.redirect_existing_links = true
199 # used to display the *original* title if some AR validation errors occur
199 # used to display the *original* title if some AR validation errors occur
200 @original_title = @page.pretty_title
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 flash[:notice] = l(:notice_successful_update)
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 end
205 end
205 end
206 end
206
207
@@ -344,7 +345,11 private
344 end
345 end
345
346
346 def redirect_to_page(page)
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 end
353 end
349
354
350 # Returns true if the current user is allowed to edit the page, otherwise false
355 # Returns true if the current user is allowed to edit the page, otherwise false
@@ -35,6 +35,16 module WikiHelper
35 s
35 s
36 end
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 def wiki_page_breadcrumb(page)
48 def wiki_page_breadcrumb(page)
39 breadcrumb(page.ancestors.reverse.collect {|parent|
49 breadcrumb(page.ancestors.reverse.collect {|parent|
40 link_to(h(parent.pretty_title), {:controller => 'wiki', :action => 'show', :id => parent.title, :project_id => parent.project, :version => nil})
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 include Redmine::SafeAttributes
19 include Redmine::SafeAttributes
20 belongs_to :project
20 belongs_to :project
21 has_many :pages, lambda {order('title')}, :class_name => 'WikiPage', :dependent => :destroy
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 acts_as_watchable
24 acts_as_watchable
25
25
@@ -27,6 +27,8 class Wiki < ActiveRecord::Base
27 validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/
27 validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/
28 attr_protected :id
28 attr_protected :id
29
29
30 before_destroy :delete_redirects
31
30 safe_attributes 'start_page'
32 safe_attributes 'start_page'
31
33
32 def visible?(user=User.current)
34 def visible?(user=User.current)
@@ -52,11 +54,11 class Wiki < ActiveRecord::Base
52 title = start_page if title.blank?
54 title = start_page if title.blank?
53 title = Wiki.titleize(title)
55 title = Wiki.titleize(title)
54 page = pages.where("LOWER(title) = LOWER(?)", title).first
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 # search for a redirect
58 # search for a redirect
57 redirect = redirects.where("LOWER(title) = LOWER(?)", title).first
59 redirect = redirects.where("LOWER(title) = LOWER(?)", title).first
58 if redirect
60 if redirect
59 page = find_page(redirect.redirects_to, :with_redirect => false)
61 page = redirect.target_page
60 @page_found_with_redirect = true
62 @page_found_with_redirect = true
61 end
63 end
62 end
64 end
@@ -68,6 +70,12 class Wiki < ActiveRecord::Base
68 @page_found_with_redirect
70 @page_found_with_redirect
69 end
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 # Finds a page by title
79 # Finds a page by title
72 # The given string can be of one of the forms: "title" or "project:title"
80 # The given string can be of one of the forms: "title" or "project:title"
73 # Examples:
81 # Examples:
@@ -46,8 +46,9 class WikiPage < ActiveRecord::Base
46 attr_protected :id
46 attr_protected :id
47
47
48 validate :validate_parent_title
48 validate :validate_parent_title
49 before_destroy :remove_redirects
49 before_destroy :delete_redirects
50 before_save :handle_redirects
50 before_save :handle_rename_or_move
51 after_save :handle_children_move
51
52
52 # eager load information about last updates, without loading text
53 # eager load information about last updates, without loading text
53 scope :with_updated_on, lambda {
54 scope :with_updated_on, lambda {
@@ -58,7 +59,7 class WikiPage < ActiveRecord::Base
58 # Wiki pages that are protected by default
59 # Wiki pages that are protected by default
59 DEFAULT_PROTECTED_PAGES = %w(sidebar)
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 :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)}
63 :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)}
63
64
64 def initialize(attributes=nil, *args)
65 def initialize(attributes=nil, *args)
@@ -74,30 +75,67 class WikiPage < ActiveRecord::Base
74
75
75 def title=(value)
76 def title=(value)
76 value = Wiki.titleize(value)
77 value = Wiki.titleize(value)
77 @previous_title = read_attribute(:title) if @previous_title.blank?
78 write_attribute(:title, value)
78 write_attribute(:title, value)
79 end
79 end
80
80
81 def handle_redirects
81 def safe_attributes=(attrs, user=User.current)
82 self.title = Wiki.titleize(title)
82 return unless attrs.is_a?(Hash)
83 # Manage redirects if the title has changed
83 attrs = attrs.deep_dup
84 if !@previous_title.blank? && (@previous_title != title) && !new_record?
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 # Update redirects that point to the old title
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 r.redirects_to = title
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 end
103 end
90 # Remove redirects for the new title
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 # Create a redirect to the new title
106 # Create a redirect to the new title
93 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
107 unless redirect_existing_links == "0"
94 @previous_title = nil
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 end
118 end
96 end
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
136 # Deletes redirects to this page
99 # Remove redirects to this page
137 def delete_redirects
100 wiki.redirects.where(:redirects_to => title).each(&:destroy)
138 WikiRedirect.where(:redirects_to_wiki_id => wiki_id, :redirects_to => title).delete_all
101 end
139 end
102
140
103 def pretty_title
141 def pretty_title
@@ -136,7 +174,7 class WikiPage < ActiveRecord::Base
136 end
174 end
137
175
138 def project
176 def project
139 wiki.project
177 wiki.try(:project)
140 end
178 end
141
179
142 def text
180 def text
@@ -196,7 +234,9 class WikiPage < ActiveRecord::Base
196 def validate_parent_title
234 def validate_parent_title
197 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
235 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
198 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
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 end
240 end
201 end
241 end
202
242
@@ -18,7 +18,22
18 class WikiRedirect < ActiveRecord::Base
18 class WikiRedirect < ActiveRecord::Base
19 belongs_to :wiki
19 belongs_to :wiki
20
20
21 validates_presence_of :title, :redirects_to
21 validates_presence_of :wiki_id, :title, :redirects_to
22 validates_length_of :title, :redirects_to, :maximum => 255
22 validates_length_of :title, :redirects_to, :maximum => 255
23 attr_protected :id
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 end
39 end
@@ -16,6 +16,11
16 @wiki.pages.includes(:parent).to_a - @page.self_and_descendants,
16 @wiki.pages.includes(:parent).to_a - @page.self_and_descendants,
17 @page.parent),
17 @page.parent),
18 :label => :field_parent_title %></p>
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 </div>
24 </div>
20 <%= submit_tag l(:button_rename) %>
25 <%= submit_tag l(:button_rename) %>
21 <% end %>
26 <% end %>
@@ -660,6 +660,39 class WikiControllerTest < ActionController::TestCase
660 assert_nil WikiPage.find_by_title('Child_1').parent
660 assert_nil WikiPage.find_by_title('Child_1').parent
661 end
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 def test_destroy_a_page_without_children_should_not_ask_confirmation
696 def test_destroy_a_page_without_children_should_not_ask_confirmation
664 @request.session[:user_id] = 2
697 @request.session[:user_id] = 2
665 delete :destroy, :project_id => 1, :id => 'Child_2'
698 delete :destroy, :project_id => 1, :id => 'Child_2'
@@ -101,6 +101,26 class WikiPageTest < ActiveSupport::TestCase
101 assert page.save
101 assert page.save
102 end
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 def test_destroy
124 def test_destroy
105 page = WikiPage.find(1)
125 page = WikiPage.find(1)
106 page.destroy
126 page.destroy
@@ -25,15 +25,38 class WikiRedirectTest < ActiveSupport::TestCase
25 @original = WikiPage.create(:wiki => @wiki, :title => 'Original title')
25 @original = WikiPage.create(:wiki => @wiki, :title => 'Original title')
26 end
26 end
27
27
28 def test_create_redirect
28 def test_create_redirect_on_rename
29 @original.title = 'New title'
29 @original.title = 'New title'
30 assert @original.save
30 @original.save!
31 @original.reload
32
31
33 assert_equal 'New_title', @original.title
32 redirect = @wiki.redirects.find_by_title('Original_title')
34 assert @wiki.redirects.find_by_title('Original_title')
33 assert_not_nil redirect
35 assert @wiki.find_page('Original title')
34 assert_equal 1, redirect.redirects_to_wiki_id
36 assert @wiki.find_page('ORIGINAL title')
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 end
60 end
38
61
39 def test_update_redirect
62 def test_update_redirect
@@ -97,4 +97,18 class WikiTest < ActiveSupport::TestCase
97 assert_kind_of WikiPage, @wiki.sidebar
97 assert_kind_of WikiPage, @wiki.sidebar
98 assert_equal 'Sidebar', @wiki.sidebar.title
98 assert_equal 'Sidebar', @wiki.sidebar.title
99 end
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 end
114 end
General Comments 0
You need to be logged in to leave comments. Login now