aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities/BaseItem.cs
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-07-27 11:48:15 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-07-27 12:12:17 +0200
commit79a55327dcb3899fb85147f7ec6b19cd71e5dcfb (patch)
tree6c1a9e7358a307796f5e19ec665afa49d49d6202 /MediaBrowser.Controller/Entities/BaseItem.cs
parentdbc796b0b03ea8d09c7b7cb83fd082e9d767a853 (diff)
Fix extras naming and version assignment
Diffstat (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs52
1 files changed, 42 insertions, 10 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 209feac702..9c6d18d509 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -88,7 +88,7 @@ namespace MediaBrowser.Controller.Entities
Model.Entities.ExtraType.Short
};
- private static readonly char[] VersionDelimiters = ['-', '_', '.'];
+ private protected static readonly char[] VersionDelimiters = ['-', '_', '.'];
private string _sortName;
@@ -1543,19 +1543,33 @@ namespace MediaBrowser.Controller.Entities
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
- var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
- var newExtraIds = Array.ConvertAll(extras, x => x.Id);
-
+ // An extra is owned by the version it is named after, so all of them are maintained together.
var currentExtras = LibraryManager.GetItemList(new InternalItemsQuery()
{
- OwnerIds = [item.Id]
- });
+ OwnerIds = item.GetOwnedVersionIds()
+ }).Where(e => e.ExtraType.HasValue).ToList();
var currentExtraIds = currentExtras.Select(e => e.Id).ToArray();
+ // Snapshot the persisted names before resolving, as FindExtras corrects the name on the
+ // items it hands back and may well hand back these very instances.
+ var currentExtraNames = new Dictionary<Guid, string>();
+ foreach (var extra in currentExtras)
+ {
+ currentExtraNames[extra.Id] = extra.Name;
+ }
+
+ var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
+ var newExtraIds = Array.ConvertAll(extras, x => x.Id);
+
+ var renamedExtraIds = extras
+ .Where(e => currentExtraNames.TryGetValue(e.Id, out var oldName) && !string.Equals(oldName, e.Name, StringComparison.Ordinal))
+ .Select(e => e.Id)
+ .ToHashSet();
+
var extrasChanged = !currentExtraIds.OrderBy(x => x).SequenceEqual(newExtraIds.OrderBy(x => x));
- if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
+ if (!extrasChanged && renamedExtraIds.Count == 0 && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
{
// The owner's dates may only have become known after its extras were created, so keep
// them in sync even when there is nothing to refresh.
@@ -1570,12 +1584,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- var ownerId = item.Id;
-
var tasks = extras.Select(i =>
{
+ var ownerId = item.GetOwnerIdForExtra(i);
var subOptions = new MetadataRefreshOptions(options);
- if (!i.OwnerId.Equals(ownerId) || !i.ParentId.IsEmpty())
+ if (!i.OwnerId.Equals(ownerId) || !i.ParentId.IsEmpty() || renamedExtraIds.Contains(i.Id))
{
subOptions.ForceSave = true;
}
@@ -2921,6 +2934,25 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Gets the ids of this item and the versions of it whose extras it maintains.
+ /// </summary>
+ /// <returns>An array containing the version ids.</returns>
+ protected virtual Guid[] GetOwnedVersionIds()
+ {
+ return [Id];
+ }
+
+ /// <summary>
+ /// Gets the id of the version an extra belongs to.
+ /// </summary>
+ /// <param name="extra">The extra.</param>
+ /// <returns>The id of the owning version.</returns>
+ protected virtual Guid GetOwnerIdForExtra(BaseItem extra)
+ {
+ return Id;
+ }
+
+ /// <summary>
/// Get all extras associated with this item, sorted by <see cref="SortName"/>.
/// </summary>
/// <param name="user">The user to apply parental restrictions for, or <c>null</c> to skip restriction checks.</param>