|
|
|
@ -15,6 +15,9 @@ using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using CommonIO;
|
|
|
|
|
using MediaBrowser.Common.IO;
|
|
|
|
|
using MediaBrowser.Controller.Entities.Movies;
|
|
|
|
|
using MediaBrowser.Controller.Playlists;
|
|
|
|
|
using MediaBrowser.Model.Channels;
|
|
|
|
|
|
|
|
|
|
namespace MediaBrowser.Controller.Entities
|
|
|
|
|
{
|
|
|
|
@ -145,60 +148,38 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
item.DateModified = DateTime.UtcNow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AddChildInternal(item);
|
|
|
|
|
AddChildInternal(item.Id);
|
|
|
|
|
|
|
|
|
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
if (!EnableNewFolderQuerying())
|
|
|
|
|
{
|
|
|
|
|
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool EnableNewFolderQuerying()
|
|
|
|
|
{
|
|
|
|
|
return ConfigurationManager.Configuration.MigrationVersion >= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
|
|
|
|
|
protected void AddChildrenInternal(List<Guid> children)
|
|
|
|
|
{
|
|
|
|
|
var actualChildren = ActualChildren;
|
|
|
|
|
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
{
|
|
|
|
|
var newChildren = actualChildren.ToList();
|
|
|
|
|
var newChildren = ChildIds.ToList();
|
|
|
|
|
newChildren.AddRange(children);
|
|
|
|
|
_children = newChildren;
|
|
|
|
|
_children = newChildren.ToList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
protected void AddChildInternal(BaseItem child)
|
|
|
|
|
protected void AddChildInternal(Guid child)
|
|
|
|
|
{
|
|
|
|
|
var actualChildren = ActualChildren;
|
|
|
|
|
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
{
|
|
|
|
|
var newChildren = actualChildren.ToList();
|
|
|
|
|
newChildren.Add(child);
|
|
|
|
|
_children = newChildren;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void RemoveChildrenInternal(IEnumerable<BaseItem> children)
|
|
|
|
|
{
|
|
|
|
|
var ids = children.Select(i => i.Id).ToList();
|
|
|
|
|
var actualChildren = ActualChildren;
|
|
|
|
|
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
{
|
|
|
|
|
_children = actualChildren.Where(i => !ids.Contains(i.Id)).ToList();
|
|
|
|
|
var childIds = ChildIds.ToList();
|
|
|
|
|
if (!childIds.Contains(child))
|
|
|
|
|
{
|
|
|
|
|
childIds.Add(child);
|
|
|
|
|
_children = childIds.ToList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void ClearChildrenInternal()
|
|
|
|
|
protected void RemoveChildrenInternal(List<Guid> children)
|
|
|
|
|
{
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
{
|
|
|
|
|
_children = new List<BaseItem>();
|
|
|
|
|
_children = ChildIds.Except(children).ToList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -206,40 +187,11 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
/// Removes the child.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item">The item.</param>
|
|
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
|
|
|
|
|
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
|
|
|
|
|
public void RemoveChild(BaseItem item)
|
|
|
|
|
{
|
|
|
|
|
RemoveChildrenInternal(new[] { item });
|
|
|
|
|
RemoveChildrenInternal(new[] { item.Id }.ToList());
|
|
|
|
|
|
|
|
|
|
item.SetParent(null);
|
|
|
|
|
|
|
|
|
|
if (!EnableNewFolderQuerying())
|
|
|
|
|
{
|
|
|
|
|
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Task.FromResult(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Clears the children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
public Task ClearChildren(CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var items = ActualChildren.ToList();
|
|
|
|
|
|
|
|
|
|
ClearChildrenInternal();
|
|
|
|
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
{
|
|
|
|
|
LibraryManager.ReportItemRemoved(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Indexing
|
|
|
|
@ -276,7 +228,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The children
|
|
|
|
|
/// </summary>
|
|
|
|
|
private IReadOnlyList<BaseItem> _children;
|
|
|
|
|
private IReadOnlyList<Guid> _children;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The _children sync lock
|
|
|
|
|
/// </summary>
|
|
|
|
@ -285,21 +237,30 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
/// Gets or sets the actual children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The actual children.</value>
|
|
|
|
|
protected virtual IEnumerable<BaseItem> ActualChildren
|
|
|
|
|
protected virtual IEnumerable<Guid> ChildIds
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_children == null)
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
{
|
|
|
|
|
lock (_childrenSyncLock)
|
|
|
|
|
if (_children == null)
|
|
|
|
|
{
|
|
|
|
|
if (_children == null)
|
|
|
|
|
{
|
|
|
|
|
_children = LoadChildren().ToList();
|
|
|
|
|
}
|
|
|
|
|
_children = LoadChildren().ToList();
|
|
|
|
|
}
|
|
|
|
|
return _children.ToList();
|
|
|
|
|
}
|
|
|
|
|
return _children;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the actual children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The actual children.</value>
|
|
|
|
|
protected virtual IEnumerable<BaseItem> ActualChildren
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -353,7 +314,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
/// Loads our children. Validation will occur externally.
|
|
|
|
|
/// We want this sychronous.
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual IEnumerable<BaseItem> LoadChildren()
|
|
|
|
|
protected virtual IEnumerable<Guid> LoadChildren()
|
|
|
|
|
{
|
|
|
|
|
//just load our children from the repo - the library will be validated and maintained in other processes
|
|
|
|
|
return GetCachedChildren();
|
|
|
|
@ -503,7 +464,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
|
|
|
|
|
if (actualRemovals.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
RemoveChildrenInternal(actualRemovals);
|
|
|
|
|
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
|
|
|
|
|
|
|
|
|
|
foreach (var item in actualRemovals)
|
|
|
|
|
{
|
|
|
|
@ -518,12 +479,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
|
|
|
|
|
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
AddChildrenInternal(newItems);
|
|
|
|
|
|
|
|
|
|
if (!EnableNewFolderQuerying())
|
|
|
|
|
{
|
|
|
|
|
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -751,51 +707,459 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
/// Get our children from the repo - stubbed for now
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
|
|
|
protected IEnumerable<BaseItem> GetCachedChildren()
|
|
|
|
|
protected IEnumerable<Guid> GetCachedChildren()
|
|
|
|
|
{
|
|
|
|
|
if (EnableNewFolderQuerying())
|
|
|
|
|
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
|
|
|
|
{
|
|
|
|
|
return ItemRepository.GetItemList(new InternalItemsQuery
|
|
|
|
|
ParentId = Id
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
|
|
|
|
|
{
|
|
|
|
|
var user = query.User;
|
|
|
|
|
|
|
|
|
|
if (RequiresPostFiltering(query))
|
|
|
|
|
{
|
|
|
|
|
IEnumerable<BaseItem> items;
|
|
|
|
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
|
|
|
|
|
|
|
|
|
if (query.User == null)
|
|
|
|
|
{
|
|
|
|
|
ParentId = Id
|
|
|
|
|
items = GetRecursiveChildren(filter);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
items = GetRecursiveChildren(user, filter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PostFilterAndSort(items, query);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}).Select(RetrieveChild).Where(i => i != null);
|
|
|
|
|
if (!(this is UserRootFolder) && !(this is AggregateFolder))
|
|
|
|
|
{
|
|
|
|
|
query.ParentId = query.ParentId ?? Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
|
|
|
|
return LibraryManager.GetItemsResult(query);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseItem RetrieveChild(BaseItem child)
|
|
|
|
|
private bool RequiresPostFiltering(InternalItemsQuery query)
|
|
|
|
|
{
|
|
|
|
|
if (child == null || child.Id == Guid.Empty)
|
|
|
|
|
if (LinkedChildren.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Item found with empty Id: " + (child.Path ?? child.Name));
|
|
|
|
|
return null;
|
|
|
|
|
if (!(this is ICollectionFolder))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to LinkedChildren");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var item = LibraryManager.GetMemoryItemById(child.Id);
|
|
|
|
|
|
|
|
|
|
if (item != null)
|
|
|
|
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (item is IByReferenceItem)
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return LibraryManager.GetOrAddByReferenceItem(item);
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Metascore, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Revenue, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Revenue");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.SeriesSortName, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item.SetParent(this);
|
|
|
|
|
if (query.ItemIds.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemIds");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
if (query.PersonIds.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to PersonIds");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsLiked");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavoriteOrLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavorite.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsFavorite");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsResumable.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsResumable");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsPlayed.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsPlayed");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsInBoxSet.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filter by Video3DFormat
|
|
|
|
|
if (query.Is3D.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to Is3D");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasImdbId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasImdbId");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasTmdbId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasTmdbId");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasTvdbId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasTvdbId");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsYearMismatched.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsYearMismatched");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasOfficialRating.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsPlaceHolder.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsPlaceHolder");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasSpecialFeature.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasSpecialFeature");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasSubtitles.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasSubtitles");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasTrailer.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasTrailer");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasThemeSong.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasThemeSong");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.HasThemeVideo.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to HasThemeVideo");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filter by VideoType
|
|
|
|
|
if (query.VideoTypes.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to VideoTypes");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.ImageTypes.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
child.SetParent(this);
|
|
|
|
|
LibraryManager.RegisterItem(child);
|
|
|
|
|
item = child;
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ImageTypes");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply studio filter
|
|
|
|
|
if (query.StudioIds.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to StudioIds");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply genre filter
|
|
|
|
|
if (query.GenreIds.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to GenreIds");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return item;
|
|
|
|
|
// Apply person filter
|
|
|
|
|
if (query.ItemIdsFromPersonFilters != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ItemIdsFromPersonFilters");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.MinPlayers.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to MinPlayers");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.MaxPlayers.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to MaxPlayers");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.OfficialRatings.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to OfficialRatings");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsMissing.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsMissing");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsUnaired.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsUnaired");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsVirtualUnaired.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to IsVirtualUnaired");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.AdjacentTo))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to AdjacentTo");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.NameContains))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to NameContains");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.NameLessThan))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to NameLessThan");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to NameStartsWith");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.AirDays.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to AirDays");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.SeriesStatuses.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to SeriesStatuses");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.AiredDuringSeason.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to AiredDuringSeason");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.AlbumArtistStartsWithOrGreater))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to AlbumArtistStartsWithOrGreater");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.AlbumNames.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to AlbumNames");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.ArtistNames.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
|
|
|
|
public virtual async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
|
|
|
|
{
|
|
|
|
|
if (SourceType == SourceType.Channel)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Don't blow up here because it could cause parent screens with other content to fail
|
|
|
|
|
return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
|
|
|
|
|
{
|
|
|
|
|
ChannelId = ChannelId,
|
|
|
|
|
FolderId = Id.ToString("N"),
|
|
|
|
|
Limit = query.Limit,
|
|
|
|
|
StartIndex = query.StartIndex,
|
|
|
|
|
UserId = query.User.Id.ToString("N"),
|
|
|
|
|
SortBy = query.SortBy,
|
|
|
|
|
SortOrder = query.SortOrder
|
|
|
|
|
|
|
|
|
|
}, new Progress<double>(), CancellationToken.None);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
// Already logged at lower levels
|
|
|
|
|
return new QueryResult<BaseItem>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.Recursive)
|
|
|
|
|
{
|
|
|
|
|
return QueryRecursive(query);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var user = query.User;
|
|
|
|
|
|
|
|
|
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
|
|
|
@ -817,7 +1181,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
|
|
|
|
|
var result = PostFilterAndSort(items, query);
|
|
|
|
|
|
|
|
|
|
return Task.FromResult(result);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
|
|
|
|