aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations
diff options
context:
space:
mode:
authorJacob Warren <109393233+jjwarrenSEP@users.noreply.github.com>2025-03-27 20:05:03 -0400
committerGitHub <noreply@github.com>2025-03-27 18:05:03 -0600
commit07f07ba6bcd4d5466412d1c9965f06a358690545 (patch)
tree7d495ba56efce165c2df0130d7ec9c3d4889e6a9 /Jellyfin.Server.Implementations
parenta123a2cb22096c558953c73432f254eb120a5839 (diff)
Fix Sort by Year Bug (#12101) (#13733)
Diffstat (limited to 'Jellyfin.Server.Implementations')
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.cs46
-rw-r--r--Jellyfin.Server.Implementations/Item/OrderMapper.cs57
2 files changed, 59 insertions, 44 deletions
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
index 7b5b6b94d..b0a36b3ae 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
@@ -7,11 +7,8 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Globalization;
-using System.IO;
using System.Linq;
-using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.Json;
@@ -1209,45 +1206,6 @@ public sealed class BaseItemRepository
return query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(type);
}
- private Expression<Func<BaseItemEntity, object>> MapOrderByField(ItemSortBy sortBy, InternalItemsQuery query)
- {
-#pragma warning disable CS8603 // Possible null reference return.
- return sortBy switch
- {
- ItemSortBy.AirTime => e => e.SortName, // TODO
- ItemSortBy.Runtime => e => e.RunTimeTicks,
- ItemSortBy.Random => e => EF.Functions.Random(),
- ItemSortBy.DatePlayed => e => e.UserData!.FirstOrDefault(f => f.UserId == query.User!.Id)!.LastPlayedDate,
- ItemSortBy.PlayCount => e => e.UserData!.FirstOrDefault(f => f.UserId == query.User!.Id)!.PlayCount,
- ItemSortBy.IsFavoriteOrLiked => e => e.UserData!.FirstOrDefault(f => f.UserId == query.User!.Id)!.IsFavorite,
- ItemSortBy.IsFolder => e => e.IsFolder,
- ItemSortBy.IsPlayed => e => e.UserData!.FirstOrDefault(f => f.UserId == query.User!.Id)!.Played,
- ItemSortBy.IsUnplayed => e => !e.UserData!.FirstOrDefault(f => f.UserId == query.User!.Id)!.Played,
- ItemSortBy.DateLastContentAdded => e => e.DateLastMediaAdded,
- ItemSortBy.Artist => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.Artist).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
- ItemSortBy.AlbumArtist => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.AlbumArtist).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
- ItemSortBy.Studio => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.Studios).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
- ItemSortBy.OfficialRating => e => e.InheritedParentalRatingValue,
- // ItemSortBy.SeriesDatePlayed => "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)",
- ItemSortBy.SeriesSortName => e => e.SeriesName,
- // ItemSortBy.AiredEpisodeOrder => "AiredEpisodeOrder",
- ItemSortBy.Album => e => e.Album,
- ItemSortBy.DateCreated => e => e.DateCreated,
- ItemSortBy.PremiereDate => e => e.PremiereDate,
- ItemSortBy.StartDate => e => e.StartDate,
- ItemSortBy.Name => e => e.Name,
- ItemSortBy.CommunityRating => e => e.CommunityRating,
- ItemSortBy.ProductionYear => e => e.ProductionYear,
- ItemSortBy.CriticRating => e => e.CriticRating,
- ItemSortBy.VideoBitRate => e => e.TotalBitrate,
- ItemSortBy.ParentIndexNumber => e => e.ParentIndexNumber,
- ItemSortBy.IndexNumber => e => e.IndexNumber,
- _ => e => e.SortName
- };
-#pragma warning restore CS8603 // Possible null reference return.
-
- }
-
private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query)
{
if (!query.GroupByPresentationUniqueKey)
@@ -1302,7 +1260,7 @@ public sealed class BaseItemRepository
var firstOrdering = orderBy.FirstOrDefault();
if (firstOrdering != default)
{
- var expression = MapOrderByField(firstOrdering.OrderBy, filter);
+ var expression = OrderMapper.MapOrderByField(firstOrdering.OrderBy, filter);
if (firstOrdering.SortOrder == SortOrder.Ascending)
{
orderedQuery = query.OrderBy(expression);
@@ -1327,7 +1285,7 @@ public sealed class BaseItemRepository
foreach (var item in orderBy.Skip(1))
{
- var expression = MapOrderByField(item.OrderBy, filter);
+ var expression = OrderMapper.MapOrderByField(item.OrderBy, filter);
if (item.SortOrder == SortOrder.Ascending)
{
orderedQuery = orderedQuery!.ThenBy(expression);
diff --git a/Jellyfin.Server.Implementations/Item/OrderMapper.cs b/Jellyfin.Server.Implementations/Item/OrderMapper.cs
new file mode 100644
index 000000000..df2fd08b1
--- /dev/null
+++ b/Jellyfin.Server.Implementations/Item/OrderMapper.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Entities;
+using Microsoft.EntityFrameworkCore;
+
+namespace Jellyfin.Server.Implementations.Item;
+
+/// <summary>
+/// Static class for methods which maps types of ordering to their respecting ordering functions.
+/// </summary>
+public static class OrderMapper
+{
+ /// <summary>
+ /// Creates Func to be executed later with a given BaseItemEntity input for sorting items on query.
+ /// </summary>
+ /// <param name="sortBy">Item property to sort by.</param>
+ /// <param name="query">Context Query.</param>
+ /// <returns>Func to be executed later for sorting query.</returns>
+ public static Expression<Func<BaseItemEntity, object?>> MapOrderByField(ItemSortBy sortBy, InternalItemsQuery query)
+ {
+ return sortBy switch
+ {
+ ItemSortBy.AirTime => e => e.SortName, // TODO
+ ItemSortBy.Runtime => e => e.RunTimeTicks,
+ ItemSortBy.Random => e => EF.Functions.Random(),
+ ItemSortBy.DatePlayed => e => e.UserData!.FirstOrDefault(f => f.UserId.Equals(query.User!.Id))!.LastPlayedDate,
+ ItemSortBy.PlayCount => e => e.UserData!.FirstOrDefault(f => f.UserId.Equals(query.User!.Id))!.PlayCount,
+ ItemSortBy.IsFavoriteOrLiked => e => e.UserData!.FirstOrDefault(f => f.UserId.Equals(query.User!.Id))!.IsFavorite,
+ ItemSortBy.IsFolder => e => e.IsFolder,
+ ItemSortBy.IsPlayed => e => e.UserData!.FirstOrDefault(f => f.UserId.Equals(query.User!.Id))!.Played,
+ ItemSortBy.IsUnplayed => e => !e.UserData!.FirstOrDefault(f => f.UserId.Equals(query.User!.Id))!.Played,
+ ItemSortBy.DateLastContentAdded => e => e.DateLastMediaAdded,
+ ItemSortBy.Artist => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.Artist).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
+ ItemSortBy.AlbumArtist => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.AlbumArtist).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
+ ItemSortBy.Studio => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.Studios).Select(f => f.ItemValue.CleanValue).FirstOrDefault(),
+ ItemSortBy.OfficialRating => e => e.InheritedParentalRatingValue,
+ // ItemSortBy.SeriesDatePlayed => "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)",
+ ItemSortBy.SeriesSortName => e => e.SeriesName,
+ // ItemSortBy.AiredEpisodeOrder => "AiredEpisodeOrder",
+ ItemSortBy.Album => e => e.Album,
+ ItemSortBy.DateCreated => e => e.DateCreated,
+ ItemSortBy.PremiereDate => e => (e.PremiereDate ?? (e.ProductionYear.HasValue ? DateTime.MinValue.AddYears(e.ProductionYear.Value - 1) : null)),
+ ItemSortBy.StartDate => e => e.StartDate,
+ ItemSortBy.Name => e => e.Name,
+ ItemSortBy.CommunityRating => e => e.CommunityRating,
+ ItemSortBy.ProductionYear => e => e.ProductionYear,
+ ItemSortBy.CriticRating => e => e.CriticRating,
+ ItemSortBy.VideoBitRate => e => e.TotalBitrate,
+ ItemSortBy.ParentIndexNumber => e => e.ParentIndexNumber,
+ ItemSortBy.IndexNumber => e => e.IndexNumber,
+ _ => e => e.SortName
+ };
+ }
+}