aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities/BaseItem.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs118
1 files changed, 83 insertions, 35 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index d1a6b3584..3c46d53e5 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -24,7 +24,9 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaSegments;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
@@ -34,7 +36,6 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
-using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
@@ -107,8 +108,15 @@ namespace MediaBrowser.Controller.Entities
ProductionLocations = Array.Empty<string>();
RemoteTrailers = Array.Empty<MediaUrl>();
ExtraIds = Array.Empty<Guid>();
+ UserData = [];
}
+ /// <summary>
+ /// Gets or Sets the user data collection as cached from the last Db query.
+ /// </summary>
+ [JsonIgnore]
+ public ICollection<UserData> UserData { get; set; }
+
[JsonIgnore]
public string PreferredMetadataCountryCode { get; set; }
@@ -484,7 +492,7 @@ namespace MediaBrowser.Controller.Entities
public static IItemRepository ItemRepository { get; set; }
- public static IChapterRepository ChapterRepository { get; set; }
+ public static IChapterManager ChapterManager { get; set; }
public static IFileSystem FileSystem { get; set; }
@@ -701,19 +709,7 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- var customRating = CustomRating;
- if (!string.IsNullOrEmpty(customRating))
- {
- return customRating;
- }
-
- var parent = DisplayParent;
- if (parent is not null)
- {
- return parent.CustomRatingForComparison;
- }
-
- return null;
+ return GetCustomRatingForComparision();
}
}
@@ -791,6 +787,26 @@ namespace MediaBrowser.Controller.Entities
/// <value>The remote trailers.</value>
public IReadOnlyList<MediaUrl> RemoteTrailers { get; set; }
+ private string GetCustomRatingForComparision(HashSet<Guid> callstack = null)
+ {
+ callstack ??= new();
+ var customRating = CustomRating;
+ if (!string.IsNullOrEmpty(customRating))
+ {
+ return customRating;
+ }
+
+ callstack.Add(Id);
+
+ var parent = DisplayParent;
+ if (parent is not null && !callstack.Contains(parent.Id))
+ {
+ return parent.GetCustomRatingForComparision(callstack);
+ }
+
+ return null;
+ }
+
public virtual double GetDefaultPrimaryImageAspectRatio()
{
return 0;
@@ -1112,6 +1128,15 @@ namespace MediaBrowser.Controller.Entities
var protocol = item.PathProtocol;
+ // Resolve the item path so everywhere we use the media source it will always point to
+ // the correct path even if symlinks are in use. Calling ResolveLinkTarget on a non-link
+ // path will return null, so it's safe to check for all paths.
+ var itemPath = item.Path;
+ if (protocol is MediaProtocol.File && FileSystemHelper.ResolveLinkTarget(itemPath, returnFinalTarget: true) is { Exists: true } linkInfo)
+ {
+ itemPath = linkInfo.FullName;
+ }
+
var info = new MediaSourceInfo
{
Id = item.Id.ToString("N", CultureInfo.InvariantCulture),
@@ -1119,7 +1144,7 @@ namespace MediaBrowser.Controller.Entities
MediaStreams = MediaSourceManager.GetMediaStreams(item.Id),
MediaAttachments = MediaSourceManager.GetMediaAttachments(item.Id),
Name = GetMediaSourceName(item),
- Path = enablePathSubstitution ? GetMappedPath(item, item.Path, protocol) : item.Path,
+ Path = enablePathSubstitution ? GetMappedPath(item, itemPath, protocol) : itemPath,
RunTimeTicks = item.RunTimeTicks,
Container = item.Container,
Size = item.Size,
@@ -1266,7 +1291,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
- /// Overrides the base implementation to refresh metadata for local trailers.
+ /// The base implementation to refresh metadata.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
@@ -1363,9 +1388,7 @@ namespace MediaBrowser.Controller.Entities
protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
- var path = ContainingFolderPath;
-
- return directoryService.GetFileSystemEntries(path);
+ return directoryService.GetFileSystemEntries(ContainingFolderPath);
}
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
@@ -1394,6 +1417,23 @@ namespace MediaBrowser.Controller.Entities
return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken);
});
+ // Cleanup removed extras
+ var removedExtraIds = item.ExtraIds.Where(e => !newExtraIds.Contains(e)).ToArray();
+ if (removedExtraIds.Length > 0)
+ {
+ var removedExtras = LibraryManager.GetItemList(new InternalItemsQuery()
+ {
+ ItemIds = removedExtraIds
+ });
+ foreach (var removedExtra in removedExtras)
+ {
+ LibraryManager.DeleteItem(removedExtra, new DeleteOptions()
+ {
+ DeleteFileLocation = false
+ });
+ }
+ }
+
await Task.WhenAll(tasks).ConfigureAwait(false);
item.ExtraIds = newExtraIds;
@@ -1408,7 +1448,14 @@ namespace MediaBrowser.Controller.Entities
public virtual bool RequiresRefresh()
{
- return false;
+ if (string.IsNullOrEmpty(Path) || DateModified == DateTime.MinValue)
+ {
+ return false;
+ }
+
+ var info = FileSystem.GetFileSystemInfo(Path);
+
+ return info.Exists && this.HasChanged(info.LastWriteTimeUtc);
}
public virtual List<string> GetUserDataKeys()
@@ -1805,7 +1852,7 @@ namespace MediaBrowser.Controller.Entities
public void SetStudios(IEnumerable<string> names)
{
- Studios = names.Trimmed().Distinct().ToArray();
+ Studios = names.Trimmed().Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
/// <summary>
@@ -1971,9 +2018,10 @@ namespace MediaBrowser.Controller.Entities
}
// Remove from file system
- if (info.IsLocalFile)
+ var path = info.Path;
+ if (info.IsLocalFile && !string.IsNullOrWhiteSpace(path))
{
- FileSystem.DeleteFile(info.Path);
+ FileSystem.DeleteFile(path);
}
// Remove from item
@@ -2051,7 +2099,7 @@ namespace MediaBrowser.Controller.Entities
{
if (imageType == ImageType.Chapter)
{
- var chapter = ChapterRepository.GetChapter(this.Id, imageIndex);
+ var chapter = ChapterManager.GetChapter(Id, imageIndex);
if (chapter is null)
{
@@ -2101,7 +2149,7 @@ namespace MediaBrowser.Controller.Entities
if (image.Type == ImageType.Chapter)
{
- var chapters = ChapterRepository.GetChapters(this.Id);
+ var chapters = ChapterManager.GetChapters(Id);
for (var i = 0; i < chapters.Count; i++)
{
if (chapters[i].ImagePath == image.Path)
@@ -2284,27 +2332,27 @@ namespace MediaBrowser.Controller.Entities
return UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None);
}
- public virtual bool IsPlayed(User user)
+ public virtual bool IsPlayed(User user, UserItemData userItemData)
{
- var userdata = UserDataManager.GetUserData(user, this);
+ userItemData ??= UserDataManager.GetUserData(user, this);
- return userdata is not null && userdata.Played;
+ return userItemData is not null && userItemData.Played;
}
- public bool IsFavoriteOrLiked(User user)
+ public bool IsFavoriteOrLiked(User user, UserItemData userItemData)
{
- var userdata = UserDataManager.GetUserData(user, this);
+ userItemData ??= UserDataManager.GetUserData(user, this);
- return userdata is not null && (userdata.IsFavorite || (userdata.Likes ?? false));
+ return userItemData is not null && (userItemData.IsFavorite || (userItemData.Likes ?? false));
}
- public virtual bool IsUnplayed(User user)
+ public virtual bool IsUnplayed(User user, UserItemData userItemData)
{
ArgumentNullException.ThrowIfNull(user);
- var userdata = UserDataManager.GetUserData(user, this);
+ userItemData ??= UserDataManager.GetUserData(user, this);
- return userdata is null || !userdata.Played;
+ return userItemData is null || !userItemData.Played;
}
ItemLookupInfo IHasLookupInfo<ItemLookupInfo>.GetLookupInfo()