Skip to content

Commit

Permalink
Solve issue where an iterable cast wont cast its container if empty
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Jul 25, 2024
1 parent 2b63d72 commit 108e660
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/DataPipes/CastPropertiesDataPipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,6 @@ protected function castIterable(
array $properties,
CreationContext $creationContext
): iterable {
if (empty($values)) {
return $values;
}

if ($values instanceof Enumerable) {
$values = $values->all();
}
Expand Down Expand Up @@ -179,6 +175,10 @@ protected function castIterableItems(
array $properties,
CreationContext $creationContext
): array {
if(empty($values)) {
return $values;
}

/** @var ?IterableItemCast $cast */
$cast = $this->findCastForIterableItems($property, $values, $properties, $creationContext);

Expand Down
28 changes: 28 additions & 0 deletions tests/CreationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,34 @@ public function __invoke(SimpleData $data)
->toEqual(['a', 'collection']);
})->skip(fn () => config('data.features.cast_and_transform_iterables') === false);

it('will cast an empty iterables list into the correct type', function () {
$dataClass = new class () extends Data {
public EloquentCollection $collection;

public CustomCollection $customCollection;

public array $array;
};

$data = $dataClass::from([
'collection' => [],
'customCollection' => [],
'array' => collect([]),
]);

expect($data->collection)
->toBeInstanceOf(EloquentCollection::class)
->toEqual(new EloquentCollection([]));

expect($data->customCollection)
->toBeInstanceOf(CustomCollection::class)
->toEqual(new CustomCollection([]));

expect($data->array)
->toBeArray()
->toEqual([]);
})->skip(fn () => config('data.features.cast_and_transform_iterables') === false);

it('will cast iterables into default types', function () {
$dataClass = new class () extends Data {
/** @var array<int, string> */
Expand Down
16 changes: 16 additions & 0 deletions tests/DataTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Illuminate\Contracts\Support\Responsable;
use Illuminate\Support\Collection;
use Illuminate\Validation\ValidationException;
use Spatie\LaravelData\Concerns\AppendableData;
use Spatie\LaravelData\Concerns\BaseData;
Expand Down Expand Up @@ -78,3 +79,18 @@ public static function fromString(string $string): static
'validate',
]);
});

class TestDTO extends Data
{
public function __construct(
/** @var Collection<int, string> $items */
public readonly Collection $items
) {
}
}

it('Empty array should return Collection too', function () {
// Throws the above mentioned error
$result = TestDTO::from(['items' => []]);
expect($result->items)->toBeEmpty();
});

0 comments on commit 108e660

Please sign in to comment.