trabajo-afectivo/app/models/store.rb

329 lines
6.4 KiB
Ruby
Raw Normal View History

2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
require_dependency 'store/object'
require_dependency 'store/file'
class Store < ApplicationModel
2018-04-12 14:57:37 +00:00
belongs_to :store_object, class_name: 'Store::Object'
belongs_to :store_file, class_name: 'Store::File'
validates :filename, presence: true
store :preferences
2014-04-28 07:44:36 +00:00
=begin
add an attachment to storage
result = Store.add(
2016-01-24 11:50:29 +00:00
object: 'Ticket::Article',
o_id: 4711,
data: binary_string,
filename: 'filename.txt',
2016-01-24 11:50:29 +00:00
preferences: {
content_type: 'image/png',
content_id: 234,
2014-04-28 07:44:36 +00:00
}
)
returns
result = true
=end
2012-04-10 14:06:46 +00:00
def self.add(data)
data.deep_stringify_keys!
2012-04-10 14:06:46 +00:00
# lookup store_object.id
2016-01-24 11:50:29 +00:00
store_object = Store::Object.create_if_not_exists(name: data['object'])
2012-04-10 14:06:46 +00:00
data['store_object_id'] = store_object.id
2012-12-02 10:18:55 +00:00
# add to real store
2016-01-24 11:50:29 +00:00
file = Store::File.add(data['data'])
2012-12-02 10:18:55 +00:00
2013-01-24 08:18:29 +00:00
data['size'] = data['data'].to_s.bytesize
2012-04-10 14:06:46 +00:00
data['store_file_id'] = file.id
# not needed attributes
data.delete('data')
data.delete('object')
data['preferences'] ||= {}
resizable = false
['Mime-Type', 'Content-Type', 'mime_type', 'content_type'].each do |key|
next if data['preferences'][key].blank?
next if !data['preferences'][key].match(%r{image/(jpeg|jpg|png)}i)
resizable = true
break
end
2012-04-10 14:06:46 +00:00
# store meta data
store = Store.create!(data)
2012-04-10 14:06:46 +00:00
begin
if resizable
if store.content_preview(silence: true)
store.preferences[:resizable] = true
store.preferences[:content_preview] = true
end
if store.content_inline(silence: true)
store.preferences[:resizable] = true
store.preferences[:content_inline] = true
end
if store.preferences[:resizable]
store.save!
end
end
rescue => e
logger.error e
store.preferences[:resizable] = false
store.save!
end
2014-10-06 20:24:21 +00:00
store
2012-04-10 14:06:46 +00:00
end
2012-12-02 10:18:55 +00:00
2014-04-28 07:44:36 +00:00
=begin
get attachment of object
list = Store.list(
2016-01-24 11:50:29 +00:00
object: 'Ticket::Article',
o_id: 4711,
2014-04-28 07:44:36 +00:00
)
returns
result = [store1, store2]
store1 = {
2016-01-24 11:50:29 +00:00
size: 94123,
filename: 'image.png',
preferences: {
content_type: 'image/png',
content_id: 234,
2014-04-28 07:44:36 +00:00
}
}
store1.content # binary_string
=end
2012-04-10 14:06:46 +00:00
def self.list(data)
# search
2016-01-24 11:50:29 +00:00
store_object_id = Store::Object.lookup(name: data[:object])
stores = Store.where(store_object_id: store_object_id, o_id: data[:o_id].to_i)
.order(created_at: :asc)
stores
2012-04-10 14:06:46 +00:00
end
2014-04-28 07:44:36 +00:00
=begin
2014-10-06 20:24:21 +00:00
remove attachments of object from storage
2014-04-28 07:44:36 +00:00
result = Store.remove(
2016-01-24 11:50:29 +00:00
object: 'Ticket::Article',
o_id: 4711,
2014-04-28 07:44:36 +00:00
)
returns
result = true
=end
2012-04-10 14:06:46 +00:00
def self.remove(data)
# search
2016-01-24 11:50:29 +00:00
store_object_id = Store::Object.lookup(name: data[:object])
stores = Store.where(store_object_id: store_object_id)
.where(o_id: data[:o_id])
.order(created_at: :asc)
2012-04-10 14:06:46 +00:00
stores.each do |store|
2014-04-28 07:44:36 +00:00
# check backend for references
2016-01-24 11:50:29 +00:00
Store.remove_item(store.id)
2014-10-06 20:24:21 +00:00
end
true
2014-10-06 20:24:21 +00:00
end
=begin
remove one attachment from storage
2014-04-28 07:44:36 +00:00
Store.remove_item(store_id)
2014-10-06 20:24:21 +00:00
=end
def self.remove_item(store_id)
store = Store.find(store_id)
file_id = store.store_file_id
2014-10-06 20:24:21 +00:00
# check backend for references
files = Store.where(store_file_id: file_id)
if files.count > 1 || files.first.id != store.id
store.destroy!
return true
end
2014-10-06 20:24:21 +00:00
store.destroy!
Store::File.find(file_id).destroy!
2012-04-10 14:06:46 +00:00
end
=begin
get content of file
store = Store.find(store_id)
content_as_string = store.content
returns
content_as_string
=end
2014-04-28 07:44:36 +00:00
def content
2016-01-24 11:50:29 +00:00
file = Store::File.find_by(id: store_file_id)
if !file
2016-03-01 14:26:46 +00:00
raise "No such file #{store_file_id}!"
2014-04-28 07:44:36 +00:00
end
file.content
2012-04-10 14:06:46 +00:00
end
=begin
get content of file in preview size
store = Store.find(store_id)
content_as_string = store.content_preview
returns
content_as_string
=end
def content_preview(options = {})
file = Store::File.find_by(id: store_file_id)
if !file
raise "No such file #{store_file_id}!"
end
raise 'Unable to generate preview' if options[:silence] != true && preferences[:content_preview] != true
image_resize(file.content, 200)
end
=begin
get content of file in inline size
store = Store.find(store_id)
content_as_string = store.content_inline
returns
content_as_string
=end
def content_inline(options = {})
file = Store::File.find_by(id: store_file_id)
if !file
raise "No such file #{store_file_id}!"
end
raise 'Unable to generate inline' if options[:silence] != true && preferences[:content_inline] != true
image_resize(file.content, 1800)
end
=begin
get content of file
store = Store.find(store_id)
location_of_file = store.save_to_file
returns
location_of_file
=end
def save_to_file(path = nil)
content
file = Store::File.find_by(id: store_file_id)
if !file
raise "No such file #{store_file_id}!"
end
if !path
2017-11-23 08:09:44 +00:00
path = Rails.root.join('tmp', filename)
end
::File.open(path, 'wb') do |handle|
handle.write file.content
end
path
end
def attributes_for_display
slice :id, :filename, :size, :preferences
end
def provider
2016-01-24 11:50:29 +00:00
file = Store::File.find_by(id: store_file_id)
if !file
2016-03-01 14:26:46 +00:00
raise "No such file #{store_file_id}!"
2014-04-28 07:44:36 +00:00
end
file.provider
2014-04-28 07:44:36 +00:00
end
def self.semaphore
@semaphore ||= Mutex.new
end
private
def image_resize(content, width)
local_sha = Digest::SHA256.hexdigest(content)
cache_key = "image-resize-#{local_sha}_#{width}"
all = nil
image = Cache.get(cache_key)
return image if image
temp_file = ::Tempfile.new
temp_file.binmode
temp_file.write(content)
temp_file.close
temp_file_resize = nil
self.class.semaphore.synchronize do
image = Rszr::Image.load(temp_file.path)
# do not resize image if image is smaller or already same size
return if image.width <= width
# do not resize image if new height is smaller then 7px (images
# with small height are usally usefull to resize)
ratio = image.width / width
return if image.height / ratio <= 6
image.resize!(width, :auto)
temp_file_resize = ::Tempfile.new.path
image.save(temp_file_resize)
image.send(:handle).finalize!
end
image_resized = ::File.binread(temp_file_resize)
Cache.write(cache_key, image_resized, { expires_in: 6.months })
image_resized
end
end