Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/Console/Commands/AlgoliaImportWorldHeritages.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public function handle(): int
'world_heritage_sites.region',
'world_heritage_sites.study_region',
'world_heritage_sites.category',
'world_heritage_sites.criteria',
'world_heritage_sites.year_inscribed',
'world_heritage_sites.is_endangered',
])
Expand Down Expand Up @@ -132,6 +133,7 @@ public function handle(): int
'study_region' => $primaryStudyRegion,
'study_regions' => $studyRegions,
'category' => (string) $row->category,
'criteria' => $row->criteria,
'year_inscribed' => $row->year_inscribed !== null ? (int) $row->year_inscribed : null,
'is_endangered' => (bool) $row->is_endangered,
'thumbnail_url' => $row->images->first()?->url,
Expand Down
19 changes: 19 additions & 0 deletions src/app/Console/Commands/SplitWorldHeritageJson.php
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ private function normalizeSiteRowImportReady(array $row, int $siteId): array
'category' => $category,
'criteria' => $criteria,
'year_inscribed' => (isset($row['date_inscribed']) && is_numeric($row['date_inscribed'])) ? (int) $row['date_inscribed'] : null,
'is_endangered' => $this->boolFromDanger($row['danger'] ?? null),
'area_hectares' => isset($row['area_hectares']) ? (is_numeric($row['area_hectares']) ? (float) $row['area_hectares'] : null) : null,
'buffer_zone_hectares' => isset($row['buffer_zone_hectares']) ? (is_numeric($row['buffer_zone_hectares']) ? (float) $row['buffer_zone_hectares'] : null) : null,
'latitude' => isset($lat) ? (is_numeric($lat) ? (float) $lat : null) : null,
Expand Down Expand Up @@ -783,6 +784,10 @@ private function mergeSiteRowPreferExisting(array $existing, array $incoming): a
: 0;
}

if (($existing['is_endangered'] ?? false) === false) {
$existing['is_endangered'] = $this->boolFromDanger($incoming['danger'] ?? null);
}

if (($existing['state_party'] ?? null) === null) {
$iso2List = $this->extractIsoCodes($incoming['iso_codes'] ?? null);
if (count($iso2List) === 1) {
Expand Down Expand Up @@ -1025,6 +1030,20 @@ private function deduplicateCriteria(array $criteriaMatches): array
return $out;
}

private function boolFromDanger(mixed $value): bool
{
if (is_bool($value)) {
return $value;
}
if (is_int($value)) {
return $value === 1;
}
if (is_string($value)) {
return in_array(strtolower(trim($value)), ['true', '1', 'yes'], true);
}
return false;
}

private function toIso3OrNull(string $code): ?string
{
$code = strtoupper(trim($code));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function handle(): int
// Load translation map from JSON if --from-json is specified
$translationMap = [];
if ($fromJson) {
$translationPath = storage_path('app/private/unesco/world_heritage_sites_translation.json');
$translationPath = storage_path('app/private/unesco/short_description_ja.json');
if (!file_exists($translationPath)) {
$this->error("Translation JSON not found: {$translationPath}");
return 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ public function search(
$filters[] = 'year_inscribed <= ' . (int) $query->yearTo;
}

/**
* Inscription criteria filter (OR within criteria).
* Values are pre-validated by AlgoliaSearchListQueryFactory against the i–x whitelist.
*/
if ($query->criteria !== null && $query->criteria !== []) {
$orParts = array_map(
static fn (string $criterion) => 'criteria:' . $criterion,
$query->criteria,
);
$filters[] = '(' . implode(' OR ', $orParts) . ')';
}

/**
* Endangered status filter (boolean facet).
*/
if ($query->isEndangered !== null) {
$filters[] = 'is_endangered:' . ($query->isEndangered ? 'true' : 'false');
}

/**
* Guardrail:
* Never execute Algolia with query='' AND no filters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public function test_search_builds_algolia_params_with_filters_and_paging(): voi
category: 'Natural',
yearFrom: 1978,
yearTo: 1980,
criteria: [],
isEndangered: null,
currentPage: 2,
perPage: 30,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ protected function setUp(): void
category: null,
yearFrom: null,
yearTo: null,
criteria: [],
isEndangered: null,
currentPage: 1,
perPage: 10,
);
Expand Down
13 changes: 13 additions & 0 deletions src/app/Packages/Features/Controller/WorldHeritageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ public function searchWorldHeritages(
$keyword = $request->query('keyword');
}

$criteriaParam = $request->query('criteria');
$criteria = match (true) {
is_array($criteriaParam) => $criteriaParam,
is_string($criteriaParam) && $criteriaParam !== '' => explode(',', $criteriaParam),
default => null,
};

$isEndangered = $request->has('is_endangered')
? $request->boolean('is_endangered')
: null;

$dto = $useCase->handle(
$keyword,
$request->query('country_name'),
Expand All @@ -71,6 +82,8 @@ public function searchWorldHeritages(
$request->query('category'),
$request->query('year_inscribed_from'),
$request->query('year_inscribed_to'),
$criteria,
$isEndangered,
$currentPage,
$perPage,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

class AlgoliaSearchListQueryFactory
{
private const ALLOWED_CRITERIA = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x'];

public static function build(
?string $keyword,
?string $countryName,
Expand All @@ -16,6 +18,8 @@ public static function build(
?string $category,
?int $yearFrom,
?int $yearTo,
?array $criteria,
?bool $isEndangered,
int $currentPage,
int $perPage,
): AlgoliaSearchListQuery {
Expand All @@ -32,6 +36,17 @@ public static function build(
}
}

if ($criteria !== null) {
foreach ($criteria as $value) {
if (!in_array($value, self::ALLOWED_CRITERIA, true)) {
$printable = is_scalar($value) ? (string) $value : gettype($value);
throw new InvalidArgumentException(
"Invalid criteria value: {$printable}"
);
}
}
}

return new AlgoliaSearchListQuery(
keyword: $keyword,
countryName: $countryName,
Expand All @@ -40,6 +55,8 @@ public static function build(
category: $category,
yearFrom: $yearFrom,
yearTo: $yearTo,
criteria: $criteria,
isEndangered: $isEndangered,
currentPage: $currentPage,
perPage: $perPage,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public function __construct(
public readonly ?string $category,
public readonly ?int $yearFrom,
public readonly ?int $yearTo,
public readonly ?array $criteria,
public readonly ?bool $isEndangered,
public readonly int $currentPage,
public readonly int $perPage,
) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public function test_check_list_query_type(): void
category: 'Natural',
yearFrom: 1978,
yearTo: 2000,
criteria: null,
isEndangered: null,
currentPage: 1,
perPage: 30,
);
Expand All @@ -38,6 +40,8 @@ public function test_check_list_query_value(): void
category: 'Natural',
yearFrom: 1978,
yearTo: 2000,
criteria: null,
isEndangered: null,
currentPage: 1,
perPage: 30,
);
Expand All @@ -63,6 +67,8 @@ public function test_check_nullable_params(): void
category: null,
yearFrom: null,
yearTo: null,
criteria: null,
isEndangered: null,
currentPage: 1,
perPage: 30,
);
Expand All @@ -89,6 +95,8 @@ public function test_check_invalid_region_throws_exception(): void
category: null,
yearFrom: null,
yearTo: null,
criteria: null,
isEndangered: null,
currentPage: 1,
perPage: 30,
);
Expand All @@ -105,6 +113,8 @@ public function test_all_study_regions_are_valid(): void
category: null,
yearFrom: null,
yearTo: null,
criteria: null,
isEndangered: null,
currentPage: 1,
perPage: 30,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public function test_search_heritages_resolves_country_name_and_calls_query_serv
'test category',
2000,
2020,
null,
null,
self::CURRENT_PAGE,
self::PER_PAGE
);
Expand Down Expand Up @@ -148,6 +150,8 @@ public function test_search_nullable_params_calls_query_service_with_nulls(): vo

$result = $useCase->handle(
null, null, null, null, null, null, null,
null,
null,
self::CURRENT_PAGE,
self::PER_PAGE
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public function handle(
?string $category,
?int $yearInscribedFrom,
?int $yearInscribedTo,
?array $criteria,
?bool $isEndangered,
int $currentPage,
int $perPage
): PaginationDto {
Expand Down Expand Up @@ -69,6 +71,8 @@ public function handle(
category: $category,
yearFrom: $yearInscribedFrom,
yearTo: $yearInscribedTo,
criteria: $criteria,
isEndangered: $isEndangered,
currentPage: $currentPage,
perPage: $perPage,
);
Expand Down
Loading
Loading