mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Rework sort system to allow multiples keys
This commit is contained in:
parent
e32c09f48f
commit
c0c263c4d7
@ -16,6 +16,7 @@ dotnet_diagnostic.IDE0058.severity = none
|
||||
dotnet_diagnostic.IDE0046.severity = none
|
||||
dotnet_diagnostic.CA1848.severity = none
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
dotnet_diagnostic.CA1716.severity = none
|
||||
# Sort using and Import directives with System.* appearing first
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_using_directive_placement = outside_namespace:warning
|
||||
|
@ -19,7 +19,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -256,7 +255,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member, bool force = false)
|
||||
@ -274,7 +273,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member, bool force = false)
|
||||
@ -291,8 +290,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T>([NotNull] T obj, string memberName, bool force = false)
|
||||
where T : class, IResource;
|
||||
@ -305,8 +304,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, Expression{Func{T,ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
||||
@ -325,21 +324,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around 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>
|
||||
/// <exception cref="ItemNotFoundException">No library exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
||||
[Optional] Expression<Func<LibraryItem, bool>> where,
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetItemsFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
@ -354,21 +338,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around 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>
|
||||
/// <exception cref="ItemNotFoundException">No library exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug,
|
||||
[Optional] Expression<Func<LibraryItem, bool>> where,
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetItemsFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -383,21 +352,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = 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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="Show"/> exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetPeopleFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -412,21 +366,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = 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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="Show"/> exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetPeopleFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -441,21 +380,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="People"/> exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetRolesFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -470,21 +394,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="People"/> exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetRolesFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Setup relations between a show, a library and a collection
|
||||
/// </summary>
|
||||
@ -516,22 +425,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Pagination limit = default)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get all resources with filters
|
||||
/// </summary>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">A sort by function</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>
|
||||
Task<ICollection<T>> GetAll<T>([Optional] Expression<Func<T, bool>> where,
|
||||
Expression<Func<T, object>> sort,
|
||||
Pagination limit = default)
|
||||
where T : class, IResource
|
||||
{
|
||||
return GetAll(where, new Sort<T>(sort), limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the count of resources that match the filter
|
||||
/// </summary>
|
||||
|
@ -19,7 +19,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -106,19 +105,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get every resources that match all filters
|
||||
/// </summary>
|
||||
/// <param name="where">A filter predicate</param>
|
||||
/// <param name="sort">A sort by predicate. The order is ascending.</param>
|
||||
/// <param name="limit">How pagination should be done (where to start and how many to return)</param>
|
||||
/// <returns>A list of resources that match every filters</returns>
|
||||
[ItemNotNull]
|
||||
Task<ICollection<T>> GetAll([Optional] Expression<Func<T, bool>> where,
|
||||
Expression<Func<T, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetAll(where, new Sort<T>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of resources that match the filter's predicate.
|
||||
/// </summary>
|
||||
@ -352,21 +338,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around 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>
|
||||
/// <exception cref="ItemNotFoundException">No library exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
public Task<ICollection<LibraryItem>> GetFromLibrary(int id,
|
||||
[Optional] Expression<Func<LibraryItem, bool>> where,
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
@ -380,21 +351,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<LibraryItem, bool>> where = null,
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around 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>
|
||||
/// <exception cref="ItemNotFoundException">No library exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
public Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
|
||||
[Optional] Expression<Func<LibraryItem, bool>> where,
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -431,21 +387,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = 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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="Show"/> exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -460,21 +401,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = 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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="Show"/> exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -489,21 +415,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="People"/> exist with the given ID.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -517,21 +428,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <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>
|
||||
/// <exception cref="ItemNotFoundException">No <see cref="People"/> exist with the given slug.</exception>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
||||
[Optional] Expression<Func<PeopleRole, bool>> where,
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -551,21 +447,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Sort<MetadataID> sort = default,
|
||||
Pagination limit = default)
|
||||
where T : class, IMetadata;
|
||||
|
||||
/// <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">Pagination information (where to start and how many to get)</param>
|
||||
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
|
||||
/// <returns>A filtered list of external ids.</returns>
|
||||
Task<ICollection<MetadataID>> GetMetadataID<T>([Optional] Expression<Func<MetadataID, bool>> where,
|
||||
Expression<Func<MetadataID, object>> sort,
|
||||
Pagination limit = default
|
||||
)
|
||||
where T : class, IMetadata
|
||||
=> GetMetadataID<T>(where, new Sort<MetadataID>(sort), limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -113,7 +113,7 @@ namespace Kyoo.Abstractions.Models.Utils
|
||||
|
||||
/// <summary>
|
||||
/// A matcher overload for nullable IDs. See
|
||||
/// <see cref="Matcher{T}(System.Linq.Expressions.Expression{System.Func{T,int}},System.Linq.Expressions.Expression{System.Func{T,string}})"/>
|
||||
/// <see cref="Matcher{T}(Expression{Func{T,int}},Expression{Func{T,string}})"/>
|
||||
/// for more details.
|
||||
/// </summary>
|
||||
/// <param name="idGetter">An expression to retrieve an ID from the type <typeparamref name="T"/>.</param>
|
||||
|
@ -33,15 +33,22 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </summary>
|
||||
public int? AfterID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the previous page be returned instead of the next?
|
||||
/// </summary>
|
||||
public bool Reverse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Pagination"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="count">Set the <see cref="Count"/> value</param>
|
||||
/// <param name="afterID">Set the <see cref="AfterID"/> value. If not specified, it will start from the start</param>
|
||||
public Pagination(int count, int? afterID = null)
|
||||
/// <param name="reverse">Should the previous page be returned instead of the next?</param>
|
||||
public Pagination(int count, int? afterID = null, bool reverse = false)
|
||||
{
|
||||
Count = count;
|
||||
AfterID = afterID;
|
||||
Reverse = reverse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -17,7 +17,9 @@
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Kyoo.Utils;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
@ -26,63 +28,73 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// Information about how a query should be sorted. What factor should decide the sort and in which order.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">For witch type this sort applies</typeparam>
|
||||
public readonly struct Sort<T>
|
||||
public record Sort<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The sort key. This member will be used to sort the results.
|
||||
/// Sort by a specific key
|
||||
/// </summary>
|
||||
public Expression<Func<T, object>> Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <param name="key">The sort keys. This members will be used to sort the results.</param>
|
||||
/// <param name="desendant">
|
||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||
/// </summary>
|
||||
public bool Descendant { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="key">The sort key given. It is assigned to <see cref="Key"/>.</param>
|
||||
/// <param name="descendant">Should this be in descendant order? The default is false.</param>
|
||||
/// <exception cref="ArgumentException">If the given key is not a member.</exception>
|
||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
||||
/// </param>
|
||||
public record By(string key, bool desendant = false) : Sort<T>
|
||||
{
|
||||
Key = key;
|
||||
Descendant = descendant;
|
||||
|
||||
if (!Utility.IsPropertyExpression(Key))
|
||||
throw new ArgumentException("The given sort key is not valid.");
|
||||
}
|
||||
/// <summary>
|
||||
/// Sort by a specific key
|
||||
/// </summary>
|
||||
/// <param name="key">The sort keys. This members will be used to sort the results.</param>
|
||||
/// <param name="desendant">
|
||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||
/// </param>
|
||||
public By(Expression<Func<T, object>> key, bool desendant = false)
|
||||
: this(Utility.GetPropertyName(key), desendant) { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
||||
/// </summary>
|
||||
/// <param name="sortBy">A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key".</param>
|
||||
/// <exception cref="ArgumentException">An invalid key or sort specifier as been given.</exception>
|
||||
public Sort(string sortBy)
|
||||
/// <returns>A <see cref="Sort{T}"/> for the given string</returns>
|
||||
public static new By From(string sortBy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sortBy))
|
||||
{
|
||||
Key = null;
|
||||
Descendant = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
||||
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
||||
|
||||
ParameterExpression param = Expression.Parameter(typeof(T), "x");
|
||||
MemberExpression property = Expression.Property(param, key);
|
||||
Key = property.Type.IsValueType
|
||||
? Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param)
|
||||
: Expression.Lambda<Func<T, object>>(property, param);
|
||||
|
||||
Descendant = order switch
|
||||
bool desendant = order switch
|
||||
{
|
||||
"desc" => true,
|
||||
"asc" => false,
|
||||
null => false,
|
||||
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
||||
};
|
||||
PropertyInfo property = typeof(T).GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (property == null)
|
||||
throw new ArgumentException("The given sort key is not valid.");
|
||||
return new By(property.Name, desendant);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort by multiple keys.
|
||||
/// </summary>
|
||||
/// <param name="list">The list of keys to sort by.</param>
|
||||
public record Conglomerate(params By[] list) : Sort<T>;
|
||||
|
||||
/// <summary>The default sort method for the given type.</summary>
|
||||
public record Default : Sort<T>;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
||||
/// </summary>
|
||||
/// <param name="sortBy">A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key".</param>
|
||||
/// <exception cref="ArgumentException">An invalid key or sort specifier as been given.</exception>
|
||||
/// <returns>A <see cref="Sort{T}"/> for the given string</returns>
|
||||
public static Sort<T> From(string sortBy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sortBy))
|
||||
return new Default();
|
||||
if (sortBy.Contains(','))
|
||||
return new Conglomerate(sortBy.Split(',').Select(By.From).ToArray());
|
||||
return By.From(sortBy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,48 +163,46 @@ namespace Kyoo.Abstractions.Models
|
||||
await library.Load(ep, x => x.Show);
|
||||
await library.Load(ep, x => x.Tracks);
|
||||
|
||||
Episode previous = null;
|
||||
Episode next = null;
|
||||
if (!ep.Show.IsMovie)
|
||||
{
|
||||
if (ep.AbsoluteNumber != null)
|
||||
{
|
||||
previous = await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID && x.AbsoluteNumber < ep.AbsoluteNumber,
|
||||
new Sort<Episode>(x => x.AbsoluteNumber, true)
|
||||
);
|
||||
next = await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID && x.AbsoluteNumber > ep.AbsoluteNumber,
|
||||
new Sort<Episode>(x => x.AbsoluteNumber)
|
||||
);
|
||||
}
|
||||
else if (ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
||||
{
|
||||
previous = await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber
|
||||
&& x.EpisodeNumber < ep.EpisodeNumber,
|
||||
new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||
);
|
||||
previous ??= await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber - 1,
|
||||
new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||
);
|
||||
|
||||
next = await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber
|
||||
&& x.EpisodeNumber > ep.EpisodeNumber,
|
||||
new Sort<Episode>(x => x.EpisodeNumber)
|
||||
);
|
||||
next ??= await library.GetOrDefault(
|
||||
x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber + 1,
|
||||
new Sort<Episode>(x => x.EpisodeNumber)
|
||||
);
|
||||
}
|
||||
}
|
||||
// if (!ep.Show.IsMovie)
|
||||
// {
|
||||
// if (ep.AbsoluteNumber != null)
|
||||
// {
|
||||
// previous = await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID && x.AbsoluteNumber < ep.AbsoluteNumber,
|
||||
// new Sort<Episode>(x => x.AbsoluteNumber, true)
|
||||
// );
|
||||
// next = await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID && x.AbsoluteNumber > ep.AbsoluteNumber,
|
||||
// new Sort<Episode>(x => x.AbsoluteNumber)
|
||||
// );
|
||||
// }
|
||||
// else if (ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
||||
// {
|
||||
// previous = await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID
|
||||
// && x.SeasonNumber == ep.SeasonNumber
|
||||
// && x.EpisodeNumber < ep.EpisodeNumber,
|
||||
// new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||
// );
|
||||
// previous ??= await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID
|
||||
// && x.SeasonNumber == ep.SeasonNumber - 1,
|
||||
// new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||
// );
|
||||
//
|
||||
// next = await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID
|
||||
// && x.SeasonNumber == ep.SeasonNumber
|
||||
// && x.EpisodeNumber > ep.EpisodeNumber,
|
||||
// new Sort<Episode>(x => x.EpisodeNumber)
|
||||
// );
|
||||
// next ??= await library.GetOrDefault(
|
||||
// x => x.ShowID == ep.ShowID
|
||||
// && x.SeasonNumber == ep.SeasonNumber + 1,
|
||||
// new Sort<Episode>(x => x.EpisodeNumber)
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
return new WatchItem
|
||||
{
|
||||
@ -225,8 +223,12 @@ namespace Kyoo.Abstractions.Models
|
||||
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
||||
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
||||
Fonts = await transcoder.ListFonts(ep),
|
||||
PreviousEpisode = previous,
|
||||
NextEpisode = next,
|
||||
PreviousEpisode = ep.Show.IsMovie
|
||||
? null
|
||||
: (await library.GetAll<Episode>(limit: new Pagination(1, ep.ID, true))).FirstOrDefault(),
|
||||
NextEpisode = ep.Show.IsMovie
|
||||
? null
|
||||
: (await library.GetAll<Episode>(limit: new Pagination(1, ep.ID))).FirstOrDefault(),
|
||||
Chapters = await _GetChapters(ep, fs),
|
||||
IsMovie = ep.Show.IsMovie
|
||||
};
|
||||
|
@ -19,7 +19,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -44,7 +43,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly IProviderRepository _providers;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
|
||||
protected override Sort<Collection> DefaultSort => new Sort<Collection>.By(nameof(Collection.Name));
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CollectionRepository"/>.
|
||||
@ -61,11 +60,11 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Collection>> Search(string query)
|
||||
{
|
||||
return await _database.Collections
|
||||
return await Sort(
|
||||
_database.Collections
|
||||
.Where(_database.Like<Collection>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
).ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -19,7 +19,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -51,7 +50,12 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly ITrackRepository _tracks;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Episode, object>> DefaultSort => x => x.EpisodeNumber;
|
||||
// Use absolute numbers by default and fallback to season/episodes if it does not exists.
|
||||
protected override Sort<Episode> DefaultSort => new Sort<Episode>.Conglomerate(
|
||||
new Sort<Episode>.By(x => x.AbsoluteNumber),
|
||||
new Sort<Episode>.By(x => x.SeasonNumber),
|
||||
new Sort<Episode>.By(x => x.EpisodeNumber)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="EpisodeRepository"/>.
|
||||
@ -120,11 +124,12 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Episode>> Search(string query)
|
||||
{
|
||||
List<Episode> ret = await _database.Episodes
|
||||
List<Episode> ret = await Sort(
|
||||
_database.Episodes
|
||||
.Include(x => x.Show)
|
||||
.Where(x => x.EpisodeNumber != null || x.AbsoluteNumber != null)
|
||||
.Where(_database.Like<Episode>(x => x.Title, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
foreach (Episode ep in ret)
|
||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
|
||||
protected override Sort<Genre> DefaultSort => new Sort<Genre>.By(x => x.Slug);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="GenreRepository"/>.
|
||||
@ -54,9 +54,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Genre>> Search(string query)
|
||||
{
|
||||
return await _database.Genres
|
||||
return await Sort(
|
||||
_database.Genres
|
||||
.Where(_database.Like<Genre>(x => x.Name, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly Lazy<ILibraryRepository> _libraries;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title;
|
||||
protected override Sort<LibraryItem> DefaultSort => new Sort<LibraryItem>.By(x => x.Title);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LibraryItemRepository"/>.
|
||||
@ -92,9 +92,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<LibraryItem>> Search(string query)
|
||||
{
|
||||
return await _database.LibraryItems
|
||||
return await Sort(
|
||||
_database.LibraryItems
|
||||
.Where(_database.Like<LibraryItem>(x => x.Title, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly IProviderRepository _providers;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
||||
protected override Sort<Library> DefaultSort => new Sort<Library>.By(x => x.ID);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LibraryRepository"/> instance.
|
||||
@ -62,9 +62,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Library>> Search(string query)
|
||||
{
|
||||
return await _database.Libraries
|
||||
return await Sort(
|
||||
_database.Libraries
|
||||
.Where(_database.Like<Library>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -47,7 +48,7 @@ namespace Kyoo.Core.Controllers
|
||||
/// <summary>
|
||||
/// The default sort order that will be used for this resource's type.
|
||||
/// </summary>
|
||||
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
||||
protected abstract Sort<T> DefaultSort { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
||||
@ -61,6 +62,206 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc/>
|
||||
public Type RepositoryType => typeof(T);
|
||||
|
||||
/// <summary>
|
||||
/// Sort the given query.
|
||||
/// </summary>
|
||||
/// <param name="query">The query to sort.</param>
|
||||
/// <param name="sortBy">How to sort the query</param>
|
||||
/// <returns>The newly sorted query.</returns>
|
||||
protected IOrderedQueryable<T> Sort(IQueryable<T> query, Sort<T> sortBy = null)
|
||||
{
|
||||
sortBy ??= DefaultSort;
|
||||
|
||||
switch (sortBy)
|
||||
{
|
||||
case Sort<T>.Default:
|
||||
return Sort(query, DefaultSort);
|
||||
case Sort<T>.By(var key, var desc):
|
||||
return desc
|
||||
? query.OrderByDescending(x => EF.Property<object>(x, key))
|
||||
: query.OrderBy(x => EF.Property<T>(x, key));
|
||||
case Sort<T>.Conglomerate(var keys):
|
||||
IOrderedQueryable<T> nQuery = Sort(query, keys[0]);
|
||||
foreach ((string key, bool desc) in keys.Skip(1))
|
||||
{
|
||||
nQuery = desc
|
||||
? nQuery.ThenByDescending(x => EF.Property<object>(x, key))
|
||||
: nQuery.ThenBy(x => EF.Property<object>(x, key));
|
||||
}
|
||||
return nQuery;
|
||||
default:
|
||||
// The language should not require me to do this...
|
||||
throw new SwitchExpressionException();
|
||||
}
|
||||
}
|
||||
|
||||
private static Func<Expression, Expression, BinaryExpression> GetComparisonExpression(
|
||||
bool desc,
|
||||
bool next,
|
||||
bool orEqual)
|
||||
{
|
||||
bool greaterThan = desc ^ next;
|
||||
|
||||
return orEqual
|
||||
? (greaterThan ? Expression.GreaterThanOrEqual : Expression.LessThanOrEqual)
|
||||
: (greaterThan ? Expression.GreaterThan : Expression.LessThan);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a filter (where) expression on the query to skip everything before/after the referenceID.
|
||||
/// The generalized expression for this in pseudocode is:
|
||||
/// (x > a) OR
|
||||
/// (x = a AND y > b) OR
|
||||
/// (x = a AND y = b AND z > c) OR...
|
||||
///
|
||||
/// Of course, this will be a bit more complex when ASC and DESC are mixed.
|
||||
/// Assume x is ASC, y is DESC, and z is ASC:
|
||||
/// (x > a) OR
|
||||
/// (x = a AND y < b) OR
|
||||
/// (x = a AND y = b AND z > c) OR...
|
||||
/// </summary>
|
||||
protected Expression<Func<T, bool>> KeysetPaginatate(
|
||||
Sort<T> sort,
|
||||
T reference,
|
||||
bool next = true)
|
||||
{
|
||||
if (sort is Sort<T>.Default)
|
||||
sort = DefaultSort;
|
||||
|
||||
// x =>
|
||||
ParameterExpression x = Expression.Parameter(typeof(T), "x");
|
||||
ConstantExpression referenceC = Expression.Constant(reference, typeof(T));
|
||||
|
||||
if (sort is Sort<T>.By(var key, var desc))
|
||||
{
|
||||
Func<Expression, Expression, BinaryExpression> comparer = GetComparisonExpression(desc, next, false);
|
||||
MemberExpression xkey = Expression.Property(x, key);
|
||||
MemberExpression rkey = Expression.Property(referenceC, key);
|
||||
BinaryExpression compare = ApiHelper.StringCompatibleExpression(comparer, xkey, rkey);
|
||||
return Expression.Lambda<Func<T, bool>>(compare, x);
|
||||
}
|
||||
|
||||
if (sort is Sort<T>.Conglomerate(var list))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// BinaryExpression orExpression;
|
||||
//
|
||||
// foreach ((string key, bool desc) in list)
|
||||
// {
|
||||
// query.Where(x =>
|
||||
// }
|
||||
}
|
||||
throw new SwitchExpressionException();
|
||||
|
||||
// Shamlessly stollen from https://github.com/mrahhal/MR.EntityFrameworkCore.KeysetPagination/blob/main/src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs#L191
|
||||
// // A composite keyset pagination in sql looks something like this:
|
||||
// // (x, y, ...) > (a, b, ...)
|
||||
// // Where, x/y/... represent the column and a/b/... represent the reference's respective values.
|
||||
// //
|
||||
// // In sql standard this syntax is called "row value". Check here: https://use-the-index-luke.com/sql/partial-results/fetch-next-page#sb-row-values
|
||||
// // Unfortunately, not all databases support this properly.
|
||||
// // Further, if we were to use this we would somehow need EF Core to recognise it and translate it
|
||||
// // perhaps by using a new DbFunction (https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbfunctions).
|
||||
// // There's an ongoing issue for this here: https://github.com/dotnet/efcore/issues/26822
|
||||
// //
|
||||
// // In addition, row value won't work for mixed ordered columns. i.e if x > a but y < b.
|
||||
// // So even if we can use it we'll still have to fallback to this logic in these cases.
|
||||
// //
|
||||
// // The generalized expression for this in pseudocode is:
|
||||
// // (x > a) OR
|
||||
// // (x = a AND y > b) OR
|
||||
// // (x = a AND y = b AND z > c) OR...
|
||||
// //
|
||||
// // Of course, this will be a bit more complex when ASC and DESC are mixed.
|
||||
// // Assume x is ASC, y is DESC, and z is ASC:
|
||||
// // (x > a) OR
|
||||
// // (x = a AND y < b) OR
|
||||
// // (x = a AND y = b AND z > c) OR...
|
||||
// //
|
||||
// // An optimization is to include an additional redundant wrapping clause for the 1st column when there are
|
||||
// // more than one column we're acting on, which would allow the db to use it as an access predicate on the 1st column.
|
||||
// // See here: https://use-the-index-luke.com/sql/partial-results/fetch-next-page#sb-equivalent-logic
|
||||
//
|
||||
// var referenceValues = GetValues(columns, reference);
|
||||
//
|
||||
// MemberExpression firstMemberAccessExpression;
|
||||
// Expression firstReferenceValueExpression;
|
||||
//
|
||||
// // entity =>
|
||||
// ParameterExpression param = Expression.Parameter(typeof(T), "entity");
|
||||
//
|
||||
// BinaryExpression orExpression;
|
||||
// int innerLimit = 1;
|
||||
// // This loop compounds the outer OR expressions.
|
||||
// for (int i = 0; i < sort.list.Length; i++)
|
||||
// {
|
||||
// BinaryExpression andExpression;
|
||||
//
|
||||
// // This loop compounds the inner AND expressions.
|
||||
// // innerLimit implicitly grows from 1 to items.Count by each iteration.
|
||||
// for (int j = 0; j < innerLimit; j++)
|
||||
// {
|
||||
// bool isInnerLastOperation = j + 1 == innerLimit;
|
||||
// var column = columns[j];
|
||||
// var memberAccess = column.MakeMemberAccessExpression(param);
|
||||
// var referenceValue = referenceValues[j];
|
||||
// Expression<Func<object>> referenceValueFunc = () => referenceValue;
|
||||
// var referenceValueExpression = referenceValueFunc.Body;
|
||||
//
|
||||
// if (firstMemberAccessExpression == null)
|
||||
// {
|
||||
// // This might be used later on in an optimization.
|
||||
// firstMemberAccessExpression = memberAccess;
|
||||
// firstReferenceValueExpression = referenceValueExpression;
|
||||
// }
|
||||
//
|
||||
// BinaryExpression innerExpression;
|
||||
// if (!isInnerLastOperation)
|
||||
// {
|
||||
// innerExpression = Expression.Equal(
|
||||
// memberAccess,
|
||||
// EnsureMatchingType(memberAccess, referenceValueExpression));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var compare = GetComparisonExpressionToApply(direction, column, orEqual: false);
|
||||
// innerExpression = MakeComparisonExpression(
|
||||
// column,
|
||||
// memberAccess, referenceValueExpression,
|
||||
// compare);
|
||||
// }
|
||||
//
|
||||
// andExpression = andExpression == null ? innerExpression : Expression.And(andExpression, innerExpression);
|
||||
// }
|
||||
//
|
||||
// orExpression = orExpression == null ? andExpression : Expression.Or(orExpression, andExpression);
|
||||
//
|
||||
// innerLimit++;
|
||||
// }
|
||||
//
|
||||
// var finalExpression = orExpression;
|
||||
// if (columns.Count > 1)
|
||||
// {
|
||||
// // Implement the optimization that allows an access predicate on the 1st column.
|
||||
// // This is done by generating the following expression:
|
||||
// // (x >=|<= a) AND (previous generated expression)
|
||||
// //
|
||||
// // This effectively adds a redundant clause on the 1st column, but it's a clause all dbs
|
||||
// // understand and can use as an access predicate (most commonly when the column is indexed).
|
||||
//
|
||||
// var firstColumn = columns[0];
|
||||
// var compare = GetComparisonExpressionToApply(direction, firstColumn, orEqual: true);
|
||||
// var accessPredicateClause = MakeComparisonExpression(
|
||||
// firstColumn,
|
||||
// firstMemberAccessExpression!, firstReferenceValueExpression!,
|
||||
// compare);
|
||||
// finalExpression = Expression.And(accessPredicateClause, finalExpression);
|
||||
// }
|
||||
//
|
||||
// return Expression.Lambda<Func<T, bool>>(finalExpression, param);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a resource from it's ID and make the <see cref="Database"/> instance track it.
|
||||
/// </summary>
|
||||
@ -117,10 +318,7 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where, Sort<T> sortBy = default)
|
||||
{
|
||||
IQueryable<T> query = Database.Set<T>();
|
||||
Expression<Func<T, object>> sortKey = sortBy.Key ?? DefaultSort;
|
||||
query = sortBy.Descendant ? query.OrderByDescending(sortKey) : query.OrderBy(sortKey);
|
||||
return query.FirstOrDefaultAsync(where);
|
||||
return Sort(Database.Set<T>(), sortBy).FirstOrDefaultAsync(where);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@ -142,54 +340,19 @@ namespace Kyoo.Core.Controllers
|
||||
/// <param name="sort">The sort settings (sort order and sort by)</param>
|
||||
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||
/// <returns>The filtered query</returns>
|
||||
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
|
||||
protected async Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
|
||||
Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
return ApplyFilters(query, GetOrDefault, DefaultSort, where, sort, limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply filters to a query to ease sort, pagination and where queries for any resources types.
|
||||
/// For resources of type <typeparamref name="T"/>, see <see cref="ApplyFilters"/>
|
||||
/// </summary>
|
||||
/// <param name="query">The base query to filter.</param>
|
||||
/// <param name="get">A function to asynchronously get a resource from the database using it's ID.</param>
|
||||
/// <param name="defaultSort">The default sort order of this resource's type.</param>
|
||||
/// <param name="where">An expression to filter based on arbitrary conditions</param>
|
||||
/// <param name="sort">The sort settings (sort order and sort by)</param>
|
||||
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||
/// <typeparam name="TValue">The type of items to query.</typeparam>
|
||||
/// <returns>The filtered query</returns>
|
||||
protected async Task<ICollection<TValue>> ApplyFilters<TValue>(IQueryable<TValue> query,
|
||||
Func<int, Task<TValue>> get,
|
||||
Expression<Func<TValue, object>> defaultSort,
|
||||
Expression<Func<TValue, bool>> where = null,
|
||||
Sort<TValue> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
query = Sort(query, sort);
|
||||
if (where != null)
|
||||
query = query.Where(where);
|
||||
|
||||
Expression<Func<TValue, object>> sortKey = sort.Key ?? defaultSort;
|
||||
Expression sortExpression = sortKey.Body.NodeType == ExpressionType.Convert
|
||||
? ((UnaryExpression)sortKey.Body).Operand
|
||||
: sortKey.Body;
|
||||
|
||||
if (typeof(Enum).IsAssignableFrom(sortExpression.Type))
|
||||
throw new ArgumentException("Invalid sort key.");
|
||||
|
||||
query = sort.Descendant ? query.OrderByDescending(sortKey) : query.OrderBy(sortKey);
|
||||
|
||||
if (limit.AfterID != null)
|
||||
{
|
||||
TValue after = await get(limit.AfterID.Value);
|
||||
Expression key = Expression.Constant(sortKey.Compile()(after), sortExpression.Type);
|
||||
query = query.Where(Expression.Lambda<Func<TValue, bool>>(
|
||||
ApiHelper.StringCompatibleExpression(Expression.GreaterThan, sortExpression, key),
|
||||
sortKey.Parameters.First()
|
||||
));
|
||||
T reference = await Get(limit.AfterID.Value);
|
||||
query = query.Where(KeysetPaginatate(sort, reference));
|
||||
}
|
||||
if (limit.Count > 0)
|
||||
query = query.Take(limit.Count);
|
||||
|
@ -51,7 +51,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly Lazy<IShowRepository> _shows;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
|
||||
protected override Sort<People> DefaultSort => new Sort<People>.By(x => x.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="PeopleRepository"/>
|
||||
@ -72,9 +72,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<People>> Search(string query)
|
||||
{
|
||||
return await _database.People
|
||||
return await Sort(
|
||||
_database.People
|
||||
.Where(_database.Like<People>(x => x.Name, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
@ -152,19 +153,19 @@ namespace Kyoo.Core.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||
.Where(x => x.ShowID == showID)
|
||||
.Include(x => x.People),
|
||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||
x => x.People.Name,
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
if (!people.Any() && await _shows.Value.GetOrDefault(showID) == null)
|
||||
throw new ItemNotFoundException();
|
||||
foreach (PeopleRole role in people)
|
||||
role.ForPeople = true;
|
||||
return people;
|
||||
throw new NotImplementedException();
|
||||
// ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||
// .Where(x => x.ShowID == showID)
|
||||
// .Include(x => x.People),
|
||||
// x => x.People.Name,
|
||||
// where,
|
||||
// sort,
|
||||
// limit);
|
||||
// if (!people.Any() && await _shows.Value.GetOrDefault(showID) == null)
|
||||
// throw new ItemNotFoundException();
|
||||
// foreach (PeopleRole role in people)
|
||||
// role.ForPeople = true;
|
||||
// return people;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -173,20 +174,21 @@ namespace Kyoo.Core.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||
.Where(x => x.Show.Slug == showSlug)
|
||||
.Include(x => x.People)
|
||||
.Include(x => x.Show),
|
||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||
x => x.People.Name,
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
if (!people.Any() && await _shows.Value.GetOrDefault(showSlug) == null)
|
||||
throw new ItemNotFoundException();
|
||||
foreach (PeopleRole role in people)
|
||||
role.ForPeople = true;
|
||||
return people;
|
||||
throw new NotImplementedException();
|
||||
// ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||
// .Where(x => x.Show.Slug == showSlug)
|
||||
// .Include(x => x.People)
|
||||
// .Include(x => x.Show),
|
||||
// id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||
// x => x.People.Name,
|
||||
// where,
|
||||
// sort,
|
||||
// limit);
|
||||
// if (!people.Any() && await _shows.Value.GetOrDefault(showSlug) == null)
|
||||
// throw new ItemNotFoundException();
|
||||
// foreach (PeopleRole role in people)
|
||||
// role.ForPeople = true;
|
||||
// return people;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -195,17 +197,18 @@ namespace Kyoo.Core.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||
.Where(x => x.PeopleID == id)
|
||||
.Include(x => x.Show),
|
||||
y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y),
|
||||
x => x.Show.Title,
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
if (!roles.Any() && await GetOrDefault(id) == null)
|
||||
throw new ItemNotFoundException();
|
||||
return roles;
|
||||
throw new NotImplementedException();
|
||||
// ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||
// .Where(x => x.PeopleID == id)
|
||||
// .Include(x => x.Show),
|
||||
// y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y),
|
||||
// x => x.Show.Title,
|
||||
// where,
|
||||
// sort,
|
||||
// limit);
|
||||
// if (!roles.Any() && await GetOrDefault(id) == null)
|
||||
// throw new ItemNotFoundException();
|
||||
// return roles;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -214,17 +217,18 @@ namespace Kyoo.Core.Controllers
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default)
|
||||
{
|
||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||
.Where(x => x.People.Slug == slug)
|
||||
.Include(x => x.Show),
|
||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||
x => x.Show.Title,
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
if (!roles.Any() && await GetOrDefault(slug) == null)
|
||||
throw new ItemNotFoundException();
|
||||
return roles;
|
||||
throw new NotImplementedException();
|
||||
// ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||
// .Where(x => x.People.Slug == slug)
|
||||
// .Include(x => x.Show),
|
||||
// id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||
// x => x.Show.Title,
|
||||
// where,
|
||||
// sort,
|
||||
// limit);
|
||||
// if (!roles.Any() && await GetOrDefault(slug) == null)
|
||||
// throw new ItemNotFoundException();
|
||||
// return roles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,14 +49,15 @@ namespace Kyoo.Core.Controllers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Provider, object>> DefaultSort => x => x.Slug;
|
||||
protected override Sort<Provider> DefaultSort => new Sort<Provider>.By(x => x.Slug);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Provider>> Search(string query)
|
||||
{
|
||||
return await _database.Providers
|
||||
return await Sort(
|
||||
_database.Providers
|
||||
.Where(_database.Like<Provider>(x => x.Name, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
@ -87,13 +88,14 @@ namespace Kyoo.Core.Controllers
|
||||
Pagination limit = default)
|
||||
where T : class, IMetadata
|
||||
{
|
||||
return ApplyFilters(_database.MetadataIds<T>()
|
||||
.Include(y => y.Provider),
|
||||
x => _database.MetadataIds<T>().FirstOrDefaultAsync(y => y.ResourceID == x),
|
||||
x => x.ResourceID,
|
||||
where,
|
||||
sort,
|
||||
limit);
|
||||
throw new NotImplementedException();
|
||||
// return ApplyFilters(_database.MetadataIds<T>()
|
||||
// .Include(y => y.Provider),
|
||||
// x => _database.MetadataIds<T>().FirstOrDefaultAsync(y => y.ResourceID == x),
|
||||
// x => x.ResourceID,
|
||||
// where,
|
||||
// sort,
|
||||
// limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly IProviderRepository _providers;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Expression<Func<Season, object>> DefaultSort => x => x.SeasonNumber;
|
||||
protected override Sort<Season> DefaultSort => new Sort<Season>.By(x => x.SeasonNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SeasonRepository"/>.
|
||||
@ -95,9 +95,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc/>
|
||||
public override async Task<ICollection<Season>> Search(string query)
|
||||
{
|
||||
return await _database.Seasons
|
||||
return await Sort(
|
||||
_database.Seasons
|
||||
.Where(_database.Like<Season>(x => x.Title, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly IProviderRepository _providers;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
|
||||
protected override Sort<Show> DefaultSort => new Sort<Show>.By(x => x.Title);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ShowRepository"/>.
|
||||
@ -88,9 +88,10 @@ namespace Kyoo.Core.Controllers
|
||||
public override async Task<ICollection<Show>> Search(string query)
|
||||
{
|
||||
query = $"%{query}%";
|
||||
return await _database.Shows
|
||||
return await Sort(
|
||||
_database.Shows
|
||||
.Where(_database.Like<Show>(x => x.Title + " " + x.Slug, query))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly IProviderRepository _providers;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
|
||||
protected override Sort<Studio> DefaultSort => new Sort<Studio>.By(x => x.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StudioRepository"/>.
|
||||
@ -61,9 +61,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Studio>> Search(string query)
|
||||
{
|
||||
return await _database.Studios
|
||||
return await Sort(
|
||||
_database.Studios
|
||||
.Where(_database.Like<Studio>(x => x.Name, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -38,7 +37,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
|
||||
protected override Sort<Track> DefaultSort => new Sort<Track>.By(x => x.TrackIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TrackRepository"/>.
|
||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Core.Controllers
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Expression<Func<User, object>> DefaultSort => x => x.Username;
|
||||
protected override Sort<User> DefaultSort => new Sort<User>.By(x => x.Username);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="UserRepository"/>
|
||||
@ -54,9 +54,10 @@ namespace Kyoo.Core.Controllers
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<User>> Search(string query)
|
||||
{
|
||||
return await _database.Users
|
||||
return await Sort(
|
||||
_database.Users
|
||||
.Where(_database.Like<User>(x => x.Username, $"%{query}%"))
|
||||
.OrderBy(DefaultSort)
|
||||
)
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<T> resources = await Repository.GetAll(
|
||||
ApiHelper.ParseWhere<T>(where),
|
||||
new Sort<T>(sortBy),
|
||||
Sort<T>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
@ -88,7 +88,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Genre>(x => x.Genres)),
|
||||
new Sort<Show>(sortBy),
|
||||
Sort<Show>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
@ -93,7 +93,7 @@ namespace Kyoo.Core.Api
|
||||
try
|
||||
{
|
||||
Expression<Func<PeopleRole, bool>> whereQuery = ApiHelper.ParseWhere<PeopleRole>(where);
|
||||
Sort<PeopleRole> sort = new(sortBy);
|
||||
Sort<PeopleRole> sort = Sort<PeopleRole>.From(sortBy);
|
||||
Pagination pagination = new(limit, afterID);
|
||||
|
||||
ICollection<PeopleRole> resources = await identifier.Match(
|
||||
|
@ -88,7 +88,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.Matcher<Show>(x => x.StudioID, x => x.Studio.Slug)),
|
||||
new Sort<Show>(sortBy),
|
||||
Sort<Show>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Collection>(x => x.Collections)),
|
||||
new Sort<Show>(sortBy),
|
||||
Sort<Show>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -136,7 +136,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Library> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Collection>(x => x.Collections)),
|
||||
new Sort<Library>(sortBy),
|
||||
Sort<Library>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
@ -160,7 +160,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Track> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.Matcher<Track>(x => x.EpisodeID, x => x.Episode.Slug)),
|
||||
new Sort<Track>(sortBy),
|
||||
Sort<Track>.From(sortBy),
|
||||
new Pagination(limit, afterID));
|
||||
|
||||
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Episode>()) == null)
|
||||
|
@ -91,7 +91,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Library>(x => x.Libraries)),
|
||||
new Sort<Show>(sortBy),
|
||||
Sort<Show>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -135,7 +135,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Collection> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Library>(x => x.Libraries)),
|
||||
new Sort<Collection>(sortBy),
|
||||
Sort<Collection>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -181,7 +181,7 @@ namespace Kyoo.Core.Api
|
||||
try
|
||||
{
|
||||
Expression<Func<LibraryItem, bool>> whereQuery = ApiHelper.ParseWhere<LibraryItem>(where);
|
||||
Sort<LibraryItem> sort = new(sortBy);
|
||||
Sort<LibraryItem> sort = Sort<LibraryItem>.From(sortBy);
|
||||
Pagination pagination = new(limit, afterID);
|
||||
|
||||
ICollection<LibraryItem> resources = await identifier.Match(
|
||||
|
@ -89,7 +89,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<LibraryItem> resources = await _libraryItems.GetAll(
|
||||
ApiHelper.ParseWhere<LibraryItem>(where),
|
||||
new Sort<LibraryItem>(sortBy),
|
||||
Sort<LibraryItem>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Episode> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.Matcher<Episode>(x => x.SeasonID, x => x.Season.Slug)),
|
||||
new Sort<Episode>(sortBy),
|
||||
Sort<Episode>.From(sortBy),
|
||||
new Pagination(limit, afterID));
|
||||
|
||||
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Season>()) == null)
|
||||
|
@ -96,7 +96,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Season> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.Matcher<Season>(x => x.ShowID, x => x.Show.Slug)),
|
||||
new Sort<Season>(sortBy),
|
||||
Sort<Season>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -140,7 +140,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Episode> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.Matcher<Episode>(x => x.ShowID, x => x.Show.Slug)),
|
||||
new Sort<Episode>(sortBy),
|
||||
Sort<Episode>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -183,7 +183,7 @@ namespace Kyoo.Core.Api
|
||||
try
|
||||
{
|
||||
Expression<Func<PeopleRole, bool>> whereQuery = ApiHelper.ParseWhere<PeopleRole>(where);
|
||||
Sort<PeopleRole> sort = new(sortBy);
|
||||
Sort<PeopleRole> sort = Sort<PeopleRole>.From(sortBy);
|
||||
Pagination pagination = new(limit, afterID);
|
||||
|
||||
ICollection<PeopleRole> resources = await identifier.Match(
|
||||
@ -232,7 +232,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Genre> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Genre, Show>(x => x.Shows)),
|
||||
new Sort<Genre>(sortBy),
|
||||
Sort<Genre>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -298,7 +298,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Library> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Show>(x => x.Shows)),
|
||||
new Sort<Library>(sortBy),
|
||||
Sort<Library>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
@ -342,7 +342,7 @@ namespace Kyoo.Core.Api
|
||||
{
|
||||
ICollection<Collection> resources = await _libraryManager.GetAll(
|
||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Show>(x => x.Shows)),
|
||||
new Sort<Collection>(sortBy),
|
||||
Sort<Collection>.From(sortBy),
|
||||
new Pagination(limit, afterID)
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user