summaryrefslogtreecommitdiff
path: root/app/services/work_items/task_list_reference_replacement_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/work_items/task_list_reference_replacement_service.rb')
-rw-r--r--app/services/work_items/task_list_reference_replacement_service.rb52
1 files changed, 52 insertions, 0 deletions
diff --git a/app/services/work_items/task_list_reference_replacement_service.rb b/app/services/work_items/task_list_reference_replacement_service.rb
new file mode 100644
index 00000000000..1044a4feb88
--- /dev/null
+++ b/app/services/work_items/task_list_reference_replacement_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class TaskListReferenceReplacementService
+ STALE_OBJECT_MESSAGE = 'Stale work item. Check lock version'
+
+ def initialize(work_item:, work_item_reference:, line_number_start:, line_number_end:, title:, lock_version:)
+ @work_item = work_item
+ @work_item_reference = work_item_reference
+ @line_number_start = line_number_start
+ @line_number_end = line_number_end
+ @title = title
+ @lock_version = lock_version
+ end
+
+ def execute
+ return ::ServiceResponse.error(message: STALE_OBJECT_MESSAGE) if @work_item.lock_version > @lock_version
+ return ::ServiceResponse.error(message: 'line_number_start must be greater than 0') if @line_number_start < 1
+ return ::ServiceResponse.error(message: 'line_number_end must be greater or equal to line_number_start') if @line_number_end < @line_number_start
+ return ::ServiceResponse.error(message: "Work item description can't be blank") if @work_item.description.blank?
+
+ source_lines = @work_item.description.split("\n")
+ markdown_task_first_line = source_lines[@line_number_start - 1]
+ task_line = Taskable::ITEM_PATTERN.match(markdown_task_first_line)
+
+ return ::ServiceResponse.error(message: "Unable to detect a task on line #{@line_number_start}") unless task_line
+
+ captures = task_line.captures
+
+ markdown_task_first_line.sub!(Taskable::ITEM_PATTERN, "#{captures[0]} #{captures[1]} #{@work_item_reference}+")
+
+ source_lines[@line_number_start - 1] = markdown_task_first_line
+ remove_additional_lines!(source_lines)
+
+ @work_item.update!(description: source_lines.join("\n"))
+
+ ::ServiceResponse.success
+ rescue ActiveRecord::StaleObjectError
+ ::ServiceResponse.error(message: STALE_OBJECT_MESSAGE)
+ end
+
+ private
+
+ def remove_additional_lines!(source_lines)
+ return if @line_number_end <= @line_number_start
+
+ source_lines.delete_if.each_with_index do |_line, index|
+ index >= @line_number_start && index < @line_number_end
+ end
+ end
+ end
+end