diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index a244b71df5..3e79fb91c5 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -279,6 +279,7 @@ namespace MediaBrowser.Api episode.AirsAfterSeasonNumber = request.AirsAfterSeasonNumber; episode.AirsBeforeEpisodeNumber = request.AirsBeforeEpisodeNumber; episode.AirsBeforeSeasonNumber = request.AirsBeforeSeasonNumber; + episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber; } var hasTags = item as IHasTags; diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index b45d4dfb04..11cd72cf40 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Api.UserLibrary; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -364,12 +365,11 @@ namespace MediaBrowser.Api var series = _libraryManager.GetItemById(request.Id) as Series; - var fields = request.GetItemFields().ToList(); - - var seasons = series.GetChildren(user, true) - .OfType(); - - var sortOrder = ItemSortBy.SortName; + if (series == null) + { + throw new ResourceNotFoundException("No series exists with Id " + request.Id); + } + var seasons = series.GetSeasons(user); if (request.IsSpecialSeason.HasValue) { @@ -378,29 +378,8 @@ namespace MediaBrowser.Api seasons = seasons.Where(i => i.IsSpecialSeason == val); } - var config = user.Configuration; - - if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) - { - seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired); - } - else - { - if (!config.DisplayMissingEpisodes) - { - seasons = seasons.Where(i => !i.IsMissingSeason); - } - if (!config.DisplayUnairedEpisodes) - { - seasons = seasons.Where(i => !i.IsVirtualUnaired); - } - } - seasons = FilterVirtualSeasons(request, seasons); - seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) - .Cast(); - // This must be the last filter if (!string.IsNullOrEmpty(request.AdjacentTo)) { @@ -408,6 +387,8 @@ namespace MediaBrowser.Api .Cast(); } + var fields = request.GetItemFields().ToList(); + var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -450,66 +431,45 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var series = _libraryManager.GetItemById(request.Id) as Series; + IEnumerable episodes; - var fields = request.GetItemFields().ToList(); + if (string.IsNullOrEmpty(request.SeasonId)) + { + var series = _libraryManager.GetItemById(request.Id) as Series; - var episodes = series.GetRecursiveChildren(user) - .OfType(); + if (series == null) + { + throw new ResourceNotFoundException("No series exists with Id " + request.Id); + } - var sortOrder = ItemSortBy.SortName; - - if (!string.IsNullOrEmpty(request.SeasonId)) + episodes = series.GetEpisodes(user, request.Season.Value); + } + else { var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; - if (season.IndexNumber.HasValue) + if (season == null) { - episodes = FilterEpisodesBySeason(episodes, season.IndexNumber.Value, true); - - sortOrder = ItemSortBy.AiredEpisodeOrder; - } - else - { - episodes = season.RecursiveChildren.OfType(); - - sortOrder = ItemSortBy.SortName; + throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId); } + + episodes = season.GetEpisodes(user); } - else if (request.Season.HasValue) - { - episodes = FilterEpisodesBySeason(episodes, request.Season.Value, true); - - sortOrder = ItemSortBy.AiredEpisodeOrder; - } - - var config = user.Configuration; - - if (!config.DisplayMissingEpisodes) - { - episodes = episodes.Where(i => !i.IsMissingEpisode); - } - if (!config.DisplayUnairedEpisodes) - { - episodes = episodes.Where(i => !i.IsVirtualUnaired); - } - + // Filter after the fact in case the ui doesn't want them if (request.IsMissing.HasValue) { var val = request.IsMissing.Value; episodes = episodes.Where(i => i.IsMissingEpisode == val); } + // Filter after the fact in case the ui doesn't want them if (request.IsVirtualUnaired.HasValue) { var val = request.IsVirtualUnaired.Value; episodes = episodes.Where(i => i.IsVirtualUnaired == val); } - episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) - .Cast(); - // This must be the last filter if (!string.IsNullOrEmpty(request.AdjacentTo)) { @@ -517,6 +477,8 @@ namespace MediaBrowser.Api .Cast(); } + var fields = request.GetItemFields().ToList(); + var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -526,27 +488,5 @@ namespace MediaBrowser.Api Items = returnItems }; } - - internal static IEnumerable FilterEpisodesBySeason(IEnumerable episodes, int seasonNumber, bool includeSpecials) - { - if (!includeSpecials || seasonNumber < 1) - { - return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber); - } - - return episodes.Where(i => - { - var episode = i; - - if (episode != null) - { - var currentSeasonNumber = episode.AiredSeasonNumber; - - return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; - } - - return false; - }); - } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 6fcff545f6..dc4a833b0e 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -1041,7 +1041,7 @@ namespace MediaBrowser.Api.UserLibrary if (request.AiredDuringSeason.HasValue) { - items = TvShowsService.FilterEpisodesBySeason(items.OfType(), request.AiredDuringSeason.Value, true); + items = Series.FilterEpisodesBySeason(items.OfType(), request.AiredDuringSeason.Value, true); } if (!string.IsNullOrEmpty(request.MinPremiereDate)) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index f24d86408e..7f94ab8e87 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -51,6 +51,12 @@ namespace MediaBrowser.Controller.Entities.TV /// The DVD episode number. public float? DvdEpisodeNumber { get; set; } + /// + /// Gets or sets the absolute episode number. + /// + /// The absolute episode number. + public int? AbsoluteEpisodeNumber { get; set; } + /// /// We want to group into series not show individually in an index /// diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 78e0b8bc4a..3a767421a6 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,5 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; using System.IO; @@ -186,7 +188,7 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsMissingSeason { - get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } + get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } } [IgnoreDataMember] @@ -198,13 +200,13 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsVirtualUnaired { - get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; } + get { return LocationType == LocationType.Virtual && IsUnaired; } } [IgnoreDataMember] public bool IsMissingOrVirtualUnaired { - get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } + get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } } [IgnoreDataMember] @@ -212,5 +214,35 @@ namespace MediaBrowser.Controller.Entities.TV { get { return (IndexNumber ?? -1) == 0; } } + + /// + /// Gets the episodes. + /// + /// The user. + /// IEnumerable{Episode}. + public IEnumerable GetEpisodes(User user) + { + if (IndexNumber.HasValue) + { + var series = Series; + + if (series != null) + { + return series.GetEpisodes(user, IndexNumber.Value); + } + } + + var episodes = GetRecursiveChildren(user) + .OfType(); + + return LibraryManager + .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) + .Cast(); + } + + public override IEnumerable GetChildren(User user, bool includeLinkedChildren, string indexBy = null) + { + return GetEpisodes(user); + } } } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 2312df2a17..1c4bef942a 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; using System.IO; @@ -117,5 +118,89 @@ namespace MediaBrowser.Controller.Entities.TV return Children.OfType