diff --git a/src/SimpleDTO.php b/src/SimpleDTO.php index 0499461..6c60a61 100644 --- a/src/SimpleDTO.php +++ b/src/SimpleDTO.php @@ -400,14 +400,35 @@ private function formatArrayableValue(mixed $value): array { return match (true) { is_array($value) => $value, - $value instanceof Collection => $value->toArray(), - $value instanceof Model => $value->toArray(), + $value instanceof Collection => $this->transformCollectionToArray($value), + $value instanceof Model => $this->transformModelToArray($value), $value instanceof SimpleDTO => $this->transformDTOToArray($value), is_object($value) => (array) $value, default => [], }; } + private function transformCollectionToArray(Collection $collection): array + { + return $collection->map(function ($item) { + return $this->isArrayable($item) + ? $this->formatArrayableValue($item) + : $item; + })->toArray(); + } + + private function transformModelToArray(Model $model): array + { + $result = []; + foreach ($model->getAttributes() as $key => $value) { + $result[$key] = $this->isArrayable($value) + ? $this->formatArrayableValue($value) + : $value; + } + + return $result; + } + private function transformDTOToArray(SimpleDTO $dto): array { $result = []; diff --git a/tests/Datasets/UserNestedCollectionDTO.php b/tests/Datasets/UserNestedCollectionDTO.php new file mode 100644 index 0000000..3288aad --- /dev/null +++ b/tests/Datasets/UserNestedCollectionDTO.php @@ -0,0 +1,37 @@ + ['required', 'array'], + 'email' => ['required', 'email'], + ]; + } + + protected function defaults(): array + { + return []; + } + + protected function casts(): array + { + return [ + 'names' => new CollectionCast(new DTOCast(NameDTO::class)), + ]; + } +} diff --git a/tests/Unit/ValidatedDTOTest.php b/tests/Unit/ValidatedDTOTest.php index 99c2c64..b62e1f3 100644 --- a/tests/Unit/ValidatedDTOTest.php +++ b/tests/Unit/ValidatedDTOTest.php @@ -16,6 +16,7 @@ use WendellAdriel\ValidatedDTO\Tests\Datasets\NullableDTO; use WendellAdriel\ValidatedDTO\Tests\Datasets\User; use WendellAdriel\ValidatedDTO\Tests\Datasets\UserDTO; +use WendellAdriel\ValidatedDTO\Tests\Datasets\UserNestedCollectionDTO; use WendellAdriel\ValidatedDTO\Tests\Datasets\UserNestedDTO; use WendellAdriel\ValidatedDTO\Tests\Datasets\ValidatedDTOInstance; use WendellAdriel\ValidatedDTO\ValidatedDTO; @@ -200,78 +201,129 @@ public function __invoke() }); it('validates that the ValidatedDTO can be converted into an array', function () { - $validatedDTO = new ValidatedDTOInstance(['name' => $this->subject_name]); + $dataStructure = ['name' => $this->subject_name]; + $validatedDTO = new ValidatedDTOInstance($dataStructure); expect($validatedDTO)->toArray() - ->toBe(['name' => $this->subject_name]); + ->toBe($dataStructure); }); it('validates that the ValidatedDTO can be converted into a JSON string', function () { - $validatedDTO = new ValidatedDTOInstance(['name' => $this->subject_name]); + $dataStructure = ['name' => $this->subject_name]; + $validatedDTO = new ValidatedDTOInstance($dataStructure); expect($validatedDTO)->toJson() - ->toBe('{"name":"' . $this->subject_name . '"}'); + ->toBe(json_encode($dataStructure)); }); it('validates that the ValidatedDTO can be converted into a pretty JSON string', function () { - $validatedDTO = new ValidatedDTOInstance(['name' => $this->subject_name]); + $dataStructure = ['name' => $this->subject_name]; + $validatedDTO = new ValidatedDTOInstance($dataStructure); expect($validatedDTO)->toPrettyJson() - ->toBe(json_encode(['name' => $this->subject_name], JSON_PRETTY_PRINT)); + ->toBe(json_encode($dataStructure, JSON_PRETTY_PRINT)); }); it('validates that the ValidatedDTO with nested data can be converted into an array', function () { - $validatedDTO = new UserNestedDTO([ + $dataStructure = [ 'name' => [ 'first_name' => $this->subject_name, 'last_name' => 'Doe', ], 'email' => $this->subject_email, - ]); + ]; + $validatedDTO = new UserNestedDTO($dataStructure); expect($validatedDTO)->toArray() - ->toBe([ - 'name' => [ - 'first_name' => $this->subject_name, - 'last_name' => 'Doe', - ], - 'email' => $this->subject_email, - ]); + ->toBe($dataStructure); }); it('validates that the ValidatedDTO with nested data can be converted into a JSON string', function () { - $validatedDTO = new UserNestedDTO([ + $dataStructure = [ 'name' => [ 'first_name' => $this->subject_name, 'last_name' => 'Doe', ], 'email' => $this->subject_email, - ]); + ]; + $validatedDTO = new UserNestedDTO($dataStructure); expect($validatedDTO)->toJson() - ->toBe('{"name":{"first_name":"' . $this->subject_name . '","last_name":"Doe"},"email":"' . $this->subject_email . '"}'); + ->toBe(json_encode($dataStructure)); }); it('validates that the ValidatedDTO with nested data can be converted into a pretty JSON string', function () { - $validatedDTO = new UserNestedDTO([ + $dataStructure = [ 'name' => [ 'first_name' => $this->subject_name, 'last_name' => 'Doe', ], 'email' => $this->subject_email, - ]); + ]; + $validatedDTO = new UserNestedDTO($dataStructure); expect($validatedDTO)->toPrettyJson() - ->toBe(json_encode( + ->toBe(json_encode($dataStructure, JSON_PRETTY_PRINT)); +}); + +it('validates that the ValidatedDTO with nested collection data can be converted into an array', function () { + $dataStructure = [ + 'names' => [ [ - 'name' => [ - 'first_name' => $this->subject_name, - 'last_name' => 'Doe', - ], - 'email' => $this->subject_email, + 'first_name' => $this->subject_name, + 'last_name' => 'Doe', + ], + [ + 'first_name' => 'Jane', + 'last_name' => 'Doe', ], - JSON_PRETTY_PRINT - )); + ], + 'email' => $this->subject_email, + ]; + $validatedDTO = new UserNestedCollectionDTO($dataStructure); + + expect($validatedDTO)->toArray() + ->toBe($dataStructure); +}); + +it('validates that the ValidatedDTO with nested collection data can be converted into a JSON string', function () { + $dataStructure = [ + 'names' => [ + [ + 'first_name' => $this->subject_name, + 'last_name' => 'Doe', + ], + [ + 'first_name' => 'Jane', + 'last_name' => 'Doe', + ], + ], + 'email' => $this->subject_email, + ]; + $validatedDTO = new UserNestedCollectionDTO($dataStructure); + + expect($validatedDTO)->toJson() + ->toBe(json_encode($dataStructure)); +}); + +it('validates that the ValidatedDTO with nested collection data can be converted into a pretty JSON string', function () { + $dataStructure = [ + 'names' => [ + [ + 'first_name' => $this->subject_name, + 'last_name' => 'Doe', + ], + [ + 'first_name' => 'Jane', + 'last_name' => 'Doe', + ], + ], + 'email' => $this->subject_email, + ]; + $validatedDTO = new UserNestedCollectionDTO($dataStructure); + + expect($validatedDTO)->toPrettyJson() + ->toBe(json_encode($dataStructure, JSON_PRETTY_PRINT)); }); it('validates that the ValidatedDTO can be converted into an Eloquent Model', function () {