From e782fdf2de6e698ac84c59ca3055415250bf18fa Mon Sep 17 00:00:00 2001 From: Tofandel Date: Tue, 15 Oct 2024 18:12:16 +0200 Subject: [PATCH 1/3] Fix BlockRepository setting relation of an object and improve amount of queries during saves --- src/Repositories/BlockRepository.php | 61 ++++++++++++---------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/src/Repositories/BlockRepository.php b/src/Repositories/BlockRepository.php index ed721d7f7..2fdceae7f 100644 --- a/src/Repositories/BlockRepository.php +++ b/src/Repositories/BlockRepository.php @@ -5,14 +5,12 @@ use A17\Twill\Facades\TwillBlocks; use A17\Twill\Models\Block; use A17\Twill\Models\Contracts\TwillModelContract; +use A17\Twill\Models\RelatedItem; use A17\Twill\Repositories\Behaviors\HandleFiles; use A17\Twill\Repositories\Behaviors\HandleMedias; use A17\Twill\Services\Blocks\Block as BlockConfig; use Illuminate\Config\Repository as Config; use Illuminate\Support\Collection; -use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Schema; -use ReflectionException; class BlockRepository extends ModuleRepository { @@ -35,42 +33,37 @@ public function getCrops(string $role): array public function hydrate(TwillModelContract $model, array $fields): TwillModelContract { - if (Schema::hasTable(config('twill.related_table', 'twill_related'))) { - $relatedItems = Collection::make(); - - Collection::make($fields['browsers'])->each(function ($items, $browserName) use (&$relatedItems) { - Collection::make($items)->each(function ($item) use ($browserName, &$relatedItems) { - try { - // @todo: Repository could be null. - $repository = $this->getModelRepository($item['endpointType'] ?? $browserName); - $relatedItems->push( - (object) [ - 'related' => $repository->getById($item['id']), - 'browser_name' => $browserName, - ] - ); - } catch (ReflectionException $reflectionException) { - Log::error($reflectionException); - } - }); - }); - - $model->setRelation('relatedItems', $relatedItems); - } + $relatedItems = collect($fields['browsers']) + ->flatMap(fn($items, $browserName) => collect($items) + ->map(fn($item, $position) => RelatedItem::make([ + 'subject_id' => $model->getKey(), + 'subject_type' => $model->getMorphClass(), + 'related_id' => $item['id'], + 'related_type' => $item['endpointType'], + 'browser_name' => $browserName, + 'position' => $position, + ]) + ) + ); + + $model->setRelation('relatedItems', $relatedItems); return parent::hydrate($model, $fields); } + /** @param Block $model */ public function afterSave(TwillModelContract $model, array $fields): void { - if (Schema::hasTable(config('twill.related_table', 'twill_related'))) { + if (!empty($fields['browsers'])) { + $browserNames = collect($fields['browsers'])->each(function ($items, $browserName) use ($model) { + // This will create items or delete them if they are missing + $model->saveRelated($items, $browserName); + })->keys(); + + // Delete all the related items that were emptied + RelatedItem::query()->whereMorphedTo('subject', $model)->whereNotIn('browser_name', $browserNames)->delete(); + } else { $model->clearAllRelated(); - - if (isset($fields['browsers'])) { - Collection::make($fields['browsers'])->each(function ($items, $browserName) use ($model) { - $model->saveRelated($items, $browserName); - }); - } } parent::afterSave($model, $fields); @@ -82,9 +75,7 @@ public function afterDelete(TwillModelContract $object): void $object->medias()->detach(); $object->files()->detach(); - if (Schema::hasTable(config('twill.related_table', 'twill_related'))) { - $object->clearAllRelated(); - } + $object->clearAllRelated(); } public function buildFromCmsArray(array $block, bool $repeater = false): array From a9a1d52dfec50ff1073ff226b5dfa9da6728a587 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Tue, 15 Oct 2024 18:22:16 +0200 Subject: [PATCH 2/3] Fix use of make and position is in the wrong place --- src/Repositories/Behaviors/HandleRevisions.php | 4 ++-- src/Repositories/BlockRepository.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Repositories/Behaviors/HandleRevisions.php b/src/Repositories/Behaviors/HandleRevisions.php index c8a9cbd5e..3e489315f 100644 --- a/src/Repositories/Behaviors/HandleRevisions.php +++ b/src/Repositories/Behaviors/HandleRevisions.php @@ -158,10 +158,10 @@ public function hydrateRelatedBrowsers(TwillModelContract $object, array $fields foreach ($relatedBrowsers as $browser) { $browserField = $fields['browsers'][$browser['browserName']] ?? []; + $position = 1; foreach ($browserField as $values) { - $position = 1; - $relatedBrowserItems->push(RelatedItem::make([ + $relatedBrowserItems->push(new RelatedItem([ 'subject_id' => $object->getKey(), 'subject_type' => $object->getMorphClass(), 'related_id' => $values['id'], diff --git a/src/Repositories/BlockRepository.php b/src/Repositories/BlockRepository.php index 2fdceae7f..c8fff3531 100644 --- a/src/Repositories/BlockRepository.php +++ b/src/Repositories/BlockRepository.php @@ -35,7 +35,7 @@ public function hydrate(TwillModelContract $model, array $fields): TwillModelCon { $relatedItems = collect($fields['browsers']) ->flatMap(fn($items, $browserName) => collect($items) - ->map(fn($item, $position) => RelatedItem::make([ + ->map(fn($item, $position) => new RelatedItem([ 'subject_id' => $model->getKey(), 'subject_type' => $model->getMorphClass(), 'related_id' => $item['id'], From 1c5ebbaf476a9faffaa8eb67d3fd11ab0b659474 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Tue, 15 Oct 2024 18:25:58 +0200 Subject: [PATCH 3/3] Eager load all the related items at once --- src/Repositories/Behaviors/HandleRevisions.php | 2 -- src/Repositories/BlockRepository.php | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Repositories/Behaviors/HandleRevisions.php b/src/Repositories/Behaviors/HandleRevisions.php index 3e489315f..bb1bef427 100644 --- a/src/Repositories/Behaviors/HandleRevisions.php +++ b/src/Repositories/Behaviors/HandleRevisions.php @@ -157,10 +157,8 @@ public function hydrateRelatedBrowsers(TwillModelContract $object, array $fields foreach ($relatedBrowsers as $browser) { $browserField = $fields['browsers'][$browser['browserName']] ?? []; - $position = 1; foreach ($browserField as $values) { - $relatedBrowserItems->push(new RelatedItem([ 'subject_id' => $object->getKey(), 'subject_type' => $object->getMorphClass(), diff --git a/src/Repositories/BlockRepository.php b/src/Repositories/BlockRepository.php index c8fff3531..86dc0ac8a 100644 --- a/src/Repositories/BlockRepository.php +++ b/src/Repositories/BlockRepository.php @@ -42,11 +42,10 @@ public function hydrate(TwillModelContract $model, array $fields): TwillModelCon 'related_type' => $item['endpointType'], 'browser_name' => $browserName, 'position' => $position, - ]) - ) - ); + ]))); $model->setRelation('relatedItems', $relatedItems); + $model->loadMissing('relatedItems.related'); return parent::hydrate($model, $fields); }