@@ -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 |
# |
|
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 |
|
|
450 | self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id")) | |
404 |
|
|
451 | project.wiki.pages.each do |page| | |
405 |
|
|
452 | new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id")) | |
406 |
|
|
453 | new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id")) | |
407 |
|
|
454 | new_wiki_page.content = new_wiki_content | |
408 |
|
||||
409 |
|
|
455 | self.wiki.pages << new_wiki_page | |
410 |
|
|
456 | end | |
|
457 | end | |||
411 |
|
458 | |||
412 | # Versions |
|
459 | # Copies versions from +project+ | |
|
460 | def copy_versions(project) | |||
413 |
|
|
461 | project.versions.each do |version| | |
414 |
|
|
462 | new_version = Version.new | |
415 |
|
|
463 | new_version.attributes = version.attributes.dup.except("project_id") | |
416 |
|
|
464 | self.versions << new_version | |
417 |
|
|
465 | end | |
|
466 | end | |||
418 |
|
467 | |||
|
468 | # Copies issue categories from +project+ | |||
|
469 | def copy_issue_categories(project) | |||
419 |
|
|
470 | project.issue_categories.each do |issue_category| | |
420 |
|
|
471 | new_issue_category = IssueCategory.new | |
421 |
|
|
472 | new_issue_category.attributes = issue_category.attributes.dup.except("project_id") | |
422 |
|
|
473 | self.issue_categories << new_issue_category | |
423 |
|
|
474 | end | |
|
475 | end | |||
424 |
|
476 | |||
425 | # Issues |
|
477 | # Copies issues from +project+ | |
|
478 | def copy_issues(project) | |||
426 |
|
|
479 | project.issues.each do |issue| | |
427 |
|
|
480 | new_issue = Issue.new | |
428 |
|
|
481 | new_issue.copy_from(issue) | |
@@ -436,11 +489,12 class Project < ActiveRecord::Base | |||||
436 |
|
|
489 | if issue.category | |
437 |
|
|
490 | new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first | |
438 |
|
|
491 | end | |
439 |
|
||||
440 |
|
|
492 | self.issues << new_issue | |
441 |
|
|
493 | end | |
|
494 | end | |||
442 |
|
495 | |||
443 | # Members |
|
496 | # Copies members from +project+ | |
|
497 | def copy_members(project) | |||
444 |
|
|
498 | project.members.each do |member| | |
445 |
|
|
499 | new_member = Member.new | |
446 |
|
|
500 | new_member.attributes = member.attributes.dup.except("project_id") | |
@@ -448,8 +502,10 class Project < ActiveRecord::Base | |||||
448 |
|
|
502 | new_member.project = self | |
449 |
|
|
503 | self.members << new_member | |
450 |
|
|
504 | end | |
|
505 | end | |||
451 |
|
506 | |||
452 | # Queries |
|
507 | # Copies queries from +project+ | |
|
508 | def copy_queries(project) | |||
453 |
|
|
509 | project.queries.each do |query| | |
454 |
|
|
510 | new_query = Query.new | |
455 |
|
|
511 | new_query.attributes = query.attributes.dup.except("project_id", "sort_criteria") | |
@@ -457,36 +513,8 class Project < ActiveRecord::Base | |||||
457 |
|
|
513 | new_query.project = self | |
458 |
|
|
514 | self.queries << new_query | |
459 |
|
|
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