lib/scribd_fu.rb in mdarby-scribd_fu-1.2.3.2 vs lib/scribd_fu.rb in mdarby-scribd_fu-2.0

- old
+ new

@@ -1,108 +1,250 @@ -require 'attachment_fu/methods' -require 'paperclip/methods' - module ScribdFu - # A list of content types supported by scribd. - CONTENT_TYPES = ['application/pdf', 'image/jpeg', 'image/pjpeg', - 'image/gif', 'image/png', 'image/x-png', 'image/jpg', - 'application/msword', 'application/mspowerpoint', - 'application/vnd.ms-powerpoint', 'application/excel', - 'application/vnd.ms-excel', 'application/postscript', - 'text/plain', 'application/rtf', - 'application/vnd.oasis.opendocument.text', - 'application/vnd.oasis.opendocument.presentation', - 'application/vnd.oasis.opendocument.spreadsheet', - 'application/vnd.sun.xml.writer', - 'application/vnd.sun.xml.impress', - 'application/vnd.sun.xml.calc', - # OOXML, AKA `the MIME types from hell'. Seriously, these are long enough to - # start their own dictionary... + + ConfigPath = "#{RAILS_ROOT}/config/scribd_fu.yml".freeze + + # A list of content types supported by iPaper. + ContentTypes = [ + 'application/pdf', + 'application/msword', + 'application/mspowerpoint', + 'application/vnd.ms-powerpoint', + 'application/excel', + 'application/vnd.ms-excel', + 'application/postscript', + 'text/plain', + 'application/rtf', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.sun.xml.writer', + 'application/vnd.sun.xml.impress', + 'application/vnd.sun.xml.calc', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'application/vnd.openxmlformats-officedocument.presentationml.template', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.template'] + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' + ] - def self.included(base) - base.extend ActsAsScribdDocument + # Available parameters for the JS API + # http://www.scribd.com/publisher/api/api?method_name=Javascript+API + Available_JS_Params = [ :height, :width, :page, :my_user_id, :search_query, + :jsapi_version, :disable_related_docs, :mode, :auto_size ] + + class ScribdFuError < StandardError #:nodoc: end - module ActsAsScribdDocument - # Synonym for <tt>has_scribdable_attachment(nil)</tt>. - def acts_as_scribd_document - has_scribdable_attachment + class ScribdFuUploadError < ScribdFuError #:nodoc: + end + + + class << self + + def included(base) #:nodoc: + base.extend ClassMethods end - # Marks the given +attribute+ as a scribdable document file. If +attribute+ - # is nil, assumes this is an Attachment_fu model and deals with the setup - # accordingly; otherwise, assumes a +paperclip+ model and sets up scribding - # related to the particular given attribute. - def has_scribdable_attachment(attribute = nil) - class_eval do - include ScribdFu::InstanceMethods + # Login, store, and return a handle to the Scribd user account + def scribd_user + begin + # Ensure we can login to Scribd, and get a handle on the account + Scribd::API.instance.key = config[:key] + Scribd::API.instance.secret = config[:secret] + @scribd_user = Scribd::User.login(config[:user], config[:password]) + rescue + raise ScribdFuError, "Your Scribd credentials are incorrect" + end + end - if attribute.nil? - include ScribdFu::AttachmentFu::InstanceMethods - else - include ScribdFu::Paperclip::InstanceMethods # ignored if already done + # Upload a file to Scribd + def upload(obj, file_path) + begin + res = scribd_user.upload(:file => "#{file_path}", :access => access_level) + obj.update_attributes({:ipaper_id => res.doc_id, :ipaper_access_key => res.access_key}) + rescue + raise ScribdFuUploadError, "Sorry, but #{obj.class} ##{obj.id} could not be uploaded to Scribd" + end + end - add_scribd_attribute attribute # class method added by above include - end + # Delete an iPaper document + def destroy(document) + document.destroy + end + + # Read, store, and return the ScribdFu config file's contents + def config + raise ScribdFuError, "#{ConfigPath} does not exist" unless File.file?(ConfigPath) + + # Load the config file and strip any whitespace from the values + @config ||= YAML.load_file(ConfigPath).each_pair{|k,v| {k=>v.to_s.strip}}.symbolize_keys! + end + + # Get the preferred access level for iPaper documents + def access_level + config[:access] || 'private' + end + + # Load, store, and return the associated iPaper document + def load_ipaper_document(id) + begin + @document ||= scribd_user.find_document(id) + rescue + raise ScribdFuError, "Scribd Document ##{id} not found!" end end + end - module InstanceMethods - # Sets up Scribd configuration info when this module is included. - def self.included(base) - base.extend ClassMethods + module ClassMethods - mattr_reader :scribd_config, :scribd_login + # Load and inject ScribdFu goodies + def has_ipaper_and_uses(str) + check_environment + load_base_plugin(str) - begin - require 'rscribd' - rescue LoadError - raise RequiredLibraryNotFoundError.new('rscribd could not be loaded') + include InstanceMethods + + after_save :upload_to_scribd # This *MUST* be an after_save + before_destroy :destroy_ipaper_document + end + + private + + # Configure ScribdFu for this particular environment + def check_environment + load_rscribd + check_config + check_fields end - begin - unless @@scribd_login - @@scribd_config = YAML.load_file("#{RAILS_ROOT}/config/scribd.yml").symbolize_keys - @@scribd_config = @@scribd_config[:scribd] + def check_config + ScribdFu::config + end - # Ensure we can connect to the Service - Scribd::API.instance.key = @@scribd_config['key'].to_s.strip - Scribd::API.instance.secret = @@scribd_config['secret'].to_s.strip + # Load the rscribd gem + def load_rscribd + begin + require 'rscribd' + rescue LoadError + raise ScribdFuError, 'Please install the rscribd gem' + end + end - @@scribd_login = Scribd::User.login @@scribd_config['user'].to_s.strip, @@scribd_config['password'].to_s.strip + # Load Attachment_Fu specific methods and files + def load_attachment_fu + require 'scribd_fu/attachment_fu' + include ScribdFu::AttachmentFu::InstanceMethods + end + + # Load Paperclip specific methods and files + def load_paperclip + require 'scribd_fu/paperclip' + include ScribdFu::Paperclip::InstanceMethods + end + + # Ensure ScribdFu-centric attributes exist + def check_fields + fields = %w{ipaper_id ipaper_access_key}.inject([]){|stack, f| stack << "#{name}##{f}" unless column_names.include?(f); stack} + raise ScribdFuError, "These fields are missing: #{fields.to_sentence}" if fields.size > 0 + end + + # Load either AttachmentFu or Paperclip-specific methods + def load_base_plugin(str) + if str == 'AttachmentFu' + load_attachment_fu + elsif str == 'Paperclip' + load_paperclip + else + raise ScribdFuError, "Sorry, only Attachment_fu and Paperclip are supported." end - rescue - raise "config/scribd.yml file not found, or your credentials are incorrect." end + + end + + module InstanceMethods + + def self.included(base) + base.extend ClassMethods end - def access_level - if self.respond_to?(:is_public) && self.is_public != nil - scribd_access = self.is_public ? 'public' : 'private' - else - scribd_access = scribd_config['access'] - end + # Upload the associated file to Scribd for iPaper conversion + # This is called +after_save+ and cannot be called earlier, + # so don't get any ideas. + def upload_to_scribd + ScribdFu::upload(self, file_path) if scribdable? + end - scribd_access + # Checks whether the associated file is convertable to iPaper + def scribdable? + ContentTypes.include?(get_content_type) && ipaper_id.blank? end - end - module ClassMethods - # Sets up the scribd_options accessor, a before_destroy hook to ensure the - # deletion of associated Scribd documents, and an after_save hook to upload - # to scribd. - def self.extended(base) - base.class_inheritable_accessor :scribd_options + # Responds true if the conversion is converting + def conversion_processing? + !(conversion_complete? || conversion_successful? || conversion_error?) + end - base.before_destroy :destroy_scribd_documents - base.before_validation :upload_to_scribd + # Responds true if the conversion is complete -- note that this gives no + # indication as to whether the conversion had an error or was succesful, + # just that the conversion completed. + def conversion_complete? + ipaper_document && ipaper_document.conversion_status != 'PROCESSING' end + + # Responds true if the document has been converted. + def conversion_successful? + ipaper_document && ipaper_document.conversion_status =~ /^DISPLAYABLE|DONE$/ + end + + # Responds true if there was a conversion error while converting to iPaper. + def conversion_error? + ipaper_document && ipaper_document.conversion_status == 'ERROR' + end + + # Responds the Scribd::Document associated with this model, or nil if it does not exist. + def ipaper_document + @document ||= ScribdFu::load_ipaper_document(ipaper_id) + end + + # Destroys the scribd document for this record. This is called +before_destroy+ + def destroy_ipaper_document + ScribdFu::destroy(ipaper_document) if ipaper_document + end + + # Display the iPaper document in a view + def display_ipaper(options = {}) + alt = options.has_key?(:alt) ? options[:alt] : "" + + <<-END + <script type="text/javascript" src="http://www.scribd.com/javascripts/view.js"></script> + <div id="embedded_flash">#{alt}</div> + <script type="text/javascript"> + var scribd_doc = scribd.Document.getDoc(#{ipaper_id}, '#{ipaper_access_key}'); + #{js_params(options)} + scribd_doc.write("embedded_flash"); + </script> + END + end + + + private + + # Check and collect any Javascript params that might have been passed in + def js_params(options) + opt = [] + + options.each_pair do |k, v| + opt << "scribd_doc.addParam('#{k}', '#{v}');" if Available_JS_Params.include?(k) + end + + opt.compact.join("\n") + end + end + end + +# Let's do this. +ActiveRecord::Base.send(:include, ScribdFu) if Object.const_defined?("ActiveRecord") \ No newline at end of file