jonassiewertsen / statamic-livewire

A Laravel Livewire integration for Statamics antlers engine
91 stars 16 forks source link

Add synthesizers for statamic entries #33

Closed jonassiewertsen closed 1 year ago

ajnsn commented 1 year ago

Hey @jonassiewertsen

I recently implemented the LW synthesizers myself and just saw your package today. Just FYI that imHo it might be not the idea of hydration and dehydration of "models" (or "entries") to pass all the data back and forth. Could be a security issue as well?

Instead just leave the value empty and pass the id (or ids) in the meta, like LW's ModelSynth and EloquentCollectionSynth do. As Statamic typically has unique IDs across collections it might not be necessary to maintain even a collection classname within the meta array.

Here's my current implementation which works just by passing the IDs.

class EntrySynth extends Synth
{
    public static string $key = 'ent';

    public static function match($target): bool
    {
        return $target instanceof Entry;
    }

    public function dehydrate(Entry $target): array
    {
        $meta = [
            'id' => $target->id(),
        ];

        return [
            null,
            $meta,
        ];
    }

    public function hydrate(?array $value, array $meta): ?Entry
    {
        return Entry::find($meta['id']);
    }
}
class EntryCollectionSynth extends Synth
{
    public static string $key = 'entcln';

    public static function match($target): bool
    {
        return $target instanceof EntryCollection;
    }

    public function dehydrate(EntryCollection $target): array
    {
        $meta = [
            'ids' => $target->pluck('id')->toArray(),
        ];

        return [
            null,
            $meta,
        ];
    }

    public function hydrate(?array $value, array $meta): EntryCollection
    {
        $entries = Entry::query()
            ->whereIn('id', $meta['ids'])
            ->get();

        return new EntryCollection(
            collect($meta['ids'])
                ->map(fn (string $id): ?Entry => $entries->firstWhere('id', $id))
                ->filter()
        );
    }
}