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