From 9f2997ef6d3c762e3927a9ca1c05c93b580b17a2 Mon Sep 17 00:00:00 2001 From: abbasmashaddy72 Date: Sat, 18 May 2024 06:25:36 +0530 Subject: [PATCH 1/4] Support For Morphable --- CHANGELOG.md | 16 +++++++ README.md | 27 +++++++++++ src/Components/Forms/CuratorPicker.php | 63 ++++++++++++++++++++------ 3 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a0c99b1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## [Unreleased] + +### Added + +- Support for `MorphMany` relationships in `CuratorPicker`. +- Method to handle state hydration and saving for `MorphMany` relationships. +- Handling for related media data retrieval in `loadStateFromRelationshipsUsing`. + +### Changed + +- Modified `saveRelationshipsUsing` method to correctly manage `MorphMany` relationships, including ordering. +- Updated `getRelationship` method to recognize `MorphMany`. + +This changelog provides an overview of the modifications made to support `MorphMany` relationships in the `CuratorPicker` component. diff --git a/README.md b/README.md index 7443f06..d59f165 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,33 @@ public function productPictures(): BelongsToMany } ``` +#### MorphAble + +**Note:** The current implementation supports morphable relationships in forms, but it is not yet functional in table columns. Further adjustments are required for full compatibility in all display contexts. + +Migration + +`media_id` relationship on media_id + +Model + +```php +public function documents(): MorphMany +{ + return $this->morphMany(MediaItem::class, 'mediable') + ->orderBy('order'); +} +``` + +Form component + +```php +CuratorPicker::make('document_ids') + ->multiple() + ->relationship('documents', 'id') + ->orderColumn('order'), // only necessary if you need to rename the order column +``` + ### Path Generation By default, Curator will use the directory and disk set in the config to diff --git a/src/Components/Forms/CuratorPicker.php b/src/Components/Forms/CuratorPicker.php index bc7c18a..3afc7b4 100644 --- a/src/Components/Forms/CuratorPicker.php +++ b/src/Components/Forms/CuratorPicker.php @@ -16,6 +16,7 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; @@ -184,7 +185,7 @@ public function getOrderColumn(): string return $this->orderColumn ?? 'order'; } - public function getRelationship(): BelongsTo | BelongsToMany | null + public function getRelationship(): BelongsTo | BelongsToMany | MorphMany | null { $name = $this->getRelationshipName(); @@ -426,10 +427,21 @@ public function relationship(string | Closure $relationshipName, string | Closur $relationship = $component->getRelationship(); if ($component->isMultiple()) { - $relatedModels = $relationship->getResults(); + if ($relationship instanceof MorphMany) { + // Load related media items + $relatedMediaItems = $relationship->with('media')->get(); - $component->state($relatedModels); + // Map related media data + $relatedMedia = $relatedMediaItems->map(function ($item) { + return $item->media->toArray(); + })->toArray(); + + $component->state($relatedMedia); + return; + } + $relatedModels = $relationship->getResults(); + $component->state($relatedModels); return; } @@ -456,24 +468,45 @@ public function relationship(string | Closure $relationshipName, string | Closur } if ($component->isMultiple()) { - if ( - ($relationship instanceof BelongsToMany) && - in_array($component->getOrderColumn(), $relationship->getPivotColumns()) - ) { + if ($relationship instanceof BelongsToMany) { $orderColumn = $component->getOrderColumn(); - $state = collect(array_values($state))->mapWithKeys(function ($item, $index) use ($orderColumn) { - return [$item['id'] => [$orderColumn => $index + 1]]; - }); + if (in_array($orderColumn, $relationship->getPivotColumns())) { + $state = collect(array_values($state))->mapWithKeys(function ($item, $index) use ($orderColumn) { + return [$item['id'] => [$orderColumn => $index + 1]]; + }); - $relationship->sync($state ?? []); + $relationship->sync($state ?? []); + return; + } + $state = Arr::pluck($state, 'id'); + $relationship->sync($state ?? []); return; } - $state = Arr::pluck($state, 'id'); - $relationship->sync($state ?? []); - - return; + if ($relationship instanceof MorphMany) { + $orderColumn = $component->getOrderColumn(); + $existingIds = $relationship->pluck('id')->toArray(); + + // Delete removed items + $relationship->whereNotIn('id', Arr::pluck($state, 'id'))->delete(); + + // Update or create new items + $i = 1; // Initialize counter + foreach ($state as $item) { + $itemId = $item['id']; + if (in_array($itemId, $existingIds)) { + $relationship->where('media_id', $itemId)->update([$orderColumn => $i]); + } else { + $relationship->create([ + 'media_id' => $itemId, + $orderColumn => $i, + ]); + } + $i++; // Increment counter + } + return; + } } if (blank($state) && $relationship->exists()) { From 021cd3c712d10ee1e6760d58324797f25bd14b1d Mon Sep 17 00:00:00 2001 From: abbasmashaddy72 Date: Sat, 18 May 2024 07:12:18 +0530 Subject: [PATCH 2/4] Support for Type on Morphable Added --- README.md | 26 ++++++++---- src/Components/Forms/CuratorPicker.php | 59 +++++++++++++++++++++----- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d59f165..75b4bdd 100644 --- a/README.md +++ b/README.md @@ -195,19 +195,27 @@ public function productPictures(): BelongsToMany #### MorphAble -**Note:** The current implementation supports morphable relationships in forms, but it is not yet functional in table columns. Further adjustments are required for full compatibility in all display contexts. +**Note:** The current implementation supports morphable relationships in forms, but it is not yet functional in table columns. Further adjustments are required for full compatibility. -Migration +Example Migration -`media_id` relationship on media_id +```php +Schema::create('media_items', function (Blueprint $table) { + $table->id(); + $table->morphs('mediable'); + $table->foreignId('media_id')->constrained()->onDelete('cascade'); + $table->integer('order'); + $table->string('type'); + $table->timestamps(); +}); +``` Model ```php -public function documents(): MorphMany +public function media(): MorphMany { - return $this->morphMany(MediaItem::class, 'mediable') - ->orderBy('order'); + return $this->morphMany(MediaItem::class, 'mediable')->orderBy('order'); } ``` @@ -216,8 +224,10 @@ Form component ```php CuratorPicker::make('document_ids') ->multiple() - ->relationship('documents', 'id') - ->orderColumn('order'), // only necessary if you need to rename the order column + ->relationship('media', 'id') + ->orderColumn('order') // Optional: Rename the order column if needed + ->typeColumn('type') // Optional: Rename the type column if needed + ->typeValue('document'); // Optional: Specify the type value if using types ``` ### Path Generation diff --git a/src/Components/Forms/CuratorPicker.php b/src/Components/Forms/CuratorPicker.php index 3afc7b4..65a2521 100644 --- a/src/Components/Forms/CuratorPicker.php +++ b/src/Components/Forms/CuratorPicker.php @@ -54,6 +54,10 @@ class CuratorPicker extends Field protected ?string $orderColumn = null; + protected ?string $typeColumn = null; + + protected ?string $typeValue = null; + protected string | Closure | null $relationship = null; protected string | Closure | null $relationshipTitleColumnName = null; @@ -185,6 +189,16 @@ public function getOrderColumn(): string return $this->orderColumn ?? 'order'; } + public function getTypeColumn(): string + { + return $this->typeColumn ?? 'type'; + } + + public function getTypeValue(): ?string + { + return $this->typeValue ?? null; + } + public function getRelationship(): BelongsTo | BelongsToMany | MorphMany | null { $name = $this->getRelationshipName(); @@ -414,6 +428,20 @@ public function orderColumn(string $column): static return $this; } + public function typeColumn(string $column): static + { + $this->typeColumn = $column; + + return $this; + } + + public function typeValue(string $value): static + { + $this->typeValue = $value; + + return $this; + } + public function relationship(string | Closure $relationshipName, string | Closure $titleColumnName, ?Closure $callback = null): static { $this->relationship = $relationshipName; @@ -428,10 +456,15 @@ public function relationship(string | Closure $relationshipName, string | Closur if ($component->isMultiple()) { if ($relationship instanceof MorphMany) { - // Load related media items - $relatedMediaItems = $relationship->with('media')->get(); + $typeColumn = $component->getTypeColumn(); + $typeValue = $component->getTypeValue(); + + $query = $relationship->with('media'); + if ($typeColumn && $typeValue) { + $query->where($typeColumn, $typeValue); + } + $relatedMediaItems = $query->get(); - // Map related media data $relatedMedia = $relatedMediaItems->map(function ($item) { return $item->media->toArray(); })->toArray(); @@ -486,22 +519,26 @@ public function relationship(string | Closure $relationshipName, string | Closur if ($relationship instanceof MorphMany) { $orderColumn = $component->getOrderColumn(); + $typeColumn = $component->getTypeColumn(); + $typeValue = $component->getTypeValue(); $existingIds = $relationship->pluck('id')->toArray(); - // Delete removed items $relationship->whereNotIn('id', Arr::pluck($state, 'id'))->delete(); - // Update or create new items - $i = 1; // Initialize counter + $i = 1; foreach ($state as $item) { $itemId = $item['id']; + $data = [ + 'media_id' => $itemId, + $orderColumn => $i, + ]; + if ($typeColumn && $typeValue) { + $data[$typeColumn] = $typeValue; + } if (in_array($itemId, $existingIds)) { - $relationship->where('media_id', $itemId)->update([$orderColumn => $i]); + $relationship->where('media_id', $itemId)->update($data); } else { - $relationship->create([ - 'media_id' => $itemId, - $orderColumn => $i, - ]); + $relationship->create($data); } $i++; // Increment counter } From 3a4b9adf9f9ee5d2e77dedb51f480fbe9e5e5fc3 Mon Sep 17 00:00:00 2001 From: abbasmashaddy72 Date: Sat, 18 May 2024 07:15:08 +0530 Subject: [PATCH 3/4] Removed the temporary CHANGELOGS file I had added earlier. --- CHANGELOG.md | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index a0c99b1..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,16 +0,0 @@ -# Changelog - -## [Unreleased] - -### Added - -- Support for `MorphMany` relationships in `CuratorPicker`. -- Method to handle state hydration and saving for `MorphMany` relationships. -- Handling for related media data retrieval in `loadStateFromRelationshipsUsing`. - -### Changed - -- Modified `saveRelationshipsUsing` method to correctly manage `MorphMany` relationships, including ordering. -- Updated `getRelationship` method to recognize `MorphMany`. - -This changelog provides an overview of the modifications made to support `MorphMany` relationships in the `CuratorPicker` component. From c1e0ff00f1a21d83fc14c68bc128e7c445c58f94 Mon Sep 17 00:00:00 2001 From: abbasmashaddy72 Date: Sat, 18 May 2024 17:21:53 +0530 Subject: [PATCH 4/4] Had some Issues When Testing Sorted Them --- src/Components/Forms/CuratorPicker.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Components/Forms/CuratorPicker.php b/src/Components/Forms/CuratorPicker.php index 65a2521..a43a7ad 100644 --- a/src/Components/Forms/CuratorPicker.php +++ b/src/Components/Forms/CuratorPicker.php @@ -521,26 +521,29 @@ public function relationship(string | Closure $relationshipName, string | Closur $orderColumn = $component->getOrderColumn(); $typeColumn = $component->getTypeColumn(); $typeValue = $component->getTypeValue(); - $existingIds = $relationship->pluck('id')->toArray(); + $existingItems = $relationship->where($typeColumn, $typeValue)->get()->keyBy('media_id')->toArray(); + $newIds = collect($state)->pluck('id')->toArray(); - $relationship->whereNotIn('id', Arr::pluck($state, 'id'))->delete(); + $relationship->whereNotIn('media_id', $newIds) + ->where($typeColumn, $typeValue) + ->delete(); - $i = 1; + $i = count($existingItems) + 1; foreach ($state as $item) { $itemId = $item['id']; $data = [ 'media_id' => $itemId, $orderColumn => $i, ]; - if ($typeColumn && $typeValue) { + if ($typeValue) { $data[$typeColumn] = $typeValue; } - if (in_array($itemId, $existingIds)) { + if (isset($existingItems[$itemId])) { $relationship->where('media_id', $itemId)->update($data); } else { $relationship->create($data); } - $i++; // Increment counter + $i++; } return; }