require 'fileutils' module Orange class Orange::Carton # Define a helper for input type="text" type database stuff # Show in a context if wrapped in one of the helpers def self.asset(name, opts = {}) add_scaffold(name, :asset, Integer, opts.with_defaults(:lazy => true)) end end class AssetResource < Orange::ModelResource use OrangeAsset call_me :assets def stack_init if orange.options[:s3_bucket] require 'aws/s3' options[:s3_bucket] = orange.options[:s3_bucket] options[:s3_access_key_id] = orange.options[:s3_access_key_id] options[:s3_secret_access_key] = orange.options[:s3_secret_access_key] end orange[:admin, true].add_link("Content", :resource => @my_orange_name, :text => 'Assets') orange[:radius, true].define_tag "asset" do |tag| if tag.attr['id'] ret = (m = model_class.first(:id => tag.attr['id'])) ? m.to_asset_tag : 'Invalid Asset' if tag.attr['wrap'] ret = "
#{ret}
" else ret end else '' end end orange[:scaffold].add_scaffold_type(:asset) do |name, val, opts| if opts[:show] opts[:model].to_asset_tag else packet = opts[:packet] asset_html = val ? orange[:assets].asset_html(packet, val) : "" ret = "" if val.blank? ret += "Insert Asset" else ret += "#{asset_html}Change Asset" end ret = "
" + ret if opts[:label] end end end def onNew(packet, params = {}) m = false if(file = params['file'][:tempfile]) file_path = handle_new_file(params['file'][:filename], file) if(params['file2'] && secondary = params['file2'][:tempfile]) secondary_path = handle_new_file(params['file2'][:filename], secondary) else secondary_path = nil end params['path'] = file_path if file_path params['secondary_path'] = secondary_path if secondary_path params['mime_type'] = params['file'][:type] if file_path params['secondary_mime_type'] = params['file2'][:type] if secondary_path params.delete('file') params.delete('file2') params['s3_bucket'] = options[:s3_bucket] if options[:s3_bucket] m = model_class.new(params) end m end def onSave(packet, obj, params = {}) if(params['file'] && file = params['file'][:tempfile]) file_path = handle_new_file(params['file'][:filename], file) if(params['file2'] && secondary = params['file2'][:tempfile]) secondary_path = handle_new_file(params['file2'][:filename], secondary) else secondary_path = nil end params['path'] = file_path if file_path params['secondary_path'] = secondary_path if secondary_path params['mime_type'] = params['file'][:type] if file_path params['secondary_mime_type'] = params['file2'][:type] if secondary_path params['s3_bucket'] = options[:s3_bucket] if options[:s3_bucket] end params.delete('file') params.delete('file2') obj.update(params) end def s3_connect! if(options[:s3_bucket]) id = options[:s3_access_key_id] || ENV['S3_KEY'] secret = options[:s3_secret_access_key] || ENV['S3_SECRET'] AWS::S3::Base.establish_connection!( :access_key_id => id, :secret_access_key => secret ) end end def ensure_dir! if(options[:s3_bucket]) AWS::S3::Bucket.create(options[:s3_bucket]) unless AWS::S3::Bucket.find(options[:s3_bucket]) else FileUtils.mkdir_p(orange.app_dir('assets','uploaded')) unless File.exists?(orange.app_dir('assets','uploaded')) end end def handle_new_file(filename, file) s3_connect! ensure_dir! if(options[:s3_bucket]) filename = unique_s3_name(filename) AWS::S3::S3Object.store(filename, file, options[:s3_bucket], :access => :public_read) else filename = unique_local_name(filename) FileUtils.cp(file.path, orange.app_dir('assets','uploaded', filename)) FileUtils.chmod(0644, orange.app_dir('assets','uploaded', filename)) end return filename end def unique_s3_name(filename) return filename unless AWS::S3::S3Object.exists?(filename, options[:s3_bucket]) i = 1 extname = File.extname(filename) basename = File.basename(filename, extname) while AWS::S3::S3Object.exists?("#{basename}_#{i}#{extname}", options[:s3_bucket]) i += 1 end "#{basename}_#{i}#{extname}" end def unique_local_name(filename) return filename unless File.exists?(orange.app_dir('assets','uploaded', filename)) i = 1 extname = File.extname(filename) basename = File.basename(filename, extname) while File.exists?(orange.app_dir('assets', 'uploaded', "#{basename}_#{i}#{extname}")) i += 1 end "#{basename}_#{i}#{extname}" end # Creates a new model object and saves it (if a post), then reroutes to the main page # @param [Orange::Packet] packet the packet being routed def new(packet, opts = {}) no_reroute = opts.delete(:no_reroute) xhr = packet.request.xhr? || packet.request.params["fake_xhr"] if packet.request.post? || !opts.blank? params = opts.with_defaults(opts.delete(:params) || packet.request.params[@my_orange_name.to_s] || {}) before = beforeNew(packet, params) obj = onNew(packet, params) if before afterNew(packet, obj, params) if before obj.save if obj && before end packet.reroute(@my_orange_name, :orange) unless (xhr || no_reroute) packet['template.disable'] = true if xhr (xhr ? obj.to_s : obj) || false end def insert(packet, opts = {}) do_view(packet, :insert, opts) end def change(packet, opts = {}) do_view(packet, :change, opts) end def find_extras(packet, mode, opts = {}) {:list => model_class.all} end def onDelete(packet, m, opts = {}) begin if(m.s3_bucket) s3_connect! AWS::S3::S3Object.delete(m.path, m.s3_bucket) if m.path AWS::S3::S3Object.delete(m.secondary_path, m.s3_bucket) if m.secondary_path else FileUtils.rm(orange.app_dir('assets','uploaded', m.path)) if m.path FileUtils.rm(orange.app_dir('assets','uploaded', m.secondary_path)) if m.secondary_path end rescue # Problem deleting file end m.destroy if m end def asset_html(packet, id = false) id ||= packet['route.resource_id'] m = model_class.get(id) m ? m.to_asset_tag : false end end end