From 9bbbe99fff420b11a1c0d0b6481207ba6c5f19eb Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 10:58:36 +0900 Subject: [PATCH 1/6] feat: add mainImageUrl to WorldHeritageDto Adds an optional ?string $mainImageUrl constructor parameter and a getMainImageUrl() getter so downstream layers can read the raw main_image_url straight from the DTO. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Features/QueryUseCases/Dto/WorldHeritageDto.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDto.php b/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDto.php index d849d56..0bd3ac6 100644 --- a/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDto.php +++ b/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDto.php @@ -27,6 +27,7 @@ public function __construct( private readonly ?string $shortDescriptionJp = null, private readonly array $statePartyCodes = [], private readonly array $statePartiesMeta = [], + private readonly ?string $mainImageUrl = null, ){} @@ -125,6 +126,11 @@ public function getUnescoSiteUrl(): ?string return $this->unescoSiteUrl; } + public function getMainImageUrl(): ?string + { + return $this->mainImageUrl; + } + public function getStatePartyCodes(): array { return $this->statePartyCodes ?: $this->getStatePartyCodesOrFallback(); From 1dee45ff4c2e2fd10eb343168e47ce7ac8ec73c8 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 10:58:51 +0900 Subject: [PATCH 2/6] feat: pass main_image_url through WorldHeritageDetailFactory::build Reads main_image_url from the input array and forwards it to the WorldHeritageDto constructor so detail-path callers carry the value. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../QueryUseCases/Factory/Dto/WorldHeritageDetailFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageDetailFactory.php b/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageDetailFactory.php index 7ad069b..b5c380f 100644 --- a/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageDetailFactory.php +++ b/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageDetailFactory.php @@ -48,6 +48,7 @@ public static function build(array $data): WorldHeritageDto shortDescriptionJp: $data['short_description_jp'] ?? null, statePartyCodes: $statePartyCodes, statePartiesMeta: $statePartiesMeta, + mainImageUrl: $data['main_image_url'] ?? null, ); } From 7c905778a2f43b630c1605f653297eb2f97cc483 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 10:59:09 +0900 Subject: [PATCH 3/6] feat: pass main_image_url through WorldHeritageSummaryFactory::build Reads main_image_url from the input array and forwards it to the WorldHeritageDto constructor so list/summary callers carry the value. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../QueryUseCases/Factory/Dto/WorldHeritageSummaryFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageSummaryFactory.php b/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageSummaryFactory.php index 8735972..ce6cfa2 100644 --- a/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageSummaryFactory.php +++ b/src/app/Packages/Features/QueryUseCases/Factory/Dto/WorldHeritageSummaryFactory.php @@ -63,6 +63,7 @@ public static function build(array $data): WorldHeritageDto shortDescriptionJp: $data['short_description_jp'] ?? null, statePartyCodes: $statePartyCodes, statePartiesMeta: $statePartiesMeta, + mainImageUrl: $data['main_image_url'] ?? null, ); } From fbfc9bfb96a4041288963b12a8620e437156ee2a Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 11:00:10 +0900 Subject: [PATCH 4/6] feat: prefer main_image_url over images[0] in WorldHeritageViewModel thumbnail Updates WorldHeritageViewModel::getThumbnailUrl to fall back as main_image_url ?? images[0]?->url ?? null so the exposed thumbnail_url reflects the new field. The view model summary test mock is updated to cover the new path via getMainImageUrl. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ViewModel/WorldHeritageSummaryViewModelFactoryTest.php | 2 +- .../QueryUseCases/ViewModel/WorldHeritageViewModel.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageSummaryViewModelFactoryTest.php b/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageSummaryViewModelFactoryTest.php index 7b235c1..01d00ae 100644 --- a/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageSummaryViewModelFactoryTest.php +++ b/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageSummaryViewModelFactoryTest.php @@ -141,7 +141,7 @@ private function mockDto(): WorldHeritageDto $mock->shouldReceive('getStatePartiesMeta') ->andReturn($this->arrayData()['state_parties_meta']); - $mock->shouldReceive('getThumbnailUrl') + $mock->shouldReceive('getMainImageUrl') ->andReturn($this->arrayData()['thumbnail_url']); $mock->shouldReceive('getCountryNameJp') diff --git a/src/app/Packages/Features/QueryUseCases/ViewModel/WorldHeritageViewModel.php b/src/app/Packages/Features/QueryUseCases/ViewModel/WorldHeritageViewModel.php index 4dd77cc..02ff6f8 100644 --- a/src/app/Packages/Features/QueryUseCases/ViewModel/WorldHeritageViewModel.php +++ b/src/app/Packages/Features/QueryUseCases/ViewModel/WorldHeritageViewModel.php @@ -12,7 +12,8 @@ public function __construct( public function getThumbnailUrl(): ?string { - return $this->dto->getThumbnailUrl(); + return $this->dto->getMainImageUrl() + ?? ($this->dto->getImages()[0]['url'] ?? null); } public function getId(): int From 332d4d3d70eb1882b1db9124309cef5140dc0534 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 11:02:04 +0900 Subject: [PATCH 5/6] feat: expose thumbnail_url in WorldHeritageDtoCollection::toSummaryArray Renames the existing 'thumbnail' summary key to 'thumbnail_url' and fills it with main_image_url ?? images[0]?->url ?? null so the list endpoint surfaces the new field with the same fallback semantics as the detail ViewModel. The collection summary test is updated to assert the new key name. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Features/QueryUseCases/Dto/WorldHeritageDtoCollection.php | 3 ++- .../Tests/Dto/WorldHeritageDtoCollectionTest.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDtoCollection.php b/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDtoCollection.php index 0f6ef60..dea0ba8 100644 --- a/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDtoCollection.php +++ b/src/app/Packages/Features/QueryUseCases/Dto/WorldHeritageDtoCollection.php @@ -44,7 +44,8 @@ public function toSummaryArray(): array 'unesco_site_url' => $heritage->getUnescoSiteUrl(), 'state_party_codes' => $heritage->getStatePartyCodes(), 'state_parties_meta' => $heritage->getStatePartiesMeta(), - 'thumbnail' => $heritage->getThumbnailUrl(), + 'thumbnail_url' => $heritage->getMainImageUrl() + ?? ($heritage->getImages()[0]['url'] ?? null), ]; }, $this->heritages); } diff --git a/src/app/Packages/Features/QueryUseCases/Tests/Dto/WorldHeritageDtoCollectionTest.php b/src/app/Packages/Features/QueryUseCases/Tests/Dto/WorldHeritageDtoCollectionTest.php index e32b0d3..51622a7 100644 --- a/src/app/Packages/Features/QueryUseCases/Tests/Dto/WorldHeritageDtoCollectionTest.php +++ b/src/app/Packages/Features/QueryUseCases/Tests/Dto/WorldHeritageDtoCollectionTest.php @@ -211,8 +211,8 @@ public function test_summary_array_matches_expected_with_thumbnail(): void $this->assertArrayNotHasKey('images', $item); $this->assertArrayNotHasKey('imageUrl', $item); $this->assertArrayNotHasKey('state_parties', $item); - $this->assertArrayHasKey('thumbnail', $item); - $this->assertTrue(is_string($item['thumbnail']) || is_null($item['thumbnail'])); + $this->assertArrayHasKey('thumbnail_url', $item); + $this->assertTrue(is_string($item['thumbnail_url']) || is_null($item['thumbnail_url'])); return collect($item)->keyBy(static fn($v, $k) => Str::snake($k))->toArray(); })->toArray(); From dfcc418f9df56a740b3490290d3d45bae6c99fb6 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Tue, 5 May 2026 11:09:00 +0900 Subject: [PATCH 6/6] test: switch view model collection mock to mainImageUrl WorldHeritageViewModelCollectionFactoryTest used to seed the legacy imageUrl ImageDto field from thumbnail_url. The view model now resolves thumbnail_url via main_image_url ?? images[0]?->url, so the mock is updated to pass mainImageUrl directly. Drops the now-unused ImageDto import. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...orldHeritageViewModelCollectionFactoryTest.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageViewModelCollectionFactoryTest.php b/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageViewModelCollectionFactoryTest.php index e167c27..0a65c21 100644 --- a/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageViewModelCollectionFactoryTest.php +++ b/src/app/Packages/Features/QueryUseCases/Tests/ViewModel/WorldHeritageViewModelCollectionFactoryTest.php @@ -7,7 +7,6 @@ use App\Packages\Features\QueryUseCases\Factory\ViewModel\WorldHeritageViewModelCollectionFactory; use App\Packages\Features\QueryUseCases\ViewModel\WorldHeritageViewModelCollection; use Tests\TestCase; -use App\Packages\Features\QueryUseCases\Dto\ImageDto; class WorldHeritageViewModelCollectionFactoryTest extends TestCase { @@ -103,15 +102,6 @@ private function arrayData(): array private function mockDtoCollection(): WorldHeritageDtoCollection { $dtos = array_map(static function (array $data) { - $thumbnail = isset($data['thumbnail_url']) && $data['thumbnail_url'] - ? new ImageDto( - id: $data['id'] ?? 0, - url: $data['thumbnail_url'], - sortOrder: 0, - isPrimary: true, - ) - : null; - return new WorldHeritageDto( id: $data['id'], officialName: $data['official_name'], @@ -131,11 +121,12 @@ private function mockDtoCollection(): WorldHeritageDtoCollection bufferZoneHectares: $data['buffer_zone_hectares'] ?? null, shortDescription: $data['short_description'] ?? null, images: null, - imageUrl: $thumbnail, + imageUrl: null, unescoSiteUrl: $data['unesco_site_url'] ?? null, shortDescriptionJp: $data['short_description_jp'] ?? null, statePartyCodes: $data['state_party_codes'] ?? ($data['state_parties'] ?? []), - statePartiesMeta: $data['state_parties_meta'] ?? [] + statePartiesMeta: $data['state_parties_meta'] ?? [], + mainImageUrl: $data['thumbnail_url'] ?? null, ); }, $this->arrayData());