2011-10-30 23:02:41 +00:00
|
|
|
module Locomotive
|
|
|
|
module Extensions
|
|
|
|
module Page
|
|
|
|
module Templatized
|
|
|
|
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
included do
|
|
|
|
|
2012-03-27 22:26:32 +00:00
|
|
|
## fields ##
|
|
|
|
field :templatized, :type => Boolean, :default => false
|
|
|
|
field :templatized_from_parent, :type => Boolean, :default => false
|
2012-02-09 23:57:57 +00:00
|
|
|
field :target_klass_name
|
2011-10-30 23:02:41 +00:00
|
|
|
|
2012-02-09 23:57:57 +00:00
|
|
|
## validations ##
|
|
|
|
validates_presence_of :target_klass_name, :if => :templatized?
|
|
|
|
validate :ensure_target_klass_name_security
|
2011-10-30 23:02:41 +00:00
|
|
|
|
2012-02-09 23:57:57 +00:00
|
|
|
## callbacks ##
|
2012-03-27 22:26:32 +00:00
|
|
|
before_validation :get_templatized_from_parent
|
2011-10-30 23:02:41 +00:00
|
|
|
before_validation :set_slug_if_templatized
|
2012-02-09 23:57:57 +00:00
|
|
|
before_validation :ensure_target_klass_name_security
|
2012-03-27 22:26:32 +00:00
|
|
|
after_save :propagate_templatized
|
2012-02-10 23:39:06 +00:00
|
|
|
|
|
|
|
## scopes ##
|
|
|
|
scope :templatized, :where => { :templatized => true }
|
2012-03-26 14:31:28 +00:00
|
|
|
|
|
|
|
## virtual attributes ##
|
|
|
|
attr_accessor :content_entry
|
2012-02-09 23:57:57 +00:00
|
|
|
end
|
|
|
|
|
2012-02-10 23:39:06 +00:00
|
|
|
# Returns the class specified by the target_klass_name property
|
|
|
|
#
|
|
|
|
# @example
|
|
|
|
#
|
|
|
|
# page.target_klass_name = 'Locomotive::Entry12345'
|
|
|
|
# page.target_klass = Locomotive::Entry12345
|
|
|
|
#
|
|
|
|
# @return [ Class ] The target class
|
|
|
|
#
|
2012-02-09 23:57:57 +00:00
|
|
|
def target_klass
|
|
|
|
target_klass_name.constantize
|
|
|
|
end
|
|
|
|
|
2012-02-10 23:39:06 +00:00
|
|
|
# Gives the name which can be used in a liquid template in order
|
|
|
|
# to reference an entry. It uses the slug property if the target klass
|
|
|
|
# is a Locomotive content type or the class name itself for the other classes.
|
|
|
|
#
|
|
|
|
# @example
|
|
|
|
#
|
|
|
|
# page.target_klass_name = 'Locomotive::Entry12345' # related to the content type Articles
|
|
|
|
# page.target_entry_name = 'article'
|
|
|
|
#
|
|
|
|
# page.target_klass_name = 'OurProduct'
|
|
|
|
# page.target_entry_name = 'our_product'
|
|
|
|
#
|
|
|
|
# @return [ String ] The name in lowercase and underscored
|
|
|
|
#
|
2012-02-09 23:57:57 +00:00
|
|
|
def target_entry_name
|
|
|
|
if self.target_klass_name =~ /^Locomotive::Entry([a-z0-9]+)$/
|
|
|
|
@content_type ||= self.site.content_types.find($1)
|
|
|
|
@content_type.slug.singularize
|
|
|
|
else
|
|
|
|
self.target_klass_name.underscore
|
|
|
|
end
|
2011-10-30 23:02:41 +00:00
|
|
|
end
|
|
|
|
|
2012-02-10 23:39:06 +00:00
|
|
|
# Finds the entry both specified by the target klass and identified by the permalink
|
|
|
|
#
|
|
|
|
# @param [ String ] permalink The permalink of the entry
|
|
|
|
#
|
|
|
|
# @return [ Object ] The document
|
|
|
|
#
|
2012-02-09 23:57:57 +00:00
|
|
|
def fetch_target_entry(permalink)
|
|
|
|
target_klass.find_by_permalink(permalink)
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2012-03-27 22:26:32 +00:00
|
|
|
def get_templatized_from_parent
|
|
|
|
return if self.parent.nil?
|
|
|
|
|
|
|
|
if self.parent.templatized?
|
|
|
|
self.templatized = self.templatized_from_parent = true
|
|
|
|
self.target_klass_name = self.parent.target_klass_name
|
|
|
|
elsif !self.templatized?
|
|
|
|
self.templatized = self.templatized_from_parent = false
|
|
|
|
self.target_klass_name = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-09 23:57:57 +00:00
|
|
|
def set_slug_if_templatized
|
2012-03-27 22:26:32 +00:00
|
|
|
self.slug = 'content_type_template' if self.templatized? && !self.templatized_from_parent?
|
2012-02-09 23:57:57 +00:00
|
|
|
end
|
|
|
|
|
2012-03-27 22:26:32 +00:00
|
|
|
# Makes sure the target_klass is owned by the site OR
|
|
|
|
# if it belongs to the models allowed by the application
|
|
|
|
# thanks to the models_for_templatization option.
|
|
|
|
#
|
2012-02-09 23:57:57 +00:00
|
|
|
def ensure_target_klass_name_security
|
|
|
|
return if !self.templatized? || self.target_klass_name.blank?
|
|
|
|
|
|
|
|
if self.target_klass_name =~ /^Locomotive::Entry([a-z0-9]+)$/
|
|
|
|
content_type = Locomotive::ContentType.find($1)
|
2011-10-30 23:02:41 +00:00
|
|
|
|
2012-02-09 23:57:57 +00:00
|
|
|
if content_type.site_id != self.site_id
|
|
|
|
self.errors.add :target_klass_name, :security
|
|
|
|
end
|
|
|
|
elsif !Locomotive.config.models_for_templatization.include?(self.target_klass_name)
|
|
|
|
self.errors.add :target_klass_name, :security
|
2011-10-30 23:02:41 +00:00
|
|
|
end
|
2012-03-27 22:26:32 +00:00
|
|
|
end
|
2011-10-30 23:02:41 +00:00
|
|
|
|
2012-03-27 22:26:32 +00:00
|
|
|
# Sets the templatized, templatized_from_parent properties of
|
|
|
|
# the children of the current page ONLY IF the templatized
|
|
|
|
# attribute got changed.
|
|
|
|
#
|
|
|
|
def propagate_templatized
|
|
|
|
return unless self.templatized_changed?
|
|
|
|
|
|
|
|
selector = { 'parent_ids' => { '$in' => [self._id] } }
|
|
|
|
operations = {
|
|
|
|
'$set' => {
|
|
|
|
'templatized' => self.templatized,
|
|
|
|
'templatized_from_parent' => self.templatized,
|
|
|
|
'target_klass_name' => self.target_klass_name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.collection.update selector, operations, :multi => true
|
2011-10-30 23:02:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2011-11-26 06:24:34 +00:00
|
|
|
end
|