mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-11-02 18:47:11 -05:00 
			
		
		
		
	Implement a base repository for dapper
This commit is contained in:
		
							parent
							
								
									179b79c926
								
							
						
					
					
						commit
						ba37786038
					
				@ -174,19 +174,19 @@ namespace Kyoo.Abstractions.Models
 | 
				
			|||||||
			// language=PostgreSQL
 | 
								// language=PostgreSQL
 | 
				
			||||||
			Sql = """
 | 
								Sql = """
 | 
				
			||||||
				select
 | 
									select
 | 
				
			||||||
					"pe".* -- Episode as pe
 | 
										pe.* -- Episode as pe
 | 
				
			||||||
				from
 | 
									from
 | 
				
			||||||
					episodes as "pe"
 | 
										episodes as "pe"
 | 
				
			||||||
				where
 | 
									where
 | 
				
			||||||
					"pe".show_id = "this".show_id
 | 
										pe.show_id = "this".show_id
 | 
				
			||||||
					and ("pe".absolute_number < "this".absolute_number
 | 
										and (pe.absolute_number < "this".absolute_number
 | 
				
			||||||
						or "pe".season_number < "this".season_number
 | 
											or pe.season_number < "this".season_number
 | 
				
			||||||
						or ("pe".season_number = "this".season_number
 | 
											or (pe.season_number = "this".season_number
 | 
				
			||||||
							and e.episode_number < "this".episode_number))
 | 
												and e.episode_number < "this".episode_number))
 | 
				
			||||||
				order by
 | 
									order by
 | 
				
			||||||
					"pe".absolute_number desc,
 | 
										pe.absolute_number desc,
 | 
				
			||||||
					"pe".season_number desc,
 | 
										pe.season_number desc,
 | 
				
			||||||
					"pe".episode_number desc
 | 
										pe.episode_number desc
 | 
				
			||||||
				limit 1
 | 
									limit 1
 | 
				
			||||||
			"""
 | 
								"""
 | 
				
			||||||
		)]
 | 
							)]
 | 
				
			||||||
@ -210,19 +210,19 @@ namespace Kyoo.Abstractions.Models
 | 
				
			|||||||
			// language=PostgreSQL
 | 
								// language=PostgreSQL
 | 
				
			||||||
			Sql = """
 | 
								Sql = """
 | 
				
			||||||
				select
 | 
									select
 | 
				
			||||||
					"ne".* -- Episode as ne
 | 
										ne.* -- Episode as ne
 | 
				
			||||||
				from
 | 
									from
 | 
				
			||||||
					episodes as "ne"
 | 
										episodes as "ne"
 | 
				
			||||||
				where
 | 
									where
 | 
				
			||||||
					"ne".show_id = "this".show_id
 | 
										ne.show_id = "this".show_id
 | 
				
			||||||
					and ("ne".absolute_number > "this".absolute_number
 | 
										and (ne.absolute_number > "this".absolute_number
 | 
				
			||||||
						or "ne".season_number > "this".season_number
 | 
											or ne.season_number > "this".season_number
 | 
				
			||||||
						or ("ne".season_number = "this".season_number
 | 
											or (ne.season_number = "this".season_number
 | 
				
			||||||
							and e.episode_number > "this".episode_number))
 | 
												and e.episode_number > "this".episode_number))
 | 
				
			||||||
				order by
 | 
									order by
 | 
				
			||||||
					"ne".absolute_number,
 | 
										ne.absolute_number,
 | 
				
			||||||
					"ne".season_number,
 | 
										ne.season_number,
 | 
				
			||||||
					"ne".episode_number
 | 
										ne.episode_number
 | 
				
			||||||
				limit 1
 | 
									limit 1
 | 
				
			||||||
			"""
 | 
								"""
 | 
				
			||||||
		)]
 | 
							)]
 | 
				
			||||||
 | 
				
			|||||||
@ -158,7 +158,7 @@ namespace Kyoo.Abstractions.Models
 | 
				
			|||||||
			// language=PostgreSQL
 | 
								// language=PostgreSQL
 | 
				
			||||||
			Sql = """
 | 
								Sql = """
 | 
				
			||||||
				select
 | 
									select
 | 
				
			||||||
					"fe".* -- Episode as fe
 | 
										fe.* -- Episode as fe
 | 
				
			||||||
				from (
 | 
									from (
 | 
				
			||||||
					select
 | 
										select
 | 
				
			||||||
						e.*,
 | 
											e.*,
 | 
				
			||||||
@ -166,7 +166,7 @@ namespace Kyoo.Abstractions.Models
 | 
				
			|||||||
					from
 | 
										from
 | 
				
			||||||
						episodes as e) as "fe"
 | 
											episodes as e) as "fe"
 | 
				
			||||||
				where
 | 
									where
 | 
				
			||||||
					"fe".number <= 1
 | 
										fe.number <= 1
 | 
				
			||||||
			""",
 | 
								""",
 | 
				
			||||||
			On = "show_id = \"this\".id"
 | 
								On = "show_id = \"this\".id"
 | 
				
			||||||
		)]
 | 
							)]
 | 
				
			||||||
 | 
				
			|||||||
@ -48,11 +48,9 @@ public static class DapperHelper
 | 
				
			|||||||
		return $"coalesce({string.Join(", ", keys)})";
 | 
							return $"coalesce({string.Join(", ", keys)})";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static string ProcessSort<T>(Sort<T>? sort, bool reverse, Dictionary<string, Type> config, bool recurse = false)
 | 
						public static string ProcessSort<T>(Sort<T> sort, bool reverse, Dictionary<string, Type> config, bool recurse = false)
 | 
				
			||||||
		where T : IQuery
 | 
							where T : IQuery
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		sort ??= new Sort<T>.Default();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		string ret = sort switch
 | 
							string ret = sort switch
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Sort<T>.Default(var value) => ProcessSort(value, reverse, config, true),
 | 
								Sort<T>.Default(var value) => ProcessSort(value, reverse, config, true),
 | 
				
			||||||
@ -78,7 +76,7 @@ public static class DapperHelper
 | 
				
			|||||||
		Dictionary<string, Type> retConfig = new();
 | 
							Dictionary<string, Type> retConfig = new();
 | 
				
			||||||
		StringBuilder join = new();
 | 
							StringBuilder join = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		foreach (Include<T>.Metadata metadata in include.Metadatas)
 | 
							foreach (Include.Metadata metadata in include.Metadatas)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			relation++;
 | 
								relation++;
 | 
				
			||||||
			switch (metadata)
 | 
								switch (metadata)
 | 
				
			||||||
@ -103,7 +101,7 @@ public static class DapperHelper
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		T Map(T item, IEnumerable<object> relations)
 | 
							T Map(T item, IEnumerable<object?> relations)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			foreach ((string name, object? value) in include.Fields.Zip(relations))
 | 
								foreach ((string name, object? value) in include.Fields.Zip(relations))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@ -177,7 +175,7 @@ public static class DapperHelper
 | 
				
			|||||||
		this IDbConnection db,
 | 
							this IDbConnection db,
 | 
				
			||||||
		FormattableString command,
 | 
							FormattableString command,
 | 
				
			||||||
		Dictionary<string, Type> config,
 | 
							Dictionary<string, Type> config,
 | 
				
			||||||
		Func<object?[], T> mapper,
 | 
							Func<List<object?>, T> mapper,
 | 
				
			||||||
		Func<int, Task<T>> get,
 | 
							Func<int, Task<T>> get,
 | 
				
			||||||
		Include<T>? include,
 | 
							Include<T>? include,
 | 
				
			||||||
		Filter<T>? filter,
 | 
							Filter<T>? filter,
 | 
				
			||||||
@ -205,6 +203,7 @@ public static class DapperHelper
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		if (filter != null)
 | 
							if (filter != null)
 | 
				
			||||||
			query += ProcessFilter(filter, config);
 | 
								query += ProcessFilter(filter, config);
 | 
				
			||||||
 | 
							if (sort != null)
 | 
				
			||||||
			query += $"\norder by {ProcessSort(sort, limit.Reverse, config):raw}";
 | 
								query += $"\norder by {ProcessSort(sort, limit.Reverse, config):raw}";
 | 
				
			||||||
		query += $"\nlimit {limit.Limit}";
 | 
							query += $"\nlimit {limit.Limit}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -260,7 +259,7 @@ public static class DapperHelper
 | 
				
			|||||||
					thumbs.Thumbnail = items[++i] as Image;
 | 
										thumbs.Thumbnail = items[++i] as Image;
 | 
				
			||||||
					thumbs.Logo = items[++i] as Image;
 | 
										thumbs.Logo = items[++i] as Image;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return mapIncludes(mapper(nItems.ToArray()), nItems.Skip(config.Count));
 | 
									return mapIncludes(mapper(nItems), nItems.Skip(config.Count));
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			ParametersDictionary.LoadFrom(cmd),
 | 
								ParametersDictionary.LoadFrom(cmd),
 | 
				
			||||||
			splitOn: string.Join(',', types.Select(x => x == typeof(Image) ? "source" : "id"))
 | 
								splitOn: string.Join(',', types.Select(x => x == typeof(Image) ? "source" : "id"))
 | 
				
			||||||
@ -269,4 +268,40 @@ public static class DapperHelper
 | 
				
			|||||||
			data = data.Reverse();
 | 
								data = data.Reverse();
 | 
				
			||||||
		return data.ToList();
 | 
							return data.ToList();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static async Task<T?> QuerySingle<T>(
 | 
				
			||||||
 | 
							this IDbConnection db,
 | 
				
			||||||
 | 
							FormattableString command,
 | 
				
			||||||
 | 
							Dictionary<string, Type> config,
 | 
				
			||||||
 | 
							Func<List<object?>, T> mapper,
 | 
				
			||||||
 | 
							Include<T>? include,
 | 
				
			||||||
 | 
							Filter<T>? filter,
 | 
				
			||||||
 | 
							Sort<T>? sort = null)
 | 
				
			||||||
 | 
							where T : class, IResource, IQuery
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ICollection<T> ret = await db.Query<T>(command, config, mapper, null!, include, filter, sort, new Pagination(1));
 | 
				
			||||||
 | 
							return ret.FirstOrDefault();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static async Task<int> Count<T>(
 | 
				
			||||||
 | 
							this IDbConnection db,
 | 
				
			||||||
 | 
							FormattableString command,
 | 
				
			||||||
 | 
							Dictionary<string, Type> config,
 | 
				
			||||||
 | 
							Filter<T>? filter)
 | 
				
			||||||
 | 
							where T : class, IResource
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							InterpolatedSql.Dapper.SqlBuilders.SqlBuilder query = new(db, command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (filter != null)
 | 
				
			||||||
 | 
								query += ProcessFilter(filter, config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							IDapperSqlCommand cmd = query.Build();
 | 
				
			||||||
 | 
							// language=postgreSQL
 | 
				
			||||||
 | 
							string sql = $"select count(*) from ({cmd.Sql})";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return await db.ExecuteAsync(
 | 
				
			||||||
 | 
								sql,
 | 
				
			||||||
 | 
								ParametersDictionary.LoadFrom(cmd)
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,87 +18,156 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.ComponentModel.DataAnnotations.Schema;
 | 
					using System.Data.Common;
 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Reflection;
 | 
					 | 
				
			||||||
using System.Runtime.CompilerServices;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Kyoo.Abstractions.Controllers;
 | 
					using Kyoo.Abstractions.Controllers;
 | 
				
			||||||
using Kyoo.Abstractions.Models;
 | 
					using Kyoo.Abstractions.Models;
 | 
				
			||||||
 | 
					using Kyoo.Abstractions.Models.Exceptions;
 | 
				
			||||||
using Kyoo.Abstractions.Models.Utils;
 | 
					using Kyoo.Abstractions.Models.Utils;
 | 
				
			||||||
using Kyoo.Utils;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Kyoo.Core.Controllers;
 | 
					namespace Kyoo.Core.Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class DapperRepository<T> : IRepository<T>
 | 
					public abstract class DapperRepository<T> : IRepository<T>
 | 
				
			||||||
	where T : class, IResource, IQuery
 | 
						where T : class, IResource, IQuery
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public Type RepositoryType => typeof(T);
 | 
						public Type RepositoryType => typeof(T);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected abstract FormattableString Sql { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected abstract Dictionary<string, Type> Config { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected abstract T Mapper(List<object?> items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected DbConnection Database { get; init; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public DapperRepository(DbConnection database)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Database = database;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc/>
 | 
				
			||||||
 | 
						public virtual async Task<T> Get(int id, Include<T>? include = default)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							T? ret = await GetOrDefault(id, include);
 | 
				
			||||||
 | 
							if (ret == null)
 | 
				
			||||||
 | 
								throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc/>
 | 
				
			||||||
 | 
						public virtual async Task<T> Get(string slug, Include<T>? include = default)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							T? ret = await GetOrDefault(slug, include);
 | 
				
			||||||
 | 
							if (ret == null)
 | 
				
			||||||
 | 
								throw new ItemNotFoundException($"No {typeof(T).Name} found with the slug {slug}");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc/>
 | 
				
			||||||
 | 
						public virtual async Task<T> Get(Filter<T> filter,
 | 
				
			||||||
 | 
							Include<T>? include = default)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							T? ret = await GetOrDefault(filter, include: include);
 | 
				
			||||||
 | 
							if (ret == null)
 | 
				
			||||||
 | 
								throw new ItemNotFoundException($"No {typeof(T).Name} found with the given predicate.");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<ICollection<T>> FromIds(IList<int> ids, Include<T>? include = null)
 | 
						public Task<ICollection<T>> FromIds(IList<int> ids, Include<T>? include = null)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							throw new NotImplementedException();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public Task<T> Get(int id, Include<T>? include = null)
 | 
						/// <inheritdoc />
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Task<T> Get(string slug, Include<T>? include = null)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Task<T> Get(Filter<T> filter, Include<T>? include = null)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Task<ICollection<T>> GetAll(Filter<T>? filter = null, Sort<T>? sort = null, Include<T>? include = null, Pagination? limit = null)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Task<int> GetCount(Filter<T>? filter = null)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Task<T?> GetOrDefault(int id, Include<T>? include = null)
 | 
						public Task<T?> GetOrDefault(int id, Include<T>? include = null)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return Database.QuerySingle<T>(
 | 
				
			||||||
 | 
								Sql,
 | 
				
			||||||
 | 
								Config,
 | 
				
			||||||
 | 
								Mapper,
 | 
				
			||||||
 | 
								include,
 | 
				
			||||||
 | 
								new Filter<T>.Eq(nameof(IResource.Id), id)
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T?> GetOrDefault(string slug, Include<T>? include = null)
 | 
						public Task<T?> GetOrDefault(string slug, Include<T>? include = null)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return Database.QuerySingle<T>(
 | 
				
			||||||
 | 
								Sql,
 | 
				
			||||||
 | 
								Config,
 | 
				
			||||||
 | 
								Mapper,
 | 
				
			||||||
 | 
								include,
 | 
				
			||||||
 | 
								new Filter<T>.Eq(nameof(IResource.Slug), slug)
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T?> GetOrDefault(Filter<T>? filter, Include<T>? include = null, Sort<T>? sortBy = null)
 | 
						public Task<T?> GetOrDefault(Filter<T>? filter, Include<T>? include = null, Sort<T>? sortBy = null)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return Database.QuerySingle<T>(
 | 
				
			||||||
 | 
								Sql,
 | 
				
			||||||
 | 
								Config,
 | 
				
			||||||
 | 
								Mapper,
 | 
				
			||||||
 | 
								include,
 | 
				
			||||||
 | 
								filter,
 | 
				
			||||||
 | 
								sortBy
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public Task<ICollection<T>> Search(string query, Include<T>? include = null)
 | 
						/// <inheritdoc />
 | 
				
			||||||
 | 
						public Task<ICollection<T>> GetAll(Filter<T>? filter = default,
 | 
				
			||||||
 | 
							Sort<T>? sort = default,
 | 
				
			||||||
 | 
							Include<T>? include = default,
 | 
				
			||||||
 | 
							Pagination? limit = default)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return Database.Query<T>(
 | 
				
			||||||
 | 
								Sql,
 | 
				
			||||||
 | 
								Config,
 | 
				
			||||||
 | 
								Mapper,
 | 
				
			||||||
 | 
								(id) => Get(id),
 | 
				
			||||||
 | 
								include,
 | 
				
			||||||
 | 
								filter,
 | 
				
			||||||
 | 
								sort ?? new Sort<T>.Default(),
 | 
				
			||||||
 | 
								limit ?? new()
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
 | 
						public Task<int> GetCount(Filter<T>? filter = null)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Database.Count(
 | 
				
			||||||
 | 
								Sql,
 | 
				
			||||||
 | 
								Config,
 | 
				
			||||||
 | 
								filter
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
 | 
						public Task<ICollection<T>> Search(string query, Include<T>? include = null) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T> Create(T obj) => throw new NotImplementedException();
 | 
						public Task<T> Create(T obj) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T> CreateIfNotExists(T obj) => throw new NotImplementedException();
 | 
						public Task<T> CreateIfNotExists(T obj) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task Delete(int id) => throw new NotImplementedException();
 | 
						public Task Delete(int id) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task Delete(string slug) => throw new NotImplementedException();
 | 
						public Task Delete(string slug) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task Delete(T obj) => throw new NotImplementedException();
 | 
						public Task Delete(T obj) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task DeleteAll(Filter<T> filter) => throw new NotImplementedException();
 | 
						public Task DeleteAll(Filter<T> filter) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T> Edit(T edited) => throw new NotImplementedException();
 | 
						public Task<T> Edit(T edited) => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <inheritdoc />
 | 
				
			||||||
	public Task<T> Patch(int id, Func<T, Task<bool>> patch) => throw new NotImplementedException();
 | 
						public Task<T> Patch(int id, Func<T, Task<bool>> patch) => throw new NotImplementedException();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,91 +18,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.ComponentModel.DataAnnotations.Schema;
 | 
					 | 
				
			||||||
using System.Data.Common;
 | 
					using System.Data.Common;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Linq.Expressions;
 | 
					using System.Linq.Expressions;
 | 
				
			||||||
using System.Reflection;
 | 
					 | 
				
			||||||
using System.Runtime.CompilerServices;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Dapper;
 | 
					 | 
				
			||||||
using InterpolatedSql.Dapper;
 | 
					 | 
				
			||||||
using Kyoo.Abstractions.Controllers;
 | 
					using Kyoo.Abstractions.Controllers;
 | 
				
			||||||
using Kyoo.Abstractions.Models;
 | 
					using Kyoo.Abstractions.Models;
 | 
				
			||||||
using Kyoo.Abstractions.Models.Exceptions;
 | 
					 | 
				
			||||||
using Kyoo.Abstractions.Models.Utils;
 | 
					using Kyoo.Abstractions.Models.Utils;
 | 
				
			||||||
using Kyoo.Utils;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Kyoo.Core.Controllers
 | 
					namespace Kyoo.Core.Controllers
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/// <summary>
 | 
						/// <summary>
 | 
				
			||||||
	/// A local repository to handle library items.
 | 
						/// A local repository to handle library items.
 | 
				
			||||||
	/// </summary>
 | 
						/// </summary>
 | 
				
			||||||
	public class LibraryItemRepository : IRepository<ILibraryItem>
 | 
						public class LibraryItemRepository : DapperRepository<ILibraryItem>
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		private readonly DbConnection _database;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Type RepositoryType => typeof(ILibraryItem);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public LibraryItemRepository(DbConnection database)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_database = database;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc/>
 | 
					 | 
				
			||||||
		public virtual async Task<ILibraryItem> Get(int id, Include<ILibraryItem>? include = default)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ILibraryItem? ret = await GetOrDefault(id, include);
 | 
					 | 
				
			||||||
			if (ret == null)
 | 
					 | 
				
			||||||
				throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the id {id}");
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc/>
 | 
					 | 
				
			||||||
		public virtual async Task<ILibraryItem> Get(string slug, Include<ILibraryItem>? include = default)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ILibraryItem? ret = await GetOrDefault(slug, include);
 | 
					 | 
				
			||||||
			if (ret == null)
 | 
					 | 
				
			||||||
				throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the slug {slug}");
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc/>
 | 
					 | 
				
			||||||
		public virtual async Task<ILibraryItem> Get(Filter<ILibraryItem> filter,
 | 
					 | 
				
			||||||
			Include<ILibraryItem>? include = default)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ILibraryItem? ret = await GetOrDefault(filter, include: include);
 | 
					 | 
				
			||||||
			if (ret == null)
 | 
					 | 
				
			||||||
				throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the given predicate.");
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task<ILibraryItem?> GetOrDefault(int id, Include<ILibraryItem>? include = null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task<ILibraryItem?> GetOrDefault(string slug, Include<ILibraryItem>? include = null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task<ILibraryItem?> GetOrDefault(Filter<ILibraryItem>? filter, Include<ILibraryItem>? include = default,
 | 
					 | 
				
			||||||
			Sort<ILibraryItem>? sortBy = default)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task<ICollection<ILibraryItem>> GetAll(
 | 
					 | 
				
			||||||
			Filter<ILibraryItem>? filter = null,
 | 
					 | 
				
			||||||
			Sort<ILibraryItem>? sort = default,
 | 
					 | 
				
			||||||
			Include<ILibraryItem>? include = default,
 | 
					 | 
				
			||||||
			Pagination? limit = default)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// language=PostgreSQL
 | 
							// language=PostgreSQL
 | 
				
			||||||
			FormattableString sql = $"""
 | 
							protected override FormattableString Sql => $"""
 | 
				
			||||||
			select
 | 
								select
 | 
				
			||||||
				s.*, -- Show as s
 | 
									s.*, -- Show as s
 | 
				
			||||||
				m.*,
 | 
									m.*,
 | 
				
			||||||
@ -122,13 +54,14 @@ namespace Kyoo.Core.Controllers
 | 
				
			|||||||
						collections) as c on false
 | 
											collections) as c on false
 | 
				
			||||||
		""";
 | 
							""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return _database.Query<ILibraryItem>(sql, new()
 | 
							protected override Dictionary<string, Type> Config => new()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			{ "s", typeof(Show) },
 | 
								{ "s", typeof(Show) },
 | 
				
			||||||
			{ "m", typeof(Movie) },
 | 
								{ "m", typeof(Movie) },
 | 
				
			||||||
			{ "c", typeof(Collection) }
 | 
								{ "c", typeof(Collection) }
 | 
				
			||||||
				},
 | 
							};
 | 
				
			||||||
				items =>
 | 
					
 | 
				
			||||||
 | 
							protected override ILibraryItem Mapper(List<object?> items)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (items[0] is Show show && show.Id != 0)
 | 
								if (items[0] is Show show && show.Id != 0)
 | 
				
			||||||
				return show;
 | 
									return show;
 | 
				
			||||||
@ -137,38 +70,11 @@ namespace Kyoo.Core.Controllers
 | 
				
			|||||||
			if (items[2] is Collection collection && collection.Id != 0)
 | 
								if (items[2] is Collection collection && collection.Id != 0)
 | 
				
			||||||
				return collection;
 | 
									return collection;
 | 
				
			||||||
			throw new InvalidDataException();
 | 
								throw new InvalidDataException();
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				(id) => Get(id),
 | 
					 | 
				
			||||||
				include, filter, sort, limit ?? new()
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Task<int> GetCount(Filter<ILibraryItem>? filter = null)
 | 
							public LibraryItemRepository(DbConnection database)
 | 
				
			||||||
		{
 | 
								: base(database)
 | 
				
			||||||
			throw new NotImplementedException();
 | 
							{ }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task<ICollection<ILibraryItem>> FromIds(IList<int> ids, Include<ILibraryItem>? include = null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Task DeleteAll(Filter<ILibraryItem> filter)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public async Task<ICollection<ILibraryItem>> Search(string query, Include<ILibraryItem>? include = default)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotImplementedException();
 | 
					 | 
				
			||||||
			// return await Sort(
 | 
					 | 
				
			||||||
			// 		AddIncludes(_database.LibraryItems, include)
 | 
					 | 
				
			||||||
			// 			.Where(_database.Like<LibraryItem>(x => x.Name, $"%{query}%"))
 | 
					 | 
				
			||||||
			// 	)
 | 
					 | 
				
			||||||
			// 	.Take(20)
 | 
					 | 
				
			||||||
			// 	.ToListAsync();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public async Task<ICollection<ILibraryItem>> GetAllOfCollection(
 | 
							public async Task<ICollection<ILibraryItem>> GetAllOfCollection(
 | 
				
			||||||
			Expression<Func<Collection, bool>> selector,
 | 
								Expression<Func<Collection, bool>> selector,
 | 
				
			||||||
@ -193,33 +99,5 @@ namespace Kyoo.Core.Controllers
 | 
				
			|||||||
			// 	limit,
 | 
								// 	limit,
 | 
				
			||||||
			// 	include);
 | 
								// 	include);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task<ILibraryItem> Create(ILibraryItem obj)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task<ILibraryItem> CreateIfNotExists(ILibraryItem obj)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task<ILibraryItem> Edit(ILibraryItem edited)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task<ILibraryItem> Patch(int id, Func<ILibraryItem, Task<bool>> patch)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task Delete(int id)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task Delete(string slug)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <inheritdoc />
 | 
					 | 
				
			||||||
		public Task Delete(ILibraryItem obj)
 | 
					 | 
				
			||||||
			=> throw new InvalidOperationException();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user