# module Locomotive # module Extensions # module Page # module Templatized # # extend ActiveSupport::Concern # # included do # # ## fields ## # field :wildcards, :type => Array # field :with_wildcards, :type => Boolean, :default => false # field :fullpath_with_wildcards, :default => false, :localize => true # # ## callbacks ## # before_validation :get_wildcards_from_parent # before_validation :add_slug_to_wildcards # before_save :build_fullpath_with_wildcards # after_save :propagate_wildcards # # ## scopes ## # # ## virtual attributes ## # attr_accessor :wildcards_map # # end # # protected # # def get_wildcards_from_parent # return if self.parent.nil? # # if self.parent.with_wildcards? # self.wildcards = self.parent.wildcards # self.with_wildcards = true # elsif !self.with_wildcards? # self.wildcards = [] # self.with_wildcards = false # end # end # # def add_slug_to_wildcards # (self.wildcards ||= []) << self.slug if self.will_wildcards? # end # # def build_fullpath_with_wildcards # if self.index? || self.not_found? # self.fullpath_with_wildcards = self.slug # else # slugs = self.ancestors_and_self.map { |page| page.with_wildcards? ? '*' : page.slug } # slugs.shift unless slugs.size == 1 # self.fullpath_with_wildcards = File.join slugs.compact # end # end # # def propagate_wildcards # return unless self.with_wildcards_changed? || (self.with_wildcards? && self.slug_changed?) # # parent_identities = { self._id => self } # # self.descendants.order_by([[:depth, :asc]]).each do |page| # _parent = parent_identities[page._id] # _wildcards = _parent.wildcards + (page.wildcards? ? [page.slug] : []) # _fullpath_with_wildcards = File.join(_parent.fullpath_with_wildcards, page.wildcards? ? '*' : page.slug) # # # TODO: fullpath_with_wildcards is localized !!!! # # selector = { 'id' => page._id } # operations = { # '$set' => { # 'wildcards' => _wildcards, # 'with_wildcards' => true, # 'fullpath_with_wildcards' => _fullpath_with_wildcards # } # } # self.collection.update selector, operations # # parent_identities[page._id] = page # end # end # # end # end # end # end # # # # # field :templatized_from_parent, :type => Boolean, :default => false # # field :target_klass_name # # # # ## validations ## # # validates_presence_of :target_klass_name, :if => :templatized? # # validate :ensure_target_klass_name_security # # # # ## callbacks ## # # before_validation :get_templatized_from_parent # # before_validation :set_slug_if_templatized # # before_validation :ensure_target_klass_name_security # # after_save :propagate_templatized # # # # ## scopes ## # # scope :templatized, :where => { :templatized => true } # # # # ## virtual attributes ## # # attr_accessor :content_entry # # end # # # # # 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 # # # # # def target_klass # # target_klass_name.constantize # # end # # # # # 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 # # # # # 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 # # end # # # # # 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 # # # # # def fetch_target_entry(permalink) # # target_klass.find_by_permalink(permalink) # # end # # # # protected # # # # 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 # # # # def set_slug_if_templatized # # self.slug = 'content_type_template' if self.templatized? && !self.templatized_from_parent? # # end # # # # # 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. # # # # # 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) # # # # 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 # # end # # end # # # # # 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 # # end # # # # end # # end # # end # # end