243 lines
8.2 KiB
Ruby
243 lines
8.2 KiB
Ruby
require 'ostruct'
|
|
|
|
module Locomotive
|
|
module Import
|
|
class ContentTypes < Base
|
|
|
|
def process
|
|
return if content_types.nil?
|
|
|
|
contents_with_associations, content_types_with_associations = [], []
|
|
|
|
content_types.each do |name, attributes|
|
|
self.log "[content_types] slug = #{attributes['slug']}"
|
|
|
|
content_type = site.content_types.where(:slug => attributes['slug']).first
|
|
|
|
content_type_name = attributes['name'] || name
|
|
|
|
if content_type.nil?
|
|
content_type = self.build_content_type(attributes.merge(:name => content_type_name))
|
|
else
|
|
self.update_attributes(content_type, attributes.merge(:name => content_type_name))
|
|
end
|
|
|
|
self.add_or_update_fields(content_type, attributes['fields'])
|
|
|
|
if content_type.content_custom_fields.any? { |f| ['has_many', 'has_one'].include?(f.kind) }
|
|
content_types_with_associations << content_type
|
|
end
|
|
|
|
self.set_highlighted_field_name(content_type)
|
|
|
|
self.set_order_by_value(content_type)
|
|
|
|
self.set_group_by_value(content_type)
|
|
|
|
if options[:samples] && attributes['contents']
|
|
contents_with_associations += self.insert_samples(content_type, attributes['contents'])
|
|
end
|
|
|
|
content_type.save!
|
|
end
|
|
|
|
# look up for associations and replace their target field by the real class name
|
|
self.replace_target(content_types_with_associations)
|
|
|
|
# update all the contents with associations now that every content is stored in mongodb
|
|
self.insert_samples_with_associations(contents_with_associations)
|
|
|
|
# invalidate the cache of the dynamic classes (custom fields)
|
|
site.content_types.all.collect { |c| c.invalidate_content_klass; c.fetch_content_klass }
|
|
end
|
|
|
|
protected
|
|
|
|
def content_types
|
|
database['site']['content_types']
|
|
end
|
|
|
|
def cleanse_attributes(data)
|
|
attributes = { :group_by_field_name => data.delete('group_by') }.merge(data)
|
|
|
|
attributes.delete_if { |name, value| %w{fields contents}.include?(name) }
|
|
attributes
|
|
end
|
|
|
|
def build_content_type(data)
|
|
attributes = cleanse_attributes(data)
|
|
site.content_types.build(attributes)
|
|
end
|
|
|
|
def update_attributes(content_type, data)
|
|
attributes = cleanse_attributes(data)
|
|
content_type.update_attributes!(attributes)
|
|
end
|
|
|
|
def add_or_update_fields(content_type, fields)
|
|
fields.each_with_index do |data, position|
|
|
name, data = data.keys.first, data.values.first
|
|
|
|
reverse_lookup = data.delete('reverse')
|
|
|
|
attributes = { :_alias => name, :label => name.humanize, :kind => 'string', :position => position }.merge(data).symbolize_keys
|
|
|
|
field = content_type.content_custom_fields.detect { |f| f._alias == attributes[:_alias] }
|
|
|
|
field ||= content_type.content_custom_fields.build(attributes)
|
|
|
|
field.send(:set_unique_name!) if field.new_record?
|
|
|
|
field.attributes = attributes
|
|
|
|
field[:kind] = field[:kind].downcase # old versions of the kind field are capitalized
|
|
|
|
field[:tmp_reverse_lookup] = reverse_lookup # use the ability in mongoid to set free attributes on the fly
|
|
end
|
|
end
|
|
|
|
def replace_target(content_types)
|
|
content_types.each do |content_type|
|
|
content_type.content_custom_fields.each do |field|
|
|
next unless ['has_many', 'has_one'].include?(field.kind)
|
|
|
|
target_content_type = site.content_types.where(:slug => field.target).first
|
|
|
|
if target_content_type
|
|
field.target = target_content_type.content_klass.to_s
|
|
|
|
if field[:tmp_reverse_lookup]
|
|
field.reverse_lookup = field[:tmp_reverse_lookup]
|
|
field.reverse_lookup = field.safe_reverse_lookup # make sure we store the true value
|
|
end
|
|
end
|
|
end
|
|
|
|
content_type.save
|
|
end
|
|
end
|
|
|
|
def insert_samples(content_type, contents)
|
|
contents_with_associations = []
|
|
|
|
contents.each_with_index do |data, position|
|
|
value, attributes = data.is_a?(Array) ? [data.first, data.last] : [data.keys.first, data.values.first]
|
|
|
|
associations = []
|
|
|
|
# build with default attributes
|
|
content = content_type.contents.where(content_type.highlighted_field_name.to_sym => value).first
|
|
|
|
if content.nil?
|
|
content = content_type.contents.build(content_type.highlighted_field_name.to_sym => value, :_position_in_list => position)
|
|
end
|
|
|
|
%w(_permalink seo_title meta_description meta_keywords).each do |attribute|
|
|
new_value = attributes.delete(attribute)
|
|
|
|
next if new_value.blank?
|
|
|
|
content.send("#{attribute}=".to_sym, new_value)
|
|
end
|
|
|
|
attributes.each do |name, value|
|
|
field = content_type.content_custom_fields.detect { |f| f._alias == name }
|
|
|
|
next if field.nil? # the attribute name is not related to a field (name misspelled ?)
|
|
|
|
kind = field.kind
|
|
|
|
if ['has_many', 'has_one'].include?(kind)
|
|
associations << OpenStruct.new(:name => name, :kind => kind, :value => value, :target => field.target)
|
|
next
|
|
end
|
|
|
|
value = (case kind
|
|
when 'file' then self.open_sample_asset(value)
|
|
when 'boolean' then Boolean.set(value)
|
|
when 'date' then value.is_a?(Date) ? value : Date.parse(value)
|
|
when 'category'
|
|
if field.category_items.detect { |item| item.name == value }.nil?
|
|
field.category_items.build :name => value
|
|
end
|
|
value
|
|
else # string, text
|
|
value
|
|
end)
|
|
|
|
content.send("#{name}=", value)
|
|
end
|
|
|
|
content.send(:set_slug)
|
|
|
|
content.save(:validate => false)
|
|
|
|
contents_with_associations << [content, associations] unless associations.empty?
|
|
|
|
self.log "insert content '#{content.send(content_type.highlighted_field_name.to_sym)}'"
|
|
end
|
|
|
|
contents_with_associations
|
|
end
|
|
|
|
def insert_samples_with_associations(contents)
|
|
contents.each do |content_information|
|
|
next if content_information.empty?
|
|
|
|
content, associations = content_information
|
|
|
|
content = content._parent.reload.contents.find(content._id) # target should be updated
|
|
|
|
associations.each do |association|
|
|
target_content_type = site.content_types.where(:name => association.target).first
|
|
|
|
next if target_content_type.nil?
|
|
|
|
value = (case association.kind
|
|
when 'has_one' then
|
|
target_content_type.contents.detect { |c| c.highlighted_field_value == association.value }
|
|
when 'has_many' then
|
|
association.value.collect do |v|
|
|
target_content_type.contents.detect { |c| c.highlighted_field_value == v }._id
|
|
end
|
|
end)
|
|
|
|
content.send("#{association.name}=", value)
|
|
end
|
|
|
|
content.save
|
|
end
|
|
end
|
|
|
|
def set_highlighted_field_name(content_type)
|
|
field = content_type.content_custom_fields.detect { |f| f._alias == content_type.highlighted_field_name }
|
|
|
|
content_type.highlighted_field_name = field._name if field
|
|
end
|
|
|
|
def set_order_by_value(content_type)
|
|
self.log "order by #{content_type.order_by}"
|
|
|
|
order_by = (case content_type.order_by
|
|
when 'manually', '_position_in_list' then '_position_in_list'
|
|
when 'default', 'created_at' then 'created_at'
|
|
else
|
|
content_type.content_custom_fields.detect { |f| f._alias == content_type.order_by }._name rescue nil
|
|
end)
|
|
|
|
self.log "order by (after) #{order_by}"
|
|
|
|
content_type.order_by = order_by || '_position_in_list'
|
|
end
|
|
|
|
def set_group_by_value(content_type)
|
|
return if content_type.group_by_field_name.blank?
|
|
|
|
field = content_type.content_custom_fields.detect { |f| f._alias == content_type.group_by_field_name }
|
|
|
|
content_type.group_by_field_name = field._name if field
|
|
end
|
|
|
|
end
|
|
end
|
|
end |