using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; using System.Linq; namespace MediaBrowser.Controller.Entities { public class Folder : BaseItem { public override bool IsFolder { get { return true; } } public bool IsRoot { get; set; } public bool IsVirtualFolder { get { return Parent != null && Parent.IsRoot; } } public IEnumerable Children { get; set; } /// /// Gets allowed children of an item /// public IEnumerable GetParentalAllowedChildren(User user) { return Children.Where(c => c.IsParentalAllowed(user)); } /// /// Gets allowed recursive children of an item /// public IEnumerable GetParentalAllowedRecursiveChildren(User user) { foreach (var item in GetParentalAllowedChildren(user)) { yield return item; var subFolder = item as Folder; if (subFolder != null) { foreach (var subitem in subFolder.GetParentalAllowedRecursiveChildren(user)) { yield return subitem; } } } } /// /// Since it can be slow to make all of these calculations at once, this method will provide a way to get them all back together /// public ItemSpecialCounts GetSpecialCounts(User user) { ItemSpecialCounts counts = new ItemSpecialCounts(); IEnumerable recursiveChildren = GetParentalAllowedRecursiveChildren(user); counts.RecentlyAddedItemCount = GetRecentlyAddedItems(recursiveChildren, user).Count(); counts.RecentlyAddedUnPlayedItemCount = GetRecentlyAddedUnplayedItems(recursiveChildren, user).Count(); counts.InProgressItemCount = GetInProgressItems(recursiveChildren, user).Count(); counts.PlayedPercentage = GetPlayedPercentage(recursiveChildren, user); return counts; } /// /// Finds all recursive items within a top-level parent that contain the given genre and are allowed for the current user /// public IEnumerable GetItemsWithGenre(string genre, User user) { return GetParentalAllowedRecursiveChildren(user).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase))); } /// /// Finds all recursive items within a top-level parent that contain the given year and are allowed for the current user /// public IEnumerable GetItemsWithYear(int year, User user) { return GetParentalAllowedRecursiveChildren(user).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year); } /// /// Finds all recursive items within a top-level parent that contain the given studio and are allowed for the current user /// public IEnumerable GetItemsWithStudio(string studio, User user) { return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase))); } /// /// Finds all recursive items within a top-level parent that the user has marked as a favorite /// public IEnumerable GetFavoriteItems(User user) { return GetParentalAllowedRecursiveChildren(user).Where(c => { UserItemData data = c.GetUserData(user, false); if (data != null) { return data.IsFavorite; } return false; }); } /// /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user /// public IEnumerable GetItemsWithPerson(string person, User user) { return GetParentalAllowedRecursiveChildren(user).Where(c => { if (c.People != null) { return c.People.ContainsKey(person); } return false; }); } /// /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user /// /// Specify this to limit results to a specific PersonType public IEnumerable GetItemsWithPerson(string person, string personType, User user) { return GetParentalAllowedRecursiveChildren(user).Where(c => { if (c.People != null) { return c.People.ContainsKey(person) && c.People[person].Type.Equals(personType, StringComparison.OrdinalIgnoreCase); } return false; }); } /// /// Gets all recently added items (recursive) within a folder, based on configuration and parental settings /// public IEnumerable GetRecentlyAddedItems(User user) { return GetRecentlyAddedItems(GetParentalAllowedRecursiveChildren(user), user); } /// /// Gets all recently added unplayed items (recursive) within a folder, based on configuration and parental settings /// public IEnumerable GetRecentlyAddedUnplayedItems(User user) { return GetRecentlyAddedUnplayedItems(GetParentalAllowedRecursiveChildren(user), user); } /// /// Gets all in-progress items (recursive) within a folder /// public IEnumerable GetInProgressItems(User user) { return GetInProgressItems(GetParentalAllowedRecursiveChildren(user), user); } /// /// Takes a list of items and returns the ones that are recently added /// private static IEnumerable GetRecentlyAddedItems(IEnumerable itemSet, User user) { return itemSet.Where(i => !(i.IsFolder) && i.IsRecentlyAdded(user)); } /// /// Takes a list of items and returns the ones that are recently added and unplayed /// private static IEnumerable GetRecentlyAddedUnplayedItems(IEnumerable itemSet, User user) { return GetRecentlyAddedItems(itemSet, user).Where(i => { var userdata = i.GetUserData(user, false); return userdata == null || userdata.PlayCount == 0; }); } /// /// Takes a list of items and returns the ones that are in progress /// private static IEnumerable GetInProgressItems(IEnumerable itemSet, User user) { return itemSet.Where(i => { if (i.IsFolder) { return false; } var userdata = i.GetUserData(user, false); return userdata != null && userdata.PlaybackPositionTicks > 0; }); } /// /// Gets the total played percentage for a set of items /// private static decimal GetPlayedPercentage(IEnumerable itemSet, User user) { itemSet = itemSet.Where(i => !(i.IsFolder)); decimal totalPercent = 0; int count = 0; foreach (BaseItem item in itemSet) { count++; UserItemData data = item.GetUserData(user, false); if (data == null) { continue; } if (data.PlayCount > 0) { totalPercent += 100; } else if (data.PlaybackPositionTicks > 0 && item.RunTimeTicks.HasValue) { decimal itemPercent = data.PlaybackPositionTicks; itemPercent /= item.RunTimeTicks.Value; totalPercent += itemPercent; } } if (count == 0) { return 0; } return totalPercent / count; } /// /// Marks the item as either played or unplayed /// public override void SetPlayedStatus(User user, bool wasPlayed) { base.SetPlayedStatus(user, wasPlayed); // Now sweep through recursively and update status foreach (BaseItem item in GetParentalAllowedChildren(user)) { item.SetPlayedStatus(user, wasPlayed); } } /// /// Finds an item by ID, recursively /// public override BaseItem FindItemById(Guid id) { var result = base.FindItemById(id); if (result != null) { return result; } foreach (BaseItem item in Children) { result = item.FindItemById(id); if (result != null) { return result; } } return null; } /// /// Finds an item by path, recursively /// public BaseItem FindByPath(string path) { if (Path.Equals(path, StringComparison.OrdinalIgnoreCase)) { return this; } foreach (BaseItem item in Children) { var folder = item as Folder; if (folder != null) { var foundItem = folder.FindByPath(path); if (foundItem != null) { return foundItem; } } else if (item.Path.Equals(path, StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } } }