Skip to content

Commit e8f84a1

Browse files
committed
Fix: save of nested repeaters
1 parent 5c2c58d commit e8f84a1

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

src/Repositories/Behaviors/HandleRepeaters.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use A17\Twill\Repositories\ModuleRepository;
1010
use Carbon\Carbon;
1111
use Exception;
12+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
13+
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
14+
use Illuminate\Database\Eloquent\Relations\Relation;
1215
use Illuminate\Support\Arr;
1316
use Illuminate\Support\Collection;
1417
use Illuminate\Support\Str;
@@ -124,13 +127,15 @@ public function updateRepeaterMorphMany(
124127

125128
// @todo: This needs refactoring in 3.x
126129
foreach ($relationFields as $index => $relationField) {
130+
$this->extractRepeaters($repeaterName, $fields, $relationField);
127131
$relationField['position'] = $index + 1;
128132
$relationField[$morphFieldId] = $object->id;
129133
$relationField[$morphFieldType] = $object->getMorphClass();
130134

131135
if (isset($relationField['id']) && Str::startsWith($relationField['id'], $relation)) {
132136
// row already exists, let's update
133137
$id = str_replace($relation . '-', '', $relationField['id']);
138+
134139
$relationRepository->update($id, $relationField);
135140
$currentIdList[] = (int)$id;
136141
} else {
@@ -175,6 +180,7 @@ public function updateRepeaterWithPivot(
175180
$object->{$relation}()->detach();
176181
}
177182

183+
178184
// Add the position to the pivot fields.
179185
$pivotFields[] = 'position';
180186

@@ -186,6 +192,7 @@ public function updateRepeaterWithPivot(
186192
$currentRelations = $object->{$relation}()->withPivot('id')->get();
187193

188194
foreach ($relationFields as $index => $relationField) {
195+
$this->extractRepeaters($repeaterName, $fields, $relationField);
189196
$relationField['position'] = $index + 1;
190197

191198
// If the relation is not an "existing" one try to match it with our session.
@@ -280,20 +287,31 @@ public function updateRepeater(
280287

281288
$relationRepository = $this->getModelRepository($relation, $modelOrRepository);
282289

290+
291+
if (method_exists($this->model, $relation)) {
292+
/** @var Relation $relationInstance */
293+
$relationInstance = $this->model->$relation();
294+
if ($relationInstance instanceof BelongsTo || $relationInstance instanceof HasOneOrMany) {
295+
$fk = $relationInstance->getForeignKeyName();
296+
}
297+
}
298+
$fk ??= $this->model->getForeignKey();
299+
283300
// If no relation field submitted, soft deletes all associated rows.
284301
// We only do this when the model is already existing.
285302
if (! $relationFields && ! $object->wasRecentlyCreated) {
286303
$relationRepository->updateBasic(null, [
287304
'deleted_at' => Carbon::now(),
288305
], [
289-
$this->model->getForeignKey() => $object->id,
306+
$fk => $object->id,
290307
]);
291308
}
292309

293310
// keep a list of updated and new rows to delete (soft delete?) old rows that were deleted from the frontend
294311
$currentIdList = [];
295312

296313
foreach ($relationFields as $index => $relationField) {
314+
$this->extractRepeaters($repeaterName, $fields, $relationField);
297315
$relationField['position'] = $index + 1;
298316
// If the relation is not an "existing" one try to match it with our session.
299317
if (
@@ -317,12 +335,13 @@ public function updateRepeater(
317335
if (isset($relationField['id']) && Str::startsWith($relationField['id'], $relation)) {
318336
// row already exists, let's update
319337
$id = str_replace($relation . '-', '', $relationField['id']);
338+
320339
$relationRepository->update($id, $relationField);
321340

322341
$currentIdList[] = (int)$id;
323342
} else {
324343
// new row, let's attach to our object and create
325-
$relationField[$this->model->getForeignKey()] = $object->id;
344+
$relationField[$fk] = $object->id;
326345
$frontEndId = $relationField['id'];
327346
unset($relationField['id']);
328347
$newRelation = $relationRepository->create($relationField);
@@ -344,6 +363,21 @@ public function updateRepeater(
344363
}
345364
}
346365

366+
private function extractRepeaters(string $repeaterName, array $fields, ?array &$relationField): void
367+
{
368+
if (!isset($relationField) || empty($fields['repeaters'])) {
369+
return;
370+
}
371+
372+
$prefix = $repeaterName . '|blocks-' . $relationField['id'] . '|';
373+
foreach ($fields['repeaters'] as $key => $repeater) {
374+
if (str_starts_with($key, $prefix)) {
375+
unset($fields['repeaters'][$key]);
376+
$relationField['repeaters'][substr($key, strlen($prefix))] = $repeater;
377+
}
378+
}
379+
}
380+
347381
/**
348382
* This makes sure that arrays are json encode (translations).
349383
*/

0 commit comments

Comments
 (0)