2010-08-21 22:48:24 +00:00
|
|
|
module Models
|
|
|
|
module Extensions
|
|
|
|
module Page
|
|
|
|
module Parse
|
|
|
|
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
included do
|
|
|
|
field :serialized_template, :type => Binary
|
2010-08-22 23:48:11 +00:00
|
|
|
field :template_dependencies, :type => Array, :default => []
|
2010-08-24 13:04:53 +00:00
|
|
|
field :snippet_dependencies, :type => Array, :default => []
|
2010-08-21 22:48:24 +00:00
|
|
|
|
2010-08-28 00:00:05 +00:00
|
|
|
attr_reader :template_changed
|
|
|
|
|
2010-08-21 22:48:24 +00:00
|
|
|
before_validation :serialize_template
|
2010-08-22 23:48:11 +00:00
|
|
|
after_save :update_template_descendants
|
2010-08-21 23:56:44 +00:00
|
|
|
|
|
|
|
validate :template_must_be_valid
|
2010-08-22 23:48:11 +00:00
|
|
|
|
|
|
|
scope :pages, lambda { |domain| { :any_in => { :domains => [*domain] } } }
|
2010-08-21 22:48:24 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
module InstanceMethods
|
|
|
|
|
|
|
|
def template
|
|
|
|
@template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def serialize_template
|
|
|
|
if self.new_record? || self.raw_template_changed?
|
2010-08-22 23:48:11 +00:00
|
|
|
@template_changed = true
|
2010-08-21 23:56:44 +00:00
|
|
|
|
2010-08-22 23:48:11 +00:00
|
|
|
@parsing_errors = []
|
2010-08-24 22:59:22 +00:00
|
|
|
|
2010-08-21 22:48:24 +00:00
|
|
|
begin
|
2010-08-24 13:04:53 +00:00
|
|
|
self._parse_and_serialize_template
|
2010-08-21 22:48:24 +00:00
|
|
|
rescue ::Liquid::SyntaxError => error
|
2010-08-21 23:56:44 +00:00
|
|
|
@parsing_errors << :liquid_syntax
|
2010-08-21 22:58:26 +00:00
|
|
|
rescue ::Locomotive::Liquid::PageNotFound => error
|
2010-08-21 23:56:44 +00:00
|
|
|
@parsing_errors << :liquid_extend
|
2010-08-21 22:48:24 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-08-24 13:04:53 +00:00
|
|
|
def _parse_and_serialize_template(context = {})
|
2010-08-22 23:48:11 +00:00
|
|
|
self.parse(context)
|
2010-08-24 13:04:53 +00:00
|
|
|
self._serialize_template
|
|
|
|
end
|
|
|
|
|
|
|
|
def _serialize_template
|
2010-08-22 23:48:11 +00:00
|
|
|
self.serialized_template = BSON::Binary.new(Marshal.dump(@template))
|
|
|
|
end
|
|
|
|
|
2010-08-24 13:04:53 +00:00
|
|
|
def parse(context = {})
|
2010-08-24 22:59:22 +00:00
|
|
|
self.disable_all_editable_elements
|
|
|
|
|
|
|
|
default_context = { :site => self.site, :page => self, :templates => [], :snippets => [] }
|
2010-08-24 13:04:53 +00:00
|
|
|
|
2010-08-26 11:06:44 +00:00
|
|
|
context = default_context.merge(context)
|
|
|
|
|
|
|
|
@template = ::Liquid::Template.parse(self.raw_template, context)
|
2010-09-26 22:31:50 +00:00
|
|
|
|
2010-08-24 22:59:22 +00:00
|
|
|
self.template_dependencies = context[:templates]
|
|
|
|
self.snippet_dependencies = context[:snippets]
|
2010-08-24 13:04:53 +00:00
|
|
|
|
2010-08-24 22:59:22 +00:00
|
|
|
@template.root.context.clear
|
2010-08-24 13:04:53 +00:00
|
|
|
end
|
|
|
|
|
2010-08-21 23:56:44 +00:00
|
|
|
def template_must_be_valid
|
|
|
|
@parsing_errors.try(:each) { |msg| self.errors.add :template, msg }
|
|
|
|
end
|
|
|
|
|
2010-08-22 23:48:11 +00:00
|
|
|
def update_template_descendants
|
|
|
|
return unless @template_changed == true
|
|
|
|
|
|
|
|
# we admit at this point that the current template is up-to-date
|
2010-08-26 11:06:44 +00:00
|
|
|
template_descendants = self.site.pages.any_in(:template_dependencies => [self.id]).to_a
|
2010-08-22 23:48:11 +00:00
|
|
|
|
|
|
|
# group them by fullpath for better performance
|
2010-08-26 11:06:44 +00:00
|
|
|
cached = template_descendants.inject({}) { |memo, page| memo[page.fullpath] = page; memo }
|
2010-08-22 23:48:11 +00:00
|
|
|
|
2010-08-26 11:06:44 +00:00
|
|
|
self._update_direct_template_descendants(template_descendants, cached)
|
2010-08-22 23:48:11 +00:00
|
|
|
|
|
|
|
# finally save them all
|
2010-08-26 11:06:44 +00:00
|
|
|
template_descendants.map(&:save)
|
2010-08-22 23:48:11 +00:00
|
|
|
end
|
|
|
|
|
2010-08-26 11:06:44 +00:00
|
|
|
def _update_direct_template_descendants(template_descendants, cached)
|
|
|
|
direct_descendants = template_descendants.select do |page|
|
2010-08-29 23:41:44 +00:00
|
|
|
((page.template_dependencies || []) - (self.template_dependencies || [])).size == 1
|
2010-08-22 23:48:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
direct_descendants.each do |page|
|
2010-08-24 13:04:53 +00:00
|
|
|
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })
|
2010-08-22 23:48:11 +00:00
|
|
|
|
2010-08-26 11:06:44 +00:00
|
|
|
page.send(:_update_direct_template_descendants, template_descendants, cached)
|
2010-08-22 23:48:11 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-08-21 22:48:24 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|