Skip to content

Commit

Permalink
fix: cascade duplicates down the full element tree while preventing w…
Browse files Browse the repository at this point in the history
…rites to original
  • Loading branch information
Severin Hauser committed Apr 16, 2024
1 parent c304203 commit 9ccd86b
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 27 deletions.
46 changes: 46 additions & 0 deletions src/PageElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ public function canCreate($member = null, $context = [])
"Children",
];

private static $cascade_duplicates = [
"Children",
];

private static $summary_fields = [
"GridFieldPreview",
];
Expand Down Expand Up @@ -112,6 +116,10 @@ public function onBeforeWrite()
{
parent::onBeforeWrite();

if (!$this->isInDB()) {
return;
}

// If a field changed then update the counter, unless it's the counter that changed
$changed = $this->getChangedFields(true, DataObject::CHANGE_VALUE);
if (count($changed) > 0 && (!isset($changed["__Counter"]) || $changed["__Counter"]["level"] <= 1)) {
Expand All @@ -129,6 +137,10 @@ public function onAfterWrite()
{
parent::onAfterWrite();

if (!PageSectionChangeState::propagateWrites()) {
return;
}

if (Versioned::get_stage() == Versioned::DRAFT && $this->isChanged("__Counter", DataObject::CHANGE_VALUE)) {
foreach ($this->PageSections() as $section) {
$section->__Counter++;
Expand Down Expand Up @@ -180,6 +192,40 @@ public function onAfterArchive()
}
}

/**
* Overwrites the parent version so that it actually clones Children rather than rereferencing them
*
* @param DataObject $sourceObject
* @param DataObject $destinationObject
* @param string $relation
*/
protected function duplicateManyManyRelation($sourceObject, $destinationObject, $relation)
{
if ($relation === 'Children') {
return $this->duplicateChildren($sourceObject, $destinationObject);
}

return parent::duplicateManyManyRelation($sourceObject, $destinationObject, $relation);
}

/**
* Custom method to clone Children
*
* @param DataObject $sourceObject
* @param DataObject $destinationObject
*/
protected function duplicateChildren($sourceObject, $destinationObject)
{
// Copy all components from source to destination
$source = $sourceObject->getManyManyComponents('Children')->sort('SortOrder');
$dest = $destinationObject->getManyManyComponents('Children');

foreach ($source as $item) {
$clonedItem = $item->duplicate(false);
$dest->add($clonedItem);
}
}

/**
* Gets the preview of this PageElement in the TreeView.
* @return string
Expand Down
4 changes: 4 additions & 0 deletions src/PageElementSelfRel.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public function onAfterWrite()
{
parent::onAfterWrite();

if (!PageSectionChangeState::propagateWrites()) {
return;
}

if (!$this->__NewOrder && Versioned::get_stage() == Versioned::DRAFT) {
$this->Parent()->__Counter++;
if ($this->Parent()->isLiveVersion()) {
Expand Down
95 changes: 78 additions & 17 deletions src/PageSection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,13 @@

namespace FLXLabs\PageSections;

use SilverStripe\Core\ClassInfo;
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldButtonRow;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Versioned\Versioned;

use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;

class PageSection extends DataObject
{
public $__isNew = false;

private static $table_name = "FLXLabs_PageSections_PageSection";

private static $db = [
Expand All @@ -36,6 +26,10 @@ class PageSection extends DataObject
"Elements",
];

private static $cascade_duplicates = [
"Elements"
];

private static $many_many = [
"Elements" => [
"through" => PageSectionPageElementRel::class,
Expand All @@ -44,28 +38,59 @@ class PageSection extends DataObject
]
];

public function Parent() {
public function Parent()
{
$parent = DataObject::get_by_id($this->__ParentClass, $this->__ParentID);
if ($parent == null) {
$parent = Versioned::get_latest_version($this->__ParentClass, $this->__ParentID);
}
return $parent;
}

public function onBeforeWrite() {

public function onBeforeDuplicate()
{
PageSectionChangeState::propagateWrites(false);
}

public function onAfterDuplicate()
{
PageSectionChangeState::propagateWrites(true);
}

public function onBeforeCopyToLocale()
{
PageSectionChangeState::propagateWrites(false);
}

public function onAfterCopyToLocale()
{
PageSectionChangeState::propagateWrites(true);
}

public function onBeforeWrite()
{
parent::onBeforeWrite();

if (!$this->isInDB()) {
return;
}

$elems = $this->Elements()->Sort("SortOrder")->Column("ID");
$count = count($elems);
for ($i = 0; $i < $count; $i++) {
$this->Elements()->Add($elems[$i], [ "SortOrder" => ($i + 1) * 2, "__NewOrder" => true ]);
$this->Elements()->Add($elems[$i], ["SortOrder" => ($i + 1) * 2, "__NewOrder" => true]);
}
}

public function onAfterWrite()
{
parent::onAfterWrite();

if (!PageSectionChangeState::propagateWrites()) {
return;
}

if (!$this->__isNew && Versioned::get_stage() == Versioned::DRAFT && $this->isChanged("__Counter", DataObject::CHANGE_VALUE)) {
$this->Parent()->__PageSectionCounter++;
// Only create a new version when the previous one is <th></th>e published one.
Expand All @@ -77,6 +102,40 @@ public function onAfterWrite()
}
}

/**
* Overwrites the parent version so that it actually clones Elements rather than rereferencing them
*
* @param DataObject $sourceObject
* @param DataObject $destinationObject
* @param string $relation
*/
protected function duplicateManyManyRelation($sourceObject, $destinationObject, $relation)
{
if ($relation === 'Elements') {
return $this->duplicateElements($sourceObject, $destinationObject);
}

return parent::duplicateManyManyRelation($sourceObject, $destinationObject, $relation);
}

/**
* Custom method to clone Elements
*
* @param DataObject $sourceObject
* @param DataObject $destinationObject
*/
protected function duplicateElements($sourceObject, $destinationObject)
{
// Copy all components from source to destination
$source = $sourceObject->getManyManyComponents('Elements')->sort('SortOrder');
$dest = $destinationObject->getManyManyComponents('Elements');

foreach ($source as $item) {
$clonedItem = $item->duplicate(false);
$dest->add($clonedItem);
}
}

public function forTemplate()
{
$elements = $this->Elements();
Expand All @@ -90,7 +149,8 @@ public function forTemplate()
* Gets the name of this PageSection
* @return string
*/
public function getName() {
public function getName()
{
return $this->__Name;
}

Expand All @@ -101,7 +161,8 @@ public function getName() {
* @param string $section The section for which to get the allowed child classes.
* @return string[]
*/
public function getAllowedPageElements() {
public function getAllowedPageElements()
{
return $this->Parent()->getAllowedPageElements($this->__Name);
}
}
43 changes: 43 additions & 0 deletions src/PageSectionChangeState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace FLXLabs\PageSections;

use SilverStripe\Core\Injector\Injector;

/**
* Utility class for storing PageSections specific state.
* @package FLXLabs\PageSections
*/
class PageSectionChangeState
{
private $propagateWrites = true;

public function setPropagateWrites(bool $value)
{
$this->propagateWrites = $value;
}

public function getPropagateWrites()
{
return $this->propagateWrites;
}

public static function inst()
{
/** @var PageSectionChangeState */
$inst = Injector::inst()->get(PageSectionChangeState::class);
return $inst;
}

/**
* @param bool|null $value
*/
public static function propagateWrites($value = null)
{
$inst = static::inst();
if ($value !== null) {
$inst->setPropagateWrites((bool) $value);
}
return $inst->getPropagateWrites();
}
}
4 changes: 4 additions & 0 deletions src/PageSectionPageElementRel.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public function onAfterWrite()
{
parent::onAfterWrite();

if (!PageSectionChangeState::propagateWrites()) {
return;
}

if (!$this->__NewOrder && Versioned::get_stage() == Versioned::DRAFT) {
$this->PageSection()->__Counter++;
if ($this->PageSection()->isLiveVersion()) {
Expand Down
10 changes: 0 additions & 10 deletions src/PageSectionsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,11 @@
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldButtonRow;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\SiteTree;
use SilverStripe\ORM\DataExtension;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\Versioned\Versioned;

use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;
use Symbiote\GridFieldExtensions\GridFieldAddExistingSearchButton;

class PageSectionsExtension extends DataExtension
{
// Generate the needed relations on the class
Expand Down

0 comments on commit 9ccd86b

Please sign in to comment.