unepwcmc/SAPI

View on GitHub
app/workers/manual_download_worker.rb

Summary

Maintainability
A
3 hrs
Test Coverage
class ManualDownloadWorker
  include Sidekiq::Worker
  include Sidekiq::Status::Worker

  sidekiq_options :retry => false, :backtrace => 50

  def perform(download_id, params)
    @locale = params['locale']
    @download = Download.find(download_id)
    @download_path = download_location('zip', params)
    @display_name = params['taxon_name'] || MTaxonConcept.find(params['taxon_concept_id']).full_name
    unless File.exist?(@download_path.gsub('.pdf', '.zip'))
      doc_ids = MaterialDocIdsRetriever.run(params)
      @documents = Document.for_ids_with_order(doc_ids)

      zip_file_generator
    end

    @download.path     = [Rails.root, '/public/downloads/checklist/', @filename , '.zip'].join
    @download.filename = download_filename

    @download.display_name = @display_name # 'Id Manual resources'

    @download.status = "completed"

    @download.save!
  rescue => exception
    Appsignal.add_exception(exception) if defined? Appsignal
    @download.status = "failed"
    @download.save!
    raise exception
  end

  private

  def download_filename
    ctime = File.ctime(@download.path).strftime('%Y-%m-%d %H:%M')
    @download_name = "ID_Materials-#{@display_name}-#{ctime}.zip"
  end

  def download_location(ext, params)
    require 'digest/sha1'

    @filename = Digest::SHA1.hexdigest(
      params.
      merge(format: ext).
      merge(type: 'citesidmanual').
      merge(locale: I18n.locale).
      to_hash.
      symbolize_keys!.
      sort.
      to_s
    )
    return [Rails.root, '/public/downloads/checklist/', @filename, '.', 'pdf'].join
  end

  def zip_file_generator
    missing_files = []
    pdf_file_paths = []
    tmp_dir_path = [Rails.root, "/tmp/", SecureRandom.hex(8)].join
    FileUtils.mkdir tmp_dir_path
    input_name = 'merged_file.pdf'
    file_path = tmp_dir_path + '/' + input_name
    cover_path_generator
    pdf_file_paths << @cover_path
    @documents.each do |document|
      path_to_file = document.filename.path
      filename = path_to_file.split('/').last
      unless File.exists?(path_to_file)
        missing_files <<
          "{\n  title: #{document.title},\n  filename: #{filename}\n}"
      else
        pdf_file_paths << path_to_file
      end
    end
    PdfMerger.new(pdf_file_paths, file_path).merge

    FileUtils.cp file_path, @download_path
    FileUtils.rm_rf(tmp_dir_path)
    FileUtils.rm_rf(@cover_path)

    Zip::File.open([Rails.root, '/public/downloads/checklist/', @filename , '.zip'].join, Zip::File::CREATE) do |zip|
      zip.add("Identification-materials-#{@display_name}.pdf", @download_path)
      if missing_files.present?
        zip.add('missing_files.txt', missing_files.join("\n\n"))
      end
    end
    FileUtils.rm(@download_path)
  rescue => exception
    Appsignal.add_exception(exception) if defined? Appsignal
    @download.status = "failed"
    @download.save!
    raise exception
  end

  def cover_path_generator
    I18n.locale = @locale

    kit = PDFKit.new(
      ActionController::Base.new().render_to_string(
          template: '/checklist/_custom_id_manual_cover.html.erb',
          locals: { taxon_name: @display_name }
      ),
      page_size: 'A4',
      enable_local_file_access: true
    )

    kit.stylesheets << "#{Rails.root.to_s}/app/assets/stylesheets/checklist/custom_id_manual_cover.css"

    @cover_path = "public/downloads/checklist/#{@display_name}-cover.pdf"

    kit.to_file(@cover_path)
  end
end