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)
Project.transaction do
# Wikis
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
# 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 to_be_copied = %w(wiki versions issue_categories issues members queries)
project.members.each do |member| to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
new_member = Member.new
new_member.attributes = member.attributes.dup.except("project_id") Project.transaction do
new_member.role_ids = member.role_ids.dup to_be_copied.each do |name|
new_member.project = self send "copy_#{name}", project
self.members << new_member
end 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"