##// END OF EJS Templates
Project copy: let the user choose what to copy from the source project (everything by default)....
Jean-Philippe Lang -
r2852:5b787785b476
parent child
Show More
@@ -104,7 +104,7 class ProjectsController < ApplicationController
104 else
104 else
105 @project = Project.new(params[:project])
105 @project = Project.new(params[:project])
106 @project.enabled_module_names = params[:enabled_modules]
106 @project.enabled_module_names = params[:enabled_modules]
107 if @project.copy(params[:id])
107 if @project.copy(params[:id], :only => params[:only])
108 flash[:notice] = l(:notice_successful_create)
108 flash[:notice] = l(:notice_successful_create)
109 redirect_to :controller => 'admin', :action => 'projects'
109 redirect_to :controller => 'admin', :action => 'projects'
110 end
110 end
@@ -391,38 +391,91 class Project < ActiveRecord::Base
391 end
391 end
392
392
393 # Copies and saves the Project instance based on the +project+.
393 # Copies and saves the Project instance based on the +project+.
394 # Will duplicate the source project's:
394 # Duplicates the source project's:
395 # * Wiki
396 # * Versions
397 # * Categories
395 # * Issues
398 # * Issues
396 # * Members
399 # * Members
397 # * Queries
400 # * Queries
398 def copy(project)
401 #
402 # Accepts an +options+ argument to specify what to copy
403 #
404 # Examples:
405 # project.copy(1) # => copies everything
406 # project.copy(1, :only => 'members') # => copies members only
407 # project.copy(1, :only => ['members', 'versions']) # => copies members and versions
408 def copy(project, options={})
399 project = project.is_a?(Project) ? project : Project.find(project)
409 project = project.is_a?(Project) ? project : Project.find(project)
400
410
411 to_be_copied = %w(wiki versions issue_categories issues members queries)
412 to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
413
401 Project.transaction do
414 Project.transaction do
402 # Wikis
415 to_be_copied.each do |name|
416 send "copy_#{name}", project
417 end
418 Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self)
419 self.save
420 end
421 end
422
423
424 # Copies +project+ and returns the new instance. This will not save
425 # the copy
426 def self.copy_from(project)
427 begin
428 project = project.is_a?(Project) ? project : Project.find(project)
429 if project
430 # clear unique attributes
431 attributes = project.attributes.dup.except('name', 'identifier', 'id', 'status')
432 copy = Project.new(attributes)
433 copy.enabled_modules = project.enabled_modules
434 copy.trackers = project.trackers
435 copy.custom_values = project.custom_values.collect {|v| v.clone}
436 copy.issue_custom_fields = project.issue_custom_fields
437 return copy
438 else
439 return nil
440 end
441 rescue ActiveRecord::RecordNotFound
442 return nil
443 end
444 end
445
446 private
447
448 # Copies wiki from +project+
449 def copy_wiki(project)
403 self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id"))
450 self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id"))
404 project.wiki.pages.each do |page|
451 project.wiki.pages.each do |page|
405 new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id"))
452 new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id"))
406 new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id"))
453 new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id"))
407 new_wiki_page.content = new_wiki_content
454 new_wiki_page.content = new_wiki_content
408
409 self.wiki.pages << new_wiki_page
455 self.wiki.pages << new_wiki_page
410 end
456 end
457 end
411
458
412 # Versions
459 # Copies versions from +project+
460 def copy_versions(project)
413 project.versions.each do |version|
461 project.versions.each do |version|
414 new_version = Version.new
462 new_version = Version.new
415 new_version.attributes = version.attributes.dup.except("project_id")
463 new_version.attributes = version.attributes.dup.except("project_id")
416 self.versions << new_version
464 self.versions << new_version
417 end
465 end
466 end
418
467
468 # Copies issue categories from +project+
469 def copy_issue_categories(project)
419 project.issue_categories.each do |issue_category|
470 project.issue_categories.each do |issue_category|
420 new_issue_category = IssueCategory.new
471 new_issue_category = IssueCategory.new
421 new_issue_category.attributes = issue_category.attributes.dup.except("project_id")
472 new_issue_category.attributes = issue_category.attributes.dup.except("project_id")
422 self.issue_categories << new_issue_category
473 self.issue_categories << new_issue_category
423 end
474 end
475 end
424
476
425 # Issues
477 # Copies issues from +project+
478 def copy_issues(project)
426 project.issues.each do |issue|
479 project.issues.each do |issue|
427 new_issue = Issue.new
480 new_issue = Issue.new
428 new_issue.copy_from(issue)
481 new_issue.copy_from(issue)
@@ -436,11 +489,12 class Project < ActiveRecord::Base
436 if issue.category
489 if issue.category
437 new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first
490 new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first
438 end
491 end
439
440 self.issues << new_issue
492 self.issues << new_issue
441 end
493 end
494 end
442
495
443 # Members
496 # Copies members from +project+
497 def copy_members(project)
444 project.members.each do |member|
498 project.members.each do |member|
445 new_member = Member.new
499 new_member = Member.new
446 new_member.attributes = member.attributes.dup.except("project_id")
500 new_member.attributes = member.attributes.dup.except("project_id")
@@ -448,8 +502,10 class Project < ActiveRecord::Base
448 new_member.project = self
502 new_member.project = self
449 self.members << new_member
503 self.members << new_member
450 end
504 end
505 end
451
506
452 # Queries
507 # Copies queries from +project+
508 def copy_queries(project)
453 project.queries.each do |query|
509 project.queries.each do |query|
454 new_query = Query.new
510 new_query = Query.new
455 new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria")
511 new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria")
@@ -457,36 +513,8 class Project < ActiveRecord::Base
457 new_query.project = self
513 new_query.project = self
458 self.queries << new_query
514 self.queries << new_query
459 end
515 end
460
461 Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self)
462 self.save
463 end
464 end
516 end
465
517
466
467 # Copies +project+ and returns the new instance. This will not save
468 # the copy
469 def self.copy_from(project)
470 begin
471 project = project.is_a?(Project) ? project : Project.find(project)
472 if project
473 # clear unique attributes
474 attributes = project.attributes.dup.except('name', 'identifier', 'id', 'status')
475 copy = Project.new(attributes)
476 copy.enabled_modules = project.enabled_modules
477 copy.trackers = project.trackers
478 copy.custom_values = project.custom_values.collect {|v| v.clone}
479 copy.issue_custom_fields = project.issue_custom_fields
480 return copy
481 else
482 return nil
483 end
484 rescue ActiveRecord::RecordNotFound
485 return nil
486 end
487 end
488
489 private
490 def allowed_permissions
518 def allowed_permissions
491 @allowed_permissions ||= begin
519 @allowed_permissions ||= begin
492 module_names = enabled_modules.collect {|m| m.name}
520 module_names = enabled_modules.collect {|m| m.name}
@@ -12,5 +12,15
12 <% end %>
12 <% end %>
13 </fieldset>
13 </fieldset>
14
14
15 <fieldset class="box"><legend><%= l(:button_copy) %></legend>
16 <label class="floating"><%= check_box_tag 'only[]', 'members', true %> <%= l(:label_member_plural) %></label>
17 <label class="floating"><%= check_box_tag 'only[]', 'versions', true %> <%= l(:label_version_plural) %></label>
18 <label class="floating"><%= check_box_tag 'only[]', 'issue_categories', true %> <%= l(:label_issue_category_plural) %></label>
19 <label class="floating"><%= check_box_tag 'only[]', 'issues', true %> <%= l(:label_issue_plural) %></label>
20 <label class="floating"><%= check_box_tag 'only[]', 'queries', true %> <%= l(:label_query_plural) %></label>
21 <label class="floating"><%= check_box_tag 'only[]', 'wiki', true %> <%= l(:label_wiki) %></label>
22 <%= hidden_field_tag 'only[]', '' %>
23 </fieldset>
24
15 <%= submit_tag l(:button_copy) %>
25 <%= submit_tag l(:button_copy) %>
16 <% end %>
26 <% end %>
@@ -499,6 +499,18 class ProjectTest < ActiveSupport::TestCase
499 end
499 end
500 end
500 end
501
501
502 should "limit copy with :only option" do
503 assert @project.members.empty?
504 assert @project.issue_categories.empty?
505 assert @source_project.issues.any?
506
507 assert @project.copy(@source_project, :only => ['members', 'issue_categories'])
508
509 assert @project.members.any?
510 assert @project.issue_categories.any?
511 assert @project.issues.empty?
512 end
513
502 should "copy issue relations"
514 should "copy issue relations"
503 should "link issue relations if cross project issue relations are valid"
515 should "link issue relations if cross project issue relations are valid"
504
516
General Comments 0
You need to be logged in to leave comments. Login now