aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities/Folder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Entities/Folder.cs')
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs141
1 files changed, 106 insertions, 35 deletions
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index ab0dd6820..151b957fe 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -337,6 +337,11 @@ namespace MediaBrowser.Controller.Entities
try
{
+ if (GetParents().Any(f => f.Id.Equals(Id)))
+ {
+ throw new InvalidOperationException("Recursive datastructure detected abort processing this item.");
+ }
+
await ValidateChildrenInternal2(progress, recursive, refreshChildMetadata, allowRemoveRoot, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
}
finally
@@ -452,6 +457,12 @@ namespace MediaBrowser.Controller.Entities
{
foreach (var item in itemsRemoved)
{
+ if (!item.CanDelete())
+ {
+ Logger.LogDebug("Item marked as non-removable, skipping: {Path}", item.Path ?? item.Name);
+ continue;
+ }
+
if (item.IsFileProtocol)
{
Logger.LogDebug("Removed item: {Path}", item.Path);
@@ -704,14 +715,21 @@ namespace MediaBrowser.Controller.Entities
}
else
{
- items = GetRecursiveChildren(user, query, out totalCount);
+ // Save pagination params before clearing them to prevent pagination from happening
+ // before sorting. PostFilterAndSort will apply pagination after sorting.
+ var limit = query.Limit;
+ var startIndex = query.StartIndex;
query.Limit = null;
- query.StartIndex = null; // override these here as they have already been applied
+ query.StartIndex = null;
+
+ items = GetRecursiveChildren(user, query, out totalCount);
+
+ // Restore pagination params so PostFilterAndSort can apply them after sorting
+ query.Limit = limit;
+ query.StartIndex = startIndex;
}
- var result = PostFilterAndSort(items, query);
- result.TotalRecordCount = totalCount;
- return result;
+ return PostFilterAndSort(items, query);
}
if (this is not UserRootFolder
@@ -969,22 +987,19 @@ namespace MediaBrowser.Controller.Entities
else
{
// need to pass this param to the children.
+ // Note: Don't pass Limit/StartIndex here as pagination should happen after sorting in PostFilterAndSort
var childQuery = new InternalItemsQuery
{
DisplayAlbumFolders = query.DisplayAlbumFolders,
- Limit = query.Limit,
- StartIndex = query.StartIndex
+ NameStartsWith = query.NameStartsWith,
+ NameStartsWithOrGreater = query.NameStartsWithOrGreater,
+ NameLessThan = query.NameLessThan
};
items = GetChildren(user, true, out totalItemCount, childQuery).Where(filter);
-
- query.Limit = null;
- query.StartIndex = null;
}
- var result = PostFilterAndSort(items, query);
- result.TotalRecordCount = totalItemCount;
- return result;
+ return PostFilterAndSort(items, query);
}
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
@@ -1020,7 +1035,15 @@ namespace MediaBrowser.Controller.Entities
items = UserViewBuilder.FilterForAdjacency(items.ToList(), query.AdjacentTo.Value);
}
- return UserViewBuilder.SortAndPage(items, null, query, LibraryManager);
+ var filteredItems = items as IReadOnlyList<BaseItem> ?? items.ToList();
+ var result = UserViewBuilder.SortAndPage(filteredItems, null, query, LibraryManager);
+
+ if (query.EnableTotalRecordCount)
+ {
+ result.TotalRecordCount = filteredItems.Count;
+ }
+
+ return result;
}
private static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(
@@ -1033,12 +1056,49 @@ namespace MediaBrowser.Controller.Entities
{
ArgumentNullException.ThrowIfNull(items);
- if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
+ if (!CollapseBoxSetItems(query, queryParent, user, configurationManager))
+ {
+ return items;
+ }
+
+ var config = configurationManager.Configuration;
+
+ bool collapseMovies = config.EnableGroupingMoviesIntoCollections;
+ bool collapseSeries = config.EnableGroupingShowsIntoCollections;
+
+ if (user is null || (collapseMovies && collapseSeries))
{
- items = collectionManager.CollapseItemsWithinBoxSets(items, user);
+ return collectionManager.CollapseItemsWithinBoxSets(items, user);
}
- return items;
+ if (!collapseMovies && !collapseSeries)
+ {
+ return items;
+ }
+
+ var collapsibleItems = new List<BaseItem>();
+ var remainingItems = new List<BaseItem>();
+
+ foreach (var item in items)
+ {
+ if ((collapseMovies && item is Movie) || (collapseSeries && item is Series))
+ {
+ collapsibleItems.Add(item);
+ }
+ else
+ {
+ remainingItems.Add(item);
+ }
+ }
+
+ if (collapsibleItems.Count == 0)
+ {
+ return remainingItems;
+ }
+
+ var collapsedItems = collectionManager.CollapseItemsWithinBoxSets(collapsibleItems, user);
+
+ return collapsedItems.Concat(remainingItems);
}
private static bool CollapseBoxSetItems(
@@ -1069,24 +1129,26 @@ namespace MediaBrowser.Controller.Entities
}
var param = query.CollapseBoxSetItems;
-
- if (!param.HasValue)
+ if (param.HasValue)
{
- if (user is not null && query.IncludeItemTypes.Any(type =>
- (type == BaseItemKind.Movie && !configurationManager.Configuration.EnableGroupingMoviesIntoCollections) ||
- (type == BaseItemKind.Series && !configurationManager.Configuration.EnableGroupingShowsIntoCollections)))
- {
- return false;
- }
+ return param.Value && AllowBoxSetCollapsing(query);
+ }
- if (query.IncludeItemTypes.Length == 0
- || query.IncludeItemTypes.Any(type => type == BaseItemKind.Movie || type == BaseItemKind.Series))
- {
- param = true;
- }
+ var config = configurationManager.Configuration;
+
+ bool queryHasMovies = query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(BaseItemKind.Movie);
+ bool queryHasSeries = query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(BaseItemKind.Series);
+
+ bool collapseMovies = config.EnableGroupingMoviesIntoCollections;
+ bool collapseSeries = config.EnableGroupingShowsIntoCollections;
+
+ if (user is not null)
+ {
+ bool canCollapse = (queryHasMovies && collapseMovies) || (queryHasSeries && collapseSeries);
+ return canCollapse && AllowBoxSetCollapsing(query);
}
- return param.HasValue && param.Value && AllowBoxSetCollapsing(query);
+ return (queryHasMovies || queryHasSeries) && AllowBoxSetCollapsing(query);
}
private static bool AllowBoxSetCollapsing(InternalItemsQuery request)
@@ -1336,19 +1398,28 @@ namespace MediaBrowser.Controller.Entities
var limit = query.Limit > 0 ? query.Limit : int.MaxValue;
query.Limit = 0;
- var visibileChildren = children
+ var visibleChildren = children
.Where(e => e.IsVisible(user))
.ToArray();
- var realChildren = visibileChildren
+ var realChildren = visibleChildren
.Where(e => query is null || UserViewBuilder.FilterItem(e, query))
.ToArray();
+
+ if (this is BoxSet && (query.OrderBy is null || query.OrderBy.Count == 0))
+ {
+ realChildren = realChildren
+ .OrderBy(e => e.ProductionYear ?? int.MaxValue)
+ .ToArray();
+ }
+
var childCount = realChildren.Length;
if (result.Count < limit)
{
+ var remainingCount = (int)(limit - result.Count);
foreach (var child in realChildren
.Skip(query.StartIndex ?? 0)
- .TakeWhile(e => limit > result.Count))
+ .Take(remainingCount))
{
result[child.Id] = child;
}
@@ -1356,7 +1427,7 @@ namespace MediaBrowser.Controller.Entities
if (recursive)
{
- foreach (var child in visibileChildren
+ foreach (var child in visibleChildren
.Where(e => e.IsFolder)
.OfType<Folder>())
{