@@ -104,7 +104,7 class ProjectsController < ApplicationController | |||
|
104 | 104 | else |
|
105 | 105 | @project = Project.new(params[:project]) |
|
106 | 106 | @project.enabled_module_names = params[:enabled_modules] |
|
107 | if @project.copy(params[:id]) | |
|
107 | if @project.copy(params[:id], :only => params[:only]) | |
|
108 | 108 | flash[:notice] = l(:notice_successful_create) |
|
109 | 109 | redirect_to :controller => 'admin', :action => 'projects' |
|
110 | 110 | end |
@@ -391,73 +391,30 class Project < ActiveRecord::Base | |||
|
391 | 391 | end |
|
392 | 392 | |
|
393 | 393 | # Copies and saves the Project instance based on the +project+. |
|
394 |
# |
|
|
394 | # Duplicates the source project's: | |
|
395 | # * Wiki | |
|
396 | # * Versions | |
|
397 | # * Categories | |
|
395 | 398 | # * Issues |
|
396 | 399 | # * Members |
|
397 | 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 | 409 | project = project.is_a?(Project) ? project : Project.find(project) |
|
400 | ||
|
401 | Project.transaction do | |
|
402 | # Wikis | |
|
403 | self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id")) | |
|
404 | project.wiki.pages.each do |page| | |
|
405 | new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id")) | |
|
406 | new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id")) | |
|
407 | new_wiki_page.content = new_wiki_content | |
|
408 | ||
|
409 | self.wiki.pages << new_wiki_page | |
|
410 | end | |
|
411 | ||
|
412 | # Versions | |
|
413 | project.versions.each do |version| | |
|
414 | new_version = Version.new | |
|
415 | new_version.attributes = version.attributes.dup.except("project_id") | |
|
416 | self.versions << new_version | |
|
417 | end | |
|
418 | ||
|
419 | project.issue_categories.each do |issue_category| | |
|
420 | new_issue_category = IssueCategory.new | |
|
421 | new_issue_category.attributes = issue_category.attributes.dup.except("project_id") | |
|
422 | self.issue_categories << new_issue_category | |
|
423 | end | |
|
424 | ||
|
425 | # Issues | |
|
426 | project.issues.each do |issue| | |
|
427 | new_issue = Issue.new | |
|
428 | new_issue.copy_from(issue) | |
|
429 | # Reassign fixed_versions by name, since names are unique per | |
|
430 | # project and the versions for self are not yet saved | |
|
431 | if issue.fixed_version | |
|
432 | new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first | |
|
433 | end | |
|
434 | # Reassign the category by name, since names are unique per | |
|
435 | # project and the categories for self are not yet saved | |
|
436 | if issue.category | |
|
437 | new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first | |
|
438 | end | |
|
439 | ||
|
440 | self.issues << new_issue | |
|
441 | end | |
|
442 | 410 | |
|
443 | # Members | |
|
444 | project.members.each do |member| | |
|
445 | new_member = Member.new | |
|
446 | new_member.attributes = member.attributes.dup.except("project_id") | |
|
447 | new_member.role_ids = member.role_ids.dup | |
|
448 | new_member.project = self | |
|
449 | self.members << new_member | |
|
450 | end | |
|
451 | ||
|
452 | # Queries | |
|
453 | project.queries.each do |query| | |
|
454 | new_query = Query.new | |
|
455 | new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria") | |
|
456 | new_query.sort_criteria = query.sort_criteria if query.sort_criteria | |
|
457 | new_query.project = self | |
|
458 | self.queries << new_query | |
|
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 | ||
|
414 | Project.transaction do | |
|
415 | to_be_copied.each do |name| | |
|
416 | send "copy_#{name}", project | |
|
459 | 417 | end |
|
460 | ||
|
461 | 418 | Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self) |
|
462 | 419 | self.save |
|
463 | 420 | end |
@@ -486,7 +443,78 class Project < ActiveRecord::Base | |||
|
486 | 443 | end |
|
487 | 444 | end |
|
488 | 445 | |
|
489 | private | |
|
446 | private | |
|
447 | ||
|
448 | # Copies wiki from +project+ | |
|
449 | def copy_wiki(project) | |
|
450 | self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id")) | |
|
451 | project.wiki.pages.each do |page| | |
|
452 | new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id")) | |
|
453 | new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id")) | |
|
454 | new_wiki_page.content = new_wiki_content | |
|
455 | self.wiki.pages << new_wiki_page | |
|
456 | end | |
|
457 | end | |
|
458 | ||
|
459 | # Copies versions from +project+ | |
|
460 | def copy_versions(project) | |
|
461 | project.versions.each do |version| | |
|
462 | new_version = Version.new | |
|
463 | new_version.attributes = version.attributes.dup.except("project_id") | |
|
464 | self.versions << new_version | |
|
465 | end | |
|
466 | end | |
|
467 | ||
|
468 | # Copies issue categories from +project+ | |
|
469 | def copy_issue_categories(project) | |
|
470 | project.issue_categories.each do |issue_category| | |
|
471 | new_issue_category = IssueCategory.new | |
|
472 | new_issue_category.attributes = issue_category.attributes.dup.except("project_id") | |
|
473 | self.issue_categories << new_issue_category | |
|
474 | end | |
|
475 | end | |
|
476 | ||
|
477 | # Copies issues from +project+ | |
|
478 | def copy_issues(project) | |
|
479 | project.issues.each do |issue| | |
|
480 | new_issue = Issue.new | |
|
481 | new_issue.copy_from(issue) | |
|
482 | # Reassign fixed_versions by name, since names are unique per | |
|
483 | # project and the versions for self are not yet saved | |
|
484 | if issue.fixed_version | |
|
485 | new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first | |
|
486 | end | |
|
487 | # Reassign the category by name, since names are unique per | |
|
488 | # project and the categories for self are not yet saved | |
|
489 | if issue.category | |
|
490 | new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first | |
|
491 | end | |
|
492 | self.issues << new_issue | |
|
493 | end | |
|
494 | end | |
|
495 | ||
|
496 | # Copies members from +project+ | |
|
497 | def copy_members(project) | |
|
498 | project.members.each do |member| | |
|
499 | new_member = Member.new | |
|
500 | new_member.attributes = member.attributes.dup.except("project_id") | |
|
501 | new_member.role_ids = member.role_ids.dup | |
|
502 | new_member.project = self | |
|
503 | self.members << new_member | |
|
504 | end | |
|
505 | end | |
|
506 | ||
|
507 | # Copies queries from +project+ | |
|
508 | def copy_queries(project) | |
|
509 | project.queries.each do |query| | |
|
510 | new_query = Query.new | |
|
511 | new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria") | |
|
512 | new_query.sort_criteria = query.sort_criteria if query.sort_criteria | |
|
513 | new_query.project = self | |
|
514 | self.queries << new_query | |
|
515 | end | |
|
516 | end | |
|
517 | ||
|
490 | 518 | def allowed_permissions |
|
491 | 519 | @allowed_permissions ||= begin |
|
492 | 520 | module_names = enabled_modules.collect {|m| m.name} |
@@ -12,5 +12,15 | |||
|
12 | 12 | <% end %> |
|
13 | 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 | 25 | <%= submit_tag l(:button_copy) %> |
|
16 | 26 | <% end %> |
@@ -499,6 +499,18 class ProjectTest < ActiveSupport::TestCase | |||
|
499 | 499 | end |
|
500 | 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 | 514 | should "copy issue relations" |
|
503 | 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