lib/spontaneous/model/page/paths.rb in spontaneous-0.2.0.beta5 vs lib/spontaneous/model/page/paths.rb in spontaneous-0.2.0.beta6

- old
+ new

@@ -11,36 +11,35 @@ def is_default_slug?(slug) /^page-\d{8}-\d{6}$/ === slug end - def create_root(slug) - create(slug: slug, :__create_hidden_root => true) + def create_root(slug, values = {}) + create(values.merge(slug: slug, :__create_private_root => true)) end end # InstanceMethods - ANCESTOR_SEP = "." - - def __create_hidden_root=(state) - @__is_hidden_root = state + def __create_private_root=(state) + @__is_private_root = state end - def __create_hidden_root? - @__is_hidden_root || false + def __create_private_root? + @__is_private_root || false end - private :__create_hidden_root=, :__create_hidden_root? + private :__create_private_root=, :__create_private_root? def after_initialize super set_generated_slug end def before_create place_in_page_tree + set_slug_from_dynamic_value super end def after_insertion super @@ -67,64 +66,67 @@ # # This doesn't happen when the item is created (i.e. #new? => true) # because otherwise the slug would always take on the title fields # default value. def before_save - unless new? - if (title = self.fields[title_field]) - set_slug_from_title(title) - end + if !new? && (title = fields[title_field_name]) + set_slug_from_title(title) end fix_generated_slug_conflicts super end + def set_slug_from_dynamic_value + if (title = fields[title_field_name]) && title.prototype.dynamic_default? + set_slug_from_title!(title) + end + end + # Syncing the slug with the title is made more difficult because the field # update mechanism works differently from the more direct, console version. # This is called by the field updater before re-serializing each modified field. def before_save_field(field) - set_slug_from_title(field) if (field.name == title_field) + set_slug_from_title(field) if (field.name == title_field_name) super end def set_slug_from_title(title) if title.modified? and !title.blank? and has_generated_slug? - self.slug = title.value + set_slug_from_title!(title) end end + def set_slug_from_title!(title) + self.slug = title.value + end + def sync_slug_to_title self.slug = title.unprocessed_value end def has_generated_slug? self.class.is_default_slug?(slug) end - def after_save - super - check_for_path_changes - end - def generate_default_slug self.class.generate_default_slug end def is_conflicting_slug?(slug) - siblings.reject { |s| s.root? }.compact.map(&:slug).include?(slug) + siblings(true).reject { |s| s.root? }.compact.map(&:slug).include?(slug) end def parent=(parent) @__parent_changed = true update_path super end def place_in_page_tree if parent_id.nil? - if __create_hidden_root? || content_model.has_root? - make_hidden_root + if __create_private_root? || content_model.has_root? + make_private_root else make_root end else update_path @@ -135,53 +137,90 @@ self[:path] = "/" self[:slug] = "" self[:ancestor_path] = "" end - def make_hidden_root + def make_private_root raise Spontaneous::AnonymousRootException.new if slug.blank? self[:path] = "##{slug}" self[:ancestor_path] = "" end def ancestor_path - (self[:ancestor_path] || "").split(ANCESTOR_SEP).map { |id| id.to_i } + (self[:ancestor_path] || "").split(Spontaneous::Model::ANCESTOR_SEP).map { |id| id.to_i } end - def root? + def is_public_root? path == Spontaneous::SLASH end - alias_method :is_root?, :root? + alias_method :root?, :is_public_root? + alias_method :is_root?, :is_public_root? + # Returns the root of the tree this page belongs to, which in the case + # of pages in an private tree will not be the same as the site's + # root/home page + def tree_root + content_model::Page.get(visibility_path_ids.first) + end + def is_private_root? + return false unless parent_id.nil? + return false if root? + path[0] == '#' + end + + def in_private_tree? + tree_root = self.tree_root + return is_private_root? if tree_root.nil? + tree_root.is_private_root? + end + + def update_path self.path = calculate_path if parent - self[:ancestor_path] = parent.ancestor_path.push(parent.id).join(ANCESTOR_SEP) + self[:ancestor_path] = parent.ancestor_path.push(parent.id).join(Spontaneous::Model::ANCESTOR_SEP) end end def calculate_path - calculate_path_with_slug(self.slug) + calculate_path_with_slug(slug) end def calculate_path_with_slug(slug) if parent.nil? root? ? Spontaneous::SLASH : "##{slug}" else File.join(parent.path, slug) end end + class SlugChange + attr_reader :old_value, :new_value + def initialize(origin, old_value, new_value) + @origin, @old_value, @new_value = origin, old_value, new_value + end + + def propagate + return if @old_value == @new_value + @origin.force_path_changes + end + end + + included do + cascading_change :slug do |origin, old_value, new_value| + SlugChange.new(origin, old_value, new_value) + end + end + # slugs can be max 64 characters long def slug=(s) if (new_slug = fit_slug_to_length(s, 64)) != slug - @__slug_changed = slug - self[:slug] = new_slug - self.update_path + super(new_slug) + update_path end end def fit_slug_to_length(s, max_length) original = s.to_url @@ -193,31 +232,21 @@ url.join('-')[0...max_length] end protected :fit_slug_to_length - def check_for_path_changes(force = false) - if @__slug_changed || force - @__slug_changed = false - children.each do |child| - child.propagate_path_changes - end - aliases.each do |link| - link.propagate_path_changes if link.page? - end + def force_path_changes + children.each do |child| + child.propagate_path_changes end + aliases.each do |link| + link.propagate_path_changes if link.page? + end end - def force_path_changes - check_for_path_changes(true) - end - def propagate_path_changes - # this happens in the child pages who shouldn't update their modification dates - # because updates to paths are handled by modifications held on the origin of the path change - @__ignore_page_modification = true - self.update_path - self.save + update_path + save children.each do |child| child.propagate_path_changes end end end