From 432ad2909afe65196fe6e62f56581976f2f8a33c Mon Sep 17 00:00:00 2001 From: Tofandel Date: Wed, 5 Jun 2024 19:45:44 +0200 Subject: [PATCH 1/4] Improve related save --- src/Models/Behaviors/HasRelated.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Models/Behaviors/HasRelated.php b/src/Models/Behaviors/HasRelated.php index 29e6c1f7d..6580bfa51 100644 --- a/src/Models/Behaviors/HasRelated.php +++ b/src/Models/Behaviors/HasRelated.php @@ -2,10 +2,9 @@ namespace A17\Twill\Models\Behaviors; -use A17\Twill\Models\Contracts\TwillModelContract; use A17\Twill\Models\RelatedItem; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphMany; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; trait HasRelated @@ -63,7 +62,7 @@ public function loadRelated(string $browserName): Collection /** * Attach items to the model for a browser field. * - * @param array $items + * @param array $items */ public function saveRelated(array|Collection $items, string $browserName): void { @@ -71,10 +70,16 @@ public function saveRelated(array|Collection $items, string $browserName): void $itemsToProcess = $this->relatedItems()->where('browser_name', $browserName)->get(); foreach ($items as $position => $item) { + if ($item instanceof Model) { + $id = $item->getKey(); + $type = $item->getMorphClass(); + } else { + $id = $item['id']; + $type = $item['endpointType']; + } + $firstMatchKey = $itemsToProcess - ->where('related_id', $item['id']) - ->where('related_type', $item['endpointType']) - ->where('browser_name', $browserName) + ->where(fn ($item) => $item->related_id === $id && $item->related_type === $type) // We should only have one item always as you cannot select the same items twice. ->keys() ->first(); @@ -90,8 +95,8 @@ public function saveRelated(array|Collection $items, string $browserName): void RelatedItem::create([ 'subject_id' => $this->getKey(), 'subject_type' => $this->getMorphClass(), - 'related_id' => $item['id'], - 'related_type' => $item['endpointType'], + 'related_id' => $id, + 'related_type' => $type, 'browser_name' => $browserName, 'position' => $position + 1, ]); From 0a455b13934a278c9f04a1a51c01e5bc86eedc7e Mon Sep 17 00:00:00 2001 From: Tofandel Date: Wed, 5 Jun 2024 19:50:06 +0200 Subject: [PATCH 2/4] Fix avoid recursive reference in relation --- src/Models/Behaviors/HasRelated.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Models/Behaviors/HasRelated.php b/src/Models/Behaviors/HasRelated.php index 6580bfa51..139b07af8 100644 --- a/src/Models/Behaviors/HasRelated.php +++ b/src/Models/Behaviors/HasRelated.php @@ -51,6 +51,7 @@ public function loadRelated(string $browserName): Collection /** @var \A17\Twill\Models\Model $model */ if ($model = $item->related) { $model->setRelation('pivot', $item); + $item->unsetRelation('related'); return $model; } @@ -79,7 +80,7 @@ public function saveRelated(array|Collection $items, string $browserName): void } $firstMatchKey = $itemsToProcess - ->where(fn ($item) => $item->related_id === $id && $item->related_type === $type) + ->where(fn (RelatedItem $item) => $item->related_id == $id && $item->related_type === $type) // We should only have one item always as you cannot select the same items twice. ->keys() ->first(); From 7b248150fa28a363cfb7686e9f92a40abe93c561 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Wed, 5 Jun 2024 21:37:23 +0200 Subject: [PATCH 3/4] Allow single model as well --- src/Models/Behaviors/HasRelated.php | 4 +++- tests/integration/Controllers/Tables/BrowserColumnTest.php | 7 +------ tests/integration/NplusOneRelatedTest.php | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Models/Behaviors/HasRelated.php b/src/Models/Behaviors/HasRelated.php index 139b07af8..661a04e03 100644 --- a/src/Models/Behaviors/HasRelated.php +++ b/src/Models/Behaviors/HasRelated.php @@ -65,8 +65,10 @@ public function loadRelated(string $browserName): Collection * * @param array $items */ - public function saveRelated(array|Collection $items, string $browserName): void + public function saveRelated(array|Collection|Model $items, string $browserName): void { + $items = collect($items); + /** @var Collection $itemsToProcess */ $itemsToProcess = $this->relatedItems()->where('browser_name', $browserName)->get(); diff --git a/tests/integration/Controllers/Tables/BrowserColumnTest.php b/tests/integration/Controllers/Tables/BrowserColumnTest.php index 9046e5b20..f2b95c39b 100644 --- a/tests/integration/Controllers/Tables/BrowserColumnTest.php +++ b/tests/integration/Controllers/Tables/BrowserColumnTest.php @@ -27,12 +27,7 @@ public function testWithSingleValue(): void $category = $this->createCategory(); $this->author->saveRelated( - [ - [ - 'id' => $category->id, - 'endpointType' => Category::class, - ], - ], + $category, 'categories' ); diff --git a/tests/integration/NplusOneRelatedTest.php b/tests/integration/NplusOneRelatedTest.php index a96fb05c7..c39691705 100644 --- a/tests/integration/NplusOneRelatedTest.php +++ b/tests/integration/NplusOneRelatedTest.php @@ -35,7 +35,7 @@ public function testSingleRelatedItem(): void 'published' => true, ]); - $storeArray[] = ['endpointType' => Writer::class, 'id' => $writer->id]; + $storeArray[] = $writer; } $letter->saveRelated($storeArray, 'dummyBrowser'); From d77e771e2db592506d487332c48eaf1b13bf4098 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Thu, 6 Jun 2024 15:38:03 +0200 Subject: [PATCH 4/4] Fix single model --- src/Models/Behaviors/HasRelated.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/Behaviors/HasRelated.php b/src/Models/Behaviors/HasRelated.php index 661a04e03..3996648f3 100644 --- a/src/Models/Behaviors/HasRelated.php +++ b/src/Models/Behaviors/HasRelated.php @@ -67,7 +67,7 @@ public function loadRelated(string $browserName): Collection */ public function saveRelated(array|Collection|Model $items, string $browserName): void { - $items = collect($items); + $items = is_array($items) || $items instanceof Collection ? $items : [$items]; /** @var Collection $itemsToProcess */ $itemsToProcess = $this->relatedItems()->where('browser_name', $browserName)->get();