first commit

This commit is contained in:
julien
2026-03-16 01:47:07 +01:00
commit 8f7e61bda0
185 changed files with 27731 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
namespace App\Media;
use PDO;
/**
* Dépôt pour la persistance des médias uploadés.
*
* Responsabilité unique : exécuter les requêtes SQL liées à la table `media`
* et retourner des instances de Media hydratées.
*/
final class MediaRepository implements MediaRepositoryInterface
{
/**
* Fragment SELECT commun à toutes les requêtes de lecture.
*/
private const SELECT = 'SELECT id, filename, url, hash, user_id, created_at FROM media';
/**
* @param PDO $db Instance de connexion à la base de données
*/
public function __construct(private readonly PDO $db)
{
}
/**
* Retourne tous les médias triés du plus récent au plus ancien.
*
* @return Media[] La liste complète des médias
*/
public function findAll(): array
{
$stmt = $this->db->query(self::SELECT . ' ORDER BY id DESC');
if ($stmt === false) {
throw new \RuntimeException('La requête SELECT sur media a échoué.');
}
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return array_map(fn ($row) => Media::fromArray($row), $rows);
}
/**
* Retourne tous les médias appartenant à un utilisateur donné,
* triés du plus récent au plus ancien.
*
* @param int $userId Identifiant de l'utilisateur
*
* @return Media[] La liste des médias de cet utilisateur
*/
public function findByUserId(int $userId): array
{
$stmt = $this->db->prepare(self::SELECT . ' WHERE user_id = :user_id ORDER BY id DESC');
$stmt->execute([':user_id' => $userId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return array_map(fn ($row) => Media::fromArray($row), $rows);
}
/**
* Trouve un média par son identifiant.
*
* @param int $id Identifiant du média
*
* @return Media|null Le média trouvé, ou null s'il n'existe pas
*/
public function findById(int $id): ?Media
{
$stmt = $this->db->prepare(self::SELECT . ' WHERE id = :id');
$stmt->execute([':id' => $id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? Media::fromArray($row) : null;
}
/**
* Trouve un média par le hash SHA-256 de son contenu.
*
* Utilisé pour la détection des doublons à l'upload.
*
* @param string $hash Hash SHA-256 du contenu binaire du fichier
*
* @return Media|null Le média existant, ou null si aucun doublon
*/
public function findByHash(string $hash): ?Media
{
$stmt = $this->db->prepare(self::SELECT . ' WHERE hash = :hash');
$stmt->execute([':hash' => $hash]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? Media::fromArray($row) : null;
}
/**
* Persiste un nouveau média en base de données.
*
* @param Media $media Le média à créer
*
* @return int L'identifiant généré par la base de données
*/
public function create(Media $media): int
{
$stmt = $this->db->prepare('
INSERT INTO media (filename, url, hash, user_id, created_at)
VALUES (:filename, :url, :hash, :user_id, :created_at)
');
$stmt->execute([
':filename' => $media->getFilename(),
':url' => $media->getUrl(),
':hash' => $media->getHash(),
':user_id' => $media->getUserId(),
':created_at' => date('Y-m-d H:i:s'),
]);
return (int) $this->db->lastInsertId();
}
/**
* Supprime un média de la base de données.
*
* La suppression du fichier physique sur disque est à la charge de l'appelant.
*
* @param int $id Identifiant du média à supprimer
*
* @return int Nombre de lignes supprimées (0 si le média n'existe plus)
*/
public function delete(int $id): int
{
$stmt = $this->db->prepare('DELETE FROM media WHERE id = :id');
$stmt->execute([':id' => $id]);
return $stmt->rowCount();
}
}