From db8adf589071ccc2252dc355eca1f9126aef05a0 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:32:21 +1200 Subject: [PATCH] FIX Duplicate userforms using cascade_duplicates config (#1320) --- .../UserFormFieldEditorExtension.php | 21 ++++++----------- code/Model/EditableFormField.php | 4 +++- .../EditableMultipleOptionField.php | 23 ++++--------------- code/Model/Recipient/EmailRecipient.php | 4 ++++ code/UserForm.php | 9 ++++---- tests/php/Model/UserDefinedFormTest.php | 4 ++-- 6 files changed, 25 insertions(+), 40 deletions(-) diff --git a/code/Extension/UserFormFieldEditorExtension.php b/code/Extension/UserFormFieldEditorExtension.php index 682d6a9..05f1a59 100644 --- a/code/Extension/UserFormFieldEditorExtension.php +++ b/code/Extension/UserFormFieldEditorExtension.php @@ -42,6 +42,8 @@ class UserFormFieldEditorExtension extends DataExtension ); private static $owns = [ + // Note we explicitly cannot use $cascade_duplicates to duplicate this relation. + // See onAfterDuplicate() 'Fields' ]; @@ -228,13 +230,14 @@ class UserFormFieldEditorExtension extends DataExtension } /** - * When duplicating a UserDefinedForm, duplicate all of its fields and display rules + * Duplicate the Fields() relation. + * When duplicating a UserDefinedForm, ensure the group ends aren't duplicated twice, + * but also ensure they are connected to the correct duplicated Group. * * @see DataObject::duplicate * @param DataObject $oldPage * @param bool $doWrite - * @param string $manyMany - * @return DataObject + * @param null|array $manyMany */ public function onAfterDuplicate($oldPage, $doWrite, $manyMany) { @@ -243,10 +246,7 @@ class UserFormFieldEditorExtension extends DataExtension foreach ($oldPage->Fields() as $field) { /** @var EditableFormField $newField */ $newField = $field->duplicate(false); - $newField->ParentID = $this->owner->ID; - $newField->ParentClass = $this->owner->ClassName; - $newField->Version = 0; - $newField->write(); + $this->getOwner()->Fields()->add($newField); // If we encounter a group start, record it for later use if ($field instanceof EditableFieldGroup) { @@ -259,13 +259,6 @@ class UserFormFieldEditorExtension extends DataExtension $groupStart->EndID = $newField->ID; $groupStart->write(); } - - foreach ($field->DisplayRules() as $customRule) { - $newRule = $customRule->duplicate(false); - $newRule->ParentID = $newField->ID; - $newRule->Version = 0; - $newRule->write(); - } } } diff --git a/code/Model/EditableFormField.php b/code/Model/EditableFormField.php index e9f3af4..37f438b 100755 --- a/code/Model/EditableFormField.php +++ b/code/Model/EditableFormField.php @@ -181,7 +181,9 @@ class EditableFormField extends DataObject 'DisplayRules', ]; - private static $cascade_duplicates = false; + private static $cascade_duplicates = [ + 'DisplayRules', + ]; /** * This is protected rather that private so that it's unit testable diff --git a/code/Model/EditableFormField/EditableMultipleOptionField.php b/code/Model/EditableFormField/EditableMultipleOptionField.php index feb2a98..a8f76fb 100644 --- a/code/Model/EditableFormField/EditableMultipleOptionField.php +++ b/code/Model/EditableFormField/EditableMultipleOptionField.php @@ -55,6 +55,10 @@ class EditableMultipleOptionField extends EditableFormField 'Options', ]; + private static $cascade_duplicates = [ + 'Options', + ]; + private static $table_name = 'EditableMultipleOptionField'; /** @@ -112,25 +116,6 @@ class EditableMultipleOptionField extends EditableFormField return $fields; } - /** - * Duplicate a pages content. We need to make sure all the fields attached - * to that page go with it - * {@inheritDoc} - */ - public function duplicate(bool $doWrite = true, array|null $relations = null): static - { - $clonedNode = parent::duplicate(true); - - foreach ($this->Options() as $field) { - $newField = $field->duplicate(false); - $newField->ParentID = $clonedNode->ID; - $newField->Version = 0; - $newField->write(); - } - - return $clonedNode; - } - /** * Return whether or not this field has addable options such as a * {@link EditableDropdown} or {@link EditableRadioField} diff --git a/code/Model/Recipient/EmailRecipient.php b/code/Model/Recipient/EmailRecipient.php index c5b9ee7..5e456e2 100644 --- a/code/Model/Recipient/EmailRecipient.php +++ b/code/Model/Recipient/EmailRecipient.php @@ -103,6 +103,10 @@ class EmailRecipient extends DataObject 'CustomRules', ]; + private static $cascade_duplicates = [ + 'CustomRules', + ]; + private static $summary_fields = [ 'EmailAddress', 'EmailSubject', diff --git a/code/UserForm.php b/code/UserForm.php index 82540a8..4858b0b 100644 --- a/code/UserForm.php +++ b/code/UserForm.php @@ -125,7 +125,9 @@ trait UserForm 'EmailRecipients', ]; - private static $cascade_duplicates = false; + private static $cascade_duplicates = [ + 'EmailRecipients', + ]; /** * @var array @@ -161,9 +163,8 @@ trait UserForm private static $non_live_permissions = ['SITETREE_VIEW_ALL']; /** - * Temporary storage of field ids when the form is duplicated. - * Example layout: array('EditableCheckbox3' => 'EditableCheckbox14') - * @var array + * Unused property + * @deprecated 5.3.0 Will be removed without equivalent functionality to replace it */ protected $fieldsFromTo = []; diff --git a/tests/php/Model/UserDefinedFormTest.php b/tests/php/Model/UserDefinedFormTest.php index c434201..e538d19 100644 --- a/tests/php/Model/UserDefinedFormTest.php +++ b/tests/php/Model/UserDefinedFormTest.php @@ -363,7 +363,7 @@ class UserDefinedFormTest extends FunctionalTest $form2 = $this->objFromFixture(UserDefinedForm::class, 'page-with-group'); $form2Validator = new UserFormValidator(); $form2Validator->setForm(new Form(new Controller(), Form::class, new FieldList(), new FieldList())); - $this->assertTrue($form2Validator->php($form2->toMap())); + $this->assertTrue($form2Validator->php($form2->toMap()), json_encode($form2Validator->getResult()->getMessages())); // Check field groups exist $form2GroupStart = $form2->Fields()->filter('ClassName', EditableFieldGroup::class)->first(); @@ -374,7 +374,7 @@ class UserDefinedFormTest extends FunctionalTest $form3 = $form2->duplicate(); $form3Validator = new UserFormValidator(); $form3Validator->setForm(new Form(new Controller(), Form::class, new FieldList(), new FieldList())); - $this->assertTrue($form3Validator->php($form3->toMap())); + $this->assertTrue($form3Validator->php($form3->toMap()), json_encode($form3Validator->getResult()->getMessages())); // Check field groups exist $form3GroupStart = $form3->Fields()->filter('ClassName', EditableFieldGroup::class)->first(); $form3GroupEnd = $form3->Fields()->filter('ClassName', EditableFieldGroupEnd::class)->first();