You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In this example, Foo has a list of Bar stored in a many_many with a SortOrder extra field, and Bazhas_oneBar.
I didn't put SortOrder on Bar because SortOrder is a property of the list, not an intrinsic property of the related object. Bar shouldn't care, or even know, that it's appearing in a list, let alone have properties that relate to being in one.
Additionally, Bar may be used in other places where it obviously makes no sense to have a SortOrder, eg. in a has_one relation on Baz.
Therefore, a built-in way to have the duplication recurse into the related object would directly allow this to work.
For anyone else with this problem, the workaround I'm using at the moment is to overwrite the duplicateManyManyRelation method from DataObject to clone the related objects.
Code
classBarextendsDataObject {}
classFooextendsDataObject
{
privatestatic$many_many = [
'Bars' => Bar::class,
];
privatestatic$many_many_extraFields = [
'Bars' => [
'SortOrder' => 'Int',
],
];
privatestatic$cascade_duplicates = [
'Bars',
];
/** * Overwrites the parent version so that it actually clones Bars rather than rereferencing them * * @param DataObject $sourceObject * @param DataObject $destinationObject * @param string $relation */protectedfunctionduplicateManyManyRelation($sourceObject, $destinationObject, $relation)
{
// Decide if we need to cascade the duplicationif ($relation !== 'Bars') {
returnparent::duplicateManyManyRelation($sourceObject, $destinationObject, $relation);
}
// Copy all components from source to destination$source = $sourceObject->getManyManyComponents($relation);
$dest = $destinationObject->getManyManyComponents($relation);
if ($source instanceof ManyManyList) {
$extraFieldNames = $source->getExtraFields();
} else {
$extraFieldNames = [];
}
foreach ($sourceas$item) {
// Merge extra fields$extraFields = [];
foreach ($extraFieldNamesas$fieldName => $fieldType) {
$extraFields[$fieldName] = $item->getField($fieldName);
}
// This part is the change from `parent::duplicateManyManyRelation` - actually duplicate the object$clonedItem = $item->duplicate(false);
$dest->add($clonedItem, $extraFields);
}
}
}
classBazextendsDataObject {
privatestatic$has_one = [
'Bar' => Bar::class,
];
}
The text was updated successfully, but these errors were encountered:
OldStarchy
changed the title
Cascade Duplicate on many_many does not cascade duplicatecascade_duplicate on many_many does not cascade duplicate
Nov 18, 2020
OldStarchy
changed the title
cascade_duplicate on many_many does not cascade duplicatecascade_duplicate on many_many does not cascade duplicate
Nov 18, 2020
Affected Version
At least 4.6.0, probably all versions
Description
TL;DR: workaround at the bottom
So this is technically by design, see this note from the docs:
And while I get that this would be useful, it would be better to at least provide an option to recurse duplications into many_many fields.
My use case is an ordered list where the
SortOrder
is stored as an extrafield.Code
In this example,
Foo
has a list ofBar
stored in amany_many
with aSortOrder
extra field, andBaz
has_one
Bar
.I didn't put
SortOrder
onBar
becauseSortOrder
is a property of the list, not an intrinsic property of the related object.Bar
shouldn't care, or even know, that it's appearing in a list, let alone have properties that relate to being in one.Additionally,
Bar
may be used in other places where it obviously makes no sense to have aSortOrder
, eg. in ahas_one
relation onBaz
.Therefore, a built-in way to have the duplication recurse into the related object would directly allow this to work.
For anyone else with this problem, the workaround I'm using at the moment is to overwrite the
duplicateManyManyRelation
method fromDataObject
to clone the related objects.Code
The text was updated successfully, but these errors were encountered: