diff --git a/Webzine.Repository/DbCommentaireRepository.cs b/Webzine.Repository/DbCommentaireRepository.cs new file mode 100644 index 0000000..d87696b --- /dev/null +++ b/Webzine.Repository/DbCommentaireRepository.cs @@ -0,0 +1,139 @@ +using Microsoft.EntityFrameworkCore; +using Webzine.EntitiesContext; +using Microsoft.Extensions.Logging; +using Webzine.Entity; +using Webzine.Repository.Contracts; + +namespace Webzine.Repository; + +/// +/// Classe qui implémente le repository pour les commentaires en utilisant une base de données. +/// +public class DbCommentaireRepository : ICommentaireRepository +{ + private readonly ILogger logger; + private readonly WebzineDbContext context; + + /// + /// Initialisation de . + /// + /// Le service de journalisation injecté pour suivre les opérations du repository. + /// Le contexte de base de données injecté. + public DbCommentaireRepository(ILogger logger, WebzineDbContext context) + { + this.logger = logger; + this.context = context; + this.logger.LogDebug("NLog injecté dans DbCommentaireRepository"); + } + + /// + public void Add(Commentaire commentaire) + { + try + { + this.logger.LogDebug("Ajout d'un nouveau commentaire de l'auteur : {Auteur}", commentaire.Auteur); + this.context.Commentaires.Add(commentaire); + this.context.SaveChanges(); + this.logger.LogDebug("Commentaire ajouté avec l'id : {Id}", commentaire.IdCommentaire); + } + catch (DbUpdateException dbex) + { + this.logger.LogError(dbex, "Erreur de base de données lors de l'ajout du commentaire de l'auteur : {Auteur}", commentaire?.Auteur); + throw; + } + catch (Exception ex) + { + this.logger.LogError(ex, "Une erreur est survenue lors de l'ajout d'un commentaire."); + throw new Exception("Une erreur est survenue lors de l'ajout du commentaire.", ex); + } + } + + /// + public void Delete(Commentaire commentaire) + { + try + { + if (commentaire == null) + { + throw new ArgumentNullException(nameof(commentaire), "Le commentaire à supprimer ne peut pas être null."); + } + + this.context.Commentaires.Remove(commentaire); + this.context.SaveChanges(); + this.logger.LogDebug("Le commentaire {IdCommentaire} a bien été supprimé", commentaire.IdCommentaire); + } + catch (DbUpdateException dbex) + { + this.logger.LogError(dbex, "Erreur de base de données lors de la suppression du commentaire : {Id}", commentaire.IdCommentaire); + throw; + } + catch (Exception ex) + { + this.logger.LogError(ex, "Une erreur est survenue lors de la suppression du commentaire {Id}.", commentaire?.IdCommentaire); + throw new Exception("Une erreur est survenue lors de la suppression du commentaire.", ex); + } + } + + /// + public int Count() + { + var count = this.context.Commentaires.Count(); + this.logger.LogDebug("Compte total des commentaires : {Count}", count); + return count; + } + + /// + public Commentaire Find(int idCommentaire) + { + this.logger.LogDebug("Recherche du commentaire avec l'id : {Id}", idCommentaire); + + // On inclut le titre car il est souvent affiché avec le commentaire + return this.context.Commentaires + .Include(c => c.Titre) + .FirstOrDefault(c => c.IdCommentaire == idCommentaire); + } + + /// + public IEnumerable FindAll() + { + this.logger.LogDebug("Récupération de tous les commentaires"); + + var commentaires = this.context.Commentaires + .Include(c => c.Titre) + .OrderByDescending(c => c.DateCreation) + .ToList(); + + this.logger.LogDebug("Nombre de commentaires trouvés : {Count}", commentaires.Count); + return commentaires; + } + + /// + public IEnumerable FindCommentaires(int offset, int limit) + { + this.logger.LogDebug("Recherche paginée des commentaires (offset : {Offset}, limit : {Limit})", offset, limit); + + var commentaires = this.context.Commentaires + .Include(c => c.Titre) + .OrderByDescending(c => c.DateCreation) + .Skip(offset) + .Take(limit) + .ToList(); + + this.logger.LogDebug("{Count} commentaires trouvés pour cette page", commentaires.Count); + return commentaires; + } + + /// + public IEnumerable FindByIdTitre(int idTitre) + { + this.logger.LogDebug("Recherche des commentaires pour le titre ID : {IdTitre}", idTitre); + + var commentaires = this.context.Commentaires + .Where(c => c.Titre.IdTitre == idTitre) + .OrderByDescending(c => c.DateCreation) + .ToList(); + + this.logger.LogDebug($"{commentaires.Count} commentaires trouvés pour l'ID de titre : {idTitre}"); + return commentaires; + } +} \ No newline at end of file diff --git a/Webzine.Repository/LocalCommentaireRepository.cs b/Webzine.Repository/LocalCommentaireRepository.cs index 6727642..95620bd 100644 --- a/Webzine.Repository/LocalCommentaireRepository.cs +++ b/Webzine.Repository/LocalCommentaireRepository.cs @@ -2,42 +2,96 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +namespace Webzine.Repository +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Extensions.Logging; using Webzine.Entity; using Webzine.Repository.Contracts; -namespace Webzine.Repository -{ + /// + /// Initialise une classe qui implémente l'interface pour gérer les opérations liées aux commentaires. + /// Utilise en injection de dépendances. + /// public class LocalCommentaireRepository : ICommentaireRepository { + private readonly ILogger logger; private readonly InMemoryDataStore dataStore; - public LocalCommentaireRepository(InMemoryDataStore dataStore) + /// + /// Initialise une nouvelle instance du . + /// Est liée à un magasin de données en mémoire et utilise un logger pour enregistrer les opérations. + /// + /// Le magasin de données en mémoire. Ne peut pas être null. + /// Le logger à utiliser pour enregistrer les messages de journalisation. Ne peut pas être null. + public LocalCommentaireRepository(InMemoryDataStore dataStore, ILogger logger) { + this.logger = logger; this.dataStore = dataStore; } /// public void Add(Commentaire commentaire) { - throw new NotSupportedException(); + throw new NotSupportedException("Mode Local"); } /// public void Delete(Commentaire commentaire) { - throw new NotSupportedException(); + throw new NotSupportedException("Mode Local"); } /// - public Commentaire Find(int id) + public int Count() { - return this.dataStore.Commentaires.Find(c => c.IdCommentaire == id); + return this.dataStore.Commentaires.Count; + } + + /// + public Commentaire Find(int idCommentaire) + { + var commentaire = this.dataStore.Commentaires.FirstOrDefault(c => c.IdCommentaire == idCommentaire); + if (commentaire == null) + { + return new Commentaire(); + } + + return commentaire; } /// public IEnumerable FindAll() { - return this.dataStore.Commentaires.ToList(); + return this.dataStore.Commentaires + .OrderByDescending(c => c.DateCreation) + .ToList(); + } + + /// + public IEnumerable FindCommentaires(int offset, int limit) + { + if (offset < 0 || limit <= 0) + { + return Enumerable.Empty(); + } + + return this.dataStore.Commentaires + .OrderByDescending(c => c.DateCreation) + .Skip(offset) + .Take(limit) + .ToList(); + } + + /// + public IEnumerable FindByIdTitre(int idTitre) + { + return this.dataStore.Commentaires + .Where(c => c.Titre != null && c.Titre.IdTitre == idTitre) + .OrderByDescending(c => c.DateCreation) + .ToList(); } } } diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs index 0f16425..a1734bd 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Webzine.Entity; -using Webzine.Entity.Fixtures; +using Webzine.Repository.Contracts; using Webzine.WebApplication.Areas.Administration.ViewModels.Commentaire; namespace Webzine.WebApplication.Areas.Administration.Controllers @@ -9,59 +9,48 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers public class CommentaireController : Controller { private readonly ILogger logger; - private readonly List _commentaires; + private readonly ICommentaireRepository commentaireRepository; /// /// Initialise une nouvelle instance de la classe . - /// Initialise une nouvelle instance du . - /// Les données sont générées dynamiquement via . + /// Utilise l'injection de dépendances pour récupérer le repository. /// /// Service de journalisation injecté. - public CommentaireController(ILogger logger) + /// Le repository des commentaires injecté. + public CommentaireController(ILogger logger, ICommentaireRepository commentaireRepository) { this.logger = logger; + this.commentaireRepository = commentaireRepository; this.logger.LogInformation("Initialisation du contrôleur CommentaireController."); - - var factory = new DataFactory(); // TODO injecter le factory via DI pour éviter de le recréer à chaque fois - // faire une classe statique - - var _artistes = factory.GenerateArtists(10); - var _styles = factory.GenerateStyles(10); - var _titres = factory.GenerateTitres(30, _artistes, _styles); - - _commentaires = factory.GenerateCommentaires(50, _titres); - - this.logger.LogInformation("Données fictives générées avec succès."); } /// /// Affiche la liste des commentaires dans la vue Index. /// - /// >La vue Index avec le ViewModel contenant la liste des commentaires. + /// La vue Index avec le ViewModel contenant la liste des commentaires. public IActionResult Index() { - // Création de données "bouchon" (mock) pour tester l'affichage + // Récupération des commentaires depuis le repository + var commentaires = this.commentaireRepository.FindAll(); // Initialisation du ViewModel var viewModel = new CommentaireViewModel { - Commentaires = _commentaires + Commentaires = commentaires }; return View(viewModel); } - /// - /// Affiche la vue de confirmation de suppression d'un commentaire, en récupérant les détails du commentaire à supprimer à partir de l'identifiant fourni. + /// Affiche la vue de confirmation de suppression d'un commentaire, en récupérant les détails à partir de l'identifiant fourni. /// /// L'identifiant du commentaire à supprimer. - /// La vue de confirmation de suppression avec le ViewModel contenant les détails du commentaire à supprimer, ou une redirection vers l'index si le commentaire n'existe pas. + /// La vue de confirmation de suppression avec le ViewModel contenant les détails, ou une redirection vers l'index si introuvable. public IActionResult Delete(int id) { - var commentaire = _commentaires - .FirstOrDefault(c => c.IdCommentaire == id); + var commentaire = this.commentaireRepository.Find(id); if (commentaire == null) { @@ -80,5 +69,27 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers return View(vm); } + + /// + /// Effectue la suppression réelle du commentaire (accessible via un simple lien sans HttpPost). + /// + /// L'identifiant du commentaire à supprimer. + /// Redirection vers la vue Index après suppression. + public IActionResult DeleteConfirm(int id) + { + var commentaire = this.commentaireRepository.Find(id); + + if (commentaire != null) + { + this.commentaireRepository.Delete(commentaire); + this.logger.LogInformation("Commentaire {Id} supprimé avec succès.", id); + } + else + { + this.logger.LogWarning("Échec de la suppression : Commentaire avec ID {Id} introuvable.", id); + } + + return RedirectToAction("Index"); + } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Program.cs b/Webzine.WebApplication/Program.cs index 0ac5209..2a2e962 100644 --- a/Webzine.WebApplication/Program.cs +++ b/Webzine.WebApplication/Program.cs @@ -37,7 +37,7 @@ try builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - //builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); } else