fix: review fixes — cache Wikidata calls, add timeout, improve escaping, hide empty popovers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
thibaud-leclere
2026-03-30 22:38:05 +02:00
parent 91f45448f0
commit 8d413b5c57
3 changed files with 17 additions and 10 deletions

View File

@@ -21,6 +21,8 @@ export default function ActorPopover({ hintType, hintText }) {
const dismiss = useDismiss(context); const dismiss = useDismiss(context);
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]); const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
if (!hintText) return null;
const iconClass = HINT_ICONS[hintType] || 'fa-solid fa-circle-question'; const iconClass = HINT_ICONS[hintType] || 'fa-solid fa-circle-question';
return ( return (

View File

@@ -35,6 +35,7 @@ class GameGridGenerator
$rowOrder = 0; $rowOrder = 0;
$usedMovieRoleIds = []; $usedMovieRoleIds = [];
$usedHintKeys = []; $usedHintKeys = [];
$cachedAwards = null;
foreach (str_split(strtolower($mainActor->getName())) as $char) { foreach (str_split(strtolower($mainActor->getName())) as $char) {
if (!preg_match('/[a-z]/', $char)) { if (!preg_match('/[a-z]/', $char)) {
@@ -57,7 +58,7 @@ class GameGridGenerator
$row->setPosition(strpos(strtolower($actor->getName()), $char)); $row->setPosition(strpos(strtolower($actor->getName()), $char));
$row->setRowOrder($rowOrder); $row->setRowOrder($rowOrder);
$hint = $this->generateHint($mainActor, $usedMovieRoleIds, $usedHintKeys); $hint = $this->generateHint($mainActor, $usedMovieRoleIds, $usedHintKeys, $cachedAwards);
if ($hint !== null) { if ($hint !== null) {
$row->setHintType($hint['type']); $row->setHintType($hint['type']);
$row->setHintData($hint['data']); $row->setHintData($hint['data']);
@@ -138,13 +139,13 @@ class GameGridGenerator
* @param list<string> $usedHintKeys Semantic keys like "film:42" to avoid duplicate hints * @param list<string> $usedHintKeys Semantic keys like "film:42" to avoid duplicate hints
* @return array{type: string, data: string}|null * @return array{type: string, data: string}|null
*/ */
private function generateHint(Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys): ?array private function generateHint(Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys, ?array &$cachedAwards): ?array
{ {
$types = ['film', 'character', 'award']; $types = ['film', 'character', 'award'];
shuffle($types); shuffle($types);
foreach ($types as $type) { foreach ($types as $type) {
$hint = $this->resolveHint($type, $mainActor, $usedMovieRoleIds, $usedHintKeys); $hint = $this->resolveHint($type, $mainActor, $usedMovieRoleIds, $usedHintKeys, $cachedAwards);
if ($hint !== null) { if ($hint !== null) {
return $hint; return $hint;
} }
@@ -158,7 +159,7 @@ class GameGridGenerator
* @param list<string> $usedHintKeys * @param list<string> $usedHintKeys
* @return array{type: string, data: string}|null * @return array{type: string, data: string}|null
*/ */
private function resolveHint(string $type, Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys): ?array private function resolveHint(string $type, Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys, ?array &$cachedAwards): ?array
{ {
switch ($type) { switch ($type) {
case 'film': case 'film':
@@ -196,12 +197,15 @@ class GameGridGenerator
return ['type' => 'character', 'data' => $roleId]; return ['type' => 'character', 'data' => $roleId];
case 'award': case 'award':
try { if ($cachedAwards === null) {
$awards = $this->wikidataAwardGateway->getAwards($mainActor); try {
} catch (\Throwable) { $cachedAwards = $this->wikidataAwardGateway->getAwards($mainActor);
return null; } catch (\Throwable) {
$cachedAwards = [];
return null;
}
} }
foreach ($awards as $award) { foreach ($cachedAwards as $award) {
$text = $award['name'] . ' (' . $award['year'] . ')'; $text = $award['name'] . ' (' . $award['year'] . ')';
$key = 'award:' . $text; $key = 'award:' . $text;
if (!in_array($key, $usedHintKeys)) { if (!in_array($key, $usedHintKeys)) {

View File

@@ -33,6 +33,7 @@ class WikidataAwardGateway
'Accept' => 'application/sparql-results+json', 'Accept' => 'application/sparql-results+json',
'User-Agent' => 'LtbxdActorle/1.0', 'User-Agent' => 'LtbxdActorle/1.0',
], ],
'timeout' => 5,
]); ]);
$data = $response->toArray(); $data = $response->toArray();
@@ -55,7 +56,7 @@ class WikidataAwardGateway
private function buildQuery(string $actorName): string private function buildQuery(string $actorName): string
{ {
$escaped = str_replace('"', '\\"', $actorName); $escaped = str_replace(['\\', '"', "\n", "\r"], ['\\\\', '\\"', '\\n', '\\r'], $actorName);
return <<<SPARQL return <<<SPARQL
SELECT ?awardLabel ?year WHERE { SELECT ?awardLabel ?year WHERE {