Skip to content

Commit b611dea

Browse files
committed
Add collection method to ResourceDTO
1 parent ab812e0 commit b611dea

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

src/ResourceDTO.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Contracts\Support\Responsable;
88
use Illuminate\Http\JsonResponse;
99
use Symfony\Component\HttpFoundation\Request;
10+
use WendellAdriel\ValidatedDTO\Support\ResourceCollection;
1011

1112
abstract class ResourceDTO extends SimpleDTO implements Responsable
1213
{
@@ -21,6 +22,11 @@ public function __construct(?array $data = null, int $status = 200, array $heade
2122
$this->headers = $headers;
2223
}
2324

25+
public static function collection(array $data, int $status = 200, array $headers = []): ResourceCollection
26+
{
27+
return new ResourceCollection($data, static::class, $status, $headers);
28+
}
29+
2430
/**
2531
* @param Request $request
2632
*/

src/Support/ResourceCollection.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WendellAdriel\ValidatedDTO\Support;
6+
7+
use Illuminate\Contracts\Support\Responsable;
8+
use Illuminate\Http\JsonResponse;
9+
use Illuminate\Validation\ValidationException;
10+
use Symfony\Component\HttpFoundation\Request;
11+
use WendellAdriel\ValidatedDTO\Casting\DTOCast;
12+
use WendellAdriel\ValidatedDTO\Exceptions\CastException;
13+
use WendellAdriel\ValidatedDTO\Exceptions\CastTargetException;
14+
15+
/**
16+
* @internal
17+
*/
18+
class ResourceCollection implements Responsable
19+
{
20+
public function __construct(
21+
private array $data,
22+
private string $dtoClass,
23+
private int $status = 200,
24+
private array $headers = []
25+
) {
26+
}
27+
28+
/**
29+
* @param Request $request
30+
*
31+
* @throws CastException|CastTargetException|ValidationException
32+
*/
33+
public function toResponse($request): JsonResponse
34+
{
35+
$result = [];
36+
37+
$dtoCast = new DTOCast($this->dtoClass);
38+
foreach ($this->data as $item) {
39+
$result[] = $dtoCast->cast('', $item)->toArray();
40+
}
41+
42+
return new JsonResponse($result, $this->status, $this->headers);
43+
}
44+
}

tests/Unit/ResourceDTOTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Http\Request;
77
use function Pest\Faker\faker;
88
use WendellAdriel\ValidatedDTO\ResourceDTO;
9+
use WendellAdriel\ValidatedDTO\Support\ResourceCollection;
910
use WendellAdriel\ValidatedDTO\Tests\Datasets\UserResourceDTO;
1011

1112
beforeEach(function () {
@@ -42,3 +43,47 @@
4243
->and($response->getStatusCode())
4344
->toBe(201);
4445
});
46+
47+
it('validates that a ResourceDTO can return a collection of data into a JsonResponse', function () {
48+
$list = [
49+
['name' => $this->name, 'age' => $this->age],
50+
['name' => $this->name, 'age' => $this->age],
51+
['name' => $this->name, 'age' => $this->age],
52+
];
53+
54+
$resourceDTO = UserResourceDTO::collection($list);
55+
$response = $resourceDTO->toResponse(new Request());
56+
57+
expect($resourceDTO)->toBeInstanceOf(ResourceCollection::class)
58+
->and($response)
59+
->toBeInstanceOf(JsonResponse::class)
60+
->and((array) $response->getData())
61+
->toBeArray()
62+
->toHaveCount(3)
63+
->each()
64+
->toHaveProperties(['name', 'age'])
65+
->and($response->getStatusCode())
66+
->toBe(200);
67+
});
68+
69+
it('validates that a ResourceDTO can return a collection of data into a JsonResponse with custom code', function () {
70+
$list = [
71+
['name' => $this->name, 'age' => $this->age],
72+
['name' => $this->name, 'age' => $this->age],
73+
['name' => $this->name, 'age' => $this->age],
74+
];
75+
76+
$resourceDTO = UserResourceDTO::collection($list, 201);
77+
$response = $resourceDTO->toResponse(new Request());
78+
79+
expect($resourceDTO)->toBeInstanceOf(ResourceCollection::class)
80+
->and($response)
81+
->toBeInstanceOf(JsonResponse::class)
82+
->and((array) $response->getData())
83+
->toBeArray()
84+
->toHaveCount(3)
85+
->each()
86+
->toHaveProperties(['name', 'age'])
87+
->and($response->getStatusCode())
88+
->toBe(201);
89+
});

0 commit comments

Comments
 (0)