diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 6d5462b..e08c1dd 100644 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -5,12 +5,69 @@ document.addEventListener("DOMContentLoaded", () => const zoneResultats = document.getElementById("resultatsApi"); const formAppliquer = document.getElementById("formAppliquerApi"); const champRawgId = document.getElementById("rawgId"); + const formJeu = document.getElementById("formJeu"); if (!boutonRecherche || !champRecherche || !zoneResultats) { return; } + const collecterChampsFormulaire = () => + { + if (!formJeu || !formAppliquer) + { + return; + } + + formAppliquer.querySelectorAll("[data-from-form]").forEach((element) => + { + element.remove(); + }); + + const noms = [ + "titre", + "description", + "dateSortie", + "genres", + "editeur", + "developpeur", + "jaquette", + "consoleId", + "etat", + "notes", + "sourceEnrichissement" + ]; + + noms.forEach((nom) => + { + const champ = formJeu.elements.namedItem(nom); + + if (!champ || typeof champ.value !== "string") + { + return; + } + + const cache = document.createElement("input"); + cache.type = "hidden"; + cache.name = nom; + cache.value = champ.value; + cache.setAttribute("data-from-form", "1"); + formAppliquer.appendChild(cache); + }); + + const formats = formJeu.querySelectorAll('input[name="formats[]"]:checked'); + + formats.forEach((caseCochee) => + { + const cache = document.createElement("input"); + cache.type = "hidden"; + cache.name = "formats[]"; + cache.value = caseCochee.value; + cache.setAttribute("data-from-form", "1"); + formAppliquer.appendChild(cache); + }); + }; + const lancerRecherche = async () => { const terme = champRecherche.value.trim(); @@ -84,6 +141,7 @@ document.addEventListener("DOMContentLoaded", () => return; } + collecterChampsFormulaire(); champRawgId.value = String(jeu.rawgId); formAppliquer.submit(); }); diff --git a/src/Controllers/JeuController.php b/src/Controllers/JeuController.php index 697e730..3e0773b 100644 --- a/src/Controllers/JeuController.php +++ b/src/Controllers/JeuController.php @@ -98,6 +98,7 @@ final class JeuController try { $donnees = $this->collecterDonneesFormulaire(); + $donnees = $this->appliquerUploadJaquette($donnees); $donnees = $this->completerJaquetteSiAbsente($donnees); $jeu = $this->jeuService->creer($utilisateur["id"], $donnees); Flash::definir("success", "Jeu ajouté à votre bibliothèque."); @@ -140,6 +141,7 @@ final class JeuController try { $donnees = $this->collecterDonneesFormulaire(); + $donnees = $this->appliquerUploadJaquette($donnees); $donnees = $this->completerJaquetteSiAbsente($donnees); $jeu = $this->jeuService->modifier($id, $utilisateur["id"], $donnees); Flash::definir("success", "Jeu mis à jour."); @@ -151,9 +153,13 @@ final class JeuController $jeu = array_merge($jeu, $_POST); } } + else + { + $jeu = $this->appliquerPrefillGetSurJeu($jeu); + } View::rendre("jeux/formulaire", [ - "titrePage" => "Modifier " . $jeu["titre"], + "titrePage" => "Modifier " . ($jeu["titre"] ?? "jeu"), "utilisateur" => $utilisateur, "jeu" => $jeu, "consoles" => $consoles, @@ -219,21 +225,77 @@ final class JeuController Helpers::rediriger($retour); } - $jaquette = $this->enrichissementService->telechargerJaquette($detail["jaquetteUrl"] ?? null); + $existants = [ + "titre" => Helpers::champ("titre"), + "description" => Helpers::champ("description"), + "dateSortie" => Helpers::champ("dateSortie"), + "genres" => Helpers::champ("genres"), + "editeur" => Helpers::champ("editeur"), + "developpeur" => Helpers::champ("developpeur"), + "jaquette" => Helpers::champ("jaquette"), + "consoleId" => Helpers::champ("consoleId"), + "etat" => Helpers::champ("etat"), + "notes" => Helpers::champ("notes"), + "formats" => isset($_POST["formats"]) && is_array($_POST["formats"]) + ? Helpers::normaliserFormats($_POST["formats"]) + : [] + ]; + + $depuisApi = [ + "titre" => (string) ($detail["titre"] ?? ""), + "description" => (string) ($detail["description"] ?? ""), + "dateSortie" => (string) ($detail["dateSortie"] ?? ""), + "genres" => implode(", ", $detail["genres"] ?? []), + "editeur" => (string) ($detail["editeur"] ?? ""), + "developpeur" => (string) ($detail["developpeur"] ?? "") + ]; + + $fusion = []; + + foreach ($depuisApi as $cle => $valeurApi) + { + $valeurActuelle = trim((string) ($existants[$cle] ?? "")); + $fusion[$cle] = $valeurActuelle !== "" ? $valeurActuelle : trim($valeurApi); + } + + $fusion["consoleId"] = $existants["consoleId"]; + $fusion["etat"] = $existants["etat"] !== "" ? $existants["etat"] : "possede"; + $fusion["notes"] = $existants["notes"]; + $fusion["formats"] = $existants["formats"]; + + if (!Helpers::jaquetteAbsente($existants["jaquette"])) + { + $fusion["jaquette"] = $existants["jaquette"]; + } + else + { + $jaquette = $this->enrichissementService->telechargerJaquette($detail["jaquetteUrl"] ?? null); + $fusion["jaquette"] = $jaquette ?? ""; + } + + $fusion["sourceEnrichissement"] = !Helpers::jaquetteAbsente($fusion["jaquette"] ?? null) + || $fusion["description"] !== "" + || $fusion["dateSortie"] !== "" + ? "api" + : (Helpers::champ("sourceEnrichissement", "manuel")); $query = http_build_query([ - "titre" => $detail["titre"] ?? "", - "description" => $detail["description"] ?? "", - "dateSortie" => $detail["dateSortie"] ?? "", - "genres" => implode(", ", $detail["genres"] ?? []), - "editeur" => $detail["editeur"] ?? "", - "developpeur" => $detail["developpeur"] ?? "", - "jaquette" => $jaquette ?? "", - "sourceEnrichissement" => "api" + "titre" => $fusion["titre"], + "description" => $fusion["description"], + "dateSortie" => $fusion["dateSortie"], + "genres" => $fusion["genres"], + "editeur" => $fusion["editeur"], + "developpeur" => $fusion["developpeur"], + "jaquette" => $fusion["jaquette"], + "consoleId" => $fusion["consoleId"], + "etat" => $fusion["etat"], + "notes" => $fusion["notes"], + "formats" => $fusion["formats"], + "sourceEnrichissement" => $fusion["sourceEnrichissement"] ]); - $separateur = str_contains($retour, "?") ? "&" : "?"; - Helpers::rediriger($retour . $separateur . $query); + $cheminRetour = parse_url($retour, PHP_URL_PATH) ?: "/jeux/creer"; + Helpers::rediriger($cheminRetour . "?" . $query); } public function recupererJaquette(string $id): void @@ -280,6 +342,56 @@ final class JeuController Helpers::rediriger("/jeux/" . $id); } + public function envoyerJaquette(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"); + } + + try + { + $this->jeuService->remplacerJaquette( + $id, + $utilisateur["id"], + $_FILES["jaquetteFichier"] ?? [] + ); + Flash::definir("success", "Jaquette remplacée."); + } + catch (InvalidArgumentException | RuntimeException $exception) + { + Flash::definir("danger", $exception->getMessage()); + } + + Helpers::rediriger("/jeux/" . $id); + } + + private function appliquerUploadJaquette(array $donnees): array + { + $fichier = $_FILES["jaquetteFichier"] ?? null; + + if (!is_array($fichier) || (($fichier["error"] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE)) + { + return $donnees; + } + + $nomFichier = ImageUpload::enregistrer( + $fichier, + Config::get("jaquettesPath") + ); + + $donnees["jaquette"] = $nomFichier; + $donnees["sourceEnrichissement"] = "manuel"; + + return $donnees; + } + private function completerJaquetteSiAbsente(array $donnees): array { if (!Helpers::jaquetteAbsente($donnees["jaquette"] ?? null)) @@ -328,12 +440,18 @@ final class JeuController private function construirePrefillDepuisGet(): array { $genres = Helpers::champ("genres"); + $formats = $_GET["formats"] ?? []; + + if (!is_array($formats)) + { + $formats = []; + } return [ "titre" => Helpers::champ("titre"), "consoleId" => Helpers::champ("consoleId"), "etat" => Helpers::champ("etat", "possede"), - "formats" => [], + "formats" => Helpers::normaliserFormats($formats), "jaquette" => Helpers::champ("jaquette"), "description" => Helpers::champ("description"), "dateSortie" => Helpers::champ("dateSortie"), @@ -344,4 +462,44 @@ final class JeuController "sourceEnrichissement" => Helpers::champ("sourceEnrichissement", "manuel") ]; } + + private function appliquerPrefillGetSurJeu(array $jeu): array + { + if (empty($_GET)) + { + return $jeu; + } + + $prefill = $this->construirePrefillDepuisGet(); + + foreach ($prefill as $cle => $valeur) + { + if ($cle === "formats") + { + if ($valeur !== []) + { + $jeu[$cle] = $valeur; + } + + continue; + } + + if ($cle === "genres") + { + if ($valeur !== []) + { + $jeu[$cle] = $valeur; + } + + continue; + } + + if (is_string($valeur) && trim($valeur) !== "") + { + $jeu[$cle] = $valeur; + } + } + + return $jeu; + } } diff --git a/src/Services/JeuService.php b/src/Services/JeuService.php index 289c511..889a8a3 100644 --- a/src/Services/JeuService.php +++ b/src/Services/JeuService.php @@ -132,6 +132,7 @@ final class JeuService throw new RuntimeException("Jeu introuvable."); } + $ancienneJaquette = $existant["jaquette"] ?? null; $jeu = $this->preparerDonnees($utilisateurId, $donnees, $existant); $jeu["updatedAt"] = Helpers::maintenant(); @@ -142,6 +143,47 @@ final class JeuService throw new RuntimeException("Échec de la mise à jour."); } + $nouvelleJaquette = $miseAJour["jaquette"] ?? null; + + if ( + $ancienneJaquette !== null + && $ancienneJaquette !== "" + && $ancienneJaquette !== $nouvelleJaquette + ) + { + $this->supprimerJaquetteLocale($ancienneJaquette); + } + + return $miseAJour; + } + + public function remplacerJaquette(string $id, string $utilisateurId, array $fichier): array + { + $jeu = $this->trouverPourUtilisateur($id, $utilisateurId); + + if ($jeu === null) + { + throw new RuntimeException("Jeu introuvable."); + } + + $nouvelleJaquette = ImageUpload::enregistrer( + $fichier, + Config::get("jaquettesPath") + ); + + $this->supprimerJaquetteLocale($jeu["jaquette"] ?? null); + + $miseAJour = $this->store->mettreAJour($id, [ + "jaquette" => $nouvelleJaquette, + "sourceEnrichissement" => "manuel", + "updatedAt" => Helpers::maintenant() + ]); + + if ($miseAJour === null) + { + throw new RuntimeException("Échec de la mise à jour de la jaquette."); + } + return $miseAJour; } diff --git a/src/bootstrap.php b/src/bootstrap.php index 8e7edf4..030d652 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -77,6 +77,7 @@ $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}/jaquette/upload", [$jeuController, "envoyerJaquette"]); $router->post("/jeux/{id}/supprimer", [$jeuController, "supprimer"]); $router->get("/admin/utilisateurs", [$adminController, "index"]); diff --git a/templates/jeux/detail.php b/templates/jeux/detail.php index 625f9c7..e6cf9c2 100644 --- a/templates/jeux/detail.php +++ b/templates/jeux/detail.php @@ -43,6 +43,33 @@ + +
diff --git a/templates/jeux/formulaire.php b/templates/jeux/formulaire.php index aef491c..e1e8809 100644 --- a/templates/jeux/formulaire.php +++ b/templates/jeux/formulaire.php @@ -40,7 +40,7 @@ $retourEnrichissement = $action; -