diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index fbe20a95..d4485716 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -375,14 +375,6 @@ namespace Kyoo.Controllers /// If the item is not found /// The episode found Task Get(string showSlug, int seasonNumber, int episodeNumber); - /// - /// Get a episode from it's season ID and it's episode number. - /// - /// The ID of the season - /// The episode number - /// If the item is not found - /// The episode found - Task Get(int seasonID, int episodeNumber); /// /// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found. diff --git a/Kyoo.CommonAPI/LocalRepository.cs b/Kyoo.CommonAPI/LocalRepository.cs index 8f82093e..8e78964f 100644 --- a/Kyoo.CommonAPI/LocalRepository.cs +++ b/Kyoo.CommonAPI/LocalRepository.cs @@ -97,19 +97,19 @@ namespace Kyoo.Controllers } /// - public Task GetOrDefault(int id) + public virtual Task GetOrDefault(int id) { return Database.Set().FirstOrDefaultAsync(x => x.ID == id); } /// - public Task GetOrDefault(string slug) + public virtual Task GetOrDefault(string slug) { return Database.Set().FirstOrDefaultAsync(x => x.Slug == slug); } /// - public Task GetOrDefault(Expression> where) + public virtual Task GetOrDefault(Expression> where) { return Database.Set().FirstOrDefaultAsync(where); } diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index 84232067..fc384904 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -5,21 +5,49 @@ using System.Linq.Expressions; using System.Text.RegularExpressions; using System.Threading.Tasks; using Kyoo.Models; +using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle episodes. + /// public class EpisodeRepository : LocalRepository, IEpisodeRepository { + /// + /// Has this instance been disposed and should not handle requests? + /// private bool _disposed; + /// + /// The databse handle + /// private readonly DatabaseContext _database; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + /// + /// A show repository to get show's slug from their ID and keep the slug in each episode. + /// private readonly IShowRepository _shows; + /// + /// A track repository to handle creation and deletion of tracks related to the current episode. + /// private readonly ITrackRepository _tracks; + + /// protected override Expression> DefaultSort => x => x.EpisodeNumber; - public EpisodeRepository(DatabaseContext database, + /// + /// Create a new . + /// + /// The database handle to use. + /// A provider repository + /// A show repository + /// A track repository + public EpisodeRepository(DatabaseContext database, IProviderRepository providers, IShowRepository shows, ITrackRepository tracks) @@ -32,6 +60,7 @@ namespace Kyoo.Controllers } + /// public override void Dispose() { if (_disposed) @@ -43,6 +72,7 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } + /// public override async ValueTask DisposeAsync() { if (_disposed) @@ -53,7 +83,8 @@ namespace Kyoo.Controllers await _shows.DisposeAsync(); } - public override async Task Get(int id) + /// + public override async Task GetOrDefault(int id) { Episode ret = await base.Get(id); if (ret != null) @@ -61,13 +92,14 @@ namespace Kyoo.Controllers return ret; } - public override async Task Get(string slug) + /// + public override async Task GetOrDefault(string slug) { Match match = Regex.Match(slug, @"(?.*)-s(?\d*)e(?\d*)"); if (match.Success) { - return await Get(match.Groups["show"].Value, + return await GetOrDefault(match.Groups["show"].Value, int.Parse(match.Groups["season"].Value), int.Parse(match.Groups["episode"].Value)); } @@ -78,7 +110,8 @@ namespace Kyoo.Controllers return episode; } - public override async Task Get(Expression> predicate) + /// + public override async Task GetOrDefault(Expression> predicate) { Episode ret = await base.Get(predicate); if (ret != null) @@ -86,7 +119,8 @@ namespace Kyoo.Controllers return ret; } - public async Task Get(string showSlug, int seasonNumber, int episodeNumber) + /// + public async Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber) { Episode ret = await _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber @@ -96,7 +130,26 @@ namespace Kyoo.Controllers return ret; } + /// public async Task Get(int showID, int seasonNumber, int episodeNumber) + { + Episode ret = await GetOrDefault(showID, seasonNumber, episodeNumber); + if (ret == null) + throw new ItemNotFound($"No episode S{seasonNumber}E{episodeNumber} found on the show {showID}."); + return ret; + } + + /// + public async Task Get(string showSlug, int seasonNumber, int episodeNumber) + { + Episode ret = await GetOrDefault(showSlug, seasonNumber, episodeNumber); + if (ret == null) + throw new ItemNotFound($"No episode S{seasonNumber}E{episodeNumber} found on the show {showSlug}."); + return ret; + } + + /// + public async Task GetOrDefault(int showID, int seasonNumber, int episodeNumber) { Episode ret = await _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID && x.SeasonNumber == seasonNumber @@ -106,15 +159,7 @@ namespace Kyoo.Controllers return ret; } - public async Task Get(int seasonID, int episodeNumber) - { - Episode ret = await _database.Episodes.FirstOrDefaultAsync(x => x.SeasonID == seasonID - && x.EpisodeNumber == episodeNumber); - if (ret != null) - ret.ShowSlug = await _shows.GetSlug(ret.ShowID); - return ret; - } - + /// public async Task GetAbsolute(int showID, int absoluteNumber) { Episode ret = await _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID @@ -124,6 +169,7 @@ namespace Kyoo.Controllers return ret; } + /// public async Task GetAbsolute(string showSlug, int absoluteNumber) { Episode ret = await _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug @@ -133,6 +179,7 @@ namespace Kyoo.Controllers return ret; } + /// public override async Task> Search(string query) { List episodes = await _database.Episodes @@ -145,6 +192,7 @@ namespace Kyoo.Controllers return episodes; } + /// public override async Task> GetAll(Expression> where = null, Sort sort = default, Pagination limit = default) @@ -155,6 +203,7 @@ namespace Kyoo.Controllers return episodes; } + /// public override async Task Create(Episode obj) { await base.Create(obj); @@ -164,6 +213,7 @@ namespace Kyoo.Controllers return await ValidateTracks(obj); } + /// protected override async Task EditRelations(Episode resource, Episode changed, bool resetOld) { if (resource.ShowID <= 0) @@ -185,6 +235,11 @@ namespace Kyoo.Controllers await Validate(resource); } + /// + /// Set track's index and ensure that every tracks is well-formed. + /// + /// The resource to fix. + /// The parameter is returnned. private async Task ValidateTracks(Episode resource) { resource.Tracks = await resource.Tracks.MapAsync((x, i) => @@ -199,6 +254,7 @@ namespace Kyoo.Controllers return resource; } + /// protected override async Task Validate(Episode resource) { await base.Validate(resource); @@ -211,6 +267,7 @@ namespace Kyoo.Controllers }).ToListAsync(); } + /// public override async Task Delete(Episode obj) { if (obj == null) diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index fb17d58f..22ee9a64 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -20,9 +20,21 @@ namespace Kyoo.Controllers /// Has this instance been disposed and should not handle requests? /// private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + /// + /// A show repository to get show's slug from their ID and keep the slug in each episode. + /// private readonly IShowRepository _shows; + /// + /// A lazilly loaded episode repository to handle deletion of episodes with the season. + /// private readonly Lazy _episodes; /// diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index f07e4f5a..e94419c2 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -9,18 +9,56 @@ using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { + /// + /// A local repository to handle shows + /// public class ShowRepository : LocalRepository, IShowRepository { + /// + /// Has this instance been disposed and should not handle requests? + /// private bool _disposed; + /// + /// The databse handle + /// private readonly DatabaseContext _database; + /// + /// A studio repository to handle creation/validation of related studios. + /// private readonly IStudioRepository _studios; + /// + /// A people repository to handle creation/validation of related people. + /// private readonly IPeopleRepository _people; + /// + /// A genres repository to handle creation/validation of related genres. + /// private readonly IGenreRepository _genres; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + /// + /// A lazy loaded season repository to handle cascade deletion (seasons deletion whith it's show) + /// private readonly Lazy _seasons; + /// + /// A lazy loaded episode repository to handle cascade deletion (episode deletion whith it's show) + /// private readonly Lazy _episodes; + + /// protected override Expression> DefaultSort => x => x.Title; + /// + /// Create a new . + /// + /// The database handle to use + /// A studio repository + /// A people repository + /// A genres repository + /// A provider repository + /// A service provider to lazilly request a season and an episode repository public ShowRepository(DatabaseContext database, IStudioRepository studios, IPeopleRepository people, @@ -38,6 +76,7 @@ namespace Kyoo.Controllers _episodes = new Lazy(services.GetRequiredService); } + /// public override void Dispose() { if (_disposed) @@ -55,6 +94,7 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } + /// public override async ValueTask DisposeAsync() { if (_disposed) @@ -71,6 +111,7 @@ namespace Kyoo.Controllers await _episodes.Value.DisposeAsync(); } + /// public override async Task> Search(string query) { query = $"%{query}%"; @@ -83,6 +124,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Show obj) { await base.Create(obj); @@ -94,6 +136,7 @@ namespace Kyoo.Controllers return obj; } + /// protected override async Task Validate(Show resource) { await base.Validate(resource); @@ -119,6 +162,7 @@ namespace Kyoo.Controllers }); } + /// protected override async Task EditRelations(Show resource, Show changed, bool resetOld) { await Validate(changed); @@ -145,6 +189,7 @@ namespace Kyoo.Controllers } } + /// public async Task AddShowLink(int showID, int? libraryID, int? collectionID) { if (collectionID != null) @@ -168,6 +213,7 @@ namespace Kyoo.Controllers } } + /// public Task GetSlug(int showID) { return _database.Shows.Where(x => x.ID == showID) @@ -175,6 +221,7 @@ namespace Kyoo.Controllers .FirstOrDefaultAsync(); } + /// public override async Task Delete(Show obj) { if (obj == null)