diff --git a/src/app/Console/Commands/AlgoliaImportWorldHeritages.php b/src/app/Console/Commands/AlgoliaImportWorldHeritages.php index 4ab5b09..eae19b9 100644 --- a/src/app/Console/Commands/AlgoliaImportWorldHeritages.php +++ b/src/app/Console/Commands/AlgoliaImportWorldHeritages.php @@ -51,7 +51,12 @@ public function handle(): int WorldHeritage::query() ->with([ - 'countries', + 'images' => function ($query) { + $query->where('is_primary', true)->select(['world_heritage_site_id', 'url']); + }, + 'countries' => function ($query) { + $query->select(['countries.state_party_code', 'countries.name_en', 'countries.name_jp']); + }, ]) ->select([ 'world_heritage_sites.id', @@ -63,7 +68,6 @@ public function handle(): int 'world_heritage_sites.category', 'world_heritage_sites.year_inscribed', 'world_heritage_sites.is_endangered', - 'world_heritage_sites.image_url', ]) ->chunkById($chunk, function ($rows) use ($client, $indexName, $dryRun, &$processed) { $objects = []; @@ -130,7 +134,7 @@ public function handle(): int 'category' => (string) $row->category, 'year_inscribed' => $row->year_inscribed !== null ? (int) $row->year_inscribed : null, 'is_endangered' => (bool) $row->is_endangered, - 'thumbnail_url' => $row->image_url !== null ? (string) $row->image_url : null, + 'thumbnail_url' => $row->images->first()?->url, 'state_party_codes' => $statePartyCodes, 'country_names_jp' => $countryCount > 1 ? $countryNamesJp : [], ]; diff --git a/src/app/Console/Commands/ImportWorldHeritageSiteFromSplitFile.php b/src/app/Console/Commands/ImportWorldHeritageSiteFromSplitFile.php index d19e9aa..2cbc12e 100644 --- a/src/app/Console/Commands/ImportWorldHeritageSiteFromSplitFile.php +++ b/src/app/Console/Commands/ImportWorldHeritageSiteFromSplitFile.php @@ -96,7 +96,6 @@ public function handle(): int 'latitude' => $this->toNullableFloat($row['latitude'] ?? null), 'longitude' => $this->toNullableFloat($row['longitude'] ?? null), 'short_description' => $this->toNullableString($row['short_description'] ?? null), - 'image_url' => $this->toNullableString($row['image_url'] ?? null), 'unesco_site_url' => $this->toNullableString($row['unesco_site_url'] ?? null), 'created_at' => $now, 'updated_at' => $now, diff --git a/src/app/Console/Commands/SplitWorldHeritageJson.php b/src/app/Console/Commands/SplitWorldHeritageJson.php index d71b250..f71ba85 100644 --- a/src/app/Console/Commands/SplitWorldHeritageJson.php +++ b/src/app/Console/Commands/SplitWorldHeritageJson.php @@ -95,7 +95,13 @@ public function handle(): int $normalizer = app(CountryCodeNormalizer::class); $logged = 0; - $logSkip = function (string $reason, int $index, mixed $idNo = null, array $extra = []) use ($logLimit, &$logged): void { + $logSkip = function ( + string $reason, + int $index, + mixed $idNo = null, + array $extra = + [] + ) use ($logLimit, &$logged): void { if ($logLimit <= 0) { return; } @@ -324,9 +330,9 @@ public function handle(): int ]; } else { if (($countries[$code3]['name_en'] ?? null) === $code3) { - $better = $names[$idx] ?? $names[0] ?? null; - if (is_string($better) && trim($better) !== '') { - $countries[$code3]['name_en'] = trim($better); + $betterName = $names[$idx] ?? $names[0] ?? null; + if (is_string($betterName) && trim($betterName) !== '') { + $countries[$code3]['name_en'] = trim($betterName); } } if (($countries[$code3]['region'] ?? null) === null && $region !== null) { @@ -609,14 +615,14 @@ private function extractIsoCodes(mixed $v): array $out = []; $seen = []; - foreach ($parts as $p) { - $p = strtoupper($p); - if ($p === '') { + foreach ($parts as $part) { + $part = strtoupper($part); + if ($part === '') { continue; } - if (!isset($seen[$p])) { - $seen[$p] = true; - $out[] = $p; + if (!isset($seen[$part])) { + $seen[$part] = true; + $out[] = $part; } } @@ -632,8 +638,8 @@ private function normalizeStatesNames(mixed $statesNames): array $seen = []; $out = []; - foreach ($statesNames as $v) { - $name = trim((string) $v); + foreach ($statesNames as $stateName) { + $name = trim((string) $stateName); if ($name === '') { continue; } @@ -650,49 +656,49 @@ private function extractImageUrls(array $row): array { $urls = []; - $main = $row['main_image_url']['url'] ?? null; - if (is_string($main)) { - $main = trim($main); - if ($main !== '') { - $urls[] = $main; + $mainImageUrl = $row['main_image_url']['url'] ?? null; + if (is_string($mainImageUrl)) { + $mainImageUrl = trim($mainImageUrl); + if ($mainImageUrl !== '') { + $urls[] = $mainImageUrl; } } - $images = $row['images_urls'] ?? null; + $imageUrls = $row['images_urls'] ?? null; - if (is_string($images)) { - $parts = preg_split('/\s*,\s*/', trim($images)) ?: []; - foreach ($parts as $p) { - $p = trim($p); - if ($p !== '') { - $urls[] = $p; + if (is_string($imageUrls)) { + $parts = preg_split('/\s*,\s*/', trim($imageUrls)) ?: []; + foreach ($parts as $part) { + $part = trim($part); + if ($part !== '') { + $urls[] = $part; } } } - if (is_array($images)) { - foreach ($images as $p) { - if (!is_string($p)) { + if (is_array($imageUrls)) { + foreach ($imageUrls as $imageUrl) { + if (!is_string($imageUrl)) { continue; } - $p = trim($p); - if ($p !== '') { - $urls[] = $p; + $imageUrl = trim($imageUrl); + if ($imageUrl !== '') { + $urls[] = $imageUrl; } } } $seen = []; - $out = []; - foreach ($urls as $u) { - if (isset($seen[$u])) { + $deduplicated = []; + foreach ($urls as $url) { + if (isset($seen[$url])) { continue; } - $seen[$u] = true; - $out[] = $u; + $seen[$url] = true; + $deduplicated[] = $url; } - return $out; + return $deduplicated; } private function normalizeSiteRowImportReady(array $row, int $siteId): array @@ -735,8 +741,6 @@ private function normalizeSiteRowImportReady(array $row, int $siteId): array 'latitude' => isset($lat) ? (is_numeric($lat) ? (float) $lat : null) : null, 'longitude' => isset($lon) ? (is_numeric($lon) ? (float) $lon : null) : null, 'short_description' => $this->stringOrNull($row['short_description_en'] ?? null), - 'image_url' => $this->stringOrNull($row['image_url'] ?? null), - 'primary_image_url' => $this->stringOrNull($row['image_url'] ?? null), 'unesco_site_url' => $this->stringOrNull($row['unesco_site_url'] ?? ($row['url'] ?? null)), ]; } @@ -782,11 +786,11 @@ private function mergeSiteRowPreferExisting(array $existing, array $incoming): a if (($existing['state_party'] ?? null) === null) { $iso2List = $this->extractIsoCodes($incoming['iso_codes'] ?? null); if (count($iso2List) === 1) { - $sp = $this->toIso3OrNull($iso2List[0]); - if ($sp !== null) { - $existing['state_party'] = $sp; + $stateParty = $this->toIso3OrNull($iso2List[0]); + if ($stateParty !== null) { + $existing['state_party'] = $stateParty; if (($existing['country'] ?? null) === null) { - $existing['country'] = $sp; + $existing['country'] = $stateParty; } } } @@ -804,25 +808,9 @@ private function mergeSiteRowPreferExisting(array $existing, array $incoming): a $fill('short_description', $incoming['short_description_en'] ?? null); - if (($existing['image_url'] ?? null) === null || $existing['image_url'] === '') { - $main = $incoming['main_image_url']['url'] ?? null; - if (is_string($main)) { - $main = trim($main); - if ($main !== '') { - $existing['image_url'] = mb_substr($main, 0, 255); - } - } - } - - if (($existing['primary_image_url'] ?? null) !== null) { - $existing['primary_image_url'] = null; - } - - if (($existing['unesco_site_url'] ?? null) === null) { - $u = $incoming['unesco_site_url'] ?? ($incoming['url'] ?? null); - if ($u) { - $existing['unesco_site_url'] = $u; - } + $unescoUrl = $incoming['unesco_site_url'] ?? ($incoming['url'] ?? null); + if (($existing['unesco_site_url'] ?? null) === null && $unescoUrl) { + $existing['unesco_site_url'] = $unescoUrl; } return $existing; @@ -945,11 +933,11 @@ private function cleanOutputDir(string $outDir): void $files = glob($pattern) ?: []; $deleted = 0; - foreach ($files as $f) { - if (!is_file($f)) { + foreach ($files as $file) { + if (!is_file($file)) { continue; } - if (@unlink($f)) { + if (@unlink($file)) { $deleted++; } } @@ -963,30 +951,17 @@ private function extractCriteriaList(mixed $criteriaTxt): array return []; } - $s = trim($criteriaTxt); - if ($s === '') { + $stringText = trim($criteriaTxt); + if ($stringText === '') { return []; } - preg_match_all('/\(([ivx]+)\)/i', $s, $m); - if (!isset($m[1]) || !is_array($m[1])) { + preg_match_all('/\(([ivx]+)\)/i', $stringText, $matches); + if (!isset($matches[1]) || !is_array($matches[1])) { return []; } - $out = []; - $seen = []; - foreach ($m[1] as $v) { - $v = strtolower(trim((string) $v)); - if ($v === '') { - continue; - } - if (!isset($seen[$v])) { - $seen[$v] = true; - $out[] = $v; - } - } - - return $out; + return $this->deduplicateCriteria($matches[1]); } private function resolveCriteriaList(array $row): array @@ -1001,12 +976,7 @@ private function resolveCriteriaList(array $row): array return $criteria; } - $criteria = $this->extractCriteriaFromJustification($row['justification_en'] ?? null); - if ($criteria !== []) { - return $criteria; - } - - return []; + return $this->extractCriteriaFromJustification($row['justification_en'] ?? null); } private function extractCriteriaFromJustification(mixed $justificationEn): array @@ -1015,37 +985,41 @@ private function extractCriteriaFromJustification(mixed $justificationEn): array return []; } - $s = trim($justificationEn); - if ($s === '') { + $stringText = trim($justificationEn); + if ($stringText === '') { return []; } - $pos = stripos($s, 'criterion'); + $pos = stripos($stringText, 'criterion'); if ($pos === false) { - $pos = stripos($s, 'criteria'); + $pos = stripos($stringText, 'criteria'); } if ($pos === false) { return []; } - $slice = substr($s, $pos, 600); + $slice = substr($stringText, $pos, 600); - preg_match_all('/\(([ivx]+)\)/i', $slice, $m); - if (!isset($m[1]) || !is_array($m[1]) || $m[1] === []) { + preg_match_all('/\(([ivx]+)\)/i', $slice, $matches); + if (!isset($matches[1]) || !is_array($matches[1]) || $matches[1] === []) { return []; } + return $this->deduplicateCriteria($matches[1]); + } + + private function deduplicateCriteria(array $criteriaMatches): array + { $out = []; $seen = []; - foreach ($m[1] as $v) { - $v = strtolower(trim((string) $v)); - if ($v === '') { + + foreach ($criteriaMatches as $criterion) { + $criterion = strtolower(trim((string) $criterion)); + if ($criterion === '' || isset($seen[$criterion])) { continue; } - if (!isset($seen[$v])) { - $seen[$v] = true; - $out[] = $v; - } + $seen[$criterion] = true; + $out[] = $criterion; } return $out; diff --git a/src/app/Models/Country.php b/src/app/Models/Country.php index 1a13703..07b0b5a 100644 --- a/src/app/Models/Country.php +++ b/src/app/Models/Country.php @@ -2,7 +2,6 @@ namespace App\Models; -use App\Models\WorldHeritage; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; diff --git a/src/app/Models/Image.php b/src/app/Models/Image.php index 33dee13..7b36834 100644 --- a/src/app/Models/Image.php +++ b/src/app/Models/Image.php @@ -3,7 +3,6 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\SoftDeletes; class Image extends Model { @@ -23,6 +22,13 @@ class Image extends Model 'updated_at', ]; + public function casts(): array + { + return [ + 'is_primary' => 'boolean', + ]; + } + public function worldHeritage() { return $this->belongsTo(WorldHeritage::class, 'world_heritage_site_id', 'id'); diff --git a/src/app/Models/WorldHeritage.php b/src/app/Models/WorldHeritage.php index bacb481..a454a4f 100644 --- a/src/app/Models/WorldHeritage.php +++ b/src/app/Models/WorldHeritage.php @@ -35,7 +35,6 @@ class WorldHeritage extends Model 'longitude', 'short_description', 'unesco_site_url', - 'thumbnail_image_id', ]; protected $hidden = [ @@ -61,10 +60,6 @@ public function images(): HasMany ->orderBy('sort_order', 'asc'); } - public function thumbnail(): BelongsTo - { - return $this->belongsTo(Image::class, 'thumbnail_image_id'); - } protected function casts(): array { return [ diff --git a/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_countEachRegionTest.php b/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_countEachRegionTest.php index 4c9b246..8967852 100644 --- a/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_countEachRegionTest.php +++ b/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_countEachRegionTest.php @@ -69,7 +69,6 @@ private function baseRecord(array $override = []): array 'latitude' => null, 'longitude' => null, 'short_description' => '', - 'image_url' => null, 'unesco_site_url' => null, 'created_at' => $now, 'updated_at' => $now, diff --git a/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_getByIdTest.php b/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_getByIdTest.php index 3d1ae23..4e44032 100644 --- a/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_getByIdTest.php +++ b/src/app/Packages/Domains/Test/QueryService/WorldHeritageQueryService_getByIdTest.php @@ -12,8 +12,6 @@ use Illuminate\Support\Facades\DB; use Tests\TestCase; use App\Models\Image; -use App\Packages\Domains\Ports\SignedUrlPort; -use Mockery; class WorldHeritageQueryService_getByIdTest extends TestCase { @@ -57,49 +55,48 @@ private function refresh(): void private function arrayData(): array { - return - [ - 'id' => 1133, - 'official_name' => "Ancient and Primeval Beech Forests of the Carpathians and Other Regions of Europe", - 'name' => "Ancient and Primeval Beech Forests", - 'heritage_name_jp' => "カルパティア山脈とヨーロッパ各地の古代及び原生ブナ林", - 'country' => 'Slovakia', - 'study_region' => 'Europe', - 'category' => 'Natural', - 'criteria' => ['ix'], - 'state_party' => null, - 'year_inscribed' => 2007, - 'area_hectares' => 99947.81, - 'buffer_zone_hectares' => 296275.8, - 'is_endangered' => false, - 'latitude' => 0.0, - 'longitude' => 0.0, - 'short_description' => '氷期後のブナの自然拡散史を示すヨーロッパ各地の原生的ブナ林群から成る越境・連続資産。', - 'unesco_site_url' => 'https://whc.unesco.org/en/list/1133', - 'state_parties_codes' => [ - 'ALB','AUT','BEL','BIH','BGR','HRV','CZE','FRA','DEU','ITA','MKD','POL','ROU','SVK','SVN','ESP','CHE','UKR' - ], - 'state_parties_meta' => [ - 'ALB' => ['is_primary' => false], - 'AUT' => ['is_primary' => false], - 'BEL' => ['is_primary' => false], - 'BIH' => ['is_primary' => false], - 'BGR' => ['is_primary' => false], - 'HRV' => ['is_primary' => false], - 'CZE' => ['is_primary' => false], - 'FRA' => ['is_primary' => false], - 'DEU' => ['is_primary' => false], - 'ITA' => ['is_primary' => false], - 'MKD' => ['is_primary' => false], - 'POL' => ['is_primary' => false], - 'ROU' => ['is_primary' => false], - 'SVK' => ['is_primary' => true], - 'SVN' => ['is_primary' => false], - 'ESP' => ['is_primary' => false], - 'CHE' => ['is_primary' => false], - 'UKR' => ['is_primary' => false], - ] - ]; + return [ + 'id' => 1133, + 'official_name' => "Ancient and Primeval Beech Forests of the Carpathians and Other Regions of Europe", + 'name' => "Ancient and Primeval Beech Forests", + 'heritage_name_jp' => "カルパティア山脈とヨーロッパ各地の古代及び原生ブナ林", + 'country' => 'Slovakia', + 'study_region' => 'Europe', + 'category' => 'Natural', + 'criteria' => ['ix'], + 'state_party' => null, + 'year_inscribed' => 2007, + 'area_hectares' => 99947.81, + 'buffer_zone_hectares' => 296275.8, + 'is_endangered' => false, + 'latitude' => 0.0, + 'longitude' => 0.0, + 'short_description' => '氷期後のブナの自然拡散史を示すヨーロッパ各地の原生的ブナ林群から成る越境・連続資産。', + 'unesco_site_url' => 'https://whc.unesco.org/en/list/1133', + 'state_parties_codes' => [ + 'ALB','AUT','BEL','BIH','BGR','HRV','CZE','FRA','DEU','ITA','MKD','POL','ROU','SVK','SVN','ESP','CHE','UKR' + ], + 'state_parties_meta' => [ + 'ALB' => ['is_primary' => false], + 'AUT' => ['is_primary' => false], + 'BEL' => ['is_primary' => false], + 'BIH' => ['is_primary' => false], + 'BGR' => ['is_primary' => false], + 'HRV' => ['is_primary' => false], + 'CZE' => ['is_primary' => false], + 'FRA' => ['is_primary' => false], + 'DEU' => ['is_primary' => false], + 'ITA' => ['is_primary' => false], + 'MKD' => ['is_primary' => false], + 'POL' => ['is_primary' => false], + 'ROU' => ['is_primary' => false], + 'SVK' => ['is_primary' => true], + 'SVN' => ['is_primary' => false], + 'ESP' => ['is_primary' => false], + 'CHE' => ['is_primary' => false], + 'UKR' => ['is_primary' => false], + ] + ]; } public function test_queryService_check(): void @@ -163,13 +160,39 @@ public function test_check_data_value(): void $this->assertEquals($this->arrayData()['unesco_site_url'], $result->getUnescoSiteUrl()); $this->assertEquals($expectedCodes, $result->getStatePartyCodes()); $this->assertEquals($orderedExpected, $result->getStatePartiesMeta()); - foreach ($result->getImages() as $img) { + } + + public function test_images_contract(): void + { + $result = $this->queryService->getHeritageById($this->arrayData()['id']); + $images = $result->getImages(); + + $this->assertIsArray($images); + $this->assertNotEmpty($images); + $this->assertTrue($images[0]['is_primary']); + $this->assertEquals(0, $images[0]['sort_order']); + $this->assertFalse($images[1]['is_primary']); + $this->assertEquals(1, $images[1]['sort_order']); + + foreach ($images as $img) { $this->assertArrayHasKey('id', $img); $this->assertArrayHasKey('url', $img); $this->assertArrayHasKey('sort_order', $img); $this->assertArrayHasKey('is_primary', $img); $this->assertIsBool($img['is_primary']); - $this->assertNotEmpty($img['url']); } } + + public function test_images_empty_when_no_images(): void + { + DB::table('world_heritage_site_images') + ->where('world_heritage_site_id', 1133) + ->delete(); + + + $result = $this->queryService->getHeritageById(1133); + + $this->assertIsArray($result->getImages()); + $this->assertEmpty($result->getImages()); + } } \ No newline at end of file diff --git a/src/app/Packages/Domains/WorldHeritageQueryService.php b/src/app/Packages/Domains/WorldHeritageQueryService.php index b2cbce9..4346454 100644 --- a/src/app/Packages/Domains/WorldHeritageQueryService.php +++ b/src/app/Packages/Domains/WorldHeritageQueryService.php @@ -25,15 +25,11 @@ public function __construct( private readonly WorldHeritageSearchPort $searchPort, ) {} - /** - * 一覧(最大30件): サムネのみ、state_party/state_party_code を要件通りに整形 - */ public function getAllHeritages( int $currentPage, int $perPage, string $order - ): PaginationDto - { + ): PaginationDto { $items = WorldHeritage::query() ->select([ 'world_heritage_sites.id', @@ -50,7 +46,7 @@ public function getAllHeritages( 'world_heritage_sites.latitude', 'world_heritage_sites.longitude', 'world_heritage_sites.short_description', - 'world_heritage_sites.image_url', + 'world_heritage_sites.unesco_site_url', ]) ->with([ 'countries' => function ($q) { @@ -60,7 +56,10 @@ public function getAllHeritages( 'countries.name_jp', 'countries.region', ]); - } + }, + 'images' => function ($imagesQuery) { + $imagesQuery->where('is_primary', true)->limit(1); + }, ]) ->orderBy('world_heritage_sites.id', $order) ->paginate($perPage, page: $currentPage); @@ -107,12 +106,12 @@ public function getHeritageById(int $id): WorldHeritageDto $imageCollection = new ImageDtoCollection(); $images = ($heritage->images ?? collect())->values(); - foreach ($images as $idx => $img) { + foreach ($images as $img) { $imageCollection->add(new ImageDto( id: $img->id, url: $img->url, sortOrder: $img->sort_order, - isPrimary: $idx === 0, + isPrimary: (bool) $img->is_primary, )); } @@ -189,121 +188,6 @@ public function getHeritageById(int $id): WorldHeritageDto ]); } - public function getHeritagesByIds(array $ids, int $currentPage, int $perPage): PaginationDto - { - $paginator = $this->model - ->select([ - 'id', - 'official_name', - 'name', - 'name_jp', - 'country', - 'region', - 'study_region', - 'category', - 'criteria', - 'year_inscribed', - 'area_hectares', - 'buffer_zone_hectares', - 'is_endangered', - 'latitude', - 'longitude', - 'short_description', - 'unesco_site_url', - 'thumbnail_image_id', - ]) - ->with([ - 'countries' => function ($countriesQuery) { - $countriesQuery->withPivot(['is_primary'])->orderBy('countries.state_party_code', 'asc')->orderBy( - 'site_state_parties.inscription_year', - 'asc', - ); - }, - 'thumbnail' => function ($thumbnailQuery) { - $thumbnailQuery->select([ - 'images.id', - 'images.world_heritage_id', - 'path', - 'sort_order', - ]); - }, - ]) - ->whereIn('id', $ids) - ->paginate($perPage, ['*'], 'current_page', $currentPage) - ->through(function ($heritage) { - $countries = $heritage->countries ?? collect(); - - $codes = $countries - ->pluck('state_party_code') - ->filter() - ->map($this->statePartyCodeNormalize(...)) - ->unique() - ->values(); - - $statePartyName = null; - $statePartyCodes = null; - $stateParties = []; - - if ($codes->count() === 1) { - $onlyCode = $codes->first(); - - $countryModel = $heritage->countries->first( - fn($country) => $this->statePartyCodeNormalize($country->state_party_code) === $onlyCode, - ); - - $statePartyName = $countryModel?->name; - $statePartyCodes = null; - } elseif ($codes->count() > 1) { - $statePartyName = null; - $statePartyCodes = $codes->all(); - } - - $statePartiesMeta = []; - - foreach ($countries as $country) { - $code = strtoupper($country->state_party_code); - if ($code === '' || $code === '0') { - continue; - } - - $statePartiesMeta[$code] = [ - 'is_primary' => (bool) data_get($country, 'pivot.is_primary', false), - ]; - } - - return [ - 'id' => $heritage->id, - 'official_name' => $heritage->official_name, - 'name' => $heritage->name, - 'name_jp' => $heritage->name_jp, - 'country' => $heritage->country, - 'region' => $heritage->study_region, - 'category' => $heritage->category, - 'criteria' => $heritage->criteria, - 'state_party' => $statePartyName, - 'state_party_code' => $statePartyCodes, - 'year_inscribed' => $heritage->year_inscribed, - 'area_hectares' => $heritage->area_hectares, - 'buffer_zone_hectares' => $heritage->buffer_zone_hectares, - 'is_endangered' => (bool) $heritage->is_endangered, - 'latitude' => $heritage->latitude, - 'longitude' => $heritage->longitude, - 'short_description' => $heritage->short_description, - 'unesco_site_url' => $heritage->unesco_site_url, - 'state_parties' => $stateParties, - 'state_parties_meta' => $statePartiesMeta, - ]; - }); - - $paginationArray = $paginator->toArray(); - $dtoCollection = $this->buildDtoFromCollection($paginationArray['data']); - - return new PaginationDto( - collection: $dtoCollection, - pagination: collect($paginationArray)->except('data')->toArray(), - ); - } - public function searchHeritages(AlgoliaSearchListQuery $query): PaginationDto { $result = $this->searchPort->search( @@ -359,8 +243,6 @@ public function getEachRegionsHeritagesCount(): array $counts[$region->value] ??= 0; } - // id: 148 (Old City of Jerusalem) is stored as Unknown - // but geographically belongs to Asia $counts[StudyRegion::ASIA->value] += 1; return $counts; @@ -377,6 +259,7 @@ private function buildWorldHeritagePayload($heritage): array ->unique() ->values(); + $statePartyName = null; $statePartyCodeValue = null; $statePartyCodeList = []; @@ -385,16 +268,11 @@ private function buildWorldHeritagePayload($heritage): array $primaryCountry = $countryRelations->first( fn($country) => strtoupper($country->state_party_code) === $onlyStateParty, ); - $statePartyName = $primaryCountry?->name_en ?? $heritage->country ?? null; } elseif ($statePartyCodeCollection->count() > 1) { $statePartyName = null; $statePartyCodeValue = $statePartyCodeCollection->all(); $statePartyCodeList = $statePartyCodeCollection->all(); - } else { - $statePartyName = null; - $statePartyCodeValue = null; - $statePartyCodeList = []; } $statePartiesMeta = []; @@ -409,8 +287,6 @@ private function buildWorldHeritagePayload($heritage): array ]; } - $thumbnailModel = $heritage->thumbnail; - return [ 'id' => $heritage->id, 'official_name' => $heritage->official_name, @@ -430,11 +306,10 @@ private function buildWorldHeritagePayload($heritage): array 'latitude' => $heritage->latitude, 'longitude' => $heritage->longitude, 'short_description' => $heritage->short_description, - 'thumbnail_id' => $thumbnailModel?->id, + 'image_url' => $heritage->images->first()?->url, 'unesco_site_url' => $heritage->unesco_site_url, 'state_parties' => $statePartyCodeList, 'state_parties_meta' => $statePartiesMeta, - 'image_url' => $heritage->image_url, ]; } diff --git a/src/app/Packages/Domains/WorldHeritageReadQueryService.php b/src/app/Packages/Domains/WorldHeritageReadQueryService.php index aa0035e..309f524 100644 --- a/src/app/Packages/Domains/WorldHeritageReadQueryService.php +++ b/src/app/Packages/Domains/WorldHeritageReadQueryService.php @@ -33,13 +33,16 @@ public function findByIdsPreserveOrder(array $ids): Collection 'world_heritage_sites.latitude', 'world_heritage_sites.longitude', 'world_heritage_sites.short_description', - 'world_heritage_sites.image_url', + 'world_heritage_sites.unesco_site_url', ]) ->with([ 'countries' => function ($q) { $q->select('countries.state_party_code', 'countries.name_en', 'countries.name_jp', 'countries.region') ->orderBy('countries.state_party_code', 'asc'); }, + 'images' => function ($imageQuery) { + $imageQuery->where('is_primary', true)->limit(1); + }, ]) ->whereIn('world_heritage_sites.id', $ids) ->get() diff --git a/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php b/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php index 48f6e1b..083e2fe 100644 --- a/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php +++ b/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php @@ -21,12 +21,6 @@ public function getHeritageById( int $id ): WorldHeritageDto; - public function getHeritagesByIds( - array $ids, - int $currentPage, - int $perPage - ): PaginationDto; - public function searchHeritages( AlgoliaSearchListQuery $query ): PaginationDto; diff --git a/src/app/Packages/Features/QueryUseCases/UseCase/GetWorldHeritageByIdsUseCase.php b/src/app/Packages/Features/QueryUseCases/UseCase/GetWorldHeritageByIdsUseCase.php deleted file mode 100644 index 3831270..0000000 --- a/src/app/Packages/Features/QueryUseCases/UseCase/GetWorldHeritageByIdsUseCase.php +++ /dev/null @@ -1,27 +0,0 @@ -worldHeritageQueryService - ->getHeritagesByIds( - $ids, - $currentPage, - $perPage - ); - } -} \ No newline at end of file diff --git a/src/database/migrations/2026_03_29_151147_drop_image_url_from_world_heritage_sites.php b/src/database/migrations/2026_03_29_151147_drop_image_url_from_world_heritage_sites.php new file mode 100644 index 0000000..e52ea42 --- /dev/null +++ b/src/database/migrations/2026_03_29_151147_drop_image_url_from_world_heritage_sites.php @@ -0,0 +1,28 @@ +dropColumn('image_url'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('world_heritage_sites', function (Blueprint $table) { + $table->string('image_url')->nullable()->after('short_description'); + }); + } +}; diff --git a/src/database/migrations/2026_03_29_155722_drop_primary_image_url_from_world_heritage_sites.php b/src/database/migrations/2026_03_29_155722_drop_primary_image_url_from_world_heritage_sites.php new file mode 100644 index 0000000..57d5412 --- /dev/null +++ b/src/database/migrations/2026_03_29_155722_drop_primary_image_url_from_world_heritage_sites.php @@ -0,0 +1,28 @@ +dropColumn('primary_image_url'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('world_heritage_sites', function (Blueprint $table) { + $table->string('primary_image_url')->nullable()->after('short_description'); + }); + } +}; diff --git a/src/database/seeders/WorldHeritageSeeder.php b/src/database/seeders/WorldHeritageSeeder.php index e68ad2e..96f27be 100644 --- a/src/database/seeders/WorldHeritageSeeder.php +++ b/src/database/seeders/WorldHeritageSeeder.php @@ -32,7 +32,6 @@ public function run(): void 'latitude' => 34.8394, 'longitude' => 134.6939, 'short_description' => '白鷺城の名で知られる城郭建築の傑作。天守群と縄張りが良好に保存される。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/661', 'created_at' => $now, 'updated_at' => $now, ], @@ -56,7 +55,6 @@ public function run(): void 'latitude' => null, 'longitude' => null, 'short_description' => '巨樹・照葉樹林に代表される生態系と景観が特筆される島。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/662', 'created_at' => $now, 'updated_at' => $now, ], @@ -80,7 +78,6 @@ public function run(): void 'latitude' => null, 'longitude' => null, 'short_description' => '日本最大級のブナ天然林を中心とする山地生態系。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/663', 'created_at' => $now, 'updated_at' => $now, ], @@ -104,7 +101,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '京都・宇治・大津に点在する社寺・庭園・城郭などから成る文化遺産群。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/688', 'created_at' => $now, 'updated_at' => $now, ], @@ -128,7 +124,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '氷期後のブナの自然拡散史を示すヨーロッパ各地の原生的ブナ林群から成る越境・連続資産。', - 'image_url' => '', 'unesco_site_url' => 'https://whc.unesco.org/en/list/1133', 'created_at' => $now, 'updated_at' => $now, ], @@ -152,7 +147,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '熊野三山・高野山・吉野・大峯を結ぶ霊場と参詣道の文化的景観。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/1142', 'created_at' => $now, 'updated_at' => $now, ], @@ -176,7 +170,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '日本の象徴たる霊峰。信仰・芸術・登拝文化に深い影響を与えた文化的景観。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/1418', 'created_at' => $now, 'updated_at' => $now, ], @@ -200,7 +193,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '中国・カザフスタン・キルギスにまたがるオアシス都市や遺跡群で構成され、東西交流の歴史を物証する文化遺産群。', - 'image_url' => '', 'unesco_site_url' => 'https://whc.unesco.org/en/list/1442', 'created_at' => $now, 'updated_at' => $now, ], @@ -224,7 +216,6 @@ public function run(): void 'latitude' => 0.0, 'longitude' => 0.0, 'short_description' => '中央アジアのザラフシャン谷からカラクム砂漠にかけて展開するオアシス都市・交易遺跡群の連続資産。', - 'image_url' => null, 'unesco_site_url' => 'https://whc.unesco.org/en/list/1662', 'created_at' => $now, 'updated_at' => $now, ],