mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-11-01 11:07:22 -04:00
Merge pull request #14634 from crobibero/itemname-counts
This commit is contained in:
commit
bd94ca3071
@ -1,6 +1,7 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
@ -37,6 +38,77 @@ namespace Emby.Server.Implementations.Dto
|
||||
{
|
||||
public class DtoService : IDtoService
|
||||
{
|
||||
private static readonly FrozenDictionary<BaseItemKind, BaseItemKind[]> _relatedItemKinds = new Dictionary<BaseItemKind, BaseItemKind[]>
|
||||
{
|
||||
{
|
||||
BaseItemKind.Genre, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.Episode,
|
||||
BaseItemKind.Movie,
|
||||
BaseItemKind.LiveTvProgram,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicArtist,
|
||||
BaseItemKind.MusicVideo,
|
||||
BaseItemKind.Series,
|
||||
BaseItemKind.Trailer
|
||||
]
|
||||
},
|
||||
{
|
||||
BaseItemKind.MusicArtist, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicVideo
|
||||
]
|
||||
},
|
||||
{
|
||||
BaseItemKind.MusicGenre, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicArtist,
|
||||
BaseItemKind.MusicVideo
|
||||
]
|
||||
},
|
||||
{
|
||||
BaseItemKind.Person, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.Episode,
|
||||
BaseItemKind.Movie,
|
||||
BaseItemKind.LiveTvProgram,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicArtist,
|
||||
BaseItemKind.MusicVideo,
|
||||
BaseItemKind.Series,
|
||||
BaseItemKind.Trailer
|
||||
]
|
||||
},
|
||||
{
|
||||
BaseItemKind.Studio, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.Episode,
|
||||
BaseItemKind.Movie,
|
||||
BaseItemKind.LiveTvProgram,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicArtist,
|
||||
BaseItemKind.MusicVideo,
|
||||
BaseItemKind.Series,
|
||||
BaseItemKind.Trailer
|
||||
]
|
||||
},
|
||||
{
|
||||
BaseItemKind.Year, [
|
||||
BaseItemKind.Audio,
|
||||
BaseItemKind.Episode,
|
||||
BaseItemKind.Movie,
|
||||
BaseItemKind.LiveTvProgram,
|
||||
BaseItemKind.MusicAlbum,
|
||||
BaseItemKind.MusicArtist,
|
||||
BaseItemKind.MusicVideo,
|
||||
BaseItemKind.Series,
|
||||
BaseItemKind.Trailer
|
||||
]
|
||||
}
|
||||
}.ToFrozenDictionary();
|
||||
|
||||
private readonly ILogger<DtoService> _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IUserDataManager _userDataRepository;
|
||||
@ -102,21 +174,9 @@ namespace Emby.Server.Implementations.Dto
|
||||
(programTuples ??= []).Add((item, dto));
|
||||
}
|
||||
|
||||
if (item is IItemByName byName)
|
||||
if (options.ContainsField(ItemFields.ItemCounts))
|
||||
{
|
||||
if (options.ContainsField(ItemFields.ItemCounts))
|
||||
{
|
||||
var libraryItems = byName.GetTaggedItems(new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
DtoOptions = new DtoOptions(false)
|
||||
{
|
||||
EnableImages = false
|
||||
}
|
||||
});
|
||||
|
||||
SetItemByNameInfo(item, dto, libraryItems);
|
||||
}
|
||||
SetItemByNameInfo(dto, user);
|
||||
}
|
||||
|
||||
returnItems[index] = dto;
|
||||
@ -147,34 +207,14 @@ namespace Emby.Server.Implementations.Dto
|
||||
LivetvManager.AddInfoToProgramDto(new[] { (item, dto) }, options.Fields, user).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
if (item is IItemByName itemByName
|
||||
&& options.ContainsField(ItemFields.ItemCounts))
|
||||
if (options.ContainsField(ItemFields.ItemCounts))
|
||||
{
|
||||
SetItemByNameInfo(
|
||||
item,
|
||||
dto,
|
||||
GetTaggedItems(
|
||||
itemByName,
|
||||
user,
|
||||
new DtoOptions(false)
|
||||
{
|
||||
EnableImages = false
|
||||
}));
|
||||
SetItemByNameInfo(dto, user);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<BaseItem> GetTaggedItems(IItemByName byName, User? user, DtoOptions options)
|
||||
{
|
||||
return byName.GetTaggedItems(
|
||||
new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
DtoOptions = options
|
||||
});
|
||||
}
|
||||
|
||||
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var dto = new BaseItemDto
|
||||
@ -315,11 +355,15 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// TODO refactor this to use the new SetItemByNameInfo.
|
||||
/// Some callers already have the counts extracted so no reason to retrieve them again.
|
||||
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem>? taggedItems, User? user = null)
|
||||
{
|
||||
var dto = GetBaseItemDtoInternal(item, options, user);
|
||||
|
||||
if (taggedItems is not null && options.ContainsField(ItemFields.ItemCounts))
|
||||
if (options.ContainsField(ItemFields.ItemCounts)
|
||||
&& taggedItems is not null
|
||||
&& taggedItems.Count != 0)
|
||||
{
|
||||
SetItemByNameInfo(item, dto, taggedItems);
|
||||
}
|
||||
@ -327,6 +371,57 @@ namespace Emby.Server.Implementations.Dto
|
||||
return dto;
|
||||
}
|
||||
|
||||
private void SetItemByNameInfo(BaseItemDto dto, User? user)
|
||||
{
|
||||
if (!_relatedItemKinds.TryGetValue(dto.Type, out var relatedItemKinds))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
DtoOptions = new DtoOptions(false) { EnableImages = false },
|
||||
IncludeItemTypes = relatedItemKinds
|
||||
};
|
||||
|
||||
switch (dto.Type)
|
||||
{
|
||||
case BaseItemKind.Genre:
|
||||
case BaseItemKind.MusicGenre:
|
||||
query.GenreIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.MusicArtist:
|
||||
query.ArtistIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Person:
|
||||
query.PersonIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Studio:
|
||||
query.StudioIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Year
|
||||
when int.TryParse(dto.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year):
|
||||
query.Years = [year];
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
var counts = _libraryManager.GetItemCounts(query);
|
||||
|
||||
dto.AlbumCount = counts.AlbumCount;
|
||||
dto.ArtistCount = counts.ArtistCount;
|
||||
dto.EpisodeCount = counts.EpisodeCount;
|
||||
dto.MovieCount = counts.MovieCount;
|
||||
dto.MusicVideoCount = counts.MusicVideoCount;
|
||||
dto.ProgramCount = counts.ProgramCount;
|
||||
dto.SeriesCount = counts.SeriesCount;
|
||||
dto.SongCount = counts.SongCount;
|
||||
dto.TrailerCount = counts.TrailerCount;
|
||||
dto.ChildCount = counts.TotalItemCount();
|
||||
}
|
||||
|
||||
private static void SetItemByNameInfo(BaseItem item, BaseItemDto dto, IReadOnlyList<BaseItem> taggedItems)
|
||||
{
|
||||
if (item is MusicArtist)
|
||||
|
||||
@ -1389,6 +1389,25 @@ namespace Emby.Server.Implementations.Library
|
||||
return _itemRepository.GetCount(query);
|
||||
}
|
||||
|
||||
public ItemCounts GetItemCounts(InternalItemsQuery query)
|
||||
{
|
||||
if (query.Recursive && !query.ParentId.IsEmpty())
|
||||
{
|
||||
var parent = GetItemById(query.ParentId);
|
||||
if (parent is not null)
|
||||
{
|
||||
SetTopParentIdsOrAncestors(query, [parent]);
|
||||
}
|
||||
}
|
||||
|
||||
if (query.User is not null)
|
||||
{
|
||||
AddUserToQuery(query, query.User);
|
||||
}
|
||||
|
||||
return _itemRepository.GetItemCounts(query);
|
||||
}
|
||||
|
||||
public IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents)
|
||||
{
|
||||
SetTopParentIdsOrAncestors(query, parents);
|
||||
|
||||
@ -457,6 +457,66 @@ public sealed class BaseItemRepository
|
||||
return dbQuery.Count();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ItemCounts GetItemCounts(InternalItemsQuery filter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(filter);
|
||||
// Hack for right now since we currently don't support filtering out these duplicates within a query
|
||||
PrepareFilterQuery(filter);
|
||||
|
||||
using var context = _dbProvider.CreateDbContext();
|
||||
var dbQuery = TranslateQuery(context.BaseItems.AsNoTracking(), context, filter);
|
||||
|
||||
var counts = dbQuery
|
||||
.GroupBy(x => x.Type)
|
||||
.Select(x => new { x.Key, Count = x.Count() })
|
||||
.AsEnumerable();
|
||||
|
||||
var lookup = _itemTypeLookup.BaseItemKindNames;
|
||||
var result = new ItemCounts();
|
||||
foreach (var count in counts)
|
||||
{
|
||||
if (string.Equals(count.Key, lookup[BaseItemKind.MusicAlbum], StringComparison.Ordinal))
|
||||
{
|
||||
result.AlbumCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.MusicArtist], StringComparison.Ordinal))
|
||||
{
|
||||
result.ArtistCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.Episode], StringComparison.Ordinal))
|
||||
{
|
||||
result.EpisodeCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.Movie], StringComparison.Ordinal))
|
||||
{
|
||||
result.MovieCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.MusicVideo], StringComparison.Ordinal))
|
||||
{
|
||||
result.MusicVideoCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.LiveTvProgram], StringComparison.Ordinal))
|
||||
{
|
||||
result.ProgramCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.Series], StringComparison.Ordinal))
|
||||
{
|
||||
result.SeriesCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.Audio], StringComparison.Ordinal))
|
||||
{
|
||||
result.SongCount = count.Count;
|
||||
}
|
||||
else if (string.Equals(count.Key, lookup[BaseItemKind.Trailer], StringComparison.Ordinal))
|
||||
{
|
||||
result.TrailerCount = count.Count;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1307 // Specify StringComparison for clarity
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
|
||||
@ -630,6 +630,8 @@ namespace MediaBrowser.Controller.Library
|
||||
|
||||
int GetCount(InternalItemsQuery query);
|
||||
|
||||
ItemCounts GetItemCounts(InternalItemsQuery query);
|
||||
|
||||
Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason);
|
||||
|
||||
BaseItem GetParentItem(Guid? parentId, Guid? userId);
|
||||
|
||||
@ -84,6 +84,8 @@ public interface IItemRepository
|
||||
|
||||
int GetCount(InternalItemsQuery filter);
|
||||
|
||||
ItemCounts GetItemCounts(InternalItemsQuery filter);
|
||||
|
||||
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery filter);
|
||||
|
||||
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery filter);
|
||||
|
||||
@ -76,5 +76,14 @@ namespace MediaBrowser.Model.Dto
|
||||
/// </summary>
|
||||
/// <value>The item count.</value>
|
||||
public int ItemCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds all counts.
|
||||
/// </summary>
|
||||
/// <returns>The total of the counts.</returns>
|
||||
public int TotalItemCount()
|
||||
{
|
||||
return MovieCount + SeriesCount + EpisodeCount + ArtistCount + ProgramCount + TrailerCount + SongCount + AlbumCount + MusicVideoCount + BoxSetCount + BookCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user