Skip to content

Commit 7ac5f23

Browse files
committed
No need to namespace fields, add helper for relational save
1 parent 3cb1451 commit 7ac5f23

File tree

2 files changed

+86
-8
lines changed

2 files changed

+86
-8
lines changed

client/js/ManyField.src.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
$(row).prepend('<a class="btn btn-sm btn-danger manyfield__remove"><i class="fa fa-times"></i></a>');
1616
}
1717
} else {
18-
field.find('.manyfield__remove').removeAll();
18+
field.find('.manyfield__remove').remove();
1919
}
2020

2121
if (canSort) {
2222
if (!$(row).find('.manyfield__move').length) {
2323
$(row).prepend('<span class="btn btn-sm btn-info manyfield__move"><i class="fa fa-sort"></i></span>')
2424
}
2525
} else {
26-
field.find('.manyfield__move').removeAll()
26+
field.find('.manyfield__move').remove()
2727
}
2828
})
2929
})

src/ManyField.php

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ class ManyField extends CompositeField
5858
*/
5959
protected $fieldCallbacks = [];
6060

61+
/**
62+
*
63+
*/
64+
protected $manyChildren = [];
65+
6166
/**
6267
* @param string $name
6368
* @param array $children
@@ -67,12 +72,12 @@ public function __construct($name, $children = null) {
6772
Requirements::css('fullscreeninteractive/silverstripe-manyfield:client/css/ManyField.css');
6873

6974
if ($children instanceof FieldList) {
70-
$this->children = $children;
75+
$this->manyChildren = $children;
7176
} else if (is_array($children)) {
72-
$this->children = new FieldList($children);
77+
$this->manyChildren = new FieldList($children);
7378
}
74-
75-
$this->children->setContainerField($this);
79+
80+
$this->children = new FieldList();
7681
$this->brokenOnConstruct = false;
7782

7883
FormField::__construct($name, null);
@@ -233,7 +238,7 @@ public function saveInto(DataObjectInterface $record)
233238
} else if ($record->hasField($this->name)) {
234239
$record->setCastedField($this->name, json_encode($this->dataValue()));
235240
} else if ($record->getRelationType($this->name)) {
236-
// @todo
241+
$this->updateRelation($record, true);
237242
}
238243
}
239244

@@ -287,7 +292,7 @@ public function generateRow($index, $value = null)
287292
$row = CompositeField::create();
288293
$row->addExtraClass("row manyfield__row");
289294

290-
foreach ($this->children as $child) {
295+
foreach ($this->manyChildren as $child) {
291296
$field = clone $child;
292297
$field->name = $this->name . '['.$child->name . ']['. $index . ']';
293298

@@ -307,4 +312,77 @@ public function AbsoluteLink($action = null)
307312
{
308313
return Director::absoluteURL($this->Link($action));
309314
}
315+
316+
/**
317+
* Helper for going through all the values in this manymany field and
318+
* delete or create new records. This method won't be perfect for every case
319+
* but it'll handle most cases as long as the Field name matches the
320+
* relation name.
321+
*/
322+
public function updateRelation(DataObjectInterface $record, $delete = true)
323+
{
324+
$existing = $record->{$this->name}();
325+
$removed = [];
326+
327+
// if no value then we should clear everything out
328+
if (!$this->value) {
329+
if ($delete) {
330+
foreach ($existing as $row) {
331+
$row->delete();
332+
}
333+
} else {
334+
$existing->removeAll();
335+
}
336+
337+
return $this;
338+
}
339+
340+
foreach ($existing as $row) {
341+
if (!isset($this->value['ID'])) {
342+
throw new Exception('Missing ID field in ManyMany field list.');
343+
}
344+
345+
if (!isset($this->value['ID'][$row->ID])) {
346+
// missing so delete or remove.
347+
if ($delete) {
348+
$existing->find('ID', $row->ID)->delete();
349+
} else {
350+
$existing->removeById($row->ID);
351+
}
352+
}
353+
354+
foreach ($this->value['ID'] as $key => $id) {
355+
if ($id) {
356+
$idKeyMap[$key] = $id;
357+
}
358+
}
359+
360+
foreach ($this->value as $col => $values) {
361+
if ($col == 'ID') {
362+
continue;
363+
}
364+
365+
foreach ($values as $key => $value) {
366+
if (!isset($updatedData[$key])) {
367+
$updatedData[$key] = [];
368+
}
369+
370+
$updatedData[$key][$col] = $value;
371+
}
372+
}
373+
374+
foreach ($updatedData as $key => $data) {
375+
if (isset($idKeyMap[$key])) {
376+
$existing->find('ID', $idKeyMap[$key])->update($row);
377+
} else {
378+
$create = Injector::inst()->create($existing->dataClass());
379+
$create->update($data);
380+
$create->write();
381+
$existing->add($create);
382+
}
383+
}
384+
}
385+
386+
return $this;
387+
}
310388
}

0 commit comments

Comments
 (0)