engine/lib/locomotive/import/pages.rb

203 lines
5.7 KiB
Ruby

module Locomotive
module Import
class Pages < Base
def process
context[:done] = {} # initialize the hash storing pages already processed
self.add_page('404')
self.add_page('index')
Dir[File.join(theme_path, 'app', 'views', 'pages', '**/*')].each do |template_path|
fullpath = template_path.gsub(File.join(theme_path, 'app', 'views', 'pages'), '').gsub('.liquid', '').gsub(/^\//, '')
next if %w(index 404).include?(fullpath)
self.add_page(fullpath)
end
# make sure all the pages were processed (redirection pages without template for instance)
self.pages.each { |fullpath, attributes| self.add_page_without_template(fullpath.to_s) }
end
protected
def add_page_without_template(fullpath)
page = context[:done][fullpath]
return page if page # already added, so skip it
self._save_page!(fullpath, nil)
end
def add_page(fullpath)
page = context[:done][fullpath]
return page if page # already added, so skip it
template = File.read(File.join(theme_path, 'app', 'views', 'pages', "#{fullpath}.liquid")) rescue "Unable to find #{fullpath}.liquid"
self.replace_images!(template)
self.build_parent_template(template)
self._save_page!(fullpath, template)
end
def _save_page!(fullpath, template)
parent = self.find_parent(fullpath)
attributes = {
:title => fullpath.split('/').last.humanize,
:slug => fullpath.split('/').last,
:parent => parent,
:raw_template => template,
:published => true
}.merge(self.pages[fullpath] || {}).symbolize_keys
if %w(index 404).include?(fullpath)
attributes[:position] = fullpath == 'index' ? 0 : 1
end
attributes[:position] = attributes[:position].to_i
# templatized ?
# TODO: DEBUG PURPOSE
# if content_type_slug = attributes.delete(:content_type)
# attributes.merge!({
# :templatized => true,
# :content_type => site.content_types.where(:slug => content_type_slug).first
# })
# end
# redirection page ?
attributes[:redirect] = true if attributes[:redirect_url].present?
# Don't want the editable elements to be imported: they will be regenerated
editable_elements_attributes = attributes.delete(:editable_elements)
page = site.pages.where(:fullpath => self.sanitize_fullpath(fullpath)).first || site.pages.build
page.attributes = attributes
page.save!
unless editable_elements_attributes.nil?
self.assign_editable_elements(page, editable_elements_attributes)
end
self.log "adding #{page.fullpath} (#{template.blank? ? 'without' : 'with'} template) / #{page.position}"
site.reload
context[:done][fullpath] = page
page
end
def assign_editable_elements(page, elements)
page.reload # editable elements are not synchronized otherwise
elements.each do |attributes|
element = page.find_editable_element(attributes['block'], attributes['slug'])
next if element.nil?
if element.respond_to?(:source)
unless attributes['content'].blank?
asset_path = File.join(theme_path, 'public', attributes['content'])
if File.exists?(asset_path)
element.source = File.open(asset_path)
end
end
else
element.content = attributes['content']
end
end
page.save!
end
def build_parent_template(template)
# just check if the template contains the extends keyword
fullpath = template.scan(/\{% extends \'?([\w|\/]+)\'? %\}/).flatten.first
if fullpath # inheritance detected
return if fullpath == 'parent'
self.add_page(fullpath)
end
end
def find_parent(fullpath)
return nil if %w(index 404).include?(fullpath) # avoid cyclic issue with the index page
segments = fullpath.split('/')
return site.pages.root.first if segments.size == 1
segments.pop
parent_fullpath = segments.join('/').gsub(/^\//, '')
# look for a local index page in db
parent = site.pages.where(:fullpath => parent_fullpath).first
parent || self.add_page(parent_fullpath)
end
def replace_images!(template)
return if template.blank?
template.gsub!(/\/samples\/(.*\.[a-zA-Z0-9]{3})/) do |match|
name = File.basename($1)
if asset = site.content_assets.where(:source_filename => name).first
asset.source.url
else
match
end
end
end
def pages
@pages ||= self.retrieve_pages
end
def retrieve_pages
pages = context[:database]['site']['pages']
if pages.is_a?(Array) # ordered list of pages
tmp, positions = {}, Hash.new(0)
pages.each do |data|
position = nil
fullpath = data.keys.first.to_s
unless %w(index 404).include?(fullpath)
(segments = fullpath.split('/')).pop
position_key = segments.empty? ? 'index' : segments.join('/')
position = positions[position_key]
positions[position_key] += 1
end
attributes = (data.values.first || {}).merge(:position => position)
tmp[fullpath] = attributes
end
pages = tmp
end
pages
end
def sanitize_fullpath(fullpath)
fullpath.gsub(/\/template$/, '/content_type_template')
end
end
end
end