diff --git a/config/curator.php b/config/curator.php index 8ddf0018..b84c18b1 100644 --- a/config/curator.php +++ b/config/curator.php @@ -30,10 +30,10 @@ 'fallbacks' => [], 'route_path' => 'curator', ], + 'intermediate_model' => null, 'image_crop_aspect_ratio' => null, 'image_resize_mode' => null, 'image_resize_target_height' => null, - 'image_resize_target_width' => null, 'is_limited_to_directory' => false, 'is_tenant_aware' => true, 'tenant_ownership_relationship_name' => 'tenant', diff --git a/src/Components/Forms/CuratorPicker.php b/src/Components/Forms/CuratorPicker.php index 57821f1a..584c97b2 100644 --- a/src/Components/Forms/CuratorPicker.php +++ b/src/Components/Forms/CuratorPicker.php @@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Storage; @@ -54,6 +55,8 @@ class CuratorPicker extends Field protected ?string $orderColumn = null; + protected ?string $collection = null; + protected ?string $typeColumn = null; protected ?string $typeValue = null; @@ -194,12 +197,17 @@ public function getTypeColumn(): string return $this->typeColumn ?? 'type'; } + public function getCollection() + { + return $this->collection ?? null; + } + public function getTypeValue(): ?string { return $this->typeValue ?? null; } - public function getRelationship(): BelongsTo | BelongsToMany | MorphMany | null + public function getRelationship(): BelongsTo | BelongsToMany | MorphMany | MorphOne | null { $name = $this->getRelationshipName(); @@ -435,6 +443,13 @@ public function typeColumn(string $column): static return $this; } + public function collection(string $collection) + { + $this->collection = $collection; + + return $this; + } + public function typeValue(string $value): static { $this->typeValue = $value; @@ -458,11 +473,18 @@ public function relationship(string | Closure $relationshipName, string | Closur if ($relationship instanceof MorphMany) { $typeColumn = $component->getTypeColumn(); $typeValue = $component->getTypeValue(); + $collection = $component->getCollection(); $query = $relationship->with('media'); if ($typeColumn && $typeValue) { $query->where($typeColumn, $typeValue); } + + if ($collection) { + + $query->where('collection', $collection); + } + $relatedMediaItems = $query->get(); $relatedMedia = $relatedMediaItems->map(function ($item) { @@ -480,6 +502,32 @@ public function relationship(string | Closure $relationshipName, string | Closur return; } + if ($relationship instanceof MorphOne) { + + $typeColumn = $component->getTypeColumn(); + $typeValue = $component->getTypeValue(); + $collection = $component->getCollection(); + + $query = $relationship->with('media'); + if ($typeColumn && $typeValue) { + $query->where($typeColumn, $typeValue); + } + + if ($collection) { + $query->where('collection', $collection); + } + + $relatedMediaItems = $query->get(); + + $relatedMedia = $relatedMediaItems->map(function ($item) { + return $item->media->toArray(); + })->toArray(); + + $component->state($relatedMedia); + + return; + } + /** @var BelongsTo $relationship */ $relatedModel = $relationship->getResults(); @@ -525,10 +573,11 @@ public function relationship(string | Closure $relationshipName, string | Closur $orderColumn = $component->getOrderColumn(); $typeColumn = $component->getTypeColumn(); $typeValue = $component->getTypeValue(); - $existingItems = $component->getRelationship()->where($typeColumn, $typeValue)->get()->keyBy('media_id')->toArray(); + $collection = $component->getCollection(); + $existingItems = $relationship->where($typeColumn, $typeValue)->get()->keyBy('media_id')->toArray(); $newIds = collect($state)->pluck('id')->toArray(); - $component->getRelationship()->whereNotIn('media_id', $newIds) + $relationship->whereNotIn('media_id', $newIds) ->where($typeColumn, $typeValue) ->delete(); @@ -538,15 +587,17 @@ public function relationship(string | Closure $relationshipName, string | Closur $data = [ 'media_id' => $itemId, $orderColumn => $i, + 'collection' => $collection, ]; if ($typeValue) { $data[$typeColumn] = $typeValue; } + if ($collection) { + $data['collection'] = $collection; + } + if (isset($existingItems[$itemId])) { - $component->getRelationship() - ->where('media_id', $itemId) - ->where($typeColumn, $typeValue) - ->update($data); + $relationship->where('media_id', $itemId)->update($data); } else { $relationship->create($data); } @@ -557,6 +608,42 @@ public function relationship(string | Closure $relationshipName, string | Closur } } + if ($relationship instanceof MorphOne) { + $orderColumn = $component->getOrderColumn(); + $typeColumn = $component->getTypeColumn(); + $typeValue = $component->getTypeValue(); + $collection = $component->getCollection(); + $existingItems = $relationship->where($typeColumn, $typeValue)->get()->keyBy('media_id')->toArray(); + $newIds = collect($state)->pluck('id')->toArray(); + + $relationship->whereNotIn('media_id', $newIds) + ->where($typeColumn, $typeValue) + ->delete(); + + $i = count($existingItems) + 1; + + foreach ($state as $item) { + $itemId = $item['id']; + $data = [ + 'media_id' => $itemId, + 'collection' => $collection, + $orderColumn => $i, + ]; + if ($typeValue) { + $data[$typeColumn] = $typeValue; + } + + if (isset($existingItems[$itemId])) { + $relationship->where('media_id', $itemId)->update($data); + } else { + $relationship->create($data); + } + $i++; + } + + return; + } + if (blank($state) && $relationship->exists()) { $relationship->disassociate(); diff --git a/src/Components/Tables/CuratorColumn.php b/src/Components/Tables/CuratorColumn.php index d40438b8..db80788f 100644 --- a/src/Components/Tables/CuratorColumn.php +++ b/src/Components/Tables/CuratorColumn.php @@ -11,6 +11,7 @@ use Illuminate\Support\Arr; use function Awcodes\Curator\get_media_items; +use function Awcodes\Curator\is_related_to_media_through_pivot; class CuratorColumn extends ImageColumn { @@ -26,7 +27,15 @@ public function getMedia(): Media | Collection | array | null $state = $this->getState(); if (is_a($state, Collection::class)) { - return $state->take($this->limit); + $state = $state->take($this->limit); + + if (! is_null($state) && is_related_to_media_through_pivot($state->first())) { + $mediaIds = $state->map(fn ($model) => $model?->media_id)->toArray(); + + return Media::whereIn('id', $mediaIds)->get(); + } + + return $state; } if (is_a($state, Media::class)) { diff --git a/src/helpers.php b/src/helpers.php index ea75f1b0..dc9fb640 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -17,10 +17,18 @@ function is_media_resizable(string $type): bool if (! function_exists('get_media_items')) { function get_media_items(array | Media | int $ids): Collection | array { - if ($ids instanceof Media) { + $mediaModel = config('curator.model'); + + if ($ids instanceof $mediaModel) { return [$ids]; } + if (is_array($ids) && is_related_to_media_through_pivot(current($ids))) { + $mediaIds = collect($ids)->map(fn ($model) => $model?->media_id)->toArray(); + + return config('curator.model')::whereIn('id', $mediaIds)->get(); + } + $ids = array_values($ids); if (isset($ids[0]['id'])) { @@ -39,6 +47,15 @@ function get_media_items(array | Media | int $ids): Collection | array } } +if (! function_exists('is_related_to_media_through_pivot')) { + function is_related_to_media_through_pivot(mixed $type): bool + { + $intermediateModelType = config('curator.intermediate_model'); + + return (! is_null(config('curator.intermediate_model'))) && $type instanceof $intermediateModelType; + } +} + if (! function_exists('is_panel_auth_route')) { function is_panel_auth_route(): bool {