You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.0 KiB
168 lines
5.0 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using Jellyfin.Data.Entities;
|
|
using Jellyfin.Data.Enums;
|
|
using Jellyfin.Extensions;
|
|
using MediaBrowser.Controller.Entities;
|
|
using MediaBrowser.Controller.Persistence;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Jellyfin.Server.Implementations.Item;
|
|
|
|
/// <summary>
|
|
/// Manager for handling people.
|
|
/// </summary>
|
|
/// <param name="dbProvider">Efcore Factory.</param>
|
|
/// <remarks>
|
|
/// Initializes a new instance of the <see cref="PeopleRepository"/> class.
|
|
/// </remarks>
|
|
public class PeopleRepository(IDbContextFactory<JellyfinDbContext> dbProvider) : IPeopleRepository
|
|
{
|
|
private readonly IDbContextFactory<JellyfinDbContext> _dbProvider = dbProvider;
|
|
|
|
/// <inheritdoc/>
|
|
public IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery filter)
|
|
{
|
|
using var context = _dbProvider.CreateDbContext();
|
|
var dbQuery = TranslateQuery(context.Peoples.AsNoTracking(), context, filter);
|
|
|
|
dbQuery = dbQuery.OrderBy(e => e.ListOrder);
|
|
if (filter.Limit > 0)
|
|
{
|
|
dbQuery = dbQuery.Take(filter.Limit);
|
|
}
|
|
|
|
return dbQuery.AsEnumerable().Select(Map).ToImmutableArray();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter)
|
|
{
|
|
using var context = _dbProvider.CreateDbContext();
|
|
var dbQuery = TranslateQuery(context.Peoples.AsNoTracking(), context, filter);
|
|
|
|
dbQuery = dbQuery.OrderBy(e => e.ListOrder);
|
|
if (filter.Limit > 0)
|
|
{
|
|
dbQuery = dbQuery.Take(filter.Limit);
|
|
}
|
|
|
|
return dbQuery.Select(e => e.Name).ToImmutableArray();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void UpdatePeople(Guid itemId, IReadOnlyList<PersonInfo> people)
|
|
{
|
|
using var context = _dbProvider.CreateDbContext();
|
|
using var transaction = context.Database.BeginTransaction();
|
|
|
|
context.Peoples.Where(e => e.ItemId.Equals(itemId)).ExecuteDelete();
|
|
context.Peoples.AddRange(people.Select(Map));
|
|
context.SaveChanges();
|
|
transaction.Commit();
|
|
}
|
|
|
|
private PersonInfo Map(People people)
|
|
{
|
|
var personInfo = new PersonInfo()
|
|
{
|
|
ItemId = people.ItemId,
|
|
Name = people.Name,
|
|
Role = people.Role,
|
|
SortOrder = people.SortOrder,
|
|
};
|
|
if (Enum.TryParse<PersonKind>(people.PersonType, out var kind))
|
|
{
|
|
personInfo.Type = kind;
|
|
}
|
|
|
|
return personInfo;
|
|
}
|
|
|
|
private People Map(PersonInfo people)
|
|
{
|
|
var personInfo = new People()
|
|
{
|
|
ItemId = people.ItemId,
|
|
Name = people.Name,
|
|
Role = people.Role,
|
|
SortOrder = people.SortOrder,
|
|
PersonType = people.Type.ToString(),
|
|
Item = null!,
|
|
ListOrder = people.SortOrder
|
|
};
|
|
|
|
return personInfo;
|
|
}
|
|
|
|
private IQueryable<People> TranslateQuery(IQueryable<People> query, JellyfinDbContext context, InternalPeopleQuery filter)
|
|
{
|
|
if (filter.User is not null && filter.IsFavorite.HasValue)
|
|
{
|
|
query = query.Where(e => e.PersonType == typeof(Person).FullName)
|
|
.Where(e => context.BaseItems.Where(d => context.UserData.Where(e => e.IsFavorite == filter.IsFavorite && e.UserId.Equals(filter.User.Id)).Any(f => f.Key == d.UserDataKey))
|
|
.Select(f => f.Name).Contains(e.Name));
|
|
}
|
|
|
|
if (!filter.ItemId.IsEmpty())
|
|
{
|
|
query = query.Where(e => e.ItemId.Equals(filter.ItemId));
|
|
}
|
|
|
|
if (!filter.AppearsInItemId.IsEmpty())
|
|
{
|
|
query = query.Where(e => context.Peoples.Where(f => f.ItemId.Equals(filter.AppearsInItemId)).Select(e => e.Name).Contains(e.Name));
|
|
}
|
|
|
|
var queryPersonTypes = filter.PersonTypes.Where(IsValidPersonType).ToList();
|
|
if (queryPersonTypes.Count > 0)
|
|
{
|
|
query = query.Where(e => queryPersonTypes.Contains(e.PersonType));
|
|
}
|
|
|
|
var queryExcludePersonTypes = filter.ExcludePersonTypes.Where(IsValidPersonType).ToList();
|
|
|
|
if (queryExcludePersonTypes.Count > 0)
|
|
{
|
|
query = query.Where(e => !queryPersonTypes.Contains(e.PersonType));
|
|
}
|
|
|
|
if (filter.MaxListOrder.HasValue)
|
|
{
|
|
query = query.Where(e => e.ListOrder <= filter.MaxListOrder.Value);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(filter.NameContains))
|
|
{
|
|
query = query.Where(e => e.Name.Contains(filter.NameContains));
|
|
}
|
|
|
|
return query;
|
|
}
|
|
|
|
private bool IsAlphaNumeric(string str)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(str))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < str.Length; i++)
|
|
{
|
|
if (!char.IsLetter(str[i]) && !char.IsNumber(str[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool IsValidPersonType(string value)
|
|
{
|
|
return IsAlphaNumeric(value);
|
|
}
|
|
}
|