2011-10-30 23:02:41 +00:00
|
|
|
module Locomotive
|
|
|
|
class ThemeAsset
|
|
|
|
|
|
|
|
include Locomotive::Mongoid::Document
|
|
|
|
|
|
|
|
## extensions ##
|
|
|
|
include Extensions::Asset::Types
|
|
|
|
|
|
|
|
## fields ##
|
|
|
|
field :local_path
|
|
|
|
field :content_type
|
2011-12-07 01:09:13 +00:00
|
|
|
field :width, :type => Integer
|
|
|
|
field :height, :type => Integer
|
|
|
|
field :size, :type => Integer
|
|
|
|
field :folder, :default => nil
|
2011-11-10 21:41:20 +00:00
|
|
|
mount_uploader :source, ThemeAssetUploader, :mount_on => :source_filename
|
2011-10-30 23:02:41 +00:00
|
|
|
|
|
|
|
## associations ##
|
2012-02-27 11:48:06 +00:00
|
|
|
belongs_to :site, :class_name => 'Locomotive::Site'
|
2011-10-30 23:02:41 +00:00
|
|
|
|
|
|
|
## indexes ##
|
|
|
|
index :site_id
|
|
|
|
index [[:site_id, Mongo::ASCENDING], [:local_path, Mongo::ASCENDING]]
|
|
|
|
|
|
|
|
## callbacks ##
|
2011-12-07 01:09:13 +00:00
|
|
|
before_validation :check_for_folder_changes
|
2011-10-30 23:02:41 +00:00
|
|
|
before_validation :store_plain_text
|
|
|
|
before_validation :sanitize_folder
|
|
|
|
before_validation :build_local_path
|
|
|
|
|
|
|
|
## validations ##
|
2011-12-07 01:09:13 +00:00
|
|
|
validates_presence_of :site
|
|
|
|
validates_presence_of :source, :on => :create
|
2011-11-03 13:01:08 +00:00
|
|
|
validates_presence_of :plain_text_name, :if => Proc.new { |a| a.performing_plain_text? }
|
2011-10-30 23:02:41 +00:00
|
|
|
validates_uniqueness_of :local_path, :scope => :site_id
|
2011-11-03 13:01:08 +00:00
|
|
|
validates_integrity_of :source
|
|
|
|
validate :content_type_can_not_changed
|
2011-10-30 23:02:41 +00:00
|
|
|
|
|
|
|
## named scopes ##
|
|
|
|
|
|
|
|
## accessors ##
|
2011-12-07 01:09:13 +00:00
|
|
|
attr_accessor :plain_text_name, :plain_text, :plain_text_type, :performing_plain_text
|
|
|
|
attr_accessible :folder, :source, :plain_text_type, :performing_plain_text, :plain_text_name, :plain_text
|
2011-10-30 23:02:41 +00:00
|
|
|
|
|
|
|
## methods ##
|
|
|
|
|
|
|
|
def stylesheet_or_javascript?
|
|
|
|
self.stylesheet? || self.javascript?
|
|
|
|
end
|
|
|
|
|
|
|
|
def local_path(short = false)
|
|
|
|
if short
|
|
|
|
self.read_attribute(:local_path).gsub(/^#{self.content_type.to_s.pluralize}\//, '')
|
|
|
|
else
|
|
|
|
self.read_attribute(:local_path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def plain_text_name
|
|
|
|
if not @plain_text_name_changed
|
|
|
|
@plain_text_name ||= self.safe_source_filename
|
|
|
|
end
|
|
|
|
@plain_text_name.gsub(/(\.[a-z0-9A-Z]+)$/, '') rescue nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def plain_text_name=(name)
|
|
|
|
@plain_text_name_changed = true
|
|
|
|
@plain_text_name = name
|
|
|
|
end
|
|
|
|
|
|
|
|
def plain_text
|
|
|
|
if RUBY_VERSION =~ /1\.9/
|
|
|
|
@plain_text ||= (self.source.read.force_encoding('UTF-8') rescue nil)
|
|
|
|
else
|
|
|
|
@plain_text ||= self.source.read
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def plain_text_type
|
|
|
|
@plain_text_type || (stylesheet_or_javascript? ? self.content_type : nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
def performing_plain_text?
|
|
|
|
Boolean.set(self.performing_plain_text) || false
|
|
|
|
end
|
|
|
|
|
|
|
|
def store_plain_text
|
2011-12-07 01:09:13 +00:00
|
|
|
return if self.persisted? && !self.stylesheet_or_javascript?
|
|
|
|
|
2011-10-30 23:02:41 +00:00
|
|
|
self.content_type ||= @plain_text_type if self.performing_plain_text?
|
|
|
|
|
|
|
|
data = self.performing_plain_text? ? self.plain_text : self.source.read
|
|
|
|
|
|
|
|
return if !self.stylesheet_or_javascript? || self.plain_text_name.blank? || data.blank?
|
|
|
|
|
|
|
|
sanitized_source = self.escape_shortcut_urls(data)
|
|
|
|
|
2011-12-07 01:09:13 +00:00
|
|
|
self.source = ::CarrierWave::SanitizedFile.new({
|
2011-10-30 23:02:41 +00:00
|
|
|
:tempfile => StringIO.new(sanitized_source),
|
|
|
|
:filename => "#{self.plain_text_name}.#{self.stylesheet? ? 'css' : 'js'}"
|
|
|
|
})
|
2012-02-28 10:25:51 +00:00
|
|
|
|
|
|
|
@plain_text = sanitized_source # no need to reset the plain_text instance variable to have the last version
|
2011-10-30 23:02:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def to_liquid
|
|
|
|
{ :url => self.source.url }.merge(self.attributes).stringify_keys
|
|
|
|
end
|
|
|
|
|
2011-11-16 00:39:16 +00:00
|
|
|
def as_json(options = {})
|
2012-02-28 10:25:51 +00:00
|
|
|
Locomotive::ThemeAssetPresenter.new(self, options).as_json
|
2011-11-16 00:39:16 +00:00
|
|
|
end
|
|
|
|
|
2011-10-30 23:02:41 +00:00
|
|
|
def self.all_grouped_by_folder(site)
|
|
|
|
assets = site.theme_assets.order_by([[:slug, :asc]])
|
|
|
|
assets.group_by { |a| a.folder.split('/').first.to_sym }
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def safe_source_filename
|
|
|
|
self.source_filename || self.source.send(:original_filename) rescue nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def sanitize_folder
|
|
|
|
self.folder = self.content_type.to_s.pluralize if self.folder.blank?
|
|
|
|
|
|
|
|
# no accents, no spaces, no leading and ending trails
|
|
|
|
self.folder = ActiveSupport::Inflector.transliterate(self.folder).gsub(/(\s)+/, '_').gsub(/^\//, '').gsub(/\/$/, '')
|
|
|
|
|
|
|
|
# folder should begin by a root folder
|
2011-12-07 01:09:13 +00:00
|
|
|
if (self.folder =~ /^(stylesheets|javascripts|images|media|fonts)/).nil?
|
2011-10-30 23:02:41 +00:00
|
|
|
self.folder = File.join(self.content_type.to_s.pluralize, self.folder)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def build_local_path
|
|
|
|
if filename = self.safe_source_filename
|
|
|
|
self.local_path = File.join(self.folder, filename)
|
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def escape_shortcut_urls(text)
|
|
|
|
return if text.blank?
|
|
|
|
|
2011-12-07 01:09:13 +00:00
|
|
|
text.gsub(/[("'](\/(stylesheets|javascripts|images|media)\/(([^;.]+)\/)*([a-z_\-0-9]+)\.[a-z]{2,3})[)"']/) do |path|
|
2011-10-30 23:02:41 +00:00
|
|
|
|
|
|
|
sanitized_path = path.gsub(/[("')]/, '').gsub(/^\//, '')
|
|
|
|
|
|
|
|
if asset = self.site.theme_assets.where(:local_path => sanitized_path).first
|
|
|
|
"#{path.first}#{asset.source.url}#{path.last}"
|
|
|
|
else
|
|
|
|
path
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-12-07 01:09:13 +00:00
|
|
|
def check_for_folder_changes
|
|
|
|
# https://github.com/jnicklas/carrierwave/issues/330
|
|
|
|
# https://github.com/jnicklas/carrierwave-mongoid/issues/23
|
|
|
|
if self.persisted? && self.folder_changed? && !self.source_filename_changed?
|
|
|
|
# a simple way to rename a file
|
|
|
|
old_asset = self.class.find(self._id)
|
|
|
|
file = old_asset.source.file
|
|
|
|
file.content_type = File.mime_type?(file.path) if file.content_type.nil?
|
|
|
|
self.source = file
|
|
|
|
self.changed_attributes['source_filename'] = nil # delete the old file
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-30 23:02:41 +00:00
|
|
|
def content_type_can_not_changed
|
2011-12-07 01:09:13 +00:00
|
|
|
self.errors.add(:source, :extname_changed) if self.persisted? && self.content_type_changed?
|
2011-10-30 23:02:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|