diff --git a/src/Data/Media.php b/src/Data/Media.php new file mode 100644 index 0000000..2f5c670 --- /dev/null +++ b/src/Data/Media.php @@ -0,0 +1,38 @@ +parent->resolveEndpoint(), '/').'/media/'; + } + + /** + * @return Media[] + */ + public function createDtoFromResponse(Response $response): array + { + return array_map( + fn (array $object) => Media::fromResponse($object), + $response->json('data.objects'), + ); + } +} diff --git a/src/Resources/ProjectResource.php b/src/Resources/ProjectResource.php index f98ded3..af39d85 100644 --- a/src/Resources/ProjectResource.php +++ b/src/Resources/ProjectResource.php @@ -2,7 +2,9 @@ namespace NieuwbouwOffice\PhpSdk\Resources; +use NieuwbouwOffice\PhpSdk\Data\Media; use NieuwbouwOffice\PhpSdk\Data\Project; +use NieuwbouwOffice\PhpSdk\Requests\Media\GetMediaRequest; use NieuwbouwOffice\PhpSdk\Requests\Projects\GetProjectRequest; use NieuwbouwOffice\PhpSdk\Requests\Projects\GetProjectsRequest; use Saloon\Http\BaseResource; @@ -21,4 +23,14 @@ public function get(string $uuid): Project { return $this->connector->send(new GetProjectRequest($uuid))->dto(); } + + /** + * @return Media[] + */ + public function media(string $uuid): array + { + return $this->connector + ->send(new GetMediaRequest(new GetProjectRequest($uuid))) + ->dto(); + } } diff --git a/src/Resources/UnitResource.php b/src/Resources/UnitResource.php index 65e5fa5..10c8a43 100644 --- a/src/Resources/UnitResource.php +++ b/src/Resources/UnitResource.php @@ -2,7 +2,9 @@ namespace NieuwbouwOffice\PhpSdk\Resources; +use NieuwbouwOffice\PhpSdk\Data\Media; use NieuwbouwOffice\PhpSdk\Data\Unit; +use NieuwbouwOffice\PhpSdk\Requests\Media\GetMediaRequest; use NieuwbouwOffice\PhpSdk\Requests\Units\GetUnitRequest; use NieuwbouwOffice\PhpSdk\Requests\Units\GetUnitsRequest; use Saloon\Http\BaseResource; @@ -29,4 +31,14 @@ public function get(string $uuid): Unit { return $this->connector->send(new GetUnitRequest($this->projectUuid, $uuid))->dto(); } + + /** + * @return Media[] + */ + public function media(string $uuid): array + { + return $this->connector + ->send(new GetMediaRequest(new GetUnitRequest($this->projectUuid, $uuid))) + ->dto(); + } } diff --git a/src/Resources/UnitTypeResource.php b/src/Resources/UnitTypeResource.php index 8a407f1..01b820c 100644 --- a/src/Resources/UnitTypeResource.php +++ b/src/Resources/UnitTypeResource.php @@ -2,7 +2,9 @@ namespace NieuwbouwOffice\PhpSdk\Resources; +use NieuwbouwOffice\PhpSdk\Data\Media; use NieuwbouwOffice\PhpSdk\Data\UnitType; +use NieuwbouwOffice\PhpSdk\Requests\Media\GetMediaRequest; use NieuwbouwOffice\PhpSdk\Requests\UnitTypes\GetUnitTypeRequest; use NieuwbouwOffice\PhpSdk\Requests\UnitTypes\GetUnitTypesRequest; use Saloon\Http\BaseResource; @@ -29,4 +31,14 @@ public function get(string $uuid): UnitType { return $this->connector->send(new GetUnitTypeRequest($this->projectUuid, $uuid))->dto(); } + + /** + * @return Media[] + */ + public function media(string $uuid): array + { + return $this->connector + ->send(new GetMediaRequest(new GetUnitTypeRequest($this->projectUuid, $uuid))) + ->dto(); + } } diff --git a/tests/Data/MediaTest.php b/tests/Data/MediaTest.php new file mode 100644 index 0000000..5c6ed36 --- /dev/null +++ b/tests/Data/MediaTest.php @@ -0,0 +1,45 @@ +uuid)->toBe('f40985b31bf3ef6e78dded76be712c0e') + ->and($media->filename)->toBe('33800-ext-02-appartementen-klein.jpg') + ->and($media->title)->toBeNull() + ->and($media->extension)->toBe('jpg') + ->and($media->url)->toBe('//static.nbo.nl//media/f4/f40985b31bf3ef6e78dded76be712c0e/O/33800-ext-02-appartementen-klein.jpg') + ->and($media->label)->toBe('Algemeen') + ->and($media->order)->toBe(1) + ->and($media->created_at)->toBe($createdAt); +}); + +it('parses Media_Timestamp into a CarbonImmutable via fromResponse()', function () { + $media = Media::fromResponse([ + 'Media_UUId' => 'abc', + 'Media_Filename' => 'image.jpg', + 'Media_Titel' => null, + 'Media_Extensie' => 'jpg', + 'URL' => '//static.nbo.nl/media/ab/abc/O/image.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '3', + 'Media_Timestamp' => '2025-12-02 14:43:30', + ]); + + expect($media->created_at)->toBeInstanceOf(CarbonImmutable::class) + ->and($media->created_at->toDateTimeString())->toBe('2025-12-02 14:43:30') + ->and($media->order)->toBe(3); +}); diff --git a/tests/Requests/Media/GetMediaRequestTest.php b/tests/Requests/Media/GetMediaRequestTest.php new file mode 100644 index 0000000..f83e0b5 --- /dev/null +++ b/tests/Requests/Media/GetMediaRequestTest.php @@ -0,0 +1,77 @@ +getMethod())->toBe(Method::GET); +}); + +it('appends /media/ to the parent project endpoint', function () { + expect((new GetMediaRequest(new GetProjectRequest('proj-1')))->resolveEndpoint()) + ->toBe('/projects/proj-1/media/'); +}); + +it('appends /media/ to the parent unit-type endpoint', function () { + expect((new GetMediaRequest(new GetUnitTypeRequest('proj-1', 'type-9')))->resolveEndpoint()) + ->toBe('/projects/proj-1/projectwoningen/type-9/media/'); +}); + +it('appends /media/ to the parent unit endpoint', function () { + expect((new GetMediaRequest(new GetUnitRequest('proj-1', 'unit-9')))->resolveEndpoint()) + ->toBe('/projects/proj-1/woningen/unit-9/media/'); +}); + +it('creates an array of Media DTOs from the response', function () { + $mockClient = new MockClient([ + GetMediaRequest::class => MockResponse::make([ + 'data' => [ + 'objects' => [ + [ + 'Media_UUId' => 'f40985b31bf3ef6e78dded76be712c0e', + 'Media_Filename' => '33800-ext-02-appartementen-klein.jpg', + 'Media_Titel' => null, + 'Media_Extensie' => 'jpg', + 'Media_Timestamp' => '2025-12-02 14:43:30', + 'URL' => '//static.nbo.nl//media/f4/f40985b31bf3ef6e78dded76be712c0e/O/33800-ext-02-appartementen-klein.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '1', + ], + [ + 'Media_UUId' => 'ab59d24f8a6204830700e8ecac697d9a', + 'Media_Filename' => '33800-ext-01-rijwoningen-poort-klein.jpg', + 'Media_Titel' => null, + 'Media_Extensie' => 'jpg', + 'Media_Timestamp' => '2025-12-02 14:43:30', + 'URL' => '//static.nbo.nl//media/ab/ab59d24f8a6204830700e8ecac697d9a/O/33800-ext-01-rijwoningen-poort-klein.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '2', + ], + ], + ], + 'meta' => ['count' => 2], + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $media = $connector->send(new GetMediaRequest(new GetProjectRequest('proj-1')))->dto(); + + expect($media)->toBeArray()->toHaveCount(2) + ->and($media[0])->toBeInstanceOf(Media::class) + ->and($media[0]->uuid)->toBe('f40985b31bf3ef6e78dded76be712c0e') + ->and($media[0]->filename)->toBe('33800-ext-02-appartementen-klein.jpg') + ->and($media[0]->extension)->toBe('jpg') + ->and($media[0]->label)->toBe('Algemeen') + ->and($media[0]->order)->toBe(1) + ->and($media[0]->created_at->toDateTimeString())->toBe('2025-12-02 14:43:30') + ->and($media[1]->order)->toBe(2); +}); diff --git a/tests/Resources/ProjectResourceTest.php b/tests/Resources/ProjectResourceTest.php index 315c896..eae70a0 100644 --- a/tests/Resources/ProjectResourceTest.php +++ b/tests/Resources/ProjectResourceTest.php @@ -1,7 +1,9 @@ MockResponse::make([ + 'data' => [ + 'objects' => [ + [ + 'Media_UUId' => 'm1', + 'Media_Filename' => 'a.jpg', + 'Media_Extensie' => 'jpg', + 'URL' => '//static.nbo.nl/media/m1.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '1', + 'Media_Timestamp' => '2025-12-02 14:43:30', + ], + ], + ], + 'meta' => ['count' => 1], + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $media = $connector->projects()->media('abc-123'); + + expect($media)->toBeArray()->toHaveCount(1) + ->and($media[0])->toBeInstanceOf(Media::class) + ->and($media[0]->uuid)->toBe('m1'); + + $mockClient->assertSent(function ($request) { + return $request instanceof GetMediaRequest + && $request->resolveEndpoint() === '/projects/abc-123/media/'; + }); +}); + it('can be instantiated directly with a connector', function () { $connector = new NieuwbouwOffice('test-token'); diff --git a/tests/Resources/UnitResourceTest.php b/tests/Resources/UnitResourceTest.php index 3fb6672..f7fd3ed 100644 --- a/tests/Resources/UnitResourceTest.php +++ b/tests/Resources/UnitResourceTest.php @@ -1,7 +1,9 @@ MockResponse::make([ + 'data' => [ + 'objects' => [ + [ + 'Media_UUId' => 'm1', + 'Media_Filename' => 'a.jpg', + 'Media_Extensie' => 'jpg', + 'URL' => '//static.nbo.nl/media/m1.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '1', + 'Media_Timestamp' => '2025-12-02 14:43:30', + ], + ], + ], + 'meta' => ['count' => 1], + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $media = $connector->units('proj-1')->media('unit-9'); + + expect($media)->toBeArray()->toHaveCount(1) + ->and($media[0])->toBeInstanceOf(Media::class) + ->and($media[0]->uuid)->toBe('m1'); + + $mockClient->assertSent(function ($request) { + return $request instanceof GetMediaRequest + && $request->resolveEndpoint() === '/projects/proj-1/woningen/unit-9/media/'; + }); +}); + it('can be instantiated directly with a connector and project uuid', function () { $connector = new NieuwbouwOffice('test-token'); diff --git a/tests/Resources/UnitTypeResourceTest.php b/tests/Resources/UnitTypeResourceTest.php index 369e47b..43fd8de 100644 --- a/tests/Resources/UnitTypeResourceTest.php +++ b/tests/Resources/UnitTypeResourceTest.php @@ -1,7 +1,9 @@ MockResponse::make([ + 'data' => [ + 'objects' => [ + [ + 'Media_UUId' => 'm1', + 'Media_Filename' => 'a.jpg', + 'Media_Extensie' => 'jpg', + 'URL' => '//static.nbo.nl/media/m1.jpg', + 'Label' => 'Algemeen', + 'Volgorde' => '1', + 'Media_Timestamp' => '2025-12-02 14:43:30', + ], + ], + ], + 'meta' => ['count' => 1], + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $media = $connector->unitTypes('proj-1')->media('type-9'); + + expect($media)->toBeArray()->toHaveCount(1) + ->and($media[0])->toBeInstanceOf(Media::class) + ->and($media[0]->uuid)->toBe('m1'); + + $mockClient->assertSent(function ($request) { + return $request instanceof GetMediaRequest + && $request->resolveEndpoint() === '/projects/proj-1/projectwoningen/type-9/media/'; + }); +}); + it('can be instantiated directly with a connector and project uuid', function () { $connector = new NieuwbouwOffice('test-token');