2010-04-25 00:33:38 +00:00
|
|
|
class Page
|
|
|
|
include Mongoid::Document
|
|
|
|
include Mongoid::Timestamps
|
2010-04-30 14:05:53 +00:00
|
|
|
include Mongoid::Acts::Tree
|
2010-04-25 00:33:38 +00:00
|
|
|
|
|
|
|
## fields ##
|
|
|
|
field :title
|
2010-04-30 14:05:53 +00:00
|
|
|
field :slug
|
2010-04-25 00:33:38 +00:00
|
|
|
field :published, :type => Boolean, :default => false
|
|
|
|
field :keywords
|
|
|
|
field :description
|
2010-04-30 14:05:53 +00:00
|
|
|
field :position, :type => Integer
|
2010-04-25 00:33:38 +00:00
|
|
|
|
|
|
|
## associations ##
|
|
|
|
belongs_to_related :site
|
2010-05-09 12:44:53 +00:00
|
|
|
belongs_to_related :layout
|
2010-04-25 00:33:38 +00:00
|
|
|
embeds_many :parts, :class_name => 'PagePart'
|
2010-05-02 23:33:17 +00:00
|
|
|
|
|
|
|
## callbacks ##
|
|
|
|
before_validate :reset_parent
|
|
|
|
before_validate :normalize_slug
|
|
|
|
before_save { |p| p.parent_id = nil if p.parent_id.blank? }
|
|
|
|
before_save :change_parent
|
2010-05-11 21:38:52 +00:00
|
|
|
before_create { |p| p.parts << PagePart.build_body_part if p.parts.empty? }
|
2010-05-02 23:33:17 +00:00
|
|
|
before_create { |p| p.fix_position(false) }
|
|
|
|
before_create :add_to_list_bottom
|
2010-05-10 22:39:52 +00:00
|
|
|
before_destroy :do_not_remove_index_and_404_pages
|
|
|
|
before_destroy :remove_from_list
|
2010-04-25 00:33:38 +00:00
|
|
|
|
|
|
|
## validations ##
|
2010-04-30 14:05:53 +00:00
|
|
|
validates_presence_of :site, :title, :slug
|
2010-05-10 22:39:52 +00:00
|
|
|
validates_uniqueness_of :slug, :scope => [:site_id, :parent_id]
|
2010-04-30 14:05:53 +00:00
|
|
|
validates_exclusion_of :slug, :in => Locomotive.config.reserved_slugs, :if => Proc.new { |p| p.depth == 0 }
|
2010-04-25 00:33:38 +00:00
|
|
|
|
|
|
|
## named scopes ##
|
|
|
|
|
2010-04-30 14:05:53 +00:00
|
|
|
## behaviours ##
|
2010-05-02 23:33:17 +00:00
|
|
|
acts_as_tree :order => ['position', 'asc']
|
2010-04-30 14:05:53 +00:00
|
|
|
|
2010-04-25 00:33:38 +00:00
|
|
|
## methods ##
|
|
|
|
|
2010-05-02 23:33:17 +00:00
|
|
|
def index?
|
|
|
|
self.slug == 'index' && self.depth.to_i == 0
|
|
|
|
end
|
|
|
|
|
|
|
|
def not_found?
|
|
|
|
self.slug == '404' && self.depth.to_i == 0
|
|
|
|
end
|
|
|
|
|
2010-05-09 12:44:53 +00:00
|
|
|
def parts_attributes=(attributes)
|
|
|
|
self.update_parts(attributes.values.map { |attrs| PagePart.new(attrs) })
|
|
|
|
end
|
2010-04-30 14:05:53 +00:00
|
|
|
|
|
|
|
def parent=(owner) # missing in acts_as_tree
|
2010-05-02 23:33:17 +00:00
|
|
|
@_parent = owner
|
|
|
|
self.fix_position(false)
|
2010-04-30 14:05:53 +00:00
|
|
|
self.instance_variable_set :@_will_move, true
|
|
|
|
end
|
|
|
|
|
2010-05-02 23:33:17 +00:00
|
|
|
def sort_children!(ids)
|
|
|
|
ids.each_with_index do |id, position|
|
|
|
|
child = self.children.detect { |p| p._id == id }
|
|
|
|
child.position = position
|
|
|
|
child.save
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-04-30 14:05:53 +00:00
|
|
|
def route
|
2010-05-02 23:33:17 +00:00
|
|
|
return self.slug if self.index? || self.not_found?
|
|
|
|
slugs = self.self_and_ancestors.map(&:slug)
|
|
|
|
slugs.shift
|
|
|
|
File.join slugs
|
|
|
|
end
|
|
|
|
|
|
|
|
def url
|
|
|
|
"http://#{self.site.domains.first}/#{self.route}.html"
|
|
|
|
end
|
|
|
|
|
|
|
|
def ancestors
|
|
|
|
return [] if root?
|
2010-05-09 12:44:53 +00:00
|
|
|
self.class.find(self.path.clone << nil) # bug in mongoid (it does not handle array with one element)
|
2010-04-30 14:05:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
2010-04-25 00:33:38 +00:00
|
|
|
|
2010-05-10 22:39:52 +00:00
|
|
|
def do_not_remove_index_and_404_pages
|
|
|
|
# safe_site = self.site rescue nil
|
|
|
|
|
|
|
|
# return if safe_site.nil?
|
|
|
|
return if (self.site rescue nil).nil?
|
|
|
|
|
|
|
|
if self.index? || self.not_found?
|
|
|
|
raise I18n.t('errors.messages.protected_page')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-05-09 12:44:53 +00:00
|
|
|
def update_parts(parts)
|
|
|
|
performed = []
|
|
|
|
|
|
|
|
# add / update
|
|
|
|
parts.each do |part|
|
|
|
|
if (existing = self.parts.detect { |p| p.id == part.id || p.slug == part.slug })
|
|
|
|
existing.attributes = part.attributes.delete_if { |k, v| %w{_id slug}.include?(k) }
|
|
|
|
else
|
|
|
|
self.parts << (existing = part)
|
|
|
|
end
|
|
|
|
performed << existing unless existing.disabled?
|
|
|
|
end
|
|
|
|
|
|
|
|
# disable missing parts
|
|
|
|
(self.parts.map(&:slug) - performed.map(&:slug)).each do |slug|
|
|
|
|
self.parts.detect { |p| p.slug == slug }.disabled = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def update_parts!(new_parts)
|
|
|
|
self.update_parts(new_parts)
|
|
|
|
self.save
|
|
|
|
end
|
|
|
|
|
2010-05-02 23:33:17 +00:00
|
|
|
def change_parent
|
|
|
|
if self.parent_id_changed?
|
|
|
|
self.fix_position(false)
|
|
|
|
self.add_to_list_bottom
|
|
|
|
self.instance_variable_set :@_will_move, true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def fix_position(perform_save = true)
|
|
|
|
if parent.nil?
|
|
|
|
self[parent_id_field] = nil
|
|
|
|
self[path_field] = []
|
|
|
|
self[depth_field] = 0
|
|
|
|
else
|
|
|
|
self[parent_id_field] = parent._id
|
|
|
|
self[path_field] = parent[path_field] + [parent._id]
|
|
|
|
self[depth_field] = parent[depth_field] + 1
|
|
|
|
self.save if perform_save
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def reset_parent
|
|
|
|
if self.parent_id_changed?
|
|
|
|
@_parent = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_to_list_bottom
|
2010-04-30 14:05:53 +00:00
|
|
|
self.position = (Page.where(:_id.ne => self._id).and(:parent_id => self.parent_id).max(:position) || 0) + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def remove_from_list
|
2010-05-10 22:39:52 +00:00
|
|
|
return if (self.site rescue nil).nil?
|
|
|
|
|
2010-04-30 14:05:53 +00:00
|
|
|
Page.where(:parent_id => self.parent_id).and(:position.gt => self.position).each do |p|
|
|
|
|
p.position -= 1
|
|
|
|
p.save
|
2010-04-25 00:33:38 +00:00
|
|
|
end
|
|
|
|
end
|
2010-05-02 23:33:17 +00:00
|
|
|
|
|
|
|
def normalize_slug
|
|
|
|
self.slug = self.title.clone if self.slug.blank? && self.title.present?
|
2010-04-30 14:05:53 +00:00
|
|
|
self.slug.slugify!(:without_extension => true) if self.slug.present?
|
|
|
|
end
|
2010-04-25 00:33:38 +00:00
|
|
|
end
|