Ajout récupération de jaquette de jeux via api
This commit is contained in:
1 parent
b785db1b84
commit
df11d023f0
6 files changed
+209
-19
No files matched your search
@@ -69,7 +69,9 @@ final class JeuController
|
||||
"titrePage" => $jeu["titre"],
|
||||
"utilisateur" => $utilisateur,
|
||||
"jeu" => $jeu,
|
||||
"console" => $console
|
||||
"console" => $console,
|
||||
"jaquetteAbsente" => Helpers::jaquetteAbsente($jeu["jaquette"] ?? null),
|
||||
"apiDisponible" => $this->enrichissementService->estDisponible()
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -93,6 +95,7 @@ final class JeuController
|
||||
try
|
||||
{
|
||||
$donnees = $this->collecterDonneesFormulaire();
|
||||
$donnees = $this->completerJaquetteSiAbsente($donnees);
|
||||
$jeu = $this->jeuService->creer($utilisateur["id"], $donnees);
|
||||
Flash::definir("success", "Jeu ajouté à votre bibliothèque.");
|
||||
Helpers::rediriger("/jeux/" . $jeu["id"]);
|
||||
@@ -134,6 +137,7 @@ final class JeuController
|
||||
try
|
||||
{
|
||||
$donnees = $this->collecterDonneesFormulaire();
|
||||
$donnees = $this->completerJaquetteSiAbsente($donnees);
|
||||
$jeu = $this->jeuService->modifier($id, $utilisateur["id"], $donnees);
|
||||
Flash::definir("success", "Jeu mis à jour.");
|
||||
Helpers::rediriger("/jeux/" . $jeu["id"]);
|
||||
@@ -229,6 +233,76 @@ final class JeuController
|
||||
Helpers::rediriger($retour . $separateur . $query);
|
||||
}
|
||||
|
||||
public function recupererJaquette(string $id): void
|
||||
{
|
||||
$utilisateur = $this->auth->exigerConnexion();
|
||||
Csrf::exiger();
|
||||
|
||||
$jeu = $this->jeuService->trouverPourUtilisateur($id, $utilisateur["id"]);
|
||||
|
||||
if ($jeu === null)
|
||||
{
|
||||
Flash::definir("danger", "Jeu introuvable.");
|
||||
Helpers::rediriger("/jeux");
|
||||
}
|
||||
|
||||
if (!Helpers::jaquetteAbsente($jeu["jaquette"] ?? null))
|
||||
{
|
||||
Flash::definir("success", "Ce jeu a déjà une jaquette.");
|
||||
Helpers::rediriger("/jeux/" . $id);
|
||||
}
|
||||
|
||||
if (!$this->enrichissementService->estDisponible())
|
||||
{
|
||||
Flash::definir("warning", "Clé API RAWG absente : impossible de récupérer la jaquette.");
|
||||
Helpers::rediriger("/jeux/" . $id);
|
||||
}
|
||||
|
||||
$fichier = $this->enrichissementService->recupererJaquetteParTitre($jeu["titre"] ?? "");
|
||||
|
||||
if ($fichier === null)
|
||||
{
|
||||
Flash::definir("warning", "Aucune jaquette trouvée pour ce titre.");
|
||||
Helpers::rediriger("/jeux/" . $id);
|
||||
}
|
||||
|
||||
$this->jeuService->modifier($id, $utilisateur["id"], array_merge($jeu, [
|
||||
"jaquette" => $fichier,
|
||||
"genres" => $jeu["genres"] ?? [],
|
||||
"sourceEnrichissement" => ($jeu["sourceEnrichissement"] ?? "") === "manuel" ? "api" : ($jeu["sourceEnrichissement"] ?? "api")
|
||||
]));
|
||||
|
||||
Flash::definir("success", "Jaquette récupérée depuis RAWG.");
|
||||
Helpers::rediriger("/jeux/" . $id);
|
||||
}
|
||||
|
||||
private function completerJaquetteSiAbsente(array $donnees): array
|
||||
{
|
||||
if (!Helpers::jaquetteAbsente($donnees["jaquette"] ?? null))
|
||||
{
|
||||
return $donnees;
|
||||
}
|
||||
|
||||
if (!$this->enrichissementService->estDisponible())
|
||||
{
|
||||
return $donnees;
|
||||
}
|
||||
|
||||
$fichier = $this->enrichissementService->recupererJaquetteParTitre($donnees["titre"] ?? "");
|
||||
|
||||
if ($fichier !== null)
|
||||
{
|
||||
$donnees["jaquette"] = $fichier;
|
||||
|
||||
if (($donnees["sourceEnrichissement"] ?? "manuel") === "manuel")
|
||||
{
|
||||
$donnees["sourceEnrichissement"] = "api";
|
||||
}
|
||||
}
|
||||
|
||||
return $donnees;
|
||||
}
|
||||
|
||||
private function collecterDonneesFormulaire(): array
|
||||
{
|
||||
return [
|
||||
|
||||
+21
-4
@@ -54,17 +54,34 @@ final class Helpers
|
||||
|
||||
public static function urlJaquette(?string $chemin): string
|
||||
{
|
||||
if ($chemin === null || $chemin === "")
|
||||
if (self::jaquetteAbsente($chemin))
|
||||
{
|
||||
return "/assets/img/jaquette-manquante.svg";
|
||||
}
|
||||
|
||||
if (str_starts_with($chemin, "http://") || str_starts_with($chemin, "https://"))
|
||||
if (str_starts_with((string) $chemin, "http://") || str_starts_with((string) $chemin, "https://"))
|
||||
{
|
||||
return $chemin;
|
||||
return (string) $chemin;
|
||||
}
|
||||
|
||||
return "/jaquettes/" . ltrim($chemin, "/");
|
||||
return "/jaquettes/" . ltrim((string) $chemin, "/");
|
||||
}
|
||||
|
||||
public static function jaquetteAbsente(?string $chemin): bool
|
||||
{
|
||||
if ($chemin === null || trim($chemin) === "")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with($chemin, "http://") || str_starts_with($chemin, "https://"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$fichier = Config::get("jaquettesPath") . "/" . basename($chemin);
|
||||
|
||||
return !is_file($fichier);
|
||||
}
|
||||
|
||||
public static function tronquer(string $texte, int $longueur = 140): string
|
||||
|
||||
@@ -82,6 +82,50 @@ final class EnrichissementService
|
||||
return $detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cherche une jaquette RAWG pour un titre et la télécharge localement.
|
||||
* Ne fait rien (retourne null) si l'API est indisponible ou aucun résultat.
|
||||
*/
|
||||
public function recupererJaquetteParTitre(string $titre): ?string
|
||||
{
|
||||
$titre = trim($titre);
|
||||
|
||||
if ($titre === "" || !$this->estDisponible())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$resultats = $this->rechercher($titre, 5);
|
||||
|
||||
foreach ($resultats as $resultat)
|
||||
{
|
||||
$url = $resultat["jaquetteUrl"] ?? null;
|
||||
|
||||
if ($url === null || $url === "")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$fichier = $this->telechargerJaquette($url);
|
||||
|
||||
if ($fichier !== null && !str_starts_with($fichier, "http"))
|
||||
{
|
||||
return $fichier;
|
||||
}
|
||||
|
||||
if ($fichier !== null)
|
||||
{
|
||||
return $fichier;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Télécharge une image distante dans data/jaquettes/.
|
||||
* En cas d'échec réseau, conserve l'URL distante comme repli.
|
||||
*/
|
||||
public function telechargerJaquette(?string $urlImage): ?string
|
||||
{
|
||||
if ($urlImage === null || $urlImage === "")
|
||||
@@ -89,8 +133,15 @@ final class EnrichissementService
|
||||
return null;
|
||||
}
|
||||
|
||||
$dossier = Config::get("jaquettesPath");
|
||||
|
||||
if (!is_dir($dossier))
|
||||
{
|
||||
mkdir($dossier, 0775, true);
|
||||
}
|
||||
|
||||
$extension = pathinfo(parse_url($urlImage, PHP_URL_PATH) ?? "", PATHINFO_EXTENSION);
|
||||
$extension = $extension !== "" ? strtolower($extension) : "jpg";
|
||||
$extension = $extension !== "" ? strtolower(explode("?", $extension)[0]) : "jpg";
|
||||
|
||||
if (!in_array($extension, ["jpg", "jpeg", "png", "webp", "gif"], true))
|
||||
{
|
||||
@@ -98,18 +149,10 @@ final class EnrichissementService
|
||||
}
|
||||
|
||||
$nomFichier = Helpers::genererId() . "." . $extension;
|
||||
$cheminLocal = Config::get("jaquettesPath") . "/" . $nomFichier;
|
||||
$cheminLocal = $dossier . "/" . $nomFichier;
|
||||
$contenu = $this->telechargerContenu($urlImage);
|
||||
|
||||
$contexte = stream_context_create([
|
||||
"http" => [
|
||||
"timeout" => 10,
|
||||
"header" => "User-Agent: JeuxVideoTech/1.0\r\n"
|
||||
]
|
||||
]);
|
||||
|
||||
$contenu = @file_get_contents($urlImage, false, $contexte);
|
||||
|
||||
if ($contenu === false)
|
||||
if ($contenu === null || $contenu === "")
|
||||
{
|
||||
return $urlImage;
|
||||
}
|
||||
@@ -122,6 +165,51 @@ final class EnrichissementService
|
||||
return $nomFichier;
|
||||
}
|
||||
|
||||
private function telechargerContenu(string $url): ?string
|
||||
{
|
||||
if (function_exists("curl_init"))
|
||||
{
|
||||
$curl = curl_init($url);
|
||||
|
||||
if ($curl !== false)
|
||||
{
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_USERAGENT => "JeuxVideoTech/1.0",
|
||||
CURLOPT_SSL_VERIFYPEER => true
|
||||
]);
|
||||
|
||||
$contenu = curl_exec($curl);
|
||||
$codeHttp = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
curl_close($curl);
|
||||
|
||||
if ($contenu !== false && $codeHttp >= 200 && $codeHttp < 300)
|
||||
{
|
||||
return $contenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$contexte = stream_context_create([
|
||||
"http" => [
|
||||
"method" => "GET",
|
||||
"timeout" => 15,
|
||||
"follow_location" => 1,
|
||||
"header" => "User-Agent: JeuxVideoTech/1.0\r\n"
|
||||
],
|
||||
"ssl" => [
|
||||
"verify_peer" => true,
|
||||
"verify_peer_name" => true
|
||||
]
|
||||
]);
|
||||
|
||||
$contenu = @file_get_contents($url, false, $contexte);
|
||||
|
||||
return $contenu === false ? null : $contenu;
|
||||
}
|
||||
|
||||
private function mapperResultatListe(array $jeu): array
|
||||
{
|
||||
$genres = [];
|
||||
|
||||
@@ -73,6 +73,7 @@ $router->post("/jeux/api/appliquer", [$jeuController, "appliquerEnrichissement"]
|
||||
$router->get("/jeux/{id}", [$jeuController, "detail"]);
|
||||
$router->get("/jeux/{id}/modifier", [$jeuController, "modifier"]);
|
||||
$router->post("/jeux/{id}/modifier", [$jeuController, "modifier"]);
|
||||
$router->post("/jeux/{id}/jaquette", [$jeuController, "recupererJaquette"]);
|
||||
$router->post("/jeux/{id}/supprimer", [$jeuController, "supprimer"]);
|
||||
|
||||
$router->get("/admin/utilisateurs", [$adminController, "index"]);
|
||||
|
||||