mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 20:54:13 -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.IDE0046.severity = none
|
||||||
dotnet_diagnostic.CA1848.severity = none
|
dotnet_diagnostic.CA1848.severity = none
|
||||||
dotnet_diagnostic.CA2007.severity = none
|
dotnet_diagnostic.CA2007.severity = none
|
||||||
|
dotnet_diagnostic.CA1716.severity = none
|
||||||
# Sort using and Import directives with System.* appearing first
|
# Sort using and Import directives with System.* appearing first
|
||||||
dotnet_sort_system_directives_first = true
|
dotnet_sort_system_directives_first = true
|
||||||
csharp_using_directive_placement = outside_namespace:warning
|
csharp_using_directive_placement = outside_namespace:warning
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -256,7 +255,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">The type of the source object</typeparam>
|
/// <typeparam name="T">The type of the source object</typeparam>
|
||||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||||
/// <returns>The param <paramref name="obj"/></returns>
|
/// <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{T}(T, string, bool)"/>
|
||||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member, bool force = false)
|
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="T">The type of the source object</typeparam>
|
||||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||||
/// <returns>The param <paramref name="obj"/></returns>
|
/// <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{T}(T, string, bool)"/>
|
||||||
/// <seealso cref="Load(IResource, 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)
|
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>
|
/// </param>
|
||||||
/// <typeparam name="T">The type of the source object</typeparam>
|
/// <typeparam name="T">The type of the source object</typeparam>
|
||||||
/// <returns>The param <paramref name="obj"/></returns>
|
/// <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,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(IResource, string, bool)"/>
|
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||||
Task<T> Load<T>([NotNull] T obj, string memberName, bool force = false)
|
Task<T> Load<T>([NotNull] T obj, string memberName, bool force = false)
|
||||||
where T : class, IResource;
|
where T : class, IResource;
|
||||||
@ -305,8 +304,8 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="force">
|
/// <param name="force">
|
||||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <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,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{T}(T, string, bool)"/>
|
||||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||||
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
||||||
@ -325,21 +324,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get items (A wrapper around shows or collections) from a library.
|
/// Get items (A wrapper around shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -354,21 +338,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -383,21 +352,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get people's roles from a show.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="showID">The ID of the show</param>
|
|
||||||
/// <param name="where">A filter function</param>
|
|
||||||
/// <param name="sort">A sort by method</param>
|
|
||||||
/// <param name="limit">How many items to return and where to start</param>
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -412,21 +366,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get people's roles from a show.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="showSlug">The slug of the show</param>
|
|
||||||
/// <param name="where">A filter function</param>
|
|
||||||
/// <param name="sort">A sort by method</param>
|
|
||||||
/// <param name="limit">How many items to return and where to start</param>
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -441,21 +380,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -470,21 +394,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Setup relations between a show, a library and a collection
|
/// Setup relations between a show, a library and a collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -516,22 +425,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
where T : class, IResource;
|
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>
|
/// <summary>
|
||||||
/// Get the count of resources that match the filter
|
/// Get the count of resources that match the filter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -106,19 +105,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get the number of resources that match the filter's predicate.
|
/// Get the number of resources that match the filter's predicate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -352,21 +338,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get items (A wrapper around shows or collections) from a library.
|
/// Get items (A wrapper around shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -380,21 +351,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get items (A wrapper 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>
|
/// <summary>
|
||||||
@ -431,21 +387,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get people's roles from a show.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="showID">The ID of the show</param>
|
|
||||||
/// <param name="where">A filter function</param>
|
|
||||||
/// <param name="sort">A sort by method</param>
|
|
||||||
/// <param name="limit">How many items to return and where to start</param>
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -460,21 +401,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get people's roles from a show.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="showSlug">The slug of the show</param>
|
|
||||||
/// <param name="where">A filter function</param>
|
|
||||||
/// <param name="sort">A sort by method</param>
|
|
||||||
/// <param name="limit">How many items to return and where to start</param>
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -489,21 +415,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = 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>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -517,21 +428,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get people's roles from a 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>
|
/// <summary>
|
||||||
@ -551,21 +447,6 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Sort<MetadataID> sort = default,
|
Sort<MetadataID> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
where T : class, IMetadata;
|
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>
|
/// <summary>
|
||||||
|
@ -113,7 +113,7 @@ namespace Kyoo.Abstractions.Models.Utils
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A matcher overload for nullable IDs. See
|
/// 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.
|
/// for more details.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idGetter">An expression to retrieve an ID from the type <typeparamref name="T"/>.</param>
|
/// <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>
|
/// </summary>
|
||||||
public int? AfterID { get; }
|
public int? AfterID { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the previous page be returned instead of the next?
|
||||||
|
/// </summary>
|
||||||
|
public bool Reverse { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Pagination"/> instance.
|
/// Create a new <see cref="Pagination"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count">Set the <see cref="Count"/> value</param>
|
/// <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>
|
/// <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;
|
Count = count;
|
||||||
AfterID = afterID;
|
AfterID = afterID;
|
||||||
|
Reverse = reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
using Kyoo.Utils;
|
using Kyoo.Utils;
|
||||||
|
|
||||||
namespace Kyoo.Abstractions.Controllers
|
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.
|
/// Information about how a query should be sorted. What factor should decide the sort and in which order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">For witch type this sort applies</typeparam>
|
/// <typeparam name="T">For witch type this sort applies</typeparam>
|
||||||
public readonly struct Sort<T>
|
public record Sort<T>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The sort key. This member will be used to sort the results.
|
/// Sort by a specific key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Expression<Func<T, object>> Key { get; }
|
/// <param name="key">The sort keys. This members will be used to sort the results.</param>
|
||||||
|
/// <param name="desendant">
|
||||||
/// <summary>
|
|
||||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||||
/// </summary>
|
/// </param>
|
||||||
public bool Descendant { get; }
|
public record By(string key, bool desendant = false) : Sort<T>
|
||||||
|
{
|
||||||
|
/// <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>
|
||||||
|
/// <returns>A <see cref="Sort{T}"/> for the given string</returns>
|
||||||
|
public static new By From(string sortBy)
|
||||||
|
{
|
||||||
|
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
||||||
|
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Create a new <see cref="Sort{T}"/> instance.
|
/// Sort by multiple keys.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The sort key given. It is assigned to <see cref="Key"/>.</param>
|
/// <param name="list">The list of keys to sort by.</param>
|
||||||
/// <param name="descendant">Should this be in descendant order? The default is false.</param>
|
public record Conglomerate(params By[] list) : Sort<T>;
|
||||||
/// <exception cref="ArgumentException">If the given key is not a member.</exception>
|
|
||||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
|
||||||
{
|
|
||||||
Key = key;
|
|
||||||
Descendant = descendant;
|
|
||||||
|
|
||||||
if (!Utility.IsPropertyExpression(Key))
|
/// <summary>The default sort method for the given type.</summary>
|
||||||
throw new ArgumentException("The given sort key is not valid.");
|
public record Default : Sort<T>;
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sortBy">A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key".</param>
|
/// <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>
|
/// <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 Sort<T> From(string sortBy)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(sortBy))
|
if (string.IsNullOrEmpty(sortBy))
|
||||||
{
|
return new Default();
|
||||||
Key = null;
|
if (sortBy.Contains(','))
|
||||||
Descendant = false;
|
return new Conglomerate(sortBy.Split(',').Select(By.From).ToArray());
|
||||||
return;
|
return By.From(sortBy);
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
"desc" => true,
|
|
||||||
"asc" => false,
|
|
||||||
null => false,
|
|
||||||
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,48 +163,46 @@ namespace Kyoo.Abstractions.Models
|
|||||||
await library.Load(ep, x => x.Show);
|
await library.Load(ep, x => x.Show);
|
||||||
await library.Load(ep, x => x.Tracks);
|
await library.Load(ep, x => x.Tracks);
|
||||||
|
|
||||||
Episode previous = null;
|
// if (!ep.Show.IsMovie)
|
||||||
Episode next = null;
|
// {
|
||||||
if (!ep.Show.IsMovie)
|
// if (ep.AbsoluteNumber != null)
|
||||||
{
|
// {
|
||||||
if (ep.AbsoluteNumber != null)
|
// previous = await library.GetOrDefault(
|
||||||
{
|
// x => x.ShowID == ep.ShowID && x.AbsoluteNumber < ep.AbsoluteNumber,
|
||||||
previous = await library.GetOrDefault(
|
// new Sort<Episode>(x => x.AbsoluteNumber, true)
|
||||||
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,
|
||||||
next = await library.GetOrDefault(
|
// new Sort<Episode>(x => x.AbsoluteNumber)
|
||||||
x => x.ShowID == ep.ShowID && x.AbsoluteNumber > ep.AbsoluteNumber,
|
// );
|
||||||
new Sort<Episode>(x => x.AbsoluteNumber)
|
// }
|
||||||
);
|
// else if (ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
||||||
}
|
// {
|
||||||
else if (ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
// previous = await library.GetOrDefault(
|
||||||
{
|
// x => x.ShowID == ep.ShowID
|
||||||
previous = await library.GetOrDefault(
|
// && x.SeasonNumber == ep.SeasonNumber
|
||||||
x => x.ShowID == ep.ShowID
|
// && x.EpisodeNumber < ep.EpisodeNumber,
|
||||||
&& x.SeasonNumber == ep.SeasonNumber
|
// new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||||
&& x.EpisodeNumber < ep.EpisodeNumber,
|
// );
|
||||||
new Sort<Episode>(x => x.EpisodeNumber, true)
|
// previous ??= await library.GetOrDefault(
|
||||||
);
|
// x => x.ShowID == ep.ShowID
|
||||||
previous ??= await library.GetOrDefault(
|
// && x.SeasonNumber == ep.SeasonNumber - 1,
|
||||||
x => x.ShowID == ep.ShowID
|
// new Sort<Episode>(x => x.EpisodeNumber, true)
|
||||||
&& x.SeasonNumber == ep.SeasonNumber - 1,
|
// );
|
||||||
new Sort<Episode>(x => x.EpisodeNumber, true)
|
//
|
||||||
);
|
// next = await library.GetOrDefault(
|
||||||
|
// x => x.ShowID == ep.ShowID
|
||||||
next = await library.GetOrDefault(
|
// && x.SeasonNumber == ep.SeasonNumber
|
||||||
x => x.ShowID == ep.ShowID
|
// && x.EpisodeNumber > ep.EpisodeNumber,
|
||||||
&& x.SeasonNumber == ep.SeasonNumber
|
// new Sort<Episode>(x => x.EpisodeNumber)
|
||||||
&& x.EpisodeNumber > ep.EpisodeNumber,
|
// );
|
||||||
new Sort<Episode>(x => x.EpisodeNumber)
|
// next ??= await library.GetOrDefault(
|
||||||
);
|
// x => x.ShowID == ep.ShowID
|
||||||
next ??= await library.GetOrDefault(
|
// && x.SeasonNumber == ep.SeasonNumber + 1,
|
||||||
x => x.ShowID == ep.ShowID
|
// new Sort<Episode>(x => x.EpisodeNumber)
|
||||||
&& x.SeasonNumber == ep.SeasonNumber + 1,
|
// );
|
||||||
new Sort<Episode>(x => x.EpisodeNumber)
|
// }
|
||||||
);
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new WatchItem
|
return new WatchItem
|
||||||
{
|
{
|
||||||
@ -225,8 +223,12 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
||||||
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
||||||
Fonts = await transcoder.ListFonts(ep),
|
Fonts = await transcoder.ListFonts(ep),
|
||||||
PreviousEpisode = previous,
|
PreviousEpisode = ep.Show.IsMovie
|
||||||
NextEpisode = next,
|
? 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),
|
Chapters = await _GetChapters(ep, fs),
|
||||||
IsMovie = ep.Show.IsMovie
|
IsMovie = ep.Show.IsMovie
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -44,7 +43,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
|
protected override Sort<Collection> DefaultSort => new Sort<Collection>.By(nameof(Collection.Name));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="CollectionRepository"/>.
|
/// Create a new <see cref="CollectionRepository"/>.
|
||||||
@ -61,11 +60,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Collection>> Search(string query)
|
public override async Task<ICollection<Collection>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Collections
|
return await Sort(
|
||||||
.Where(_database.Like<Collection>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
_database.Collections
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Collection>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -51,7 +50,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly ITrackRepository _tracks;
|
private readonly ITrackRepository _tracks;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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>
|
/// <summary>
|
||||||
/// Create a new <see cref="EpisodeRepository"/>.
|
/// Create a new <see cref="EpisodeRepository"/>.
|
||||||
@ -120,11 +124,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Episode>> Search(string query)
|
public override async Task<ICollection<Episode>> Search(string query)
|
||||||
{
|
{
|
||||||
List<Episode> ret = await _database.Episodes
|
List<Episode> ret = await Sort(
|
||||||
.Include(x => x.Show)
|
_database.Episodes
|
||||||
.Where(x => x.EpisodeNumber != null || x.AbsoluteNumber != null)
|
.Include(x => x.Show)
|
||||||
.Where(_database.Like<Episode>(x => x.Title, $"%{query}%"))
|
.Where(x => x.EpisodeNumber != null || x.AbsoluteNumber != null)
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Episode>(x => x.Title, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
foreach (Episode ep in ret)
|
foreach (Episode ep in ret)
|
||||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
|
protected override Sort<Genre> DefaultSort => new Sort<Genre>.By(x => x.Slug);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="GenreRepository"/>.
|
/// Create a new <see cref="GenreRepository"/>.
|
||||||
@ -54,9 +54,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Genre>> Search(string query)
|
public override async Task<ICollection<Genre>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Genres
|
return await Sort(
|
||||||
.Where(_database.Like<Genre>(x => x.Name, $"%{query}%"))
|
_database.Genres
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Genre>(x => x.Name, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly Lazy<ILibraryRepository> _libraries;
|
private readonly Lazy<ILibraryRepository> _libraries;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title;
|
protected override Sort<LibraryItem> DefaultSort => new Sort<LibraryItem>.By(x => x.Title);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LibraryItemRepository"/>.
|
/// Create a new <see cref="LibraryItemRepository"/>.
|
||||||
@ -92,9 +92,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<LibraryItem>> Search(string query)
|
public override async Task<ICollection<LibraryItem>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.LibraryItems
|
return await Sort(
|
||||||
.Where(_database.Like<LibraryItem>(x => x.Title, $"%{query}%"))
|
_database.LibraryItems
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<LibraryItem>(x => x.Title, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
protected override Sort<Library> DefaultSort => new Sort<Library>.By(x => x.ID);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LibraryRepository"/> instance.
|
/// Create a new <see cref="LibraryRepository"/> instance.
|
||||||
@ -62,9 +62,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Library>> Search(string query)
|
public override async Task<ICollection<Library>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Libraries
|
return await Sort(
|
||||||
.Where(_database.Like<Library>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
_database.Libraries
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Library>(x => x.Name + " " + x.Slug, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -47,7 +48,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default sort order that will be used for this resource's type.
|
/// The default sort order that will be used for this resource's type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
protected abstract Sort<T> DefaultSort { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
||||||
@ -61,6 +62,206 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Type RepositoryType => typeof(T);
|
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>
|
/// <summary>
|
||||||
/// Get a resource from it's ID and make the <see cref="Database"/> instance track it.
|
/// Get a resource from it's ID and make the <see cref="Database"/> instance track it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -117,10 +318,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where, Sort<T> sortBy = default)
|
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where, Sort<T> sortBy = default)
|
||||||
{
|
{
|
||||||
IQueryable<T> query = Database.Set<T>();
|
return Sort(Database.Set<T>(), sortBy).FirstOrDefaultAsync(where);
|
||||||
Expression<Func<T, object>> sortKey = sortBy.Key ?? DefaultSort;
|
|
||||||
query = sortBy.Descendant ? query.OrderByDescending(sortKey) : query.OrderBy(sortKey);
|
|
||||||
return query.FirstOrDefaultAsync(where);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -142,54 +340,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="sort">The sort settings (sort order and sort by)</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>
|
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||||
/// <returns>The filtered query</returns>
|
/// <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,
|
Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return ApplyFilters(query, GetOrDefault, DefaultSort, where, sort, limit);
|
query = Sort(query, sort);
|
||||||
}
|
|
||||||
|
|
||||||
/// <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)
|
|
||||||
{
|
|
||||||
if (where != null)
|
if (where != null)
|
||||||
query = query.Where(where);
|
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)
|
if (limit.AfterID != null)
|
||||||
{
|
{
|
||||||
TValue after = await get(limit.AfterID.Value);
|
T reference = await Get(limit.AfterID.Value);
|
||||||
Expression key = Expression.Constant(sortKey.Compile()(after), sortExpression.Type);
|
query = query.Where(KeysetPaginatate(sort, reference));
|
||||||
query = query.Where(Expression.Lambda<Func<TValue, bool>>(
|
|
||||||
ApiHelper.StringCompatibleExpression(Expression.GreaterThan, sortExpression, key),
|
|
||||||
sortKey.Parameters.First()
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if (limit.Count > 0)
|
if (limit.Count > 0)
|
||||||
query = query.Take(limit.Count);
|
query = query.Take(limit.Count);
|
||||||
|
@ -51,7 +51,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly Lazy<IShowRepository> _shows;
|
private readonly Lazy<IShowRepository> _shows;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
|
protected override Sort<People> DefaultSort => new Sort<People>.By(x => x.Name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="PeopleRepository"/>
|
/// Create a new <see cref="PeopleRepository"/>
|
||||||
@ -72,9 +72,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<People>> Search(string query)
|
public override async Task<ICollection<People>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.People
|
return await Sort(
|
||||||
.Where(_database.Like<People>(x => x.Name, $"%{query}%"))
|
_database.People
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<People>(x => x.Name, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
@ -152,19 +153,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
throw new NotImplementedException();
|
||||||
.Where(x => x.ShowID == showID)
|
// ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||||
.Include(x => x.People),
|
// .Where(x => x.ShowID == showID)
|
||||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
// .Include(x => x.People),
|
||||||
x => x.People.Name,
|
// x => x.People.Name,
|
||||||
where,
|
// where,
|
||||||
sort,
|
// sort,
|
||||||
limit);
|
// limit);
|
||||||
if (!people.Any() && await _shows.Value.GetOrDefault(showID) == null)
|
// if (!people.Any() && await _shows.Value.GetOrDefault(showID) == null)
|
||||||
throw new ItemNotFoundException();
|
// throw new ItemNotFoundException();
|
||||||
foreach (PeopleRole role in people)
|
// foreach (PeopleRole role in people)
|
||||||
role.ForPeople = true;
|
// role.ForPeople = true;
|
||||||
return people;
|
// return people;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -173,20 +174,21 @@ namespace Kyoo.Core.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
throw new NotImplementedException();
|
||||||
.Where(x => x.Show.Slug == showSlug)
|
// ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||||
.Include(x => x.People)
|
// .Where(x => x.Show.Slug == showSlug)
|
||||||
.Include(x => x.Show),
|
// .Include(x => x.People)
|
||||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
// .Include(x => x.Show),
|
||||||
x => x.People.Name,
|
// id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||||
where,
|
// x => x.People.Name,
|
||||||
sort,
|
// where,
|
||||||
limit);
|
// sort,
|
||||||
if (!people.Any() && await _shows.Value.GetOrDefault(showSlug) == null)
|
// limit);
|
||||||
throw new ItemNotFoundException();
|
// if (!people.Any() && await _shows.Value.GetOrDefault(showSlug) == null)
|
||||||
foreach (PeopleRole role in people)
|
// throw new ItemNotFoundException();
|
||||||
role.ForPeople = true;
|
// foreach (PeopleRole role in people)
|
||||||
return people;
|
// role.ForPeople = true;
|
||||||
|
// return people;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -195,17 +197,18 @@ namespace Kyoo.Core.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
throw new NotImplementedException();
|
||||||
.Where(x => x.PeopleID == id)
|
// ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||||
.Include(x => x.Show),
|
// .Where(x => x.PeopleID == id)
|
||||||
y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y),
|
// .Include(x => x.Show),
|
||||||
x => x.Show.Title,
|
// y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y),
|
||||||
where,
|
// x => x.Show.Title,
|
||||||
sort,
|
// where,
|
||||||
limit);
|
// sort,
|
||||||
if (!roles.Any() && await GetOrDefault(id) == null)
|
// limit);
|
||||||
throw new ItemNotFoundException();
|
// if (!roles.Any() && await GetOrDefault(id) == null)
|
||||||
return roles;
|
// throw new ItemNotFoundException();
|
||||||
|
// return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -214,17 +217,18 @@ namespace Kyoo.Core.Controllers
|
|||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
throw new NotImplementedException();
|
||||||
.Where(x => x.People.Slug == slug)
|
// ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||||
.Include(x => x.Show),
|
// .Where(x => x.People.Slug == slug)
|
||||||
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
// .Include(x => x.Show),
|
||||||
x => x.Show.Title,
|
// id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
|
||||||
where,
|
// x => x.Show.Title,
|
||||||
sort,
|
// where,
|
||||||
limit);
|
// sort,
|
||||||
if (!roles.Any() && await GetOrDefault(slug) == null)
|
// limit);
|
||||||
throw new ItemNotFoundException();
|
// if (!roles.Any() && await GetOrDefault(slug) == null)
|
||||||
return roles;
|
// throw new ItemNotFoundException();
|
||||||
|
// return roles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,15 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Provider, object>> DefaultSort => x => x.Slug;
|
protected override Sort<Provider> DefaultSort => new Sort<Provider>.By(x => x.Slug);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Provider>> Search(string query)
|
public override async Task<ICollection<Provider>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Providers
|
return await Sort(
|
||||||
.Where(_database.Like<Provider>(x => x.Name, $"%{query}%"))
|
_database.Providers
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Provider>(x => x.Name, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
@ -87,13 +88,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
where T : class, IMetadata
|
where T : class, IMetadata
|
||||||
{
|
{
|
||||||
return ApplyFilters(_database.MetadataIds<T>()
|
throw new NotImplementedException();
|
||||||
.Include(y => y.Provider),
|
// return ApplyFilters(_database.MetadataIds<T>()
|
||||||
x => _database.MetadataIds<T>().FirstOrDefaultAsync(y => y.ResourceID == x),
|
// .Include(y => y.Provider),
|
||||||
x => x.ResourceID,
|
// x => _database.MetadataIds<T>().FirstOrDefaultAsync(y => y.ResourceID == x),
|
||||||
where,
|
// x => x.ResourceID,
|
||||||
sort,
|
// where,
|
||||||
limit);
|
// sort,
|
||||||
|
// limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override Expression<Func<Season, object>> DefaultSort => x => x.SeasonNumber;
|
protected override Sort<Season> DefaultSort => new Sort<Season>.By(x => x.SeasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="SeasonRepository"/>.
|
/// Create a new <see cref="SeasonRepository"/>.
|
||||||
@ -95,9 +95,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override async Task<ICollection<Season>> Search(string query)
|
public override async Task<ICollection<Season>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Seasons
|
return await Sort(
|
||||||
.Where(_database.Like<Season>(x => x.Title, $"%{query}%"))
|
_database.Seasons
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Season>(x => x.Title, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
|
protected override Sort<Show> DefaultSort => new Sort<Show>.By(x => x.Title);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="ShowRepository"/>.
|
/// Create a new <see cref="ShowRepository"/>.
|
||||||
@ -88,9 +88,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
public override async Task<ICollection<Show>> Search(string query)
|
public override async Task<ICollection<Show>> Search(string query)
|
||||||
{
|
{
|
||||||
query = $"%{query}%";
|
query = $"%{query}%";
|
||||||
return await _database.Shows
|
return await Sort(
|
||||||
.Where(_database.Like<Show>(x => x.Title + " " + x.Slug, query))
|
_database.Shows
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Show>(x => x.Title + " " + x.Slug, query))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
|
protected override Sort<Studio> DefaultSort => new Sort<Studio>.By(x => x.Name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StudioRepository"/>.
|
/// Create a new <see cref="StudioRepository"/>.
|
||||||
@ -61,9 +61,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Studio>> Search(string query)
|
public override async Task<ICollection<Studio>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Studios
|
return await Sort(
|
||||||
.Where(_database.Like<Studio>(x => x.Name, $"%{query}%"))
|
_database.Studios
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<Studio>(x => x.Name, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
@ -38,7 +37,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
|
protected override Sort<Track> DefaultSort => new Sort<Track>.By(x => x.TrackIndex);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="TrackRepository"/>.
|
/// Create a new <see cref="TrackRepository"/>.
|
||||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<User, object>> DefaultSort => x => x.Username;
|
protected override Sort<User> DefaultSort => new Sort<User>.By(x => x.Username);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="UserRepository"/>
|
/// Create a new <see cref="UserRepository"/>
|
||||||
@ -54,9 +54,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<User>> Search(string query)
|
public override async Task<ICollection<User>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Users
|
return await Sort(
|
||||||
.Where(_database.Like<User>(x => x.Username, $"%{query}%"))
|
_database.Users
|
||||||
.OrderBy(DefaultSort)
|
.Where(_database.Like<User>(x => x.Username, $"%{query}%"))
|
||||||
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<T> resources = await Repository.GetAll(
|
ICollection<T> resources = await Repository.GetAll(
|
||||||
ApiHelper.ParseWhere<T>(where),
|
ApiHelper.ParseWhere<T>(where),
|
||||||
new Sort<T>(sortBy),
|
Sort<T>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Genre>(x => x.Genres)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Genre>(x => x.Genres)),
|
||||||
new Sort<Show>(sortBy),
|
Sort<Show>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ namespace Kyoo.Core.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Expression<Func<PeopleRole, bool>> whereQuery = ApiHelper.ParseWhere<PeopleRole>(where);
|
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);
|
Pagination pagination = new(limit, afterID);
|
||||||
|
|
||||||
ICollection<PeopleRole> resources = await identifier.Match(
|
ICollection<PeopleRole> resources = await identifier.Match(
|
||||||
|
@ -88,7 +88,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.Matcher<Show>(x => x.StudioID, x => x.Studio.Slug)),
|
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)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Collection>(x => x.Collections)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Collection>(x => x.Collections)),
|
||||||
new Sort<Show>(sortBy),
|
Sort<Show>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Library> resources = await _libraryManager.GetAll(
|
ICollection<Library> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Collection>(x => x.Collections)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Collection>(x => x.Collections)),
|
||||||
new Sort<Library>(sortBy),
|
Sort<Library>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Track> resources = await _libraryManager.GetAll(
|
ICollection<Track> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.Matcher<Track>(x => x.EpisodeID, x => x.Episode.Slug)),
|
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));
|
new Pagination(limit, afterID));
|
||||||
|
|
||||||
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Episode>()) == null)
|
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Episode>()) == null)
|
||||||
|
@ -91,7 +91,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Show> resources = await _libraryManager.GetAll(
|
ICollection<Show> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Library>(x => x.Libraries)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Show, Library>(x => x.Libraries)),
|
||||||
new Sort<Show>(sortBy),
|
Sort<Show>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Collection> resources = await _libraryManager.GetAll(
|
ICollection<Collection> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Library>(x => x.Libraries)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Library>(x => x.Libraries)),
|
||||||
new Sort<Collection>(sortBy),
|
Sort<Collection>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ namespace Kyoo.Core.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Expression<Func<LibraryItem, bool>> whereQuery = ApiHelper.ParseWhere<LibraryItem>(where);
|
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);
|
Pagination pagination = new(limit, afterID);
|
||||||
|
|
||||||
ICollection<LibraryItem> resources = await identifier.Match(
|
ICollection<LibraryItem> resources = await identifier.Match(
|
||||||
|
@ -89,7 +89,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<LibraryItem> resources = await _libraryItems.GetAll(
|
ICollection<LibraryItem> resources = await _libraryItems.GetAll(
|
||||||
ApiHelper.ParseWhere<LibraryItem>(where),
|
ApiHelper.ParseWhere<LibraryItem>(where),
|
||||||
new Sort<LibraryItem>(sortBy),
|
Sort<LibraryItem>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Episode> resources = await _libraryManager.GetAll(
|
ICollection<Episode> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.Matcher<Episode>(x => x.SeasonID, x => x.Season.Slug)),
|
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));
|
new Pagination(limit, afterID));
|
||||||
|
|
||||||
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Season>()) == null)
|
if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame<Season>()) == null)
|
||||||
|
@ -96,7 +96,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Season> resources = await _libraryManager.GetAll(
|
ICollection<Season> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.Matcher<Season>(x => x.ShowID, x => x.Show.Slug)),
|
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)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Episode> resources = await _libraryManager.GetAll(
|
ICollection<Episode> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.Matcher<Episode>(x => x.ShowID, x => x.Show.Slug)),
|
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)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ namespace Kyoo.Core.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Expression<Func<PeopleRole, bool>> whereQuery = ApiHelper.ParseWhere<PeopleRole>(where);
|
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);
|
Pagination pagination = new(limit, afterID);
|
||||||
|
|
||||||
ICollection<PeopleRole> resources = await identifier.Match(
|
ICollection<PeopleRole> resources = await identifier.Match(
|
||||||
@ -232,7 +232,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Genre> resources = await _libraryManager.GetAll(
|
ICollection<Genre> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Genre, Show>(x => x.Shows)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Genre, Show>(x => x.Shows)),
|
||||||
new Sort<Genre>(sortBy),
|
Sort<Genre>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Library> resources = await _libraryManager.GetAll(
|
ICollection<Library> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Show>(x => x.Shows)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Library, Show>(x => x.Shows)),
|
||||||
new Sort<Library>(sortBy),
|
Sort<Library>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
ICollection<Collection> resources = await _libraryManager.GetAll(
|
ICollection<Collection> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Show>(x => x.Shows)),
|
ApiHelper.ParseWhere(where, identifier.IsContainedIn<Collection, Show>(x => x.Shows)),
|
||||||
new Sort<Collection>(sortBy),
|
Sort<Collection>.From(sortBy),
|
||||||
new Pagination(limit, afterID)
|
new Pagination(limit, afterID)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user