diff options
Diffstat (limited to 'MediaBrowser.Controller')
19 files changed, 225 insertions, 138 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 7974657d9..00a7e8b67 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Entities.Audio { get { - return RecursiveChildren.OfType<Audio>(); + return GetRecursiveChildren(i => i is Audio).Cast<Audio>(); } } @@ -173,7 +173,8 @@ namespace MediaBrowser.Controller.Entities.Audio id.ArtistProviderIds = artist.ProviderIds; } - id.SongInfos = RecursiveChildren.OfType<Audio>() + id.SongInfos = GetRecursiveChildren(i => i is Audio) + .Cast<Audio>() .Select(i => i.GetLookupInfo()) .ToList(); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 45476d6a6..5cca91202 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Entities.Audio { public bool IsAccessedByName { get; set; } public List<string> ProductionLocations { get; set; } - + public override bool IsFolder { get @@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.Audio public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) { - var items = RecursiveChildren.ToList(); + var items = GetRecursiveChildren().ToList(); var songs = items.OfType<Audio>().ToList(); @@ -169,7 +169,7 @@ namespace MediaBrowser.Controller.Entities.Audio // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - + // Refresh all non-songs foreach (var item in others) { @@ -204,7 +204,8 @@ namespace MediaBrowser.Controller.Entities.Audio { var info = GetItemLookupInfo<ArtistInfo>(); - info.SongInfos = RecursiveChildren.OfType<Audio>() + info.SongInfos = GetRecursiveChildren(i => i is Audio) + .Cast<Audio>() .Select(i => i.GetLookupInfo()) .ToList(); @@ -213,9 +214,19 @@ namespace MediaBrowser.Controller.Entities.Audio public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.OfType<IHasArtist>() - .Where(i => i.HasArtist(Name)) - .Cast<BaseItem>(); + return inputItems.Where(ItemFilter); + } + + public Func<BaseItem, bool> ItemFilter + { + get + { + return i => + { + var hasArtist = i as IHasArtist; + return hasArtist != null && hasArtist.HasArtist(Name); + }; + } } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index ad2d39c79..b2c2a1b48 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -52,7 +52,13 @@ namespace MediaBrowser.Controller.Entities.Audio public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => (i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(ItemFilter); + } + + + public Func<BaseItem, bool> ItemFilter + { + get { return i => (i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 234a33d78..b819d14e5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1155,7 +1155,7 @@ namespace MediaBrowser.Controller.Entities if (!string.IsNullOrWhiteSpace(info.ItemName) && !string.IsNullOrWhiteSpace(info.ItemType)) { - return LibraryManager.RootFolder.RecursiveChildren.FirstOrDefault(i => + return LibraryManager.RootFolder.GetRecursiveChildren(i => { if (string.Equals(i.Name, info.ItemName, StringComparison.OrdinalIgnoreCase)) { @@ -1173,7 +1173,8 @@ namespace MediaBrowser.Controller.Entities } return false; - }); + + }).FirstOrDefault(); } return null; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index dd3d145a0..9cc320095 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Folder /// </summary> - public class Folder : BaseItem, IHasThemeMedia, IHasTags + public class Folder : BaseItem, IHasThemeMedia, IHasTags, IHasPreferredMetadataLanguage { public static IUserManager UserManager { get; set; } public static IUserViewManager UserViewManager { get; set; } @@ -30,6 +30,14 @@ namespace MediaBrowser.Controller.Entities public List<Guid> ThemeVideoIds { get; set; } public List<string> Tags { get; set; } + public string PreferredMetadataLanguage { get; set; } + + /// <summary> + /// Gets or sets the preferred metadata country code. + /// </summary> + /// <value>The preferred metadata country code.</value> + public string PreferredMetadataCountryCode { get; set; } + public Folder() { LinkedChildren = new List<LinkedChild>(); @@ -796,18 +804,20 @@ namespace MediaBrowser.Controller.Entities { var user = query.User; + Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + var items = query.Recursive - ? GetRecursiveChildren(user) - : GetChildren(user, true); + ? GetRecursiveChildren(user, filter) + : GetChildren(user, true).Where(filter); - var result = SortAndFilter(items, query); + var result = PostFilterAndSort(items, query); return Task.FromResult(result); } - protected QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, InternalItemsQuery query) + protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query) { - return UserViewBuilder.FilterAndSort(items, this, null, query, LibraryManager, UserDataManager); + return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager); } /// <summary> @@ -832,11 +842,11 @@ namespace MediaBrowser.Controller.Entities //the true root should return our users root folder children if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren); - var list = new List<BaseItem>(); + var result = new Dictionary<Guid, BaseItem>(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, includeHidden, false); + AddChildren(user, includeLinkedChildren, result, includeHidden, false, null); - return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; + return result.Values; } protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) @@ -849,31 +859,30 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="user">The user.</param> /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> - /// <param name="list">The list.</param> + /// <param name="result">The result.</param> /// <param name="includeHidden">if set to <c>true</c> [include hidden].</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <param name="filter">The filter.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool includeHidden, bool recursive) + private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter) { - var hasLinkedChildren = false; - foreach (var child in GetEligibleChildrenForRecursiveChildren(user)) { if (child.IsVisible(user)) { if (includeHidden || !child.IsHiddenFromUser(user)) { - list.Add(child); + if (filter == null || filter(child)) + { + result[child.Id] = child; + } } if (recursive && child.IsFolder) { var folder = (Folder)child; - if (folder.AddChildrenToList(user, includeLinkedChildren, list, includeHidden, true)) - { - hasLinkedChildren = true; - } + folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter); } } } @@ -884,14 +893,13 @@ namespace MediaBrowser.Controller.Entities { if (child.IsVisible(user)) { - hasLinkedChildren = true; - - list.Add(child); + if (filter == null || filter(child)) + { + result[child.Id] = child; + } } } } - - return hasLinkedChildren; } /// <summary> @@ -901,18 +909,23 @@ namespace MediaBrowser.Controller.Entities /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> /// <returns>IEnumerable{BaseItem}.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + { + return GetRecursiveChildren(user, i => true); + } + + public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { if (user == null) { throw new ArgumentNullException("user"); } - var list = new List<BaseItem>(); + var result = new Dictionary<Guid, BaseItem>(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, true); + AddChildren(user, true, result, false, true, filter); - return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; + return result.Values; } /// <summary> @@ -921,9 +934,14 @@ namespace MediaBrowser.Controller.Entities /// <returns>IList{BaseItem}.</returns> public IList<BaseItem> GetRecursiveChildren() { + return GetRecursiveChildren(null); + } + + public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) + { var list = new List<BaseItem>(); - AddChildrenToList(list, true, null); + AddChildrenToList(list, true, filter); return list; } @@ -1136,8 +1154,7 @@ namespace MediaBrowser.Controller.Entities bool resetPosition) { // Sweep through recursively and update status - var tasks = GetRecursiveChildren(user, true) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + var tasks = GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .Select(c => c.MarkPlayed(user, datePlayed, resetPosition)); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1151,8 +1168,7 @@ namespace MediaBrowser.Controller.Entities public override async Task MarkUnplayed(User user) { // Sweep through recursively and update status - var tasks = GetRecursiveChildren(user, true) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + var tasks = GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .Select(c => c.MarkUnplayed(user)); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1181,15 +1197,15 @@ namespace MediaBrowser.Controller.Entities return this; } - return RecursiveChildren.FirstOrDefault(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) || + return GetRecursiveChildren(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) || (!i.IsFolder && !i.IsInMixedFolder && string.Equals(i.ContainingFolderPath, path, StringComparison.OrdinalIgnoreCase)) || - i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)); + i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)) + .FirstOrDefault(); } public override bool IsPlayed(User user) { - return GetRecursiveChildren(user) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + return GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .All(i => i.IsPlayed(user)); } @@ -1216,8 +1232,7 @@ namespace MediaBrowser.Controller.Entities } else { - children = folder.GetRecursiveChildren(user) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); + children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 16ca6e70a..d69a6ca46 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -42,7 +42,13 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => (i is Game) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(ItemFilter); + } + + + public Func<BaseItem, bool> ItemFilter + { + get { return i => (i is Game) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } } diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index da5569afc..a33e6131f 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -46,7 +46,12 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(ItemFilter); + } + + public Func<BaseItem, bool> ItemFilter + { + get { return i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } } diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index 70d5b840f..e303e9453 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace MediaBrowser.Controller.Entities { @@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities /// <param name="inputItems">The input items.</param> /// <returns>IEnumerable{BaseItem}.</returns> IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems); + + Func<BaseItem, bool> ItemFilter { get; } } public interface IHasDualAccess : IItemByName diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 30043682d..e99c11e87 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities public User User { get; set; } - public Func<BaseItem, User, bool> Filter { get; set; } + public Func<BaseItem, bool> Filter { get; set; } public bool? IsFolder { get; set; } public bool? IsFavorite { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 63690661a..e08d88b02 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares + public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares { public List<Share> Shares { get; set; } @@ -55,14 +55,6 @@ namespace MediaBrowser.Controller.Entities.Movies /// <value>The tags.</value> public List<string> Keywords { get; set; } - public string PreferredMetadataLanguage { get; set; } - - /// <summary> - /// Gets or sets the preferred metadata country code. - /// </summary> - /// <value>The preferred metadata country code.</value> - public string PreferredMetadataCountryCode { get; set; } - /// <summary> /// Gets or sets the display order. /// </summary> @@ -103,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.Movies var currentOfficialRating = OfficialRating; // Gather all possible ratings - var ratings = RecursiveChildren + var ratings = GetRecursiveChildren() .Concat(GetLinkedChildren()) .Where(i => i is Movie || i is Series) .Select(i => i.OfficialRating) @@ -148,7 +140,7 @@ namespace MediaBrowser.Controller.Entities.Movies { // Refresh bottom up, children first, then the boxset // By then hopefully the movies within will have Tmdb collection values - var items = RecursiveChildren.ToList(); + var items = GetRecursiveChildren().ToList(); var totalItems = items.Count; var percentages = new Dictionary<Guid, double>(totalItems); diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 6d256e81c..19af6e6f0 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -57,7 +57,13 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => i.People.Any(p => string.Equals(p.Name, Name, StringComparison.OrdinalIgnoreCase))); + return inputItems.Where(ItemFilter); + } + + + public Func<BaseItem, bool> ItemFilter + { + get { return i => i.People.Any(p => string.Equals(p.Name, Name, StringComparison.OrdinalIgnoreCase)); } } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 58d46facc..53c635eba 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -52,7 +52,13 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(ItemFilter); + } + + + public Func<BaseItem, bool> ItemFilter + { + get { return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 61d0aec60..f28306661 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -244,7 +244,7 @@ namespace MediaBrowser.Controller.Entities.TV private IEnumerable<Episode> GetEpisodes() { - var episodes = RecursiveChildren.OfType<Episode>(); + var episodes = GetRecursiveChildren().OfType<Episode>(); var series = Series; if (series != null && series.ContainsEpisodesWithoutSeasonFolders) @@ -254,12 +254,12 @@ namespace MediaBrowser.Controller.Entities.TV if (seasonNumber.HasValue) { - list.AddRange(series.RecursiveChildren.OfType<Episode>() + list.AddRange(series.GetRecursiveChildren().OfType<Episode>() .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value)); } else { - list.AddRange(series.RecursiveChildren.OfType<Episode>() + list.AddRange(series.GetRecursiveChildren().OfType<Episode>() .Where(i => !i.ParentIndexNumber.HasValue)); } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 0ec9121f3..ba537403b 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Class Series /// </summary> - public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IHasSpecialFeatures + public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IHasSpecialFeatures { public List<Guid> SpecialFeatureIds { get; set; } public List<Guid> SoundtrackIds { get; set; } @@ -23,12 +23,6 @@ namespace MediaBrowser.Controller.Entities.TV public int? AnimeSeriesIndex { get; set; } - /// <summary> - /// Gets or sets the preferred metadata country code. - /// </summary> - /// <value>The preferred metadata country code.</value> - public string PreferredMetadataCountryCode { get; set; } - public Series() { AirDays = new List<DayOfWeek>(); @@ -93,7 +87,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return RecursiveChildren.OfType<Episode>() + return GetRecursiveChildren(i => i is Episode) .Select(i => i.DateCreated) .OrderByDescending(i => i) .FirstOrDefault(); @@ -206,8 +200,8 @@ namespace MediaBrowser.Controller.Entities.TV internal IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> additionalEpisodes) { - var episodes = GetRecursiveChildren(user) - .OfType<Episode>(); + var episodes = GetRecursiveChildren(user, i => i is Episode) + .Cast<Episode>(); episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons); @@ -262,8 +256,6 @@ namespace MediaBrowser.Controller.Entities.TV return config.BlockUnratedItems.Contains(UnratedItem.Series); } - public string PreferredMetadataLanguage { get; set; } - public SeriesInfo GetLookupInfo() { var info = GetItemLookupInfo<SeriesInfo>(); diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index a7276e262..b065ae171 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -18,10 +18,13 @@ namespace MediaBrowser.Controller.Entities { public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query) { + var user = query.User; + Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + if (query.Recursive) { - var items = query.User.RootFolder.GetRecursiveChildren(query.User); - return SortAndFilter(items, query); + var items = query.User.RootFolder.GetRecursiveChildren(query.User, filter); + return PostFilterAndSort(items, query); } var result = await UserViewManager.GetUserViews(new UserViewQuery @@ -30,7 +33,7 @@ namespace MediaBrowser.Controller.Entities }, CancellationToken.None).ConfigureAwait(false); - return SortAndFilter(result, query); + return PostFilterAndSort(result.Where(filter), query); } public override bool IsPreSorted diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 0364ff678..f1436d45e 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -40,12 +40,13 @@ namespace MediaBrowser.Controller.Entities return result.Items; } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { var result = GetItems(new InternalItemsQuery { User = user, - Recursive = true + Recursive = true, + Filter = filter }).Result; diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index ac8be37d4..7b3021306 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -406,7 +406,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicVideo || i is Audio.Audio), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is MusicVideo || i is Audio.Audio && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) @@ -414,7 +416,7 @@ namespace MediaBrowser.Controller.Entities if (query.Recursive) { var recursiveItems = GetRecursiveChildren(parent, user, - new[] {CollectionType.Movies, CollectionType.BoxSets, string.Empty}) + new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }) .Where(i => i is Movie || i is BoxSet); //var collections = _collectionManager.CollapseItemsWithinBoxSets(recursiveItems, user).ToList(); @@ -490,7 +492,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query) @@ -499,7 +503,9 @@ namespace MediaBrowser.Controller.Entities query.SortOrder = SortOrder.Descending; query.IsResumable = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) @@ -544,15 +550,16 @@ namespace MediaBrowser.Controller.Entities return GetResult(GetMediaFolders(user).SelectMany(i => { var hasCollectionType = i as ICollectionFolder; + Func<BaseItem, bool> filter = b => b is BoxSet; if (hasCollectionType != null && string.Equals(hasCollectionType.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) { - return i.GetChildren(user, true); + return i.GetChildren(user, true).Where(filter); } - return i.GetRecursiveChildren(user); + return i.GetRecursiveChildren(user, filter); - }).OfType<BoxSet>(), parent, query); + }), parent, query); } private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query) @@ -598,7 +605,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query) @@ -607,7 +616,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query) @@ -622,7 +633,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query) @@ -646,7 +659,9 @@ namespace MediaBrowser.Controller.Entities query.SortOrder = SortOrder.Descending; query.IsResumable = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query) @@ -748,29 +763,32 @@ namespace MediaBrowser.Controller.Entities InternalItemsQuery query) where T : BaseItem { - return GetResult(items, queryParent, null, query); + items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager)); + + return PostFilterAndSort(items, queryParent, null, query, _libraryManager); } - private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items, + public bool FilterItem(BaseItem item, InternalItemsQuery query) + { + return Filter(item, query.User, query, _userDataManager, _libraryManager); + } + + private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query) - where T : BaseItem { - return FilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _userDataManager); + return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager); } - public static QueryResult<BaseItem> FilterAndSort(IEnumerable<BaseItem> items, + public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query, - ILibraryManager libraryManager, - IUserDataManager userDataManager) + ILibraryManager libraryManager) { var user = query.User; - items = items.Where(i => Filter(i, user, query, userDataManager, libraryManager)); - items = FilterVirtualEpisodes(items, query.IsMissing, query.IsVirtualUnaired, @@ -1169,7 +1187,7 @@ namespace MediaBrowser.Controller.Entities }; } - private static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) + public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) { if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { @@ -1191,7 +1209,7 @@ namespace MediaBrowser.Controller.Entities return false; } - if (query.Filter != null && !query.Filter(item, user)) + if (query.Filter != null && !query.Filter(item)) { return false; } @@ -1641,6 +1659,16 @@ namespace MediaBrowser.Controller.Entities return parent.GetRecursiveChildren(user); } + private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes, Func<BaseItem,bool> filter) + { + if (parent == null || parent is UserView) + { + return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user, filter)); + } + + return parent.GetRecursiveChildren(user, filter); + } + private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user) { var list = new List<BaseItem>(); diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 11b0ce3d2..bbf473a9a 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -56,5 +57,11 @@ namespace MediaBrowser.Controller.Entities return inputItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year); } + + + public Func<BaseItem, bool> ItemFilter + { + get { throw new System.NotImplementedException(); } + } } } diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index e48cddaaa..071a9bf93 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -50,9 +50,16 @@ namespace MediaBrowser.Controller.Playlists return GetPlayableItems(user); } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { - return GetPlayableItems(user); + var items = GetPlayableItems(user); + + if (filter != null) + { + items = items.Where(filter); + } + + return items; } public IEnumerable<Tuple<LinkedChild, BaseItem>> GetManageableItems() @@ -76,38 +83,38 @@ namespace MediaBrowser.Controller.Playlists .Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase)); } - private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem i, User user) + private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem item, User user) { - var musicGenre = i as MusicGenre; + var musicGenre = item as MusicGenre; if (musicGenre != null) { - var items = user == null - ? LibraryManager.RootFolder.GetRecursiveChildren() - : user.RootFolder.GetRecursiveChildren(user, true); + Func<BaseItem, bool> filter = i => i is Audio && i.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase); - var songs = items - .OfType<Audio>() - .Where(a => a.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase)); + var items = user == null + ? LibraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); - return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); } - var musicArtist = i as MusicArtist; + var musicArtist = item as MusicArtist; if (musicArtist != null) { - var items = user == null - ? LibraryManager.RootFolder.GetRecursiveChildren() - : user.RootFolder.GetRecursiveChildren(user, true); + Func<BaseItem, bool> filter = i => + { + var audio = i as Audio; + return audio != null && audio.HasArtist(musicArtist.Name); + }; - var songs = items - .OfType<Audio>() - .Where(a => a.HasArtist(musicArtist.Name)); + var items = user == null + ? LibraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); - return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); } // Grab these explicitly to avoid the sorting that will happen below - var collection = i as BoxSet; + var collection = item as BoxSet; if (collection != null) { var items = user == null @@ -119,7 +126,7 @@ namespace MediaBrowser.Controller.Playlists } // Grab these explicitly to avoid the sorting that will happen below - var season = i as Season; + var season = item as Season; if (season != null) { var items = user == null @@ -130,21 +137,18 @@ namespace MediaBrowser.Controller.Playlists .Where(m => !m.IsFolder); } - var folder = i as Folder; + var folder = item as Folder; if (folder != null) { var items = user == null - ? folder.GetRecursiveChildren() - : folder.GetRecursiveChildren(user, true); - - items = items - .Where(m => !m.IsFolder); + ? folder.GetRecursiveChildren(m => !m.IsFolder) + : folder.GetRecursiveChildren(user, m => !m.IsFolder); return LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); } - return new[] { i }; + return new[] { item }; } [IgnoreDataMember] |
