Working state
This commit is contained in:
@@ -5,109 +5,104 @@ 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);
|
||||
return array_map(fn ($row) => Media::fromArray($row), $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
|
||||
public function findPage(int $limit, int $offset): array
|
||||
{
|
||||
$stmt = $this->db->prepare(self::SELECT . ' ORDER BY id DESC LIMIT :limit OFFSET :offset');
|
||||
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
return array_map(fn ($row) => Media::fromArray($row), $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
|
||||
public function countAll(): int
|
||||
{
|
||||
$stmt = $this->db->query('SELECT COUNT(*) FROM media');
|
||||
if ($stmt === false) {
|
||||
throw new \RuntimeException('La requête COUNT sur media a échoué.');
|
||||
}
|
||||
|
||||
return (int) ($stmt->fetchColumn() ?: 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return array_map(fn ($row) => Media::fromArray($row), $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
|
||||
public function findByUserPage(int $userId, int $limit, int $offset): array
|
||||
{
|
||||
$stmt = $this->db->prepare(self::SELECT . ' WHERE user_id = :user_id ORDER BY id DESC LIMIT :limit OFFSET :offset');
|
||||
$stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
return array_map(fn ($row) => Media::fromArray($row), $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
|
||||
public function countByUserId(int $userId): int
|
||||
{
|
||||
$stmt = $this->db->prepare('SELECT COUNT(*) FROM media WHERE user_id = :user_id');
|
||||
$stmt->execute([':user_id' => $userId]);
|
||||
|
||||
return (int) $stmt->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = $this->db->prepare(self::SELECT . ' WHERE hash = :hash ORDER BY id DESC LIMIT 1');
|
||||
$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 findByHashForUser(string $hash, int $userId): ?Media
|
||||
{
|
||||
$stmt = $this->db->prepare(self::SELECT . ' WHERE hash = :hash AND user_id = :user_id ORDER BY id DESC LIMIT 1');
|
||||
$stmt->execute([':hash' => $hash, ':user_id' => $userId]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return $row ? Media::fromArray($row) : null;
|
||||
}
|
||||
|
||||
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 = $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(),
|
||||
@@ -120,15 +115,6 @@ final class MediaRepository implements MediaRepositoryInterface
|
||||
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');
|
||||
|
||||
Reference in New Issue
Block a user