Finishing documentation for all repositories

This commit is contained in:
Zoe Roux 2021-04-21 23:28:22 +02:00
parent 6cc65d5aa8
commit 8db47d62fd
10 changed files with 449 additions and 405 deletions

View File

@ -411,91 +411,240 @@ namespace Kyoo.Controllers
Task<Episode> GetAbsolute(string showSlug, int absoluteNumber); Task<Episode> GetAbsolute(string showSlug, int absoluteNumber);
} }
/// <summary>
/// A repository to handle tracks
/// </summary>
public interface ITrackRepository : IRepository<Track> public interface ITrackRepository : IRepository<Track>
{ {
/// <summary>
/// Get a track from it's slug and it's type.
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The tracl found</returns>
Task<Track> Get(string slug, StreamType type = StreamType.Unknown); Task<Track> Get(string slug, StreamType type = StreamType.Unknown);
/// <summary>
/// Get a track from it's slug and it's type or null if it is not found.
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <returns>The tracl found</returns>
Task<Track> GetOrDefault(string slug, StreamType type = StreamType.Unknown);
} }
/// <summary>
/// A repository to handle libraries.
/// </summary>
public interface ILibraryRepository : IRepository<Library> { } public interface ILibraryRepository : IRepository<Library> { }
/// <summary>
/// A repository to handle library items (A wrapper arround shows and collections).
/// </summary>
public interface ILibraryItemRepository : IRepository<LibraryItem> public interface ILibraryItemRepository : IRepository<LibraryItem>
{ {
/// <summary>
/// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="id">The ID of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetFromLibrary(int id, public Task<ICollection<LibraryItem>> GetFromLibrary(int id,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
Pagination limit = default); Pagination limit = default);
/// <summary>
/// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="id">The ID of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetFromLibrary(int id, public Task<ICollection<LibraryItem>> GetFromLibrary(int id,
[Optional] Expression<Func<LibraryItem, bool>> where, [Optional] Expression<Func<LibraryItem, bool>> where,
Expression<Func<LibraryItem, object>> sort, Expression<Func<LibraryItem, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit); ) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
public Task<ICollection<LibraryItem>> GetFromLibrary(string librarySlug, /// <summary>
/// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="slug">The slug of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
Pagination limit = default); Pagination limit = default);
/// <summary>
public Task<ICollection<LibraryItem>> GetFromLibrary(string librarySlug, /// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="slug">The slug of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
[Optional] Expression<Func<LibraryItem, bool>> where, [Optional] Expression<Func<LibraryItem, bool>> where,
Expression<Func<LibraryItem, object>> sort, Expression<Func<LibraryItem, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromLibrary(librarySlug, where, new Sort<LibraryItem>(sort), limit); ) => GetFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
} }
/// <summary>
/// A repository for collections
/// </summary>
public interface ICollectionRepository : IRepository<Collection> { } public interface ICollectionRepository : IRepository<Collection> { }
/// <summary>
/// A repository for genres.
/// </summary>
public interface IGenreRepository : IRepository<Genre> { } public interface IGenreRepository : IRepository<Genre> { }
/// <summary>
/// A repository for studios.
/// </summary>
public interface IStudioRepository : IRepository<Studio> { } public interface IStudioRepository : IRepository<Studio> { }
/// <summary>
/// A repository for people.
/// </summary>
public interface IPeopleRepository : IRepository<People> public interface IPeopleRepository : IRepository<People>
{ {
/// <summary>
/// Get people's roles from a show.
/// </summary>
/// <param name="showID">The ID of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromShow(int showID, Task<ICollection<PeopleRole>> GetFromShow(int showID,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
Pagination limit = default); Pagination limit = default);
/// <summary>
/// Get people's roles from a show.
/// </summary>
/// <param name="showID">The ID of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromShow(int showID, Task<ICollection<PeopleRole>> GetFromShow(int showID,
[Optional] Expression<Func<PeopleRole, bool>> where, [Optional] Expression<Func<PeopleRole, bool>> where,
Expression<Func<PeopleRole, object>> sort, Expression<Func<PeopleRole, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit); ) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
/// <summary>
/// Get people's roles from a show.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromShow(string showSlug, Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
Pagination limit = default); Pagination limit = default);
/// <summary>
/// Get people's roles from a show.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromShow(string showSlug, Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
[Optional] Expression<Func<PeopleRole, bool>> where, [Optional] Expression<Func<PeopleRole, bool>> where,
Expression<Func<PeopleRole, object>> sort, Expression<Func<PeopleRole, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit); ) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
Task<ICollection<PeopleRole>> GetFromPeople(int showID, /// <summary>
/// Get people's roles from a person.
/// </summary>
/// <param name="id">The id of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromPeople(int id,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
Pagination limit = default); Pagination limit = default);
Task<ICollection<PeopleRole>> GetFromPeople(int showID, /// <summary>
/// Get people's roles from a person.
/// </summary>
/// <param name="id">The id of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromPeople(int id,
[Optional] Expression<Func<PeopleRole, bool>> where, [Optional] Expression<Func<PeopleRole, bool>> where,
Expression<Func<PeopleRole, object>> sort, Expression<Func<PeopleRole, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromPeople(showID, where, new Sort<PeopleRole>(sort), limit); ) => GetFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
Task<ICollection<PeopleRole>> GetFromPeople(string showSlug, /// <summary>
/// Get people's roles from a person.
/// </summary>
/// <param name="slug">The slug of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
Pagination limit = default); Pagination limit = default);
Task<ICollection<PeopleRole>> GetFromPeople(string showSlug, /// <summary>
/// Get people's roles from a person.
/// </summary>
/// <param name="slug">The slug of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">A sort by method</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
[Optional] Expression<Func<PeopleRole, bool>> where, [Optional] Expression<Func<PeopleRole, bool>> where,
Expression<Func<PeopleRole, object>> sort, Expression<Func<PeopleRole, object>> sort,
Pagination limit = default Pagination limit = default
) => GetFromPeople(showSlug, where, new Sort<PeopleRole>(sort), limit); ) => GetFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
} }
/// <summary>
/// A repository to handle providers.
/// </summary>
public interface IProviderRepository : IRepository<Provider> public interface IProviderRepository : IRepository<Provider>
{ {
/// <summary>
/// Get a list of external ids that match all filters
/// </summary>
/// <param name="where">A predicate to add arbitrary filter</param>
/// <param name="sort">Sort information (sort order & sort by)</param>
/// <param name="limit">Paginations information (where to start and how many to get)</param>
/// <returns>A filtered list of external ids.</returns>
Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null, Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null,
Sort<MetadataID> sort = default, Sort<MetadataID> sort = default,
Pagination limit = default); Pagination limit = default);
/// <summary>
/// Get a list of external ids that match all filters
/// </summary>
/// <param name="where">A predicate to add arbitrary filter</param>
/// <param name="sort">A sort by expression</param>
/// <param name="limit">Paginations information (where to start and how many to get)</param>
/// <returns>A filtered list of external ids.</returns>
Task<ICollection<MetadataID>> GetMetadataID([Optional] Expression<Func<MetadataID, bool>> where, Task<ICollection<MetadataID>> GetMetadataID([Optional] Expression<Func<MetadataID, bool>> where,
Expression<Func<MetadataID, object>> sort, Expression<Func<MetadataID, object>> sort,
Pagination limit = default Pagination limit = default

View File

@ -15,66 +15,35 @@ namespace Kyoo.Controllers
/// </summary> /// </summary>
private readonly IBaseRepository[] _repositories; private readonly IBaseRepository[] _repositories;
/// <summary> /// <inheritdoc />
/// The repository that handle libraries.
/// </summary>
public ILibraryRepository LibraryRepository { get; } public ILibraryRepository LibraryRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle libraries's items (a wrapper arround shows & collections).
/// </summary>
public ILibraryItemRepository LibraryItemRepository { get; } public ILibraryItemRepository LibraryItemRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle collections.
/// </summary>
public ICollectionRepository CollectionRepository { get; } public ICollectionRepository CollectionRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle shows.
/// </summary>
public IShowRepository ShowRepository { get; } public IShowRepository ShowRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle seasons.
/// </summary>
public ISeasonRepository SeasonRepository { get; } public ISeasonRepository SeasonRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle episodes.
/// </summary>
public IEpisodeRepository EpisodeRepository { get; } public IEpisodeRepository EpisodeRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle tracks.
/// </summary>
public ITrackRepository TrackRepository { get; } public ITrackRepository TrackRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle people.
/// </summary>
public IPeopleRepository PeopleRepository { get; } public IPeopleRepository PeopleRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle studios.
/// </summary>
public IStudioRepository StudioRepository { get; } public IStudioRepository StudioRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle genres.
/// </summary>
public IGenreRepository GenreRepository { get; } public IGenreRepository GenreRepository { get; }
/// <inheritdoc />
/// <summary>
/// The repository that handle providers.
/// </summary>
public IProviderRepository ProviderRepository { get; } public IProviderRepository ProviderRepository { get; }
/// <summary> /// <summary>
/// Create a new <see cref="LibraryManager"/> instancce with every repository available. /// Create a new <see cref="LibraryManager"/> instancce with every repository available.
/// </summary> /// </summary>
/// <param name="repositories">The list of repositories that this library manager should manage. If a repository for every base type is not available, this instance won't be stable.</param> /// <param name="repositories">The list of repositories that this library manager should manage.
/// If a repository for every base type is not available, this instance won't be stable.</param>
public LibraryManager(IEnumerable<IBaseRepository> repositories) public LibraryManager(IEnumerable<IBaseRepository> repositories)
{ {
_repositories = repositories.ToArray(); _repositories = repositories.ToArray();
@ -91,9 +60,7 @@ namespace Kyoo.Controllers
ProviderRepository = GetRepository<Provider>() as IProviderRepository; ProviderRepository = GetRepository<Provider>() as IProviderRepository;
} }
/// <summary> /// <inheritdoc />
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose() public void Dispose()
{ {
foreach (IBaseRepository repo in _repositories) foreach (IBaseRepository repo in _repositories)
@ -101,21 +68,13 @@ namespace Kyoo.Controllers
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
/// <summary> /// <inheritdoc />
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.
/// </summary>
/// <returns>A task that represents the asynchronous dispose operation.</returns>
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
{ {
await Task.WhenAll(_repositories.Select(x => x.DisposeAsync().AsTask())); await Task.WhenAll(_repositories.Select(x => x.DisposeAsync().AsTask()));
} }
/// <summary> /// <inheritdoc />
/// Get the repository corresponding to the T item.
/// </summary>
/// <typeparam name="T">The type you want</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The repository corresponding</returns>
public IRepository<T> GetRepository<T>() public IRepository<T> GetRepository<T>()
where T : class, IResource where T : class, IResource
{ {
@ -124,208 +83,109 @@ namespace Kyoo.Controllers
throw new ItemNotFound(); throw new ItemNotFound();
} }
/// <summary> /// <inheritdoc />
/// Get the resource by it's ID
/// </summary>
/// <param name="id">The id of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The resource found</returns>
public Task<T> Get<T>(int id) public Task<T> Get<T>(int id)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Get(id); return GetRepository<T>().Get(id);
} }
/// <summary> /// <inheritdoc />
/// Get the resource by it's slug
/// </summary>
/// <param name="slug">The slug of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The resource found</returns>
public Task<T> Get<T>(string slug) public Task<T> Get<T>(string slug)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Get(slug); return GetRepository<T>().Get(slug);
} }
/// <summary> /// <inheritdoc />
/// Get the resource by a filter function.
/// </summary>
/// <param name="where">The filter function.</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The first resource found that match the where function</returns>
public Task<T> Get<T>(Expression<Func<T, bool>> where) public Task<T> Get<T>(Expression<Func<T, bool>> where)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Get(where); return GetRepository<T>().Get(where);
} }
/// <summary> /// <inheritdoc />
/// Get a season from it's showID and it's seasonNumber
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The season found</returns>
public Task<Season> Get(int showID, int seasonNumber) public Task<Season> Get(int showID, int seasonNumber)
{ {
return SeasonRepository.Get(showID, seasonNumber); return SeasonRepository.Get(showID, seasonNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a season from it's show slug and it's seasonNumber
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The season found</returns>
public Task<Season> Get(string showSlug, int seasonNumber) public Task<Season> Get(string showSlug, int seasonNumber)
{ {
return SeasonRepository.Get(showSlug, seasonNumber); return SeasonRepository.Get(showSlug, seasonNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a episode from it's showID, it's seasonNumber and it's episode number.
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The episode found</returns>
public Task<Episode> Get(int showID, int seasonNumber, int episodeNumber) public Task<Episode> Get(int showID, int seasonNumber, int episodeNumber)
{ {
return EpisodeRepository.Get(showID, seasonNumber, episodeNumber); return EpisodeRepository.Get(showID, seasonNumber, episodeNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a episode from it's show slug, it's seasonNumber and it's episode number.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The episode found</returns>
public Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber) public Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber)
{ {
return EpisodeRepository.Get(showSlug, seasonNumber, episodeNumber); return EpisodeRepository.Get(showSlug, seasonNumber, episodeNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a tracck from it's slug and it's type.
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The tracl found</returns>
public Task<Track> Get(string slug, StreamType type = StreamType.Unknown) public Task<Track> Get(string slug, StreamType type = StreamType.Unknown)
{ {
return TrackRepository.Get(slug, type); return TrackRepository.Get(slug, type);
} }
/// <summary> /// <inheritdoc />
/// Get the resource by it's ID or null if it is not found.
/// </summary>
/// <param name="id">The id of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <returns>The resource found</returns>
public async Task<T> GetOrDefault<T>(int id) public async Task<T> GetOrDefault<T>(int id)
where T : class, IResource where T : class, IResource
{ {
return await GetRepository<T>().GetOrDefault(id); return await GetRepository<T>().GetOrDefault(id);
} }
/// <summary> /// <inheritdoc />
/// Get the resource by it's slug or null if it is not found.
/// </summary>
/// <param name="slug">The slug of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <returns>The resource found</returns>
public async Task<T> GetOrDefault<T>(string slug) public async Task<T> GetOrDefault<T>(string slug)
where T : class, IResource where T : class, IResource
{ {
return await GetRepository<T>().GetOrDefault(slug); return await GetRepository<T>().GetOrDefault(slug);
} }
/// <summary> /// <inheritdoc />
/// Get the resource by a filter function or null if it is not found.
/// </summary>
/// <param name="where">The filter function.</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <returns>The first resource found that match the where function</returns>
public async Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where) public async Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where)
where T : class, IResource where T : class, IResource
{ {
return await GetRepository<T>().GetOrDefault(where); return await GetRepository<T>().GetOrDefault(where);
} }
/// <summary> /// <inheritdoc />
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <returns>The season found</returns>
public async Task<Season> GetOrDefault(int showID, int seasonNumber) public async Task<Season> GetOrDefault(int showID, int seasonNumber)
{ {
return await SeasonRepository.GetOrDefault(showID, seasonNumber); return await SeasonRepository.GetOrDefault(showID, seasonNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <returns>The season found</returns>
public async Task<Season> GetOrDefault(string showSlug, int seasonNumber) public async Task<Season> GetOrDefault(string showSlug, int seasonNumber)
{ {
return await SeasonRepository.GetOrDefault(showSlug, seasonNumber); return await SeasonRepository.GetOrDefault(showSlug, seasonNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found.
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <returns>The episode found</returns>
public async Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber) public async Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber)
{ {
return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber); return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <returns>The episode found</returns>
public async Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber) public async Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber)
{ {
return await EpisodeRepository.GetOrDefault(showSlug, seasonNumber, episodeNumber); return await EpisodeRepository.GetOrDefault(showSlug, seasonNumber, episodeNumber);
} }
/// <summary> /// <inheritdoc />
/// Get a track from it's slug and it's type or null if it is not found.
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <returns>The tracl found</returns>
public async Task<Track> GetOrDefault(string slug, StreamType type = StreamType.Unknown) public async Task<Track> GetOrDefault(string slug, StreamType type = StreamType.Unknown)
{ {
return await TrackRepository.GetOrDefault(slug, type); return await TrackRepository.GetOrDefault(slug, type);
} }
/// <summary> /// <inheritdoc />
/// Load a related resource
/// </summary>
/// <param name="obj">The source object.</param>
/// <param name="member">A getter function for the member to load</param>
/// <typeparam name="T">The type of the source object</typeparam>
/// <typeparam name="T2">The related resource's type</typeparam>
/// <returns>The param <see cref="obj"/></returns>
public Task<T> Load<T, T2>(T obj, Expression<Func<T, T2>> member) public Task<T> Load<T, T2>(T obj, Expression<Func<T, T2>> member)
where T : class, IResource where T : class, IResource
where T2 : class, IResource, new() where T2 : class, IResource, new()
@ -335,14 +195,7 @@ namespace Kyoo.Controllers
return Load(obj, Utility.GetPropertyName(member)); return Load(obj, Utility.GetPropertyName(member));
} }
/// <summary> /// <inheritdoc />
/// Load a collection of related resource
/// </summary>
/// <param name="obj">The source object.</param>
/// <param name="member">A getter function for the member to load</param>
/// <typeparam name="T">The type of the source object</typeparam>
/// <typeparam name="T2">The related resource's type</typeparam>
/// <returns>The param <see cref="obj"/></returns>
public Task<T> Load<T, T2>(T obj, Expression<Func<T, ICollection<T2>>> member) public Task<T> Load<T, T2>(T obj, Expression<Func<T, ICollection<T2>>> member)
where T : class, IResource where T : class, IResource
where T2 : class, new() where T2 : class, new()
@ -352,13 +205,7 @@ namespace Kyoo.Controllers
return Load(obj, Utility.GetPropertyName(member)); return Load(obj, Utility.GetPropertyName(member));
} }
/// <summary> /// <inheritdoc />
/// Load a related resource by it's name
/// </summary>
/// <param name="obj">The source object.</param>
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
/// <typeparam name="T">The type of the source object</typeparam>
/// <returns>The param <see cref="obj"/></returns>
public async Task<T> Load<T>(T obj, string memberName) public async Task<T> Load<T>(T obj, string memberName)
where T : class, IResource where T : class, IResource
{ {
@ -386,11 +233,7 @@ namespace Kyoo.Controllers
inverse(item, obj); inverse(item, obj);
} }
/// <summary> /// <inheritdoc />
/// Load a related resource without specifing it's type.
/// </summary>
/// <param name="obj">The source object.</param>
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
public Task Load(IResource obj, string memberName) public Task Load(IResource obj, string memberName)
{ {
if (obj == null) if (obj == null)
@ -544,14 +387,7 @@ namespace Kyoo.Controllers
}; };
} }
/// <summary> /// <inheritdoc />
/// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="id">The ID of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id, public Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
@ -560,14 +396,7 @@ namespace Kyoo.Controllers
return LibraryItemRepository.GetFromLibrary(id, where, sort, limit); return LibraryItemRepository.GetFromLibrary(id, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get items (A wrapper arround shows or collections) from a library.
/// </summary>
/// <param name="slug">The slug of the library</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug, public Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
@ -576,14 +405,7 @@ namespace Kyoo.Controllers
return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit); return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get people's roles from a show.
/// </summary>
/// <param name="showID">The ID of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID, public Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -592,14 +414,7 @@ namespace Kyoo.Controllers
return PeopleRepository.GetFromShow(showID, where, sort, limit); return PeopleRepository.GetFromShow(showID, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get people's roles from a show.
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug, public Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -608,14 +423,7 @@ namespace Kyoo.Controllers
return PeopleRepository.GetFromShow(showSlug, where, sort, limit); return PeopleRepository.GetFromShow(showSlug, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get people's roles from a person.
/// </summary>
/// <param name="id">The id of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<PeopleRole>> GetRolesFromPeople(int id, public Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -624,14 +432,7 @@ namespace Kyoo.Controllers
return PeopleRepository.GetFromPeople(id, where, sort, limit); return PeopleRepository.GetFromPeople(id, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get people's roles from a person.
/// </summary>
/// <param name="slug">The slug of the person</param>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <returns>A list of items that match every filters</returns>
public Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug, public Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -640,23 +441,13 @@ namespace Kyoo.Controllers
return PeopleRepository.GetFromPeople(slug, where, sort, limit); return PeopleRepository.GetFromPeople(slug, where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Setup relations between a show, a library and a collection
/// </summary>
/// <param name="showID">The show's ID to setup relations with</param>
/// <param name="libraryID">The library's ID to setup relations with (optional)</param>
/// <param name="collectionID">The collection's ID to setup relations with (optional)</param>
public Task AddShowLink(int showID, int? libraryID, int? collectionID) public Task AddShowLink(int showID, int? libraryID, int? collectionID)
{ {
return ShowRepository.AddShowLink(showID, libraryID, collectionID); return ShowRepository.AddShowLink(showID, libraryID, collectionID);
} }
/// <summary> /// <inheritdoc />
/// Setup relations between a show, a library and a collection
/// </summary>
/// <param name="show">The show to setup relations with</param>
/// <param name="library">The library to setup relations with (optional)</param>
/// <param name="collection">The collection to setup relations with (optional)</param>
public Task AddShowLink(Show show, Library library, Collection collection) public Task AddShowLink(Show show, Library library, Collection collection)
{ {
if (show == null) if (show == null)
@ -664,14 +455,7 @@ namespace Kyoo.Controllers
return ShowRepository.AddShowLink(show.ID, library?.ID, collection?.ID); return ShowRepository.AddShowLink(show.ID, library?.ID, collection?.ID);
} }
/// <summary> /// <inheritdoc />
/// Get all resources with filters
/// </summary>
/// <param name="where">A filter function</param>
/// <param name="sort">Sort informations (sort order & sort by)</param>
/// <param name="limit">How many items to return and where to start</param>
/// <typeparam name="T">The type of resources to load</typeparam>
/// <returns>A list of resources that match every filters</returns>
public Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null, public Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
Sort<T> sort = default, Sort<T> sort = default,
Pagination limit = default) Pagination limit = default)
@ -680,98 +464,56 @@ namespace Kyoo.Controllers
return GetRepository<T>().GetAll(where, sort, limit); return GetRepository<T>().GetAll(where, sort, limit);
} }
/// <summary> /// <inheritdoc />
/// Get the count of resources that match the filter
/// </summary>
/// <param name="where">A filter function</param>
/// <typeparam name="T">The type of resources to load</typeparam>
/// <returns>A list of resources that match every filters</returns>
public Task<int> GetCount<T>(Expression<Func<T, bool>> where = null) public Task<int> GetCount<T>(Expression<Func<T, bool>> where = null)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().GetCount(where); return GetRepository<T>().GetCount(where);
} }
/// <summary> /// <inheritdoc />
/// Search for a resource
/// </summary>
/// <param name="query">The search query</param>
/// <typeparam name="T">The type of resources</typeparam>
/// <returns>A list of 20 items that match the search query</returns>
public Task<ICollection<T>> Search<T>(string query) public Task<ICollection<T>> Search<T>(string query)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Search(query); return GetRepository<T>().Search(query);
} }
/// <summary> /// <inheritdoc />
/// Create a new resource.
/// </summary>
/// <param name="item">The item to register</param>
/// <typeparam name="T">The type of resource</typeparam>
/// <returns>The resource registers and completed by database's informations (related items & so on)</returns>
public Task<T> Create<T>(T item) public Task<T> Create<T>(T item)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Create(item); return GetRepository<T>().Create(item);
} }
/// <summary> /// <inheritdoc />
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
/// </summary>
/// <param name="item">The object to create</param>
/// <typeparam name="T">The type of resource</typeparam>
/// <returns>The newly created item or the existing value if it existed.</returns>
public Task<T> CreateIfNotExists<T>(T item) public Task<T> CreateIfNotExists<T>(T item)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().CreateIfNotExists(item); return GetRepository<T>().CreateIfNotExists(item);
} }
/// <summary> /// <inheritdoc />
/// Edit a resource
/// </summary>
/// <param name="item">The resourcce to edit, it's ID can't change.</param>
/// <param name="resetOld">Should old properties of the resource be discarded or should null values considered as not changed?</param>
/// <typeparam name="T">The type of resources</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <returns>The resource edited and completed by database's informations (related items & so on)</returns>
public Task<T> Edit<T>(T item, bool resetOld) public Task<T> Edit<T>(T item, bool resetOld)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Edit(item, resetOld); return GetRepository<T>().Edit(item, resetOld);
} }
/// <summary> /// <inheritdoc />
/// Delete a resource.
/// </summary>
/// <param name="item">The resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
public Task Delete<T>(T item) public Task Delete<T>(T item)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Delete(item); return GetRepository<T>().Delete(item);
} }
/// <summary> /// <inheritdoc />
/// Delete a resource by it's ID.
/// </summary>
/// <param name="id">The id of the resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
public Task Delete<T>(int id) public Task Delete<T>(int id)
where T : class, IResource where T : class, IResource
{ {
return GetRepository<T>().Delete(id); return GetRepository<T>().Delete(id);
} }
/// <summary> /// <inheritdoc />
/// Delete a resource by it's slug.
/// </summary>
/// <param name="slug">The slug of the resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
public Task Delete<T>(string slug) public Task Delete<T>(string slug)
where T : class, IResource where T : class, IResource
{ {

View File

@ -8,34 +8,30 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle collections
/// </summary>
public class CollectionRepository : LocalRepository<Collection>, ICollectionRepository public class CollectionRepository : LocalRepository<Collection>, ICollectionRepository
{ {
private bool _disposed; /// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <inheritdoc />
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name; protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
public CollectionRepository(DatabaseContext database) : base(database) /// <summary>
/// Create a new <see cref="CollectionRepository"/>.
/// </summary>
/// <param name="database">The database handle to use</param>
public CollectionRepository(DatabaseContext database)
: base(database)
{ {
_database = database; _database = database;
} }
public override void Dispose() /// <inheritdoc />
{
if (_disposed)
return;
_disposed = true;
_database.Dispose();
GC.SuppressFinalize(this);
}
public override async ValueTask DisposeAsync()
{
if (_disposed)
return;
_disposed = true;
await _database.DisposeAsync();
}
public override async Task<ICollection<Collection>> Search(string query) public override async Task<ICollection<Collection>> Search(string query)
{ {
return await _database.Collections return await _database.Collections
@ -45,6 +41,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<Collection> Create(Collection obj) public override async Task<Collection> Create(Collection obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -53,6 +50,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
public override async Task Delete(Collection obj) public override async Task Delete(Collection obj)
{ {
if (obj == null) if (obj == null)

View File

@ -8,35 +8,31 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository for genres.
/// </summary>
public class GenreRepository : LocalRepository<Genre>, IGenreRepository public class GenreRepository : LocalRepository<Genre>, IGenreRepository
{ {
private bool _disposed; /// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <inheritdoc />
protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug; protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
public GenreRepository(DatabaseContext database) : base(database) /// <summary>
/// Create a new <see cref="GenreRepository"/>.
/// </summary>
/// <param name="database">The database handle</param>
public GenreRepository(DatabaseContext database)
: base(database)
{ {
_database = database; _database = database;
} }
public override void Dispose() /// <inheritdoc />
{
if (_disposed)
return;
_disposed = true;
_database.Dispose();
GC.SuppressFinalize(this);
}
public override async ValueTask DisposeAsync()
{
if (_disposed)
return;
_disposed = true;
await _database.DisposeAsync();
}
public override async Task<ICollection<Genre>> Search(string query) public override async Task<ICollection<Genre>> Search(string query)
{ {
return await _database.Genres return await _database.Genres
@ -46,6 +42,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<Genre> Create(Genre obj) public override async Task<Genre> Create(Genre obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -54,6 +51,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
public override async Task Delete(Genre obj) public override async Task Delete(Genre obj)
{ {
if (obj == null) if (obj == null)

View File

@ -10,18 +10,49 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle library items.
/// </summary>
public class LibraryItemRepository : LocalRepository<LibraryItem>, ILibraryItemRepository public class LibraryItemRepository : LocalRepository<LibraryItem>, ILibraryItemRepository
{ {
/// <summary>
/// Has this instance been disposed and should not handle requests?
/// </summary>
private bool _disposed; private bool _disposed;
/// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <summary>
/// A provider repository to handle externalID creation and deletion
/// </summary>
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
/// <summary>
/// A lazy loaded library repository to validate queries (check if a library does exist)
/// </summary>
private readonly Lazy<ILibraryRepository> _libraries; private readonly Lazy<ILibraryRepository> _libraries;
/// <summary>
/// A lazy loaded show repository to get a show from it's id.
/// </summary>
private readonly Lazy<IShowRepository> _shows; private readonly Lazy<IShowRepository> _shows;
/// <summary>
/// A lazy loaded collection repository to get a collection from it's id.
/// </summary>
private readonly Lazy<ICollectionRepository> _collections; private readonly Lazy<ICollectionRepository> _collections;
/// <inheritdoc />
protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title; protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title;
public LibraryItemRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) /// <summary>
/// Create a new <see cref="LibraryItemRepository"/>.
/// </summary>
/// <param name="database">The databse instance</param>
/// <param name="providers">A provider repository</param>
/// <param name="services">A service provider to lazilly request a library, show or collection repository.</param>
public LibraryItemRepository(DatabaseContext database,
IProviderRepository providers,
IServiceProvider services)
: base(database) : base(database)
{ {
_database = database; _database = database;
@ -31,6 +62,7 @@ namespace Kyoo.Controllers
_collections = new Lazy<ICollectionRepository>(services.GetRequiredService<ICollectionRepository>); _collections = new Lazy<ICollectionRepository>(services.GetRequiredService<ICollectionRepository>);
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
if (_disposed) if (_disposed)
@ -45,6 +77,7 @@ namespace Kyoo.Controllers
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
/// <inheritdoc />
public override async ValueTask DisposeAsync() public override async ValueTask DisposeAsync()
{ {
if (_disposed) if (_disposed)
@ -58,6 +91,7 @@ namespace Kyoo.Controllers
await _collections.Value.DisposeAsync(); await _collections.Value.DisposeAsync();
} }
/// <inheritdoc />
public override async Task<LibraryItem> Get(int id) public override async Task<LibraryItem> Get(int id)
{ {
return id > 0 return id > 0
@ -65,11 +99,16 @@ namespace Kyoo.Controllers
: new LibraryItem(await _collections.Value.Get(-id)); : new LibraryItem(await _collections.Value.Get(-id));
} }
/// <inheritdoc />
public override Task<LibraryItem> Get(string slug) public override Task<LibraryItem> Get(string slug)
{ {
throw new InvalidOperationException(); throw new InvalidOperationException("You can't get a library item by a slug.");
} }
/// <summary>
/// Get a basic queryable with the right mapping from shows & collections.
/// Shows contained in a collection are excluded.
/// </summary>
private IQueryable<LibraryItem> ItemsQuery private IQueryable<LibraryItem> ItemsQuery
=> _database.Shows => _database.Shows
.Where(x => !x.Collections.Any()) .Where(x => !x.Collections.Any())
@ -77,6 +116,7 @@ namespace Kyoo.Controllers
.Concat(_database.Collections .Concat(_database.Collections
.Select(LibraryItem.FromCollection)); .Select(LibraryItem.FromCollection));
/// <inheritdoc />
public override Task<ICollection<LibraryItem>> GetAll(Expression<Func<LibraryItem, bool>> where = null, public override Task<ICollection<LibraryItem>> GetAll(Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
Pagination limit = default) Pagination limit = default)
@ -84,6 +124,7 @@ namespace Kyoo.Controllers
return ApplyFilters(ItemsQuery, where, sort, limit); return ApplyFilters(ItemsQuery, where, sort, limit);
} }
/// <inheritdoc />
public override Task<int> GetCount(Expression<Func<LibraryItem, bool>> where = null) public override Task<int> GetCount(Expression<Func<LibraryItem, bool>> where = null)
{ {
IQueryable<LibraryItem> query = ItemsQuery; IQueryable<LibraryItem> query = ItemsQuery;
@ -92,6 +133,7 @@ namespace Kyoo.Controllers
return query.CountAsync(); return query.CountAsync();
} }
/// <inheritdoc />
public override async Task<ICollection<LibraryItem>> Search(string query) public override async Task<ICollection<LibraryItem>> Search(string query)
{ {
return await ItemsQuery return await ItemsQuery
@ -101,19 +143,31 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override Task<LibraryItem> Create(LibraryItem obj) => throw new InvalidOperationException(); public override Task<LibraryItem> Create(LibraryItem obj) => throw new InvalidOperationException();
/// <inheritdoc />
public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj, bool silentFail = false) public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj, bool silentFail = false)
{ {
if (silentFail) if (silentFail)
return Task.FromResult<LibraryItem>(default); return Task.FromResult<LibraryItem>(default);
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
/// <inheritdoc />
public override Task<LibraryItem> Edit(LibraryItem obj, bool reset) => throw new InvalidOperationException(); public override Task<LibraryItem> Edit(LibraryItem obj, bool reset) => throw new InvalidOperationException();
/// <inheritdoc />
public override Task Delete(int id) => throw new InvalidOperationException(); public override Task Delete(int id) => throw new InvalidOperationException();
/// <inheritdoc />
public override Task Delete(string slug) => throw new InvalidOperationException(); public override Task Delete(string slug) => throw new InvalidOperationException();
/// <inheritdoc />
public override Task Delete(LibraryItem obj) => throw new InvalidOperationException(); public override Task Delete(LibraryItem obj) => throw new InvalidOperationException();
/// <summary>
/// Get a basic queryable for a library with the right mapping from shows & collections.
/// Shows contained in a collection are excluded.
/// </summary>
/// <param name="selector">Only items that are part of a library that match this predicate will be returned.</param>
/// <returns>A queryable containing items that are part of a library matching the selector.</returns>
private IQueryable<LibraryItem> LibraryRelatedQuery(Expression<Func<Library, bool>> selector) private IQueryable<LibraryItem> LibraryRelatedQuery(Expression<Func<Library, bool>> selector)
=> _database.Libraries => _database.Libraries
.Where(selector) .Where(selector)
@ -125,6 +179,7 @@ namespace Kyoo.Controllers
.SelectMany(x => x.Collections) .SelectMany(x => x.Collections)
.Select(LibraryItem.FromCollection)); .Select(LibraryItem.FromCollection));
/// <inheritdoc />
public async Task<ICollection<LibraryItem>> GetFromLibrary(int id, public async Task<ICollection<LibraryItem>> GetFromLibrary(int id,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,
@ -139,6 +194,7 @@ namespace Kyoo.Controllers
return items; return items;
} }
/// <inheritdoc />
public async Task<ICollection<LibraryItem>> GetFromLibrary(string slug, public async Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,
Sort<LibraryItem> sort = default, Sort<LibraryItem> sort = default,

View File

@ -8,14 +8,33 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle libraries.
/// </summary>
public class LibraryRepository : LocalRepository<Library>, ILibraryRepository public class LibraryRepository : LocalRepository<Library>, ILibraryRepository
{ {
/// <summary>
/// Has this instance been disposed and should not handle requests?
/// </summary>
private bool _disposed; private bool _disposed;
/// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <summary>
/// A provider repository to handle externalID creation and deletion
/// </summary>
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
/// <inheritdoc />
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID; protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
/// <summary>
/// Create a new <see cref="LibraryRepository"/> instance.
/// </summary>
/// <param name="database">The database handle</param>
/// <param name="providers">The providere repository</param>
public LibraryRepository(DatabaseContext database, IProviderRepository providers) public LibraryRepository(DatabaseContext database, IProviderRepository providers)
: base(database) : base(database)
{ {
@ -23,6 +42,7 @@ namespace Kyoo.Controllers
_providers = providers; _providers = providers;
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
if (_disposed) if (_disposed)
@ -33,6 +53,7 @@ namespace Kyoo.Controllers
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
/// <inheritdoc />
public override async ValueTask DisposeAsync() public override async ValueTask DisposeAsync()
{ {
if (_disposed) if (_disposed)
@ -42,6 +63,7 @@ namespace Kyoo.Controllers
await _providers.DisposeAsync(); await _providers.DisposeAsync();
} }
/// <inheritdoc />
public override async Task<ICollection<Library>> Search(string query) public override async Task<ICollection<Library>> Search(string query)
{ {
return await _database.Libraries return await _database.Libraries
@ -51,6 +73,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<Library> Create(Library obj) public override async Task<Library> Create(Library obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -61,6 +84,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
protected override async Task Validate(Library resource) protected override async Task Validate(Library resource)
{ {
await base.Validate(resource); await base.Validate(resource);
@ -69,6 +93,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
protected override async Task EditRelations(Library resource, Library changed, bool resetOld) protected override async Task EditRelations(Library resource, Library changed, bool resetOld)
{ {
if (string.IsNullOrEmpty(resource.Slug)) if (string.IsNullOrEmpty(resource.Slug))
@ -86,6 +111,7 @@ namespace Kyoo.Controllers
} }
} }
/// <inheritdoc />
public override async Task Delete(Library obj) public override async Task Delete(Library obj)
{ {
if (obj == null) if (obj == null)

View File

@ -10,15 +10,40 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle people.
/// </summary>
public class PeopleRepository : LocalRepository<People>, IPeopleRepository public class PeopleRepository : LocalRepository<People>, IPeopleRepository
{ {
/// <summary>
/// Has this instance been disposed and should not handle requests?
/// </summary>
private bool _disposed; private bool _disposed;
/// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <summary>
/// A provider repository to handle externalID creation and deletion
/// </summary>
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
/// <summary>
/// A lazy loaded show repository to validate requests from shows.
/// </summary>
private readonly Lazy<IShowRepository> _shows; private readonly Lazy<IShowRepository> _shows;
/// <inheritdoc />
protected override Expression<Func<People, object>> DefaultSort => x => x.Name; protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
public PeopleRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) /// <summary>
/// Create a new <see cref="PeopleRepository"/>
/// </summary>
/// <param name="database">The database handle</param>
/// <param name="providers">A provider repository</param>
/// <param name="services">A service provider to lazy load a show repository</param>
public PeopleRepository(DatabaseContext database,
IProviderRepository providers,
IServiceProvider services)
: base(database) : base(database)
{ {
_database = database; _database = database;
@ -27,6 +52,7 @@ namespace Kyoo.Controllers
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
if (_disposed) if (_disposed)
@ -39,6 +65,7 @@ namespace Kyoo.Controllers
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
/// <inheritdoc />
public override async ValueTask DisposeAsync() public override async ValueTask DisposeAsync()
{ {
if (_disposed) if (_disposed)
@ -50,6 +77,7 @@ namespace Kyoo.Controllers
await _shows.Value.DisposeAsync(); await _shows.Value.DisposeAsync();
} }
/// <inheritdoc />
public override async Task<ICollection<People>> Search(string query) public override async Task<ICollection<People>> Search(string query)
{ {
return await _database.People return await _database.People
@ -59,6 +87,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<People> Create(People obj) public override async Task<People> Create(People obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -68,6 +97,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
protected override async Task Validate(People resource) protected override async Task Validate(People resource)
{ {
await base.Validate(resource); await base.Validate(resource);
@ -85,6 +115,7 @@ namespace Kyoo.Controllers
}); });
} }
/// <inheritdoc />
protected override async Task EditRelations(People resource, People changed, bool resetOld) protected override async Task EditRelations(People resource, People changed, bool resetOld)
{ {
if (changed.Roles != null || resetOld) if (changed.Roles != null || resetOld)
@ -102,6 +133,7 @@ namespace Kyoo.Controllers
await base.EditRelations(resource, changed, resetOld); await base.EditRelations(resource, changed, resetOld);
} }
/// <inheritdoc />
public override async Task Delete(People obj) public override async Task Delete(People obj)
{ {
if (obj == null) if (obj == null)
@ -113,6 +145,7 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
/// <inheritdoc />
public async Task<ICollection<PeopleRole>> GetFromShow(int showID, public async Task<ICollection<PeopleRole>> GetFromShow(int showID,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -133,6 +166,7 @@ namespace Kyoo.Controllers
return people; return people;
} }
/// <inheritdoc />
public async Task<ICollection<PeopleRole>> GetFromShow(string showSlug, public async Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
@ -154,24 +188,26 @@ namespace Kyoo.Controllers
return people; return people;
} }
public async Task<ICollection<PeopleRole>> GetFromPeople(int peopleID, /// <inheritdoc />
public async Task<ICollection<PeopleRole>> GetFromPeople(int id,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,
Pagination limit = default) Pagination limit = default)
{ {
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
.Where(x => x.PeopleID == peopleID) .Where(x => x.PeopleID == id)
.Include(x => x.Show), .Include(x => x.Show),
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id), y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y),
x => x.Show.Title, x => x.Show.Title,
where, where,
sort, sort,
limit); limit);
if (!roles.Any() && await Get(peopleID) == null) if (!roles.Any() && await Get(id) == null)
throw new ItemNotFound(); throw new ItemNotFound();
return roles; return roles;
} }
/// <inheritdoc />
public async Task<ICollection<PeopleRole>> GetFromPeople(string slug, public async Task<ICollection<PeopleRole>> GetFromPeople(string slug,
Expression<Func<PeopleRole, bool>> where = null, Expression<Func<PeopleRole, bool>> where = null,
Sort<PeopleRole> sort = default, Sort<PeopleRole> sort = default,

View File

@ -8,17 +8,31 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle providers.
/// </summary>
public class ProviderRepository : LocalRepository<Provider>, IProviderRepository public class ProviderRepository : LocalRepository<Provider>, IProviderRepository
{ {
/// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <inheritdoc />
protected override Expression<Func<Provider, object>> DefaultSort => x => x.Slug; protected override Expression<Func<Provider, object>> DefaultSort => x => x.Slug;
public ProviderRepository(DatabaseContext database) : base(database) /// <summary>
/// Create a new <see cref="ProviderRepository"/>.
/// </summary>
/// <param name="database">The database handle</param>
public ProviderRepository(DatabaseContext database)
: base(database)
{ {
_database = database; _database = database;
} }
/// <inheritdoc />
public override async Task<ICollection<Provider>> Search(string query) public override async Task<ICollection<Provider>> Search(string query)
{ {
return await _database.Providers return await _database.Providers
@ -28,6 +42,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<Provider> Create(Provider obj) public override async Task<Provider> Create(Provider obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -36,6 +51,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
public override async Task Delete(Provider obj) public override async Task Delete(Provider obj)
{ {
if (obj == null) if (obj == null)
@ -46,6 +62,7 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
/// <inheritdoc />
public Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null, public Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null,
Sort<MetadataID> sort = default, Sort<MetadataID> sort = default,
Pagination limit = default) Pagination limit = default)

View File

@ -8,17 +8,31 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle studios
/// </summary>
public class StudioRepository : LocalRepository<Studio>, IStudioRepository public class StudioRepository : LocalRepository<Studio>, IStudioRepository
{ {
/// <summary>
/// The database handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <inheritdoc />
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name; protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
public StudioRepository(DatabaseContext database) : base(database) /// <summary>
/// Create a new <see cref="StudioRepository"/>.
/// </summary>
/// <param name="database">The database handle</param>
public StudioRepository(DatabaseContext database)
: base(database)
{ {
_database = database; _database = database;
} }
/// <inheritdoc />
public override async Task<ICollection<Studio>> Search(string query) public override async Task<ICollection<Studio>> Search(string query)
{ {
return await _database.Studios return await _database.Studios
@ -28,6 +42,7 @@ namespace Kyoo.Controllers
.ToListAsync(); .ToListAsync();
} }
/// <inheritdoc />
public override async Task<Studio> Create(Studio obj) public override async Task<Studio> Create(Studio obj)
{ {
await base.Create(obj); await base.Create(obj);
@ -36,6 +51,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
public override async Task Delete(Studio obj) public override async Task Delete(Studio obj)
{ {
if (obj == null) if (obj == null)

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -9,40 +10,48 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
/// <summary>
/// A local repository to handle tracks.
/// </summary>
public class TrackRepository : LocalRepository<Track>, ITrackRepository public class TrackRepository : LocalRepository<Track>, ITrackRepository
{ {
private bool _disposed; /// <summary>
/// The databse handle
/// </summary>
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
/// <inheritdoc />
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex; protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
public TrackRepository(DatabaseContext database) : base(database) /// <summary>
/// Create a new <see cref="TrackRepository"/>.
/// </summary>
/// <param name="database">The datatabse handle</param>
public TrackRepository(DatabaseContext database)
: base(database)
{ {
_database = database; _database = database;
} }
public override void Dispose()
{
if (_disposed)
return;
_disposed = true;
_database.Dispose();
}
public override async ValueTask DisposeAsync()
{
if (_disposed)
return;
_disposed = true;
await _database.DisposeAsync();
}
/// <inheritdoc />
public override Task<Track> Get(string slug) public override Task<Track> Get(string slug)
{ {
return Get(slug, StreamType.Unknown); return Get(slug, StreamType.Unknown);
} }
public Task<Track> Get(string slug, StreamType type) /// <inheritdoc />
public async Task<Track> Get(string slug, StreamType type)
{
Track ret = await GetOrDefault(slug, type);
if (ret == null)
throw new ItemNotFound($"No track found with the slug {slug} and the type {type}.");
return ret;
}
/// <inheritdoc />
public Task<Track> GetOrDefault(string slug, StreamType type)
{ {
Match match = Regex.Match(slug, Match match = Regex.Match(slug,
@"(?<show>.*)-s(?<season>\d+)e(?<episode>\d+)(\.(?<type>\w*))?\.(?<language>.{0,3})(?<forced>-forced)?(\..*)?"); @"(?<show>.*)-s(?<season>\d+)e(?<episode>\d+)(\.(?<type>\w*))?\.(?<language>.{0,3})(?<forced>-forced)?(\..*)?");
@ -65,27 +74,23 @@ namespace Kyoo.Controllers
if (match.Groups["type"].Success) if (match.Groups["type"].Success)
type = Enum.Parse<StreamType>(match.Groups["type"].Value, true); type = Enum.Parse<StreamType>(match.Groups["type"].Value, true);
if (type == StreamType.Unknown) IQueryable<Track> query = _database.Tracks.Where(x => x.Episode.Show.Slug == showSlug
{ && x.Episode.SeasonNumber == seasonNumber
return _database.Tracks.FirstOrDefaultAsync(x => x.Episode.Show.Slug == showSlug && x.Episode.EpisodeNumber == episodeNumber
&& x.Episode.SeasonNumber == seasonNumber && x.Language == language
&& x.Episode.EpisodeNumber == episodeNumber && x.IsForced == forced);
&& x.Language == language if (type != StreamType.Unknown)
&& x.IsForced == forced); return query.FirstOrDefaultAsync(x => x.Type == type);
} return query.FirstOrDefaultAsync();
return _database.Tracks.FirstOrDefaultAsync(x => x.Episode.Show.Slug == showSlug
&& x.Episode.SeasonNumber == seasonNumber
&& x.Episode.EpisodeNumber == episodeNumber
&& x.Type == type
&& x.Language == language
&& x.IsForced == forced);
} }
/// <inheritdoc />
public override Task<ICollection<Track>> Search(string query) public override Task<ICollection<Track>> Search(string query)
{ {
throw new InvalidOperationException("Tracks do not support the search method."); throw new InvalidOperationException("Tracks do not support the search method.");
} }
/// <inheritdoc />
public override async Task<Track> Create(Track obj) public override async Task<Track> Create(Track obj)
{ {
if (obj.EpisodeID <= 0) if (obj.EpisodeID <= 0)
@ -107,6 +112,7 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
/// <inheritdoc />
public override async Task Delete(Track obj) public override async Task Delete(Track obj)
{ {
if (obj == null) if (obj == null)