From 7a25303c3e0fa9a30b34b9b7832b7b2cbf1666a1 Mon Sep 17 00:00:00 2001 From: "Marco (Valandur)" Date: Mon, 15 Oct 2018 12:35:28 +0200 Subject: [PATCH] fix(page-section): Properly duplicate page sections --- src/PageElement.php | 2 +- src/PageSectionsExtension.php | 383 +++++++++++++++++----------------- 2 files changed, 195 insertions(+), 190 deletions(-) diff --git a/src/PageElement.php b/src/PageElement.php index 75a3a78..d51ebdc 100755 --- a/src/PageElement.php +++ b/src/PageElement.php @@ -195,7 +195,7 @@ public function getAllSectionParents() { $parents = ArrayList::create(); foreach ($this->PageSections() as $section) { - $p = $section->Parent()->duplicate(false); + $p = $section->Parent(); $stage = Versioned::get_stage(); Versioned::set_stage(Versioned::LIVE); $pubSection = DataObject::get_by_id($section->ClassName, $section->ID); diff --git a/src/PageSectionsExtension.php b/src/PageSectionsExtension.php index 4cdf3ee..a060f95 100755 --- a/src/PageSectionsExtension.php +++ b/src/PageSectionsExtension.php @@ -22,196 +22,201 @@ class PageSectionsExtension extends DataExtension { - // Generate the needed relations on the class - public static function get_extra_config($class = null, $extensionClass = null) - { - $has_one = []; - $owns = []; - $cascades = []; - - // Get all the sections that should be added - $sections = Config::inst()->get($class, "page_sections", Config::EXCLUDE_EXTRA_SOURCES); - if (!$sections) { - $sections = ["Main"]; - } - - foreach ($sections as $section) { - $name = "PageSection".$section; - $has_one[$name] = PageSection::class; - - $owns[] = $name; - $cascades[] = $name; - - // Add the inverse relation to the PageElement class - /*Config::inst()->update(PageElement::class, "versioned_belongs_many_many", array( - $class . "_" . $name => $class . "." . $name - ));*/ - } - - // Create the relations for our sections - return [ - "db" => ["__PageSectionCounter" => "Int"], - "has_one" => $has_one, - "owns" => $owns, - "cascade_deletes" => $cascades, - //"cascade_duplicates" => $cascades, - ]; - } - - /** - * The classes of allowed child elements - * - * Gets a list of classnames which are valid child elements of this PageSection. - * @param string $section The section for which to get the allowed child classes. - * @return string[] - */ - public function getAllowedPageElements($section = "Main") - { - $classes = array_values(ClassInfo::subclassesFor(PageElement::class)); - $classes = array_diff($classes, [PageElement::class]); - $ret = []; - foreach ($classes as $class) { + // Generate the needed relations on the class + public static function get_extra_config($class = null, $extensionClass = null) + { + $has_one = []; + $names = []; + + // Get all the sections that should be added + $sections = Config::inst()->get($class, "page_sections", Config::EXCLUDE_EXTRA_SOURCES); + if (!$sections) { + $sections = ["Main"]; + } + + foreach ($sections as $section) { + $name = "PageSection".$section; + $has_one[$name] = PageSection::class; + + $names[] = $name; + + // Add the inverse relation to the PageElement class + /*Config::inst()->update(PageElement::class, "versioned_belongs_many_many", array( + $class . "_" . $name => $class . "." . $name + ));*/ + } + + // Create the relations for our sections + return [ + "db" => ["__PageSectionCounter" => "Int"], + "has_one" => $has_one, + "owns" => $names, + "cascade_deletes" => $names, + "cascade_duplicates" => $names, + ]; + } + + /** + * The classes of allowed child elements + * + * Gets a list of classnames which are valid child elements of this PageSection. + * @param string $section The section for which to get the allowed child classes. + * @return string[] + */ + public function getAllowedPageElements($section = "Main") + { + $classes = array_values(ClassInfo::subclassesFor(PageElement::class)); + $classes = array_diff($classes, [PageElement::class]); + $ret = []; + foreach($classes as $class) { if ($class::$canBeRoot) $ret[] = $class; - } - return $ret; - } - - /** - * Gets a list of the PageSection names of this page. - * @return string[] - */ - public function getPageSectionNames() - { - $sections = Config::inst()->get($this->owner->ClassName, "page_sections", Config::EXCLUDE_EXTRA_SOURCES); - if (!$sections) { - $sections = ["Main"]; - } - return $sections; - } - - public function onAfterWrite() - { - parent::onAfterWrite(); - - if ($this->owner->ID && !$this->owner->__rewrite) { - $sections = $this->getPageSectionNames(); - - $new = false; - foreach ($sections as $sectionName) { - $name = "PageSection".$sectionName."ID"; - - // Create a page section if we don't have one yet - if (!$this->owner->$name) { - $section = PageSection::create(); - $section->__Name = $sectionName; - $section->__ParentID = $this->owner->ID; - $section->__ParentClass = $this->owner->ClassName; - $section->__isNew = true; - $section->write(); - $this->owner->$name = $section->ID; - $new = true; - } - } - - if ($new) { - $this->owner->__rewrite = true; - $this->owner->write(); - } - } - } + } + return $ret; + } + + /** + * Gets a list of the PageSection names of this page. + * @return string[] + */ + public function getPageSectionNames() + { + $sections = Config::inst()->get($this->owner->ClassName, "page_sections", Config::EXCLUDE_EXTRA_SOURCES); + if (!$sections) { + $sections = ["Main"]; + } + return $sections; + } + + public function onAfterWrite() + { + parent::onAfterWrite(); + + if ($this->owner->ID && !$this->owner->__rewrite) { + $sections = $this->getPageSectionNames(); + + foreach ($sections as $sectionName) { + $name = "PageSection".$sectionName; + + if (!$this->owner->{$name . "ID"}) { + // Restore or create a page section if we don't have one yet + $this->restoreOrCreate($sectionName); + } + } + } + } public function updateCMSFields(FieldList $fields) { - $sections = $this->getPageSectionNames(); - - $fields->removeByName("__PageSectionCounter"); - - foreach ($sections as $section) { - $name = "PageSection".$section; - - $fields->removeByName($name); - $fields->removeByName($name . "ID"); - - if ($this->owner->ID) { - $tv = new TreeView($name, $section, $this->owner->$name); - $fields->addFieldToTab("Root.PageSections.{$section}", $tv); - } - } - } - - // Add a get method for each page section to the owner - public function allMethodNames($custom = false) - { - $arr = [ - "getAllowedPageElements", - "getPageSectionNames", - "onAfterWrite", - "updateCMSFields", - "allMethodNames", - "RenderPageSection", - "getPublishState" - ]; - - $sections = $this->getPageSectionNames(); - foreach ($sections as $section) { - $arr[] = "PageSection" . $section; - $arr[] = "getPageSection" . $section; - } - - return $arr; - } - - public function __call($method, $arguments) - { - // Check if we're trying to get a page section - if (mb_strpos($method, "getPageSection") === 0) { - $name = mb_substr($method, 3); - $section = $this->owner->$name(); - // If we have a page section we're good - if ($section && $section->ID) { - if ($section->__ParentClass != $this->owner->ClassName || $section->__ParentID != $this->owner->ID) { - $section->__ParentClass = $this->owner->ClassName; - $section->__ParentID = $this->owner->ID; - $section->write(); - } - return $section; - } - - // Try restoring the section from the history - $archived = Versioned::get_latest_version(PageSection::class, $this->owner->{$name . "ID"}); - if ($archived && $archived->ID) { - // Update the back references - $archived->__ParentClass = $this->owner->ClassName; - $archived->__ParentID = $this->owner->ID; - // Save a copy in draft - $id = $archived->writeToStage(Versioned::DRAFT, true); - return DataObject::get_by_id(PageSection::class, $id, false); - } - - throw new \Error("Could not restore PageSection"); - } else { - throw new \Error("Unknown method $method on PageSectionsExtension"); - } - } - - /** - * Renders the PageSection of this page. - * @param string $name The name of the PageSection to render - */ - public function RenderPageSection($name = "Main") - { - $elements = $this->owner->{"PageSection" . $name}()->Elements()->Sort("SortOrder"); - return $this->owner->renderWith( - "RenderChildren", - ["Elements" => $elements, "ParentList" => strval($this->owner->ID)] - ); - } - - /** - * Gets the published state of the page this PageSection belongs to. - * @return \SilverStripe\ORM\FieldType\DBField - */ - public function getPublishState() - { - return DBField::create_field("HTMLText", $this->owner->latestPublished() ? "Published" : "Draft"); - } + $sections = $this->getPageSectionNames(); + + $fields->removeByName("__PageSectionCounter"); + + foreach ($sections as $section) { + $name = "PageSection".$section; + + $fields->removeByName($name); + $fields->removeByName($name . "ID"); + + if ($this->owner->ID) { + $tv = new TreeView($name, $section, $this->owner->$name); + $fields->addFieldToTab("Root.PageSections.{$section}", $tv); + } + } + } + + // Add a get method for each page section to the owner + public function allMethodNames($custom = false) + { + $arr = [ + "getAllowedPageElements", + "getPageSectionNames", + "onAfterWrite", + "updateCMSFields", + "allMethodNames", + "RenderPageSection", + "getPublishState" + ]; + + $sections = $this->getPageSectionNames(); + foreach ($sections as $section) { + $arr[] = "PageSection" . $section; + $arr[] = "getPageSection" . $section; + } + + return $arr; + } + + public function __call($method, $arguments) + { + //var_dump($method); + + // Check if we're trying to get a page section + if (mb_strpos($method, "getPageSection") === 0) { + $name = mb_substr($method, 3); + $section = $this->owner->$name(); + + // If we have a page section we're good + if ($section && $section->ID) { + if ($section->__ParentClass != $this->owner->ClassName || $section->__ParentID != $this->owner->ID) { + $section->__ParentClass = $this->owner->ClassName; + $section->__ParentID = $this->owner->ID; + $section->write(); + } + return $section; + } + + return $this->restoreOrCreate($name); + } else { + throw new \Error("Unknown method $method on PageSectionsExtension"); + } + } + + private function restoreOrCreate($name) { + // Try restoring the section from the history + $archived = Versioned::get_latest_version(PageSection::class, $this->owner->{$name . "ID"}); + if ($archived && $archived->ID) { + // Update the back references + $archived->ID = $this->owner->{$name . "ID"}; + $archived->__ParentClass = $this->owner->ClassName; + $archived->__ParentID = $this->owner->ID; + // Save a copy in draft + $id = $archived->writeToStage(Versioned::DRAFT, true); + + $this->owner->flushCache(true); + + return DataObject::get_by_id(PageSection::class, $id, false); + } else { + $section = PageSection::create(); + $section->__Name = $name; + $section->__ParentID = $this->owner->ID; + $section->__ParentClass = $this->owner->ClassName; + $section->__isNew = true; + $section->write(); + $this->owner->{$name . "ID"} = $section->ID; + $this->owner->write(); + + return $section; + } + } + + /** + * Renders the PageSection of this page. + * @param string $name The name of the PageSection to render + */ + public function RenderPageSection($name = "Main") + { + $elements = $this->owner->{"PageSection" . $name}()->Elements()->Sort("SortOrder"); + return $this->owner->renderWith( + "RenderChildren", + ["Elements" => $elements, "ParentList" => strval($this->owner->ID)] + ); + } + + /** + * Gets the published state of the page this PageSection belongs to. + * @return \SilverStripe\ORM\FieldType\DBField + */ + public function getPublishState() + { + return DBField::create_field("HTMLText", $this->owner->latestPublished() ? "Published" : "Draft"); + } }