Files
bibliogame/src/Services/JeuService.php
T

308 lines
8.7 KiB
PHP

<?php
declare(strict_types=1);
final class JeuService
{
private JsonStore $store;
public function __construct()
{
$this->store = new JsonStore(Config::get("dataPath") . "/jeux.json");
}
public function listerPourUtilisateur(
string $utilisateurId,
?string $recherche = null,
?string $consoleId = null,
?string $etat = null,
?string $format = null
): array
{
$jeux = $this->store->filtrer(
static fn (array $jeu): bool => ($jeu["utilisateurId"] ?? "") === $utilisateurId
);
if ($consoleId !== null && $consoleId !== "")
{
$jeux = array_values(array_filter(
$jeux,
static fn (array $jeu): bool => ($jeu["consoleId"] ?? "") === $consoleId
));
}
if ($etat !== null && $etat !== "")
{
$jeux = array_values(array_filter(
$jeux,
static fn (array $jeu): bool => ($jeu["etat"] ?? "") === $etat
));
}
if ($format !== null && $format !== "")
{
$jeux = array_values(array_filter(
$jeux,
static function (array $jeu) use ($format): bool
{
$formats = $jeu["formats"] ?? [];
return is_array($formats) && in_array($format, $formats, true);
}
));
}
if ($recherche !== null && $recherche !== "")
{
$terme = mb_strtolower($recherche);
$jeux = array_values(array_filter(
$jeux,
static function (array $jeu) use ($terme): bool
{
$champs = [
$jeu["titre"] ?? "",
$jeu["description"] ?? "",
$jeu["editeur"] ?? "",
$jeu["developpeur"] ?? "",
implode(" ", $jeu["genres"] ?? []),
implode(" ", $jeu["formats"] ?? [])
];
return str_contains(mb_strtolower(implode(" ", $champs)), $terme);
}
));
}
usort(
$jeux,
static fn (array $a, array $b): int => strcmp($a["titre"] ?? "", $b["titre"] ?? "")
);
return $jeux;
}
public function trouverPourUtilisateur(string $id, string $utilisateurId): ?array
{
$jeu = $this->store->trouverParId($id);
if ($jeu === null || ($jeu["utilisateurId"] ?? "") !== $utilisateurId)
{
return null;
}
return $jeu;
}
public function listerParConsole(string $consoleId, string $utilisateurId): array
{
return $this->listerPourUtilisateur($utilisateurId, null, $consoleId, null);
}
public function derniersAjouts(string $utilisateurId, int $limite = 6): array
{
$jeux = $this->listerPourUtilisateur($utilisateurId);
usort(
$jeux,
static fn (array $a, array $b): int => strcmp($b["createdAt"] ?? "", $a["createdAt"] ?? "")
);
return array_slice($jeux, 0, $limite);
}
public function creer(string $utilisateurId, array $donnees): array
{
$jeu = $this->preparerDonnees($utilisateurId, $donnees);
$maintenant = Helpers::maintenant();
$jeu["id"] = Helpers::genererId();
$jeu["utilisateurId"] = $utilisateurId;
$jeu["createdAt"] = $maintenant;
$jeu["updatedAt"] = $maintenant;
return $this->store->ajouter($jeu);
}
public function modifier(string $id, string $utilisateurId, array $donnees): array
{
$existant = $this->trouverPourUtilisateur($id, $utilisateurId);
if ($existant === null)
{
throw new RuntimeException("Jeu introuvable.");
}
$ancienneJaquette = $existant["jaquette"] ?? null;
$jeu = $this->preparerDonnees($utilisateurId, $donnees, $existant);
$jeu["updatedAt"] = Helpers::maintenant();
$miseAJour = $this->store->mettreAJour($id, $jeu);
if ($miseAJour === null)
{
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;
}
public function supprimer(string $id, string $utilisateurId): bool
{
$jeu = $this->trouverPourUtilisateur($id, $utilisateurId);
if ($jeu === null)
{
return false;
}
$this->supprimerJaquetteLocale($jeu["jaquette"] ?? null);
return $this->store->supprimer($id);
}
public function compterPourUtilisateur(string $utilisateurId): int
{
return count($this->listerPourUtilisateur($utilisateurId));
}
public function supprimerParConsole(string $consoleId, string $utilisateurId): int
{
$jeux = $this->listerParConsole($consoleId, $utilisateurId);
$compteur = 0;
foreach ($jeux as $jeu)
{
if ($this->supprimer($jeu["id"], $utilisateurId))
{
$compteur++;
}
}
return $compteur;
}
private function preparerDonnees(string $utilisateurId, array $donnees, ?array $existant = null): array
{
$titre = trim((string) ($donnees["titre"] ?? ""));
$consoleId = trim((string) ($donnees["consoleId"] ?? ""));
$etat = trim((string) ($donnees["etat"] ?? "possede"));
if ($titre === "" || $consoleId === "")
{
throw new InvalidArgumentException("Le titre et la console sont obligatoires.");
}
if (!array_key_exists($etat, Helpers::etatsJeu()))
{
throw new InvalidArgumentException("État de jeu invalide.");
}
$genres = $donnees["genres"] ?? [];
if (is_string($genres))
{
$genres = array_values(array_filter(array_map("trim", explode(",", $genres))));
}
if (!is_array($genres))
{
$genres = [];
}
$jaquette = trim((string) ($donnees["jaquette"] ?? ($existant["jaquette"] ?? "")));
return [
"titre" => $titre,
"consoleId" => $consoleId,
"etat" => $etat,
"formats" => Helpers::normaliserFormats($donnees["formats"] ?? []),
"jaquette" => $jaquette,
"description" => trim((string) ($donnees["description"] ?? "")),
"dateSortie" => $this->normaliserDate($donnees["dateSortie"] ?? null),
"genres" => array_values($genres),
"editeur" => trim((string) ($donnees["editeur"] ?? "")),
"developpeur" => trim((string) ($donnees["developpeur"] ?? "")),
"notes" => trim((string) ($donnees["notes"] ?? "")),
"sourceEnrichissement" => trim((string) ($donnees["sourceEnrichissement"] ?? "manuel"))
];
}
private function normaliserDate(mixed $date): ?string
{
if ($date === null || $date === "")
{
return null;
}
$date = (string) $date;
if (!preg_match("/^\d{4}-\d{2}-\d{2}$/", $date))
{
return null;
}
return $date;
}
private function supprimerJaquetteLocale(?string $chemin): void
{
if ($chemin === null || $chemin === "")
{
return;
}
if (str_starts_with($chemin, "http://") || str_starts_with($chemin, "https://"))
{
return;
}
$fichier = Config::get("jaquettesPath") . "/" . basename($chemin);
if (is_file($fichier))
{
unlink($fichier);
}
}
}