# frozen_string_literal: true module LetterOpenerWeb class Letter attr_reader :id, :sent_at def self.letters_location @letters_location ||= LetterOpenerWeb.config.letters_location end def self.letters_location=(directory) LetterOpenerWeb.configure { |config| config.letters_location = directory } @letters_location = nil end def self.search letters = Dir.glob("#{LetterOpenerWeb.config.letters_location}/*").map do |folder| new(id: File.basename(folder), sent_at: File.mtime(folder)) end letters.sort_by(&:sent_at).reverse end def self.find(id) new(id: id) end def self.destroy_all FileUtils.rm_rf(LetterOpenerWeb.config.letters_location) end def initialize(params) @id = params.fetch(:id) @sent_at = params[:sent_at] end def plain_text @plain_text ||= adjust_link_targets(read_file(:plain)) end def rich_text @rich_text ||= adjust_link_targets(read_file(:rich)) end def to_param id end def default_style style_exists?('rich') ? 'rich' : 'plain' end def attachments @attachments ||= Dir["#{base_dir}/attachments/*"].each_with_object({}) do |file, hash| hash[File.basename(file)] = File.expand_path(file) end end def delete FileUtils.rm_rf("#{LetterOpenerWeb.config.letters_location}/#{id}") end def exists? File.exist?(base_dir) end private def base_dir "#{LetterOpenerWeb.config.letters_location}/#{id}" end def read_file(style) File.read("#{base_dir}/#{style}.html") end def style_exists?(style) File.exist?("#{base_dir}/#{style}.html") end def adjust_link_targets(contents) # We cannot feed the whole file to an XML parser as some mails are # "complete" (as in they have the whole structure) and letter_opener # prepends some information about the mail being sent, making REXML # complain about it contents.scan(%r{]+>(?:.|\s)*?}).each do |link| fixed_link = fix_link_html(link) xml = REXML::Document.new(fixed_link).root next if xml.attributes['href'] =~ /(plain|rich).html/ xml.attributes['target'] = '_blank' xml.add_text('') unless xml.text contents.gsub!(link, xml.to_s) end contents end def fix_link_html(link_html) # REFACTOR: we need a better way of fixing the link inner html link_html.dup.tap do |fixed_link| fixed_link.gsub!('
', '
') fixed_link.scan(/]+?)>/).each do |img| fixed_img = img.dup fixed_img.gsub!(/>$/, '/>') unless img =~ %r{/>$} fixed_link.gsub!(img, fixed_img) end end end end end