SpontaneousCMS/spontaneous

View on GitHub
lib/spontaneous/cli/fields.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'open-uri'

module Spontaneous
  module Cli
    class Fields < ::Thor
      include Spontaneous::Cli::TaskUtils
      include ::Simultaneous::Task

      namespace :fields

      desc "update", "Performs asynchronous updates on provided fields"
      method_option :fields, type: :array, desc: "List of field IDs to update"
      def update(*args)
        update_fields
      end

      desc "reprocess", "Re-process the given image fields. Fields should be defined as a space-separated list of TypeName@field_name entries"
      method_option :fields, type: :array, desk: "List of field IDs to reprocess"
      def reprocess(*args)
        reprocess_fields
      end

      private

      def update_fields
        prepare! :update, :console
        site = Spontaneous::Site.instance
        fields = Spontaneous::Field.find(site.model, *options.fields)
        updater = Spontaneous::Field::Update::Immediate.new(site, fields)
        updater.run
        send_completion_event(updater)
      end

      def send_completion_event(updater)
        unlocked_pages = updater.pages.reject { |p| p.locked_for_update? }
        simultaneous_event('page_lock_status', unlocked_pages.map(&:id).to_json)
      end

      def reprocess_fields
        prepare! :reprocess, :console
        site = Spontaneous::Site.instance
        fields = lookup_fields(options.fields)
        fields.each do |type, field_name|
          instances = type.all
          instances.each_with_index do |instance, n|
            puts "===> #{type}/#{instance.id}  (#{n}/#{instances.length})"
            reprocess_field(instance, field_name, site)
          end
        end
      end

      def lookup_fields(field_list)
        field_list
          .map { |d| d.split('@') }
          .map { |type_name, field_name| [type_name.constantize, field_name.to_sym]  }
      end

      def reprocess_field(content, field_name, site)
        field = content.fields[field_name]
        url = field.original.url
        return if url.blank?
        puts " --> original: #{ url }"
        open(url) do |original|
          filename, _ = field.file_info
          Tempfile.open(["#{content.id}-#{field_name}", ::File.extname(filename)]) do |file|
            # Copy to new tempfile to get control over name & path of local tempfile
            IO.copy_stream(original, file)
            reprocess_field_original(content, field, file, site)
          end
        end
      rescue Errno::ENOENT
        puts "Failed to download #{content.class.name} id #{content.id}: #{ url }"
      end

      def reprocess_field_original(content, field, original, site)
        values = field.processed_values
        filename = field.original_filename
        digest = field.file_hash.presence || field.file_digest(original)
        field.outputs.reject { |n| n == :original }.each do |output|
          print " --> size :#{output} ... "
          media_file = site.file(content, filename, digest, field.storage_headers(field.mimetype.to_s, filename)).clone(original)
          values[output] = field.generate(output, media_file, site)
          puts values[output][:src]
        end
        field.send :processed_values=, values
        field.save
        content.save
      end
    end
  end
end