diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 2669c60e6..36110ad3a 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -36,6 +36,7 @@ class WikiController < ApplicationController
before_action :find_wiki, :authorize
before_action :find_existing_or_new_page, :only => [:show, :edit]
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
+ before_action :find_copy_from, :only => [:show, :update]
before_action :find_attachments, :only => [:preview]
accept_api_auth :index, :show, :update, :destroy
@@ -63,7 +64,7 @@ class WikiController < ApplicationController
end
def new
- @page = WikiPage.new(:wiki => @wiki, :title => params[:title])
+ @page = WikiPage.new(:wiki => @wiki, :title => (params[:title] || params[:copy_from]))
unless User.current.allowed_to?(:edit_wiki_pages, @project)
render_403
return
@@ -72,12 +73,26 @@ class WikiController < ApplicationController
@page.title = '' unless editable?
@page.validate
if @page.errors[:title].blank?
- path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
+ if params[:copy_from]
+ copy_to_project = Project.find(params[:copy_to_project_id])
+ path = project_wiki_page_path(copy_to_project, @page.title, :parent => params[:parent], :copy_from => params[:copy_from], :copy_from_project_id => @project.id)
+ else
+ path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
+ end
respond_to do |format|
format.html {redirect_to path}
format.js {render :js => "window.location = #{path.to_json}"}
end
end
+ else
+ if params[:copy_from]
+ page_title_org = @page.title
+ suffix = 1
+ while @page.validate == false && @page.errors[:title].present?
+ @page.title = page_title_org + "_#{suffix}"
+ suffix += 1
+ end
+ end
end
end
@@ -136,6 +151,9 @@ class WikiController < ApplicationController
@content = @page.content_for_version(params[:version])
@content ||= WikiContent.new(:page => @page)
+ if @copy_from
+ @content.text = @copy_from.content.try(:text)
+ end
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@content.comments = nil
@@ -179,6 +197,11 @@ class WikiController < ApplicationController
@content.author = User.current
if @page.save_with_content(@content)
+ if @copy_from && params[:copy_attachments]
+ @page.attachments = @copy_from.attachments.collect do |attachment|
+ attachment.copy(:container => @page)
+ end
+ end
attachments = Attachment.attach_files(@page, params[:attachments] || (params[:wiki_page] && params[:wiki_page][:uploads]))
render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, {:params => params, :page => @page})
@@ -373,6 +396,14 @@ class WikiController < ApplicationController
end
end
+ def find_copy_from
+ @copy_from = if params[:copy_from_project_id] && params[:copy_from]
+ Project.find(params[:copy_from_project_id]).wiki.try(:find_page, params[:copy_from]) rescue nil
+ else
+ nil
+ end
+ end
+
def redirect_to_page(page)
if page.project && page.project.visible?
redirect_to :action => action_name, :project_id => page.project, :id => page.title
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 0b5f3b8f4..730e9c773 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -46,6 +46,14 @@ module WikiHelper
end
end
+ def wiki_page_project_options_for_select(page)
+ projects = Project.allowed_to(:add_wiki_pages).joins(:wiki).preload(:wiki).to_a
+ projects.select! {|p| p.enabled_module_names.include?('wiki') }
+ projects << page.project unless projects.include?(page.project)
+
+ project_tree_options_for_select(projects, :selected => page.project)
+ end
+
def wiki_page_breadcrumb(page)
breadcrumb(
page.ancestors.reverse.collect do |parent|
diff --git a/app/views/wiki/_copy_modal.html.erb b/app/views/wiki/_copy_modal.html.erb
new file mode 100644
index 000000000..a23a6c77e
--- /dev/null
+++ b/app/views/wiki/_copy_modal.html.erb
@@ -0,0 +1,42 @@
+
<%=l(:label_wiki_page_copy)%>
+
+<%= labelled_form_for :page, @page,
+ :url => project_copy_wiki_page_path(@project),
+ :method => 'post',
+ :remote => true do |f| %>
+
+ <%= render_error_messages @page.errors.full_messages_for(:title) %>
+ <%= hidden_field_tag 'copy_from_project_id', @project.id %>
+ <%= hidden_field_tag 'copy_from', params[:copy_from] %>
+
+
+
+
+ <%= select_tag :copy_to_project_id, wiki_page_project_options_for_select(@page), :label => :label_project %>
+
+ <%= f.text_field :title, :name => 'title', :size => 60, :required => true %>
+ <%= l(:text_unallowed_characters) %>: , . / ? ; : |
+
+ <% if params[:parent].present? %>
+
+
+
+ <% end %>
+
+
+ <%= submit_tag l(:label_next), :name => nil %>
+ <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
+
+<% end %>
+<%= javascript_tag do %>
+$('#copy_to_project_id').change(function() {
+ if ($('#copy_from_project_id').val()==$(this).val()) {
+ $('#copy_parent_page').show();
+ }else{
+ $('#copy_parent_page').hide();
+ }
+});
+<% end %>
diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb
index 7e9cf42af..fb82e873a 100644
--- a/app/views/wiki/edit.html.erb
+++ b/app/views/wiki/edit.html.erb
@@ -11,6 +11,8 @@
<%= hidden_field_tag 'section_hash', @section_hash %>
<% end %>
<%= error_messages_for 'content' %>
+<%= hidden_field_tag 'copy_from_project_id', params[:copy_from_project_id] if params[:copy_from_project_id] %>
+<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
<%= text_area_tag 'content[text]', @text, :cols => 100, :rows => 25, :accesskey => accesskey(:edit),
@@ -34,6 +36,12 @@
<% end %>
<%= f.text_field :comments, :size => 120, :maxlength => 1024 %>
+<% if @copy_from && @copy_from.attachments.any? %>
+
+
+ <%= check_box_tag 'copy_attachments', '1', true %>
+
+<% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 5397a521d..cedb01a36 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -857,6 +857,7 @@ en:
label_wiki_page: Wiki page
label_wiki_page_plural: Wiki pages
label_wiki_page_new: New wiki page
+ label_wiki_page_copy: Copy wiki page
label_index_by_title: Index by title
label_index_by_date: Index by date
label_current_version: Current version
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index aab7542a3..5925f10d7 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1199,6 +1199,7 @@ ja:
mail_body_settings_updated: ! '下記の設定が変更されました:'
field_remote_ip: IPアドレス
label_wiki_page_new: 新しいWikiページ
+ label_wiki_page_copy: Wikiページのコピー
label_relations: 関係
button_filter: フィルタ
mail_body_password_updated: パスワードが変更されました。
diff --git a/config/routes.rb b/config/routes.rb
index 00eadf679..e10b2a819 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -190,6 +190,7 @@ Rails.application.routes.draw do
end
match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
+ match 'wiki/:copy_from/copy', :to => 'wiki#new', :as => 'copy_wiki_page', via: [:get, :post]
resources :wiki, :except => [:index, :create], :as => 'wiki_page' do
member do
get 'rename'
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 3765ac867..51d5d7813 100644
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -1279,4 +1279,52 @@ class WikiControllerTest < Redmine::ControllerTest
assert_response :success
assert_select 'head>meta[name="robots"]', false
end
+
+ def test_get_new_with_copy_from
+ @request.session[:user_id] = 2
+
+ get :new, :params => {:project_id => 'ecookbook', :copy_from => 'CookBook_documentation'}
+ assert_response :success
+ assert_select 'input[name=?][value=?]', 'title', 'CookBook_documentation_1'
+ end
+
+ def test_post_new_with_copy_from_should_redirect_to_edit_wity_copy_params
+ @request.session[:user_id] = 2
+
+ post :new, :params => {:project_id => 'ecookbook', :title => 'CookBook documentation 1', :copy_from => 'CookBook_documentation', :copy_to_project_id => 'ecookbook'}
+ assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation_1?copy_from=CookBook_documentation©_from_project_id=1'
+ end
+
+ def test_show_with_copy_from_should_copy_content
+ @request.session[:user_id] = 2
+
+ get :show, :params => {:project_id => 1, :id => 'CookBook_documentation_1', :copy_from => 'CookBook_documentation', :copy_from_project_id => 1}
+ assert_response :success
+ assert_select 'textarea[name=?]', 'content[text]', :text => /h1. CookBook documentation/
+ assert_select 'textarea[name=?]', 'content[text]', :text => /{{child_pages}}/
+ assert_select 'textarea[name=?]', 'content[text]', :text => /Some updated \[\[documentation\]\] here with gzipped history/
+ end
+
+ def test_update_with_copy_from_and_copy_attachments_should_copy_attachments
+ @request.session[:user_id] = 2
+
+ assert_difference 'WikiPage.count' do
+ assert_difference 'WikiContent.count' do
+ assert_difference 'Attachment.count', 2 do
+ post :update, :params => {
+ :project_id => 1,
+ :id => 'CookBook_documentation_1',
+ :content => {
+ :comments => 'Copy Wiki Page',
+ :text => 'h1. CookBook documentation',
+ :varsion => 0
+ },
+ :copy_from => 'CookBook_documentation',
+ :copy_from_project_id => 1,
+ :copy_attachments => '1'
+ }
+ end
+ end
+ end
+ end
end