Skip to content

Commit

Permalink
Fix #782
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Jun 13, 2024
1 parent 3d70e8a commit 8ff9118
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/Casts/BuiltinTypeCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Spatie\LaravelData\Casts;

use Spatie\LaravelData\Support\Creation\CreationContext;
use Spatie\LaravelData\Support\DataProperty;

class BuiltinTypeCast implements Cast, IterableItemCast
{
/**
* @param 'bool'|'int'|'float'|'array'|'string' $type
*/
public function __construct(
protected string $type,
) {
}

public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): mixed
{
return $this->runCast($value);
}

public function castIterableItem(DataProperty $property, mixed $value, array $properties, CreationContext $context): mixed
{
return $this->runCast($value);
}

protected function runCast(mixed $value): mixed
{
return match ($this->type) {
'bool' => (bool) $value,
'int' => (int) $value,
'float' => (float) $value,
'array' => (array) $value,
'string' => (string) $value,
};
}
}
5 changes: 5 additions & 0 deletions src/DataPipes/CastPropertiesDataPipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Spatie\LaravelData\DataPipes;

use Illuminate\Support\Enumerable;
use Spatie\LaravelData\Casts\BuiltinTypeCast;
use Spatie\LaravelData\Casts\IterableItemCast;
use Spatie\LaravelData\Casts\Uncastable;
use Spatie\LaravelData\Enums\DataTypeKind;
Expand Down Expand Up @@ -207,6 +208,10 @@ protected function findCastForIterableItems(
}
}

if(in_array($property->type->iterableItemType, ['bool', 'int', 'float', 'array', 'string'])) {
return new BuiltinTypeCast($property->type->iterableItemType);
}

return null;
}
}
33 changes: 33 additions & 0 deletions tests/CreationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,39 @@ public function __invoke(SimpleData $data)
->toEqual(['a', 'collection']);
})->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> */
public array $strings;

/** @var array<int, bool> */
public array $bools;

/** @var array<int, int> */
public array $ints;

/** @var array<int, float> */
public array $floats;

/** @var array<int, array> */
public array $arrays;
};

$data = $dataClass::from([
'strings' => ['Hello', 42, 3.14, true, '0', 'false'],
'bools' => ['Hello', 42, 3.14, true, ['nested'], '0', 'false'],
'ints' => ['Hello', 42, 3.14, true, ['nested'], '0', 'false'],
'floats' => ['Hello', 42, 3.14, true, ['nested'], '0', 'false'],
'arrays' => ['Hello', 42, 3.14, true, ['nested'], '0', 'false'],
]);

expect($data->strings)->toBe(['Hello', '42', '3.14', '1', '0', 'false']);
expect($data->bools)->toBe([true, true, true, true, true, false, true]);
expect($data->ints)->toBe([0, 42, 3, 1, 1, 0, 0]);
expect($data->floats)->toBe([0.0, 42.0, 3.14, 1.0, 1.0, 0.0, 0.0]);
expect($data->arrays)->toEqual([['Hello'], [42], [3.14], [true], ['nested'], ['0'], ['false']]);
})->skip(fn () => config('data.features.cast_and_transform_iterables') === false);

it('keeps the creation context path up to date', function () {
class TestCreationContextCollectorDataPipe implements DataPipe
{
Expand Down

0 comments on commit 8ff9118

Please sign in to comment.