end
end
- # Copies subtasks from the copied issue
+ # Callback for after the creation of an issue by copy
+ # * adds a "copied to" relation with the copied issue
+ # * copies subtasks from the copied issue
def after_create_from_copy
- return unless copy?
+ return unless copy? && !@after_create_from_copy_handled
- unless @copied_from.leaf? || @copy_options[:subtasks] == false || @subtasks_copied
+ if @copied_from.project_id == project_id || Setting.cross_project_issue_relations?
+ relation = IssueRelation.new(:issue_from => @copied_from, :issue_to => self, :relation_type => IssueRelation::TYPE_COPIED_TO)
+ unless relation.save
+ logger.error "Could not create relation while copying ##{@copied_from.id} to ##{id} due to validation errors: #{relation.errors.full_messages.join(', ')}" if logger
+ end
+ end
+
+ unless @copied_from.leaf? || @copy_options[:subtasks] == false
@copied_from.children.each do |child|
unless child.visible?
# Do not copy subtasks that are not visible to avoid potential disclosure of private data
logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
end
end
- @subtasks_copied = true
end
+ @after_create_from_copy_handled = true
end
def update_nested_set_attributes
TYPE_BLOCKED = "blocked"
TYPE_PRECEDES = "precedes"
TYPE_FOLLOWS = "follows"
+ TYPE_COPIED_TO = "copied_to"
+ TYPE_COPIED_FROM = "copied_from"
TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1, :sym => TYPE_RELATES },
TYPE_DUPLICATES => { :name => :label_duplicates, :sym_name => :label_duplicated_by, :order => 2, :sym => TYPE_DUPLICATED },
TYPE_BLOCKS => { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 4, :sym => TYPE_BLOCKED },
TYPE_BLOCKED => { :name => :label_blocked_by, :sym_name => :label_blocks, :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS },
TYPE_PRECEDES => { :name => :label_precedes, :sym_name => :label_follows, :order => 6, :sym => TYPE_FOLLOWS },
- TYPE_FOLLOWS => { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES }
+ TYPE_FOLLOWS => { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES },
+ TYPE_COPIED_TO => { :name => :label_copied_to, :sym_name => :label_copied_from, :order => 8, :sym => TYPE_COPIED_FROM },
+ TYPE_COPIED_FROM => { :name => :label_copied_from, :sym_name => :label_copied_to, :order => 9, :sym => TYPE_COPIED_TO, :reverse => TYPE_COPIED_TO }
}.freeze
validates_presence_of :issue_from, :issue_to, :relation_type
label_blocked_by: blocked by
label_precedes: precedes
label_follows: follows
+ label_copied_to: copied to
+ label_copied_from: copied from
label_end_to_start: end to start
label_end_to_end: end to end
label_start_to_start: start to start
label_blocked_by: bloqué par
label_precedes: précède
label_follows: suit
+ label_copied_to: copié vers
+ label_copied_from: copié depuis
label_end_to_start: fin à début
label_end_to_end: fin à fin
label_start_to_start: début à début
assert_equal count + 1, copy.attachments.count
end
+ def test_create_as_copy_should_add_relation_with_copied_issue
+ @request.session[:user_id] = 2
+
+ assert_difference 'Issue.count' do
+ assert_difference 'IssueRelation.count' do
+ post :create, :project_id => 1, :copy_from => 1,
+ :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
+ end
+ end
+ copy = Issue.first(:order => 'id DESC')
+ assert_equal 1, copy.relations.size
+ end
+
def test_create_as_copy_should_copy_subtasks
@request.session[:user_id] = 2
issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')
end
end
+ def test_bulk_copy_should_add_relations_with_copied_issues
+ @request.session[:user_id] = 2
+
+ assert_difference 'Issue.count', 2 do
+ assert_difference 'IssueRelation.count', 2 do
+ post :bulk_update, :ids => [1, 3], :copy => '1',
+ :issue => {
+ :project_id => '1'
+ }
+ end
+ end
+ end
+
def test_bulk_copy_should_allow_not_copying_the_subtasks
issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')
@request.session[:user_id] = 2
assert_equal orig.status, issue.status
end
+ def test_copy_should_add_relation_with_copied_issue
+ copied = Issue.find(1)
+ issue = Issue.new.copy_from(copied)
+ assert issue.save
+ issue.reload
+
+ assert_equal 1, issue.relations.size
+ relation = issue.relations.first
+ assert_equal 'copied_to', relation.relation_type
+ assert_equal copied, relation.issue_from
+ assert_equal issue, relation.issue_to
+ end
+
def test_copy_should_copy_subtasks
issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')