Skip to content

Commit

Permalink
Rewrite collection synth
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Mar 1, 2024
1 parent 3efe949 commit ad4ad2e
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 55 deletions.
2 changes: 2 additions & 0 deletions src/LaravelDataServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Spatie\LaravelData\Contracts\BaseData;
use Spatie\LaravelData\Support\Caching\DataStructureCache;
use Spatie\LaravelData\Support\DataConfig;
use Spatie\LaravelData\Support\Livewire\LivewireDataCollectionSynth;
use Spatie\LaravelData\Support\Livewire\LivewireDataSynth;
use Spatie\LaravelData\Support\VarDumper\VarDumperManager;
use Spatie\LaravelPackageTools\Package;
Expand Down Expand Up @@ -61,6 +62,7 @@ function () {
protected function registerLivewireSynths(): void
{
Livewire::propertySynthesizer(LivewireDataSynth::class);
Livewire::propertySynthesizer(LivewireDataCollectionSynth::class);
}

public function packageBooted(): void
Expand Down
82 changes: 82 additions & 0 deletions src/Support/Livewire/LivewireDataCollectionSynth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Spatie\LaravelData\Support\Livewire;

use Livewire\Mechanisms\HandleComponents\ComponentContext;
use Livewire\Mechanisms\HandleComponents\Synthesizers\Synth;
use Spatie\LaravelData\Contracts\BaseData;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\Support\DataConfig;

class LivewireDataCollectionSynth extends Synth
{
protected DataConfig $dataConfig;

public static string $key = 'ldco';

public function __construct(ComponentContext $context, $path)
{
$this->dataConfig = app(DataConfig::class);

parent::__construct($context, $path);
}

public static function match($target): bool
{
return is_a($target, DataCollection::class, true);
}

public function get(&$target, $key): BaseData
{
return $target[$key];
}

public function set(&$target, $key, $value)
{
$target[$key] = $value;
}

/**
* @param callable(array-key, mixed):mixed $dehydrateChild
*/
public function dehydrate(DataCollection $target, callable $dehydrateChild): array
{
$morph = $this->dataConfig->morphMap->getDataClassAlias($target->dataClass) ?? $target->dataClass;

$payload = [];

foreach ($target->toCollection() as $key => $child) {
$payload[$key] = $dehydrateChild($key, $child);
}

return [
$payload,
[
'dataCollectionClass' => $target::class,
'dataMorph' => $morph,
'context' => encrypt($target->getDataContext()),
],
];
}

/**
* @param callable(array-key, mixed):mixed $hydrateChild
*/
public function hydrate($value, $meta, $hydrateChild)
{
$context = decrypt($meta['context']);
$dataCollectionClass = $meta['dataCollectionClass'];
$dataClass = $this->dataConfig->morphMap->getMorphedDataClass($meta['dataMorph']) ?? $meta['dataMorph'];

foreach ($value as $key => $child) {
$value[$key] = $hydrateChild($key, $child);
}

/** @var DataCollection $dataCollection */
$dataCollection = new $dataCollectionClass($dataClass, $value);

$dataCollection->setDataContext($context);

return $dataCollection;
}
}
55 changes: 0 additions & 55 deletions src/Synths/DataCollectionSynth.php

This file was deleted.

39 changes: 39 additions & 0 deletions tests/Fakes/Livewire/DataCollectionComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Spatie\LaravelData\Tests\Fakes\Livewire;

use Livewire\Component;
use Spatie\LaravelData\Attributes\DataCollectionOf;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\Tests\Fakes\SimpleData;

class DataCollectionComponent extends Component
{
#[DataCollectionOf(SimpleData::class)]
public DataCollection $collection;

public function mount(): void
{
$this->collection = SimpleData::collect([
'a', 'b', 'c',
], DataCollection::class);
}

public function save()
{
}

public function render()
{
return <<<'BLADE'
<div>
@foreach($collection as $item)
<p>{{ $item->string }}</p>
@endforeach
<input type="text" wire:model.live="collection.0.string">
<p>{{ $collection[0]->string }}</p>
<button wire:click="save">Save</button>
</div>
BLADE;
}
}
15 changes: 15 additions & 0 deletions tests/LivewireTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

use Spatie\LaravelData\Concerns\WireableData;
use Spatie\LaravelData\Data;

use Spatie\LaravelData\Lazy;
use Spatie\LaravelData\Support\Livewire\LivewireDataCollectionSynth;
use Spatie\LaravelData\Support\Livewire\LivewireDataSynth;
use Spatie\LaravelData\Tests\Fakes\Livewire\ComputedDataComponent;
use Spatie\LaravelData\Tests\Fakes\Livewire\DataCollectionComponent;
use Spatie\LaravelData\Tests\Fakes\Livewire\MappedDataComponent;
use Spatie\LaravelData\Tests\Fakes\Livewire\NestedDataComponent;
use Spatie\LaravelData\Tests\Fakes\Livewire\SimpleDataComponent;
Expand Down Expand Up @@ -37,6 +40,7 @@ public function __construct(
app()->register(LivewireServiceProvider::class);

Livewire::propertySynthesizer(LivewireDataSynth::class);
Livewire::propertySynthesizer(LivewireDataCollectionSynth::class);
});

it('can initialize a data object', function () {
Expand Down Expand Up @@ -93,4 +97,15 @@ public function __construct(
->assertSet('data.last_name', 'Van Assche')
->call('save');
});

it('can use data collections', function () {
livewire(DataCollectionComponent::class)
->assertSee('a')
->assertSee('b')
->assertSee('c')
->set('collection.0.string', 'Hello World')
->assertSet('collection.0.string', 'Hello World')
->assertSee('Hello World')
->call('save');
});
});

0 comments on commit ad4ad2e

Please sign in to comment.