mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Reworking the local repository abstract class to handle an internal class
This commit is contained in:
parent
8f6578dfb9
commit
76e28d6ac2
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.CommonApi;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
@ -12,81 +13,52 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public abstract class LocalRepository<T, TInternal> : IRepository<T>
|
||||
public abstract class LocalRepository<T>
|
||||
where T : class, IResource
|
||||
where TInternal : class, T
|
||||
{
|
||||
private readonly DbContext _database;
|
||||
|
||||
protected abstract Expression<Func<TInternal, object>> DefaultSort { get; }
|
||||
|
||||
protected readonly DbContext Database;
|
||||
|
||||
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
||||
|
||||
|
||||
protected LocalRepository(DbContext database)
|
||||
{
|
||||
_database = database;
|
||||
Database = database;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
Database.Dispose();
|
||||
}
|
||||
|
||||
public virtual ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public Task<T> Get(int id)
|
||||
{
|
||||
return _Get(id).Cast<T>();
|
||||
return Database.DisposeAsync();
|
||||
}
|
||||
|
||||
public Task<T> Get(string slug)
|
||||
public virtual Task<T> Get(int id)
|
||||
{
|
||||
return _Get(slug).Cast<T>();
|
||||
}
|
||||
|
||||
protected virtual Task<TInternal> _Get(int id)
|
||||
{
|
||||
return _database.Set<TInternal>().FirstOrDefaultAsync(x => x.ID == id);
|
||||
return Database.Set<T>().FirstOrDefaultAsync(x => x.ID == id);
|
||||
}
|
||||
|
||||
protected virtual Task<TInternal> _Get(string slug)
|
||||
public virtual Task<T> Get(string slug)
|
||||
{
|
||||
return _database.Set<TInternal>().FirstOrDefaultAsync(x => x.Slug == slug);
|
||||
return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug);
|
||||
}
|
||||
|
||||
public abstract Task<ICollection<T>> Search(string query);
|
||||
|
||||
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
return ApplyFilters(_database.Set<TInternal>(), where, sort, limit);
|
||||
return ApplyFilters(Database.Set<T>(), where, sort, limit);
|
||||
}
|
||||
|
||||
protected async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
|
||||
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
|
||||
Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<TInternal> items = await ApplyFilters(query,
|
||||
_Get,
|
||||
DefaultSort,
|
||||
where.Convert<Func<TInternal, bool>>(),
|
||||
sort.To<TInternal>(),
|
||||
limit);
|
||||
|
||||
return items.ToList<T>();
|
||||
}
|
||||
|
||||
protected async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
|
||||
Expression<Func<TInternal, bool>> where = null,
|
||||
Sort<TInternal> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<TInternal> items = await ApplyFilters(query, _Get, DefaultSort, where, sort, limit);
|
||||
return items.ToList<T>();
|
||||
return ApplyFilters(query, Get, DefaultSort, where, sort, limit);
|
||||
}
|
||||
|
||||
protected async Task<ICollection<TValue>> ApplyFilters<TValue>(IQueryable<TValue> query,
|
||||
@ -123,7 +95,7 @@ namespace Kyoo.Controllers
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public abstract Task<T> Create(T obj);
|
||||
|
||||
public virtual async Task<T> CreateIfNotExists(T obj)
|
||||
@ -146,13 +118,13 @@ namespace Kyoo.Controllers
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<T> Edit(T edited, bool resetOld)
|
||||
{
|
||||
if (edited == null)
|
||||
throw new ArgumentNullException(nameof(edited));
|
||||
|
||||
TInternal old = (TInternal)await Get(edited.Slug);
|
||||
T old = await Get(edited.Slug);
|
||||
|
||||
if (old == null)
|
||||
throw new ItemNotFound($"No ressource found with the slug {edited.Slug}.");
|
||||
@ -161,25 +133,25 @@ namespace Kyoo.Controllers
|
||||
Utility.Nullify(old);
|
||||
Utility.Merge(old, edited);
|
||||
await Validate(old);
|
||||
await _database.SaveChangesAsync();
|
||||
await Database.SaveChangesAsync();
|
||||
return old;
|
||||
}
|
||||
|
||||
protected virtual Task Validate(TInternal ressource)
|
||||
|
||||
protected virtual Task Validate(T ressource)
|
||||
{
|
||||
foreach (PropertyInfo property in typeof(TInternal).GetProperties()
|
||||
foreach (PropertyInfo property in typeof(T).GetProperties()
|
||||
.Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType)
|
||||
&& !typeof(string).IsAssignableFrom(x.PropertyType)))
|
||||
{
|
||||
object value = property.GetValue(ressource);
|
||||
if (value is ICollection || value == null)
|
||||
continue;
|
||||
value = Utility.RunGenericMethod(typeof(Enumerable), "ToList", Utility.GetEnumerableType((IEnumerable)value), new [] { value});
|
||||
value = Utility.RunGenericMethod(typeof(Enumerable), "ToList", Utility.GetEnumerableType((IEnumerable)value), value);
|
||||
property.SetValue(ressource, value);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task Delete(int id)
|
||||
{
|
||||
T ressource = await Get(id);
|
||||
@ -212,4 +184,83 @@ namespace Kyoo.Controllers
|
||||
await Delete(slug);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class LocalRepository<T, TInternal> : LocalRepository<TInternal>, IRepository<T>
|
||||
where T : class, IResource
|
||||
where TInternal : class, T, new()
|
||||
{
|
||||
protected LocalRepository(DbContext database) : base(database) { }
|
||||
|
||||
public new Task<T> Get(int id)
|
||||
{
|
||||
return base.Get(id).Cast<T>();
|
||||
}
|
||||
|
||||
public new Task<T> Get(string slug)
|
||||
{
|
||||
return base.Get(slug).Cast<T>();
|
||||
}
|
||||
|
||||
public abstract Task<ICollection<T>> Search(string query);
|
||||
|
||||
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
return ApplyFilters(Database.Set<TInternal>(), where, sort, limit);
|
||||
}
|
||||
|
||||
protected virtual async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
|
||||
Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<TInternal> items = await ApplyFilters(query,
|
||||
base.Get,
|
||||
DefaultSort,
|
||||
where.Convert<Func<TInternal, bool>>(),
|
||||
sort.To<TInternal>(),
|
||||
limit);
|
||||
|
||||
return items.ToList<T>();
|
||||
}
|
||||
|
||||
public abstract override Task<TInternal> Create(TInternal obj);
|
||||
|
||||
Task<T> IRepository<T>.Create(T item)
|
||||
{
|
||||
TInternal obj = new TInternal();
|
||||
Utility.Assign(obj, item);
|
||||
return Create(obj).Cast<T>();
|
||||
}
|
||||
|
||||
Task<T> IRepository<T>.CreateIfNotExists(T item)
|
||||
{
|
||||
TInternal obj = new TInternal();
|
||||
Utility.Assign(obj, item);
|
||||
return CreateIfNotExists(obj).Cast<T>();
|
||||
}
|
||||
|
||||
public Task<T> Edit(T edited, bool resetOld)
|
||||
{
|
||||
TInternal obj = new TInternal();
|
||||
Utility.Assign(obj, edited);
|
||||
return base.Edit(obj, resetOld).Cast<T>();
|
||||
}
|
||||
|
||||
public abstract override Task Delete([NotNull] TInternal obj);
|
||||
|
||||
Task IRepository<T>.Delete(T obj)
|
||||
{
|
||||
TInternal item = new TInternal();
|
||||
Utility.Assign(item, obj);
|
||||
return Delete(item);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteRange(IEnumerable<T> objs)
|
||||
{
|
||||
foreach (T obj in objs)
|
||||
await ((IRepository<T>)this).Delete(obj);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@ namespace Kyoo.Controllers
|
||||
.ToListAsync<Collection>();
|
||||
}
|
||||
|
||||
public override async Task<Collection> Create(Collection obj)
|
||||
public override async Task<CollectionDE> Create(CollectionDE obj)
|
||||
{
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
@ -60,11 +60,10 @@ namespace Kyoo.Controllers
|
||||
return obj;
|
||||
}
|
||||
|
||||
public override async Task Delete(Collection item)
|
||||
public override async Task Delete(CollectionDE obj)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
CollectionDE obj = new CollectionDE(item);
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
_database.Entry(obj).State = EntityState.Deleted;
|
||||
if (obj.Links != null)
|
||||
|
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public class EpisodeRepository : LocalRepository<Episode, Episode>, IEpisodeRepository
|
||||
public class EpisodeRepository : LocalRepository<Episode>, IEpisodeRepository
|
||||
{
|
||||
private readonly DatabaseContext _database;
|
||||
private readonly IProviderRepository _providers;
|
||||
@ -87,7 +87,7 @@ namespace Kyoo.Controllers
|
||||
&& x.AbsoluteNumber == absoluteNumber);
|
||||
}
|
||||
|
||||
public override async Task<ICollection<Episode>> Search(string query)
|
||||
public async Task<ICollection<Episode>> Search(string query)
|
||||
{
|
||||
return await _database.Episodes
|
||||
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%"))
|
||||
@ -133,7 +133,7 @@ namespace Kyoo.Controllers
|
||||
Sort<Episode> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<Episode> episodes = await ApplyFilters<Episode>(_database.Episodes.Where(x => x.ShowID == showID),
|
||||
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.ShowID == showID),
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
|
Loading…
x
Reference in New Issue
Block a user