@@ -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,38 +391,91 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 | 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 | 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 |
|
|
404 | 451 |
|
|
405 | 452 |
|
|
406 | 453 |
|
|
407 | 454 |
|
|
408 | ||
|
409 | 455 |
|
|
410 | 456 |
|
|
457 | end | |
|
411 | 458 | |
|
412 | # Versions | |
|
459 | # Copies versions from +project+ | |
|
460 | def copy_versions(project) | |
|
413 | 461 |
|
|
414 | 462 |
|
|
415 | 463 |
|
|
416 | 464 |
|
|
417 | 465 |
|
|
466 | end | |
|
418 | 467 | |
|
468 | # Copies issue categories from +project+ | |
|
469 | def copy_issue_categories(project) | |
|
419 | 470 |
|
|
420 | 471 |
|
|
421 | 472 |
|
|
422 | 473 |
|
|
423 | 474 |
|
|
475 | end | |
|
424 | 476 | |
|
425 | # Issues | |
|
477 | # Copies issues from +project+ | |
|
478 | def copy_issues(project) | |
|
426 | 479 |
|
|
427 | 480 |
|
|
428 | 481 |
|
@@ -436,11 +489,12 class Project < ActiveRecord::Base | |||
|
436 | 489 |
|
|
437 | 490 |
|
|
438 | 491 |
|
|
439 | ||
|
440 | 492 |
|
|
441 | 493 |
|
|
494 | end | |
|
442 | 495 | |
|
443 | # Members | |
|
496 | # Copies members from +project+ | |
|
497 | def copy_members(project) | |
|
444 | 498 |
|
|
445 | 499 |
|
|
446 | 500 |
|
@@ -448,8 +502,10 class Project < ActiveRecord::Base | |||
|
448 | 502 |
|
|
449 | 503 |
|
|
450 | 504 |
|
|
505 | end | |
|
451 | 506 | |
|
452 | # Queries | |
|
507 | # Copies queries from +project+ | |
|
508 | def copy_queries(project) | |
|
453 | 509 |
|
|
454 | 510 |
|
|
455 | 511 |
|
@@ -457,36 +513,8 class Project < ActiveRecord::Base | |||
|
457 | 513 |
|
|
458 | 514 |
|
|
459 | 515 |
|
|
460 | ||
|
461 | Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self) | |
|
462 | self.save | |
|
463 | end | |
|
464 | 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 | 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