# frozen_string_literal: true require_relative 'base_command_builder' require_relative '../resource/context' module Gitlab module Triage module CommandBuilders class CommentBodyBuilder < BaseCommandBuilder SUPPORTED_PLACEHOLDERS = { created_at: "{{created_at}}", updated_at: "{{updated_at}}", closed_at: "{{closed_at}}", merged_at: "{{merged_at}}", state: "{{state}}", author: "@{{author.username}}", assignee: "@{{assignee.username}}", assignees: "@{{assignees.username}}", closed_by: "@{{closed_by.username}}", merged_by: "@{{merged_by.username}}", milestone: %(%"{{milestone.title}}"), labels: %(~"{{labels}}"), upvotes: "{{upvotes}}", downvotes: "{{downvotes}}" }.freeze PLACEHOLDER_REGEX = /{{([\w\.]+)}}/ attr_reader :resource, :net def initialize(items, resource: nil, net: {}) super(items) @resource = resource @net = net end private def separator "\n\n" end def format_item(item) return item unless resource replace_placeholders(eval_interpolation(item)) end def eval_interpolation(item) quoted_comment = "%Q{#{item}}" Resource::Context.new(resource, net).eval(quoted_comment) end def replace_placeholders(item) SUPPORTED_PLACEHOLDERS.inject(item) do |comment, (placeholder, formatted_text)| next comment unless comment.include?("{{#{placeholder}}}") methods = formatted_text.match(/.*#{PLACEHOLDER_REGEX}.*/)[1].split('.') fields = resource_fields(resource, methods) final_fields = fields.map { |field| formatted_text.sub(PLACEHOLDER_REGEX, field.to_s) } if final_fields.any? comment.gsub("{{#{placeholder}}}", final_fields.join(', ')) else comment end end end def resource_fields(resource, methods) method = methods.shift return Array(resource) unless method && resource return [] unless resource.key?(method) sub_resources = resource[method] Array.wrap(sub_resources).flat_map { |res| resource_fields(res, methods.dup) } end end end end end