Module: CamaleonCms::UploaderHelper

Includes:
ActionView::Helpers::NumberHelper
Included in:
CamaleonController
Defined in:
app/helpers/camaleon_cms/uploader_helper.rb

Overview

Camaleon CMS is a content management system

Copyright (C) 2015 by Owen Peredo Diaz
Email: [email protected]
This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License as  published by the Free Software Foundation, either version 3 of the  License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the  GNU Affero General Public License (GPLv3) for more details.

Instance Method Summary collapse

Instance Method Details

#cama_crop_image(file_path, w = nil, h = nil, w_offset = 0, h_offset = 0, resize = false, replace = true) ⇒ Object

crop and image and saved as imagename_crop.ext file: file path w: new width h: new height w_offset: left offset w_offset: top offset resize: true/false

(true => resize the image to this dimension)
(false => crop the image with this dimension)

replace: Boolean (replace current image or create another file)



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 139

def cama_crop_image(file_path, w=nil, h=nil, w_offset = 0, h_offset = 0, resize = false , replace = true)
  force = ""
  force = "!" if w.present? && h.present? && !w.include?("?") && !h.include?("?")
  image = MiniMagick::Image.open(file_path)
  w = image[:width].to_f > w.sub('?', '').to_i ? w.sub('?', "") : image[:width] if w.present? && w.to_s.include?('?')
  h = image[:height].to_f > h.sub('?', '').to_i ? h.sub('?', "") : image[:height] if h.present? && h.to_s.include?('?')
  image.combine_options do |i|
    i.resize("#{w if w.present?}x#{h if h.present?}#{force}") if resize
    i.crop "#{w if w.present?}x#{h if h.present?}+#{w_offset}+#{h_offset}#{force}" unless resize
  end

  res = file_path
  unless replace
    ext = File.extname(file_path)
    res = file_path.gsub(ext, "_crop#{ext}")
  end
  image.write res
  res
end

#cama_file_path_to_url(file_path) ⇒ Object

convert downloaded file path into public url



120
121
122
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 120

def cama_file_path_to_url(file_path)
  file_path.sub(Rails.public_path.to_s, (root_url rescue cama_root_url))
end

#cama_resize_and_crop(file, w, h, settings = {}) ⇒ Object

resize and crop a file Params:

file: (String) File path
w: (Integer) width
h: (Integer) height
settings:
  gravity: (Sym, default :north_east) Crop position: :north_west, :north, :north_east, :east, :south_east, :south, :south_west, :west, :center
  overwrite: (Boolean, default true) true for overwrite current image with resized resolutions, false: create other file called with prefix "crop_"
  output_name: (String, default prefixd name with crop_), permit to define the output name of the thumbnail if overwrite = true

Return: (String) file path where saved this cropped sample: cama_resize_and_crop(my_file, 200, 200, :north_east, overwrite: false)



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 170

def cama_resize_and_crop(file, w, h, settings = {})
  settings = {gravity: :north_east, overwrite: true, output_name: ""}.merge(settings)
  img = MiniMagick::Image.open(file)
  w = img[:width].to_f > w.sub('?', '').to_i ? w.sub('?', "") : img[:width] if w.present? && w.to_s.include?('?')
  h = img[:height].to_f > h.sub('?', '').to_i ? h.sub('?', "") : img[:height] if h.present? && h.to_s.include?('?')
  w_original, h_original = [img[:width].to_f, img[:height].to_f]
  w = w.to_i if w.present?
  h = h.to_i if h.present?

  # check proportions
  if w_original * h < h_original * w
    op_resize = "#{w.to_i}x"
    w_result = w
    h_result = (h_original * w / w_original)
  else
    op_resize = "x#{h.to_i}"
    w_result = (w_original * h / h_original)
    h_result = h
  end

  w_offset, h_offset = cama_crop_offsets_by_gravity(settings[:gravity], [w_result, h_result], [ w, h])
  img.combine_options do |i|
    i.resize(op_resize)
    i.gravity(settings[:gravity])
    i.crop "#{w.to_i}x#{h.to_i}+#{w_offset}+#{h_offset}!"
  end

  img.write(file) if settings[:overwrite]
  unless settings[:overwrite]
    if settings[:output_name].present?
      img.write(file = File.join(File.dirname(file), settings[:output_name]).to_s)
    else
      img.write(file = uploader_verify_name(File.join(File.dirname(file), "crop_#{File.basename(file)}")))
    end
  end
  file
end

#cama_resize_upload(image_path, dimesion, args = {}) ⇒ Object

resize image if the format is correct return resized file path



239
240
241
242
243
244
245
246
247
248
249
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 239

def cama_resize_upload(image_path, dimesion, args = {})
  if cama_uploader.class.validate_file_format(image_path, 'image') && dimesion.present?
    r= {file: image_path, w: dimesion.split('x')[0], h: dimesion.split('x')[1], w_offset: 0, h_offset: 0, resize: !dimesion.split('x')[2] || dimesion.split('x')[2] == "resize", replace: true, gravity: :north_east}.merge(args); hooks_run("on_uploader_resize", r)
    if r[:w].present? && r[:h].present?
      image_path = cama_resize_and_crop(r[:file], r[:w], r[:h], {overwrite: r[:replace], gravity: r[:gravity] })
    else
      image_path = cama_crop_image(r[:file], r[:w], r[:h], r[:w_offset], r[:h_offset], r[:resize] , r[:replace])
    end
  end
  image_path
end

#cama_tmp_upload(uploaded_io, args = {}) ⇒ Object

upload tmp file support for url and local path sample: cama_tmp_upload(‘’) ==> /var/rails/my_project/public/tmp/1/logo2.png cama_tmp_upload(‘/var/www/media/132/logo 2.png’) ==> /var/rails/my_project/public/tmp/1/logo-2.png accept args:

name: to indicate the name to use, sample: cama_tmp_upload('/var/www/media/132/logo 2.png', {name: 'owen.png', formats: 'images'})
formats: extensions permitted, sample: jpg,png,... or generic: images | videos | audios | documents (default *)
dimension: 20x30

return: error



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 218

def cama_tmp_upload(uploaded_io, args = {})
  tmp_path = args[:path] || Rails.public_path.join("tmp", current_site.id.to_s)
  FileUtils.mkdir_p(tmp_path) unless Dir.exist?(tmp_path)
  if uploaded_io.is_a?(String) && (uploaded_io.start_with?("http://") || uploaded_io.start_with?("https://"))
    return {error: "#{ct("file_format_error")} (#{args[:formats]})"} unless cama_uploader.class.validate_file_format(uploaded_io, args[:formats])
    uploaded_io = Rails.public_path.join(uploaded_io.sub(current_site.the_url, '')).to_s if uploaded_io.include?(current_site.the_url) && Rails.env != 'production' # local file
    _tmp_name = uploaded_io.split("/").last.split('?').first; args[:name] = args[:name] || _tmp_name
    uploaded_io = open(uploaded_io)
  end
  uploaded_io = File.open(uploaded_io) if uploaded_io.is_a?(String)
  return {error: "#{ct("file_format_error")} (#{args[:formats]})"} unless cama_uploader.class.validate_file_format(_tmp_name || uploaded_io.path, args[:formats])
  return {error: "#{ct("file_size_exceeded", default: "File size exceeded")} (#{number_to_human_size(args[:maximum])})"} if args[:maximum].present? && args[:maximum] < (uploaded_io.size rescue File.size(uploaded_io))
  name = args[:name] || uploaded_io.path.split("/").last; name = "#{File.basename(name, File.extname(name)).underscore}#{File.extname(name)}"
  path = uploader_verify_name(File.join(tmp_path, name))
  File.open(path, "wb"){|f| f.write(uploaded_io.read) }
  path = cama_resize_upload(path, args[:dimension]) if args[:dimension].present?
  {file_path: path, error: nil}
end

#cama_uploaderObject

return the current uploader



252
253
254
255
256
257
258
259
260
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 252

def cama_uploader
  @cama_uploader ||=
  case current_site.get_option("filesystem_type", "local").downcase
    when 's3' || 'aws'
      CamaleonCmsAwsUploader.new({current_site: current_site})
    else
      CamaleonCmsLocalUploader.new({current_site: current_site})
  end
end

#cama_uploader_generate_thumbnail(uploaded_io, key, thumb_size = nil) ⇒ Object

generate thumbnail of a existent image key: key of the current file the thumbnail will be saved in my_images/my_img.png => my_images/thumb/my_img.png



91
92
93
94
95
96
97
98
99
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 91

def cama_uploader_generate_thumbnail(uploaded_io, key, thumb_size = nil)
  w, h = cama_uploader.thumb[:w], cama_uploader.thumb[:h]
  w, h = thumb_size.split('x') if thumb_size.present?
  uploaded_io = File.open(uploaded_io) if uploaded_io.is_a?(String)
  path_thumb = cama_resize_and_crop(uploaded_io.path, w, h)
  thumb = cama_uploader.add_file(path_thumb, cama_uploader.version_path(key), is_thumb: true, same_name: true)
  FileUtils.rm_f(path_thumb)
  thumb
end

#cama_url_to_file_path(url) ⇒ Object

convert public url to file path



125
126
127
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 125

def cama_url_to_file_path(url)
  File.join(Rails.public_path, URI(url.to_s).path)
end

#upload_file(uploaded_io, settings = {}) ⇒ Object

upload a file into server settings:

folder: Directory where the file will be saved (default: "")
  sample: temporal => will save in /rails_path/public/temporal
generate_thumb: true, # generate thumb image if this is image format (default true)
maximum: maximum bytes permitted to upload (default: 1000MG)
dimension: dimension for the image (sample: 30x30 | x30 | 30x | 300x300?)
formats: extensions permitted, sample: jpg,png,... or generic: images | videos | audios | documents (default *)
remove_source: Boolean (delete source file after saved if this is true, default false)
same_name: Boolean (save the file with the same name if defined true, else search for a non used name)
versions: (String) Create addtional multiple versions of the image uploaded, sample: '300x300,505x350' ==> Will create two extra images with these dimensions
    sample "test.png", versions: '200x200,450x450' will generate: thumb/test-png_200x200.png, test-png_450x450.png
thumb_size: String (redefine the dimensions of the thumbnail, sample: '100x100' ==> only for images)
temporal_time: if great than 0 seconds, then this file will expire (removed) in that time (default: 0)
  To manage jobs, please check http://edgeguides.rubyonrails.org/active_job_basics.html
  Note: if you are using temporal_time, you will need to copy the file to another directory later

sample: upload_file(params, “images”, folder: “temporal”) sample: upload_file(params, “jpg,png,gif,mp3,mp4”, temporal_time: 10.minutes, maximum: 10.megabytes)



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 29

def upload_file(uploaded_io, settings = {})
  cached_name = uploaded_io.is_a?(ActionDispatch::Http::UploadedFile) ? uploaded_io.original_filename : nil
  return {error: "File is empty", file: nil, size: nil} unless uploaded_io.present?
  if uploaded_io.is_a?(String) && (uploaded_io.start_with?("http://") || uploaded_io.start_with?("https://")) # download url file
    tmp = cama_tmp_upload(uploaded_io)
    return tmp if tmp[:error].present?
    settings[:remove_source] = true
    uploaded_io = tmp[:file_path]
  end
  uploaded_io = File.open(uploaded_io) if uploaded_io.is_a?(String)
  uploaded_io = File.open(cama_resize_upload(uploaded_io.path, settings[:dimension])) if settings[:dimension].present? # resize file into specific dimensions

  settings = settings.to_sym
  settings[:uploaded_io] = uploaded_io
  settings = {
      folder: "",
      maximum: current_site.get_option('filesystem_max_size', 100).to_f.megabytes,
      formats: "*",
      generate_thumb: true,
      temporal_time: 0,
      filename: ((cached_name || uploaded_io.original_filename) rescue uploaded_io.path.split("/").last).parameterize(".").downcase.gsub(" ", "-"),
      file_size: File.size(uploaded_io.to_io),
      remove_source: false,
      same_name: false,
      versions: '',
      thumb_size: nil
  }.merge(settings)
  hooks_run("before_upload", settings)
  res = {error: nil}

  # formats validations
  return {error: "#{ct("file_format_error")} (#{settings[:formats]})"} unless cama_uploader.class.validate_file_format(uploaded_io.path, settings[:formats])

  # file size validations
  if settings[:maximum] < settings[:file_size]
    res[:error] = "#{ct("file_size_exceeded", default: "File size exceeded")} (#{number_to_human_size(settings[:maximum])})"
    return res
  end
  # save file
  key = File.join(settings[:folder], settings[:filename]).to_s.gsub(/(\/){2,}/, "/")
  res = cama_uploader.add_file(uploaded_io, key, {same_name: settings[:same_name]})
  {} if settings[:temporal_time] > 0 # temporal file upload (always put as local for temporal files) (TODO: use delayjob)

  # generate image versions
  if res['format'] == 'image'
    settings[:versions].to_s.gsub(' ', '').split(',').each do |v|
      version_path = cama_resize_upload(uploaded_io.path, v, {replace: false})
      cama_uploader.add_file(version_path, cama_uploader.version_path(res['key'], v), is_thumb: true, same_name: true)
      FileUtils.rm_f(version_path)
    end
  end

  # generate thumb
  cama_uploader_generate_thumbnail(uploaded_io.path, res['key'], settings[:thumb_size]) if settings[:generate_thumb] && res['thumb'].present?

  FileUtils.rm_f(uploaded_io.path) if settings[:remove_source]
  res
end

#uploader_verify_name(file_path) ⇒ Object

helper to find an available filename for file_path in that directory sample: uploader_verify_name(“/var/www/my_image.jpg”)

return "/var/www/my_image_1.jpg" => if "/var/www/my_image.jpg" exist
return "/var/www/my_image.jpg" => if "/var/www/my_image.jpg" doesn't exist


105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'app/helpers/camaleon_cms/uploader_helper.rb', line 105

def uploader_verify_name(file_path)
  dir, filename = File.dirname(file_path), File.basename(file_path)
  files = Dir.entries(dir)
  if files.include?(filename)
    i, _filename = 1, filename
    while files.include?(_filename) do
      _filename = "#{File.basename(filename, File.extname(filename))}_#{i}#{File.extname(filename)}"
      i += 1
    end
    filename = _filename
  end
  "#{File.dirname(file_path)}/#{filename}"
end