Skip to content

Commit

Permalink
Fix: save of nested repeaters
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofandel committed Feb 24, 2024
1 parent 5c2c58d commit 029f666
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/Repositories/Behaviors/HandleRepeaters.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use A17\Twill\Repositories\ModuleRepository;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
Expand Down Expand Up @@ -124,6 +127,7 @@ public function updateRepeaterMorphMany(

// @todo: This needs refactoring in 3.x
foreach ($relationFields as $index => $relationField) {
$this->extractRepeaters($repeaterName, $fields, $relationField);

Check warning on line 130 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L130

Added line #L130 was not covered by tests
$relationField['position'] = $index + 1;
$relationField[$morphFieldId] = $object->id;
$relationField[$morphFieldType] = $object->getMorphClass();
Expand Down Expand Up @@ -186,6 +190,7 @@ public function updateRepeaterWithPivot(
$currentRelations = $object->{$relation}()->withPivot('id')->get();

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

// If the relation is not an "existing" one try to match it with our session.
Expand Down Expand Up @@ -280,20 +285,30 @@ public function updateRepeater(

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

if (method_exists($this->model, $relation)) {

Check warning on line 288 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L288

Added line #L288 was not covered by tests
/** @var Relation $relationInstance */
$relationInstance = $this->model->$relation();
if ($relationInstance instanceof BelongsTo || $relationInstance instanceof HasOneOrMany) {
$fk = $relationInstance->getForeignKeyName();

Check warning on line 292 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L290-L292

Added lines #L290 - L292 were not covered by tests
}
}
$fk ??= $this->model->getForeignKey();

Check warning on line 295 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L295

Added line #L295 was not covered by tests

// If no relation field submitted, soft deletes all associated rows.
// We only do this when the model is already existing.
if (! $relationFields && ! $object->wasRecentlyCreated) {
$relationRepository->updateBasic(null, [
'deleted_at' => Carbon::now(),
], [
$this->model->getForeignKey() => $object->id,
$fk => $object->id,

Check warning on line 303 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L303

Added line #L303 was not covered by tests
]);
}

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

foreach ($relationFields as $index => $relationField) {
$this->extractRepeaters($repeaterName, $fields, $relationField);

Check warning on line 311 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L311

Added line #L311 was not covered by tests
$relationField['position'] = $index + 1;
// If the relation is not an "existing" one try to match it with our session.
if (
Expand Down Expand Up @@ -322,7 +337,7 @@ public function updateRepeater(
$currentIdList[] = (int)$id;
} else {
// new row, let's attach to our object and create
$relationField[$this->model->getForeignKey()] = $object->id;
$relationField[$fk] = $object->id;

Check warning on line 340 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L340

Added line #L340 was not covered by tests
$frontEndId = $relationField['id'];
unset($relationField['id']);
$newRelation = $relationRepository->create($relationField);
Expand All @@ -344,6 +359,21 @@ public function updateRepeater(
}
}

private function extractRepeaters(string $repeaterName, array $fields, ?array &$relationField): void
{
if (!isset($relationField) || empty($fields['repeaters'])) {
return;

Check warning on line 365 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L365

Added line #L365 was not covered by tests
}

$prefix = $repeaterName . '|blocks-' . $relationField['id'] . '|';
foreach ($fields['repeaters'] as $key => $repeater) {
if (str_starts_with($key, $prefix)) {
unset($fields['repeaters'][$key]);
$relationField['repeaters'][substr($key, strlen($prefix))] = $repeater;

Check warning on line 372 in src/Repositories/Behaviors/HandleRepeaters.php

View check run for this annotation

Codecov / codecov/patch

src/Repositories/Behaviors/HandleRepeaters.php#L371-L372

Added lines #L371 - L372 were not covered by tests
}
}
}

/**
* This makes sure that arrays are json encode (translations).
*/
Expand Down

0 comments on commit 029f666

Please sign in to comment.