Skip to content

Commit

Permalink
Merge pull request #485 from abbasmashaddy72/3.x
Browse files Browse the repository at this point in the history
Add support for MorphMany relationships in CuratorPicker
  • Loading branch information
awcodes authored May 26, 2024
2 parents 2b30423 + c1e0ff0 commit b50c315
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 15 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,43 @@ 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.

Example Migration

```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 media(): MorphMany
{
return $this->morphMany(MediaItem::class, 'mediable')->orderBy('order');
}
```

Form component

```php
CuratorPicker::make('document_ids')
->multiple()
->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

By default, Curator will use the directory and disk set in the config to
Expand Down
103 changes: 88 additions & 15 deletions src/Components/Forms/CuratorPicker.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -53,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;
Expand Down Expand Up @@ -184,7 +189,17 @@ public function getOrderColumn(): string
return $this->orderColumn ?? 'order';
}

public function getRelationship(): BelongsTo | BelongsToMany | null
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();

Expand Down Expand Up @@ -413,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;
Expand All @@ -426,10 +455,26 @@ public function relationship(string | Closure $relationshipName, string | Closur
$relationship = $component->getRelationship();

if ($component->isMultiple()) {
$relatedModels = $relationship->getResults();
if ($relationship instanceof MorphMany) {
$typeColumn = $component->getTypeColumn();
$typeValue = $component->getTypeValue();

$component->state($relatedModels);
$query = $relationship->with('media');
if ($typeColumn && $typeValue) {
$query->where($typeColumn, $typeValue);
}
$relatedMediaItems = $query->get();

$relatedMedia = $relatedMediaItems->map(function ($item) {
return $item->media->toArray();
})->toArray();

$component->state($relatedMedia);
return;
}

$relatedModels = $relationship->getResults();
$component->state($relatedModels);
return;
}

Expand All @@ -456,24 +501,52 @@ 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();
$typeColumn = $component->getTypeColumn();
$typeValue = $component->getTypeValue();
$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,
$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()) {
Expand Down

0 comments on commit b50c315

Please sign in to comment.