Project copy: let the user choose what to copy from the source project (everything by default).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2966 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2009-10-24 13:30:23 +00:00
parent 6842941adc
commit 5b787785b4
4 changed files with 113 additions and 63 deletions

View File

@ -104,7 +104,7 @@ class ProjectsController < ApplicationController
else else
@project = Project.new(params[:project]) @project = Project.new(params[:project])
@project.enabled_module_names = params[:enabled_modules] @project.enabled_module_names = params[:enabled_modules]
if @project.copy(params[:id]) if @project.copy(params[:id], :only => params[:only])
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'admin', :action => 'projects' redirect_to :controller => 'admin', :action => 'projects'
end end

View File

@ -391,73 +391,30 @@ class Project < ActiveRecord::Base
end end
# Copies and saves the Project instance based on the +project+. # Copies and saves the Project instance based on the +project+.
# Will duplicate the source project's: # Duplicates the source project's:
# * Wiki
# * Versions
# * Categories
# * Issues # * Issues
# * Members # * Members
# * Queries # * Queries
def copy(project) #
# Accepts an +options+ argument to specify what to copy
#
# Examples:
# project.copy(1) # => copies everything
# project.copy(1, :only => 'members') # => copies members only
# project.copy(1, :only => ['members', 'versions']) # => copies members and versions
def copy(project, options={})
project = project.is_a?(Project) ? project : Project.find(project) project = project.is_a?(Project) ? project : Project.find(project)
to_be_copied = %w(wiki versions issue_categories issues members queries)
to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
Project.transaction do Project.transaction do
# Wikis to_be_copied.each do |name|
self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id")) send "copy_#{name}", project
project.wiki.pages.each do |page|
new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id"))
new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id"))
new_wiki_page.content = new_wiki_content
self.wiki.pages << new_wiki_page
end end
# Versions
project.versions.each do |version|
new_version = Version.new
new_version.attributes = version.attributes.dup.except("project_id")
self.versions << new_version
end
project.issue_categories.each do |issue_category|
new_issue_category = IssueCategory.new
new_issue_category.attributes = issue_category.attributes.dup.except("project_id")
self.issue_categories << new_issue_category
end
# Issues
project.issues.each do |issue|
new_issue = Issue.new
new_issue.copy_from(issue)
# Reassign fixed_versions by name, since names are unique per
# project and the versions for self are not yet saved
if issue.fixed_version
new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first
end
# Reassign the category by name, since names are unique per
# project and the categories for self are not yet saved
if issue.category
new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first
end
self.issues << new_issue
end
# Members
project.members.each do |member|
new_member = Member.new
new_member.attributes = member.attributes.dup.except("project_id")
new_member.role_ids = member.role_ids.dup
new_member.project = self
self.members << new_member
end
# Queries
project.queries.each do |query|
new_query = Query.new
new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria")
new_query.sort_criteria = query.sort_criteria if query.sort_criteria
new_query.project = self
self.queries << new_query
end
Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self) Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self)
self.save self.save
end end
@ -486,7 +443,78 @@ class Project < ActiveRecord::Base
end end
end end
private private
# Copies wiki from +project+
def copy_wiki(project)
self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id"))
project.wiki.pages.each do |page|
new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id"))
new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id"))
new_wiki_page.content = new_wiki_content
self.wiki.pages << new_wiki_page
end
end
# Copies versions from +project+
def copy_versions(project)
project.versions.each do |version|
new_version = Version.new
new_version.attributes = version.attributes.dup.except("project_id")
self.versions << new_version
end
end
# Copies issue categories from +project+
def copy_issue_categories(project)
project.issue_categories.each do |issue_category|
new_issue_category = IssueCategory.new
new_issue_category.attributes = issue_category.attributes.dup.except("project_id")
self.issue_categories << new_issue_category
end
end
# Copies issues from +project+
def copy_issues(project)
project.issues.each do |issue|
new_issue = Issue.new
new_issue.copy_from(issue)
# Reassign fixed_versions by name, since names are unique per
# project and the versions for self are not yet saved
if issue.fixed_version
new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first
end
# Reassign the category by name, since names are unique per
# project and the categories for self are not yet saved
if issue.category
new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first
end
self.issues << new_issue
end
end
# Copies members from +project+
def copy_members(project)
project.members.each do |member|
new_member = Member.new
new_member.attributes = member.attributes.dup.except("project_id")
new_member.role_ids = member.role_ids.dup
new_member.project = self
self.members << new_member
end
end
# Copies queries from +project+
def copy_queries(project)
project.queries.each do |query|
new_query = Query.new
new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria")
new_query.sort_criteria = query.sort_criteria if query.sort_criteria
new_query.project = self
self.queries << new_query
end
end
def allowed_permissions def allowed_permissions
@allowed_permissions ||= begin @allowed_permissions ||= begin
module_names = enabled_modules.collect {|m| m.name} module_names = enabled_modules.collect {|m| m.name}

View File

@ -12,5 +12,15 @@
<% end %> <% end %>
</fieldset> </fieldset>
<fieldset class="box"><legend><%= l(:button_copy) %></legend>
<label class="floating"><%= check_box_tag 'only[]', 'members', true %> <%= l(:label_member_plural) %></label>
<label class="floating"><%= check_box_tag 'only[]', 'versions', true %> <%= l(:label_version_plural) %></label>
<label class="floating"><%= check_box_tag 'only[]', 'issue_categories', true %> <%= l(:label_issue_category_plural) %></label>
<label class="floating"><%= check_box_tag 'only[]', 'issues', true %> <%= l(:label_issue_plural) %></label>
<label class="floating"><%= check_box_tag 'only[]', 'queries', true %> <%= l(:label_query_plural) %></label>
<label class="floating"><%= check_box_tag 'only[]', 'wiki', true %> <%= l(:label_wiki) %></label>
<%= hidden_field_tag 'only[]', '' %>
</fieldset>
<%= submit_tag l(:button_copy) %> <%= submit_tag l(:button_copy) %>
<% end %> <% end %>

View File

@ -499,6 +499,18 @@ class ProjectTest < ActiveSupport::TestCase
end end
end end
should "limit copy with :only option" do
assert @project.members.empty?
assert @project.issue_categories.empty?
assert @source_project.issues.any?
assert @project.copy(@source_project, :only => ['members', 'issue_categories'])
assert @project.members.any?
assert @project.issue_categories.any?
assert @project.issues.empty?
end
should "copy issue relations" should "copy issue relations"
should "link issue relations if cross project issue relations are valid" should "link issue relations if cross project issue relations are valid"