Skip to content

Commit 9e3da20

Browse files
Merge pull request #59 from WendellAdriel/to-array-fix
Fix how to handle enums and carbon objects when transforming DTO
2 parents 93e7086 + 6126279 commit 9e3da20

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

src/SimpleDTO.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44

55
namespace WendellAdriel\ValidatedDTO;
66

7+
use BackedEnum;
8+
use Carbon\Carbon;
9+
use Carbon\CarbonImmutable;
710
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
811
use Illuminate\Database\Eloquent\Model;
912
use Illuminate\Support\Collection;
1013
use Illuminate\Validation\ValidationException;
1114
use ReflectionClass;
1215
use ReflectionProperty;
16+
use UnitEnum;
1317
use WendellAdriel\ValidatedDTO\Attributes\Cast;
1418
use WendellAdriel\ValidatedDTO\Attributes\DefaultValue;
1519
use WendellAdriel\ValidatedDTO\Attributes\Map;
1620
use WendellAdriel\ValidatedDTO\Attributes\Rules;
1721
use WendellAdriel\ValidatedDTO\Casting\ArrayCast;
1822
use WendellAdriel\ValidatedDTO\Casting\Castable;
23+
use WendellAdriel\ValidatedDTO\Casting\EnumCast;
1924
use WendellAdriel\ValidatedDTO\Concerns\DataResolver;
2025
use WendellAdriel\ValidatedDTO\Concerns\DataTransformer;
2126
use WendellAdriel\ValidatedDTO\Contracts\BaseDTO;
@@ -261,9 +266,17 @@ protected function buildCasts(): array
261266
{
262267
$casts = [];
263268
foreach ($this->dtoCasts as $property => $cast) {
264-
$casts[$property] = is_null($cast->param)
265-
? new $cast->type()
266-
: new $cast->type(new $cast->param());
269+
if (is_null($cast->param)) {
270+
$casts[$property] = new $cast->type();
271+
272+
continue;
273+
}
274+
275+
$param = $cast->type === EnumCast::class
276+
? $cast->param
277+
: new $cast->param();
278+
279+
$casts[$property] = new $cast->type($param);
267280
}
268281

269282
return [
@@ -420,10 +433,13 @@ private function isArrayable(mixed $value): bool
420433
is_object($value);
421434
}
422435

423-
private function formatArrayableValue(mixed $value): array
436+
private function formatArrayableValue(mixed $value): array|int|string
424437
{
425438
return match (true) {
426439
is_array($value) => $value,
440+
$value instanceof BackedEnum => $value->value,
441+
$value instanceof UnitEnum => $value->name,
442+
$value instanceof Carbon || $value instanceof CarbonImmutable => $value->toISOString(),
427443
$value instanceof Collection => $this->transformCollectionToArray($value),
428444
$value instanceof Model => $this->transformModelToArray($value),
429445
$value instanceof SimpleDTO => $this->transformDTOToArray($value),
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WendellAdriel\ValidatedDTO\Tests\Datasets;
6+
7+
use Carbon\Carbon;
8+
use Carbon\CarbonImmutable;
9+
use WendellAdriel\ValidatedDTO\Attributes\Cast;
10+
use WendellAdriel\ValidatedDTO\Attributes\DefaultValue;
11+
use WendellAdriel\ValidatedDTO\Attributes\Rules;
12+
use WendellAdriel\ValidatedDTO\Casting\CarbonCast;
13+
use WendellAdriel\ValidatedDTO\Casting\CarbonImmutableCast;
14+
use WendellAdriel\ValidatedDTO\Casting\EnumCast;
15+
use WendellAdriel\ValidatedDTO\Concerns\EmptyCasts;
16+
use WendellAdriel\ValidatedDTO\Concerns\EmptyDefaults;
17+
use WendellAdriel\ValidatedDTO\Concerns\EmptyRules;
18+
use WendellAdriel\ValidatedDTO\ValidatedDTO;
19+
20+
class ValidatedEnumDTO extends ValidatedDTO
21+
{
22+
use EmptyCasts, EmptyDefaults, EmptyRules;
23+
24+
#[Rules(['sometimes', 'string'])]
25+
#[DefaultValue('ONE')]
26+
#[Cast(EnumCast::class, DummyEnum::class)]
27+
public DummyEnum $unitEnum;
28+
29+
#[Rules(['sometimes', 'string'])]
30+
#[DefaultValue('bar')]
31+
#[Cast(EnumCast::class, DummyBackedEnum::class)]
32+
public DummyBackedEnum $backedEnum;
33+
34+
#[Rules(['sometimes', 'string'])]
35+
#[DefaultValue('2023-10-16')]
36+
#[Cast(CarbonCast::class)]
37+
public Carbon $carbon;
38+
39+
#[Rules(['sometimes', 'string'])]
40+
#[DefaultValue('2023-10-15')]
41+
#[Cast(CarbonImmutableCast::class)]
42+
public CarbonImmutable $carbonImmutable;
43+
}

tests/Unit/ValidatedDTOTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
declare(strict_types=1);
44

5+
use Carbon\Carbon;
6+
use Carbon\CarbonImmutable;
57
use Illuminate\Console\Application;
68
use Illuminate\Console\Command;
79
use Illuminate\Database\Eloquent\Model;
810
use Illuminate\Http\Request;
911
use Illuminate\Validation\ValidationException;
1012
use WendellAdriel\ValidatedDTO\Exceptions\InvalidJsonException;
13+
use WendellAdriel\ValidatedDTO\Tests\Datasets\DummyBackedEnum;
14+
use WendellAdriel\ValidatedDTO\Tests\Datasets\DummyEnum;
1115
use WendellAdriel\ValidatedDTO\Tests\Datasets\MapBeforeExportDTO;
1216
use WendellAdriel\ValidatedDTO\Tests\Datasets\MapBeforeValidationDTO;
1317
use WendellAdriel\ValidatedDTO\Tests\Datasets\MapDataDTO;
@@ -19,6 +23,7 @@
1923
use WendellAdriel\ValidatedDTO\Tests\Datasets\UserNestedCollectionDTO;
2024
use WendellAdriel\ValidatedDTO\Tests\Datasets\UserNestedDTO;
2125
use WendellAdriel\ValidatedDTO\Tests\Datasets\ValidatedDTOInstance;
26+
use WendellAdriel\ValidatedDTO\Tests\Datasets\ValidatedEnumDTO;
2227
use WendellAdriel\ValidatedDTO\ValidatedDTO;
2328

2429
beforeEach(function () {
@@ -326,6 +331,27 @@ public function __invoke()
326331
->toBe(json_encode($dataStructure, JSON_PRETTY_PRINT));
327332
});
328333

334+
it('validates that the ValidatedDTO with Enums and Carbon properties can be correctly converted into an array', function () {
335+
$dto = new ValidatedEnumDTO([]);
336+
337+
expect($dto)->toBeInstanceOf(ValidatedEnumDTO::class)
338+
->and($dto->unitEnum)
339+
->toBeInstanceOf(DummyEnum::class)
340+
->and($dto->backedEnum)
341+
->toBeInstanceOf(DummyBackedEnum::class)
342+
->and($dto->carbon)
343+
->toBeInstanceOf(Carbon::class)
344+
->and($dto->carbonImmutable)
345+
->toBeInstanceOf(CarbonImmutable::class)
346+
->and($dto->toArray())
347+
->toBe([
348+
'unitEnum' => 'ONE',
349+
'backedEnum' => 'bar',
350+
'carbon' => '2023-10-16T00:00:00.000000Z',
351+
'carbonImmutable' => '2023-10-15T00:00:00.000000Z',
352+
]);
353+
});
354+
329355
it('validates that the ValidatedDTO can be converted into an Eloquent Model', function () {
330356
$validatedDTO = new ValidatedDTOInstance(['name' => $this->subject_name]);
331357

0 commit comments

Comments
 (0)