diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 511b589e53..d629ec4d77 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -74,5 +74,15 @@ namespace MediaBrowser.Controller.Entities.Audio return Model.Entities.MediaType.Audio; } } + + /// + /// Creates the name of the sort. + /// + /// System.String. + protected override string CreateSortName() + { + return (ProductionYear != null ? ProductionYear.Value.ToString("000-") : "") + + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; + } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 9e4e3c5424..e9f2220165 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -129,5 +129,14 @@ namespace MediaBrowser.Controller.Entities.Audio base.Studios = value; } } + + /// + /// Creates the name of the sort. + /// + /// System.String. + protected override string CreateSortName() + { + return ProductionYear != null ? ProductionYear.Value.ToString("0000") : Name; + } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a69b423acd..4f34f2b675 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -370,11 +370,58 @@ namespace MediaBrowser.Controller.Entities } } + /// + /// Gets or sets the name of the forced sort. + /// + /// The name of the forced sort. + public string ForcedSortName { get; set; } + + private string _sortName; /// /// Gets or sets the name of the sort. /// /// The name of the sort. - public string SortName { get; set; } + [IgnoreDataMember] + public string SortName + { + get + { + return ForcedSortName ?? _sortName ?? (_sortName = CreateSortName()); + } + } + + /// + /// Creates the name of the sort. + /// + /// System.String. + protected virtual string CreateSortName() + { + if (Name == null) return null; //some items may not have name filled in properly + + var sortable = Name.Trim().ToLower(); + sortable = ConfigurationManager.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty)); + + sortable = ConfigurationManager.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " ")); + + foreach (var search in ConfigurationManager.Configuration.SortRemoveWords) + { + var searchLower = search.ToLower(); + // Remove from beginning if a space follows + if (sortable.StartsWith(searchLower + " ")) + { + sortable = sortable.Remove(0, searchLower.Length + 1); + } + // Remove from middle if surrounded by spaces + sortable = sortable.Replace(" " + searchLower + " ", " "); + + // Remove from end if followed by a space + if (sortable.EndsWith(" " + searchLower)) + { + sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1)); + } + } + return sortable; + } /// /// Gets or sets the parent. @@ -686,7 +733,7 @@ namespace MediaBrowser.Controller.Entities public virtual void ClearMetaValues() { Images = null; - SortName = null; + ForcedSortName = null; PremiereDate = null; BackdropImagePaths = null; OfficialRating = null; diff --git a/MediaBrowser.Controller/Entities/IndexFolder.cs b/MediaBrowser.Controller/Entities/IndexFolder.cs index 013db48536..637c4195ad 100644 --- a/MediaBrowser.Controller/Entities/IndexFolder.cs +++ b/MediaBrowser.Controller/Entities/IndexFolder.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Entities GroupContents = groupContents; if (shadow == null) { - Name = SortName = ""; + Name = ForcedSortName = ""; } else { @@ -167,7 +167,7 @@ namespace MediaBrowser.Controller.Entities if (ShadowItem != null) { Name = ShadowItem.Name; - SortName = ShadowItem.SortName; + ForcedSortName = ShadowItem.SortName; Genres = ShadowItem.Genres; Studios = ShadowItem.Studios; OfficialRating = ShadowItem.OfficialRating; diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 854b9d0183..1ec3e97a9f 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -159,5 +159,14 @@ namespace MediaBrowser.Controller.Entities.TV get { return _season ?? (_season = FindParent()); } } + /// + /// Creates the name of the sort. + /// + /// System.String. + protected override string CreateSortName() + { + return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000-") : "") + + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; + } } } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index f0a696df1f..20c2ee1fed 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -138,5 +138,14 @@ namespace MediaBrowser.Controller.Entities.TV return args; } + + /// + /// Creates the name of the sort. + /// + /// System.String. + protected override string CreateSortName() + { + return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; + } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 89353b2ef0..54ba9be55d 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -156,7 +156,6 @@ - diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index e54e6bfc2d..14c4b7ea4a 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -102,7 +102,7 @@ namespace MediaBrowser.Controller.Providers break; } case "SortTitle": - item.SortName = reader.ReadElementContentAsString(); + item.ForcedSortName = reader.ReadElementContentAsString(); break; case "Overview": diff --git a/MediaBrowser.Controller/Providers/SortNameProvider.cs b/MediaBrowser.Controller/Providers/SortNameProvider.cs deleted file mode 100644 index c36bcb6561..0000000000 --- a/MediaBrowser.Controller/Providers/SortNameProvider.cs +++ /dev/null @@ -1,145 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Model.Logging; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - /// - /// Class SortNameProvider - /// - public class SortNameProvider : BaseMetadataProvider - { - public SortNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) - { - } - - /// - /// Supportses the specified item. - /// - /// The item. - /// true if XXXX, false otherwise - public override bool Supports(BaseItem item) - { - return true; - } - - /// - /// Gets the priority. - /// - /// The priority. - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.Last; } - } - - /// - /// Needses the refresh internal. - /// - /// The item. - /// The provider info. - /// true if XXXX, false otherwise - protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) - { - return !string.IsNullOrEmpty(item.Name) && string.IsNullOrEmpty(item.SortName); - } - - // Cache these since they will be used a lot - /// - /// The false task result - /// - protected static readonly Task FalseTaskResult = Task.FromResult(false); - - /// - /// The true task result - /// - protected static readonly Task TrueTaskResult = Task.FromResult(true); - - /// - /// Fetches metadata and returns true or false indicating if any work that requires persistence was done - /// - /// The item. - /// if set to true [force]. - /// The cancellation token. - /// Task{System.Boolean}. - public override Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) - { - return SetSortName(item, cancellationToken) ? TrueTaskResult : FalseTaskResult; - } - - /// - /// Sets the name of the sort. - /// - /// The item. - /// The cancellation token. - /// true if XXXX, false otherwise - protected bool SetSortName(BaseItem item, CancellationToken cancellationToken) - { - if (!string.IsNullOrWhiteSpace(item.SortName)) return false; //let the earlier provider win - - cancellationToken.ThrowIfCancellationRequested(); - - if (item is Episode) - { - //special handling for TV episodes season and episode number - item.SortName = (item.ParentIndexNumber != null ? item.ParentIndexNumber.Value.ToString("000-") : "") - + (item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000 - ") : "") + item.Name; - - } - else if (item is Season) - { - //sort seasons by season number - numerically - item.SortName = item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000") : item.Name; - } - else if (item is Audio) - { - //sort tracks by production year and index no so they will sort in order if in a multi-album list - item.SortName = (item.ProductionYear != null ? item.ProductionYear.Value.ToString("000-") : "") - + (item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000 - ") : "") + item.Name; - } - else if (item is MusicAlbum) - { - //sort albums by year - item.SortName = item.ProductionYear != null ? item.ProductionYear.Value.ToString("0000") : item.Name; - } - else - { - if (item.Name == null) return false; //some items may not have name filled in properly - - var sortable = item.Name.Trim().ToLower(); - sortable = ConfigurationManager.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty)); - - sortable = ConfigurationManager.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " ")); - - foreach (var search in ConfigurationManager.Configuration.SortRemoveWords) - { - cancellationToken.ThrowIfCancellationRequested(); - - var searchLower = search.ToLower(); - // Remove from beginning if a space follows - if (sortable.StartsWith(searchLower + " ")) - { - sortable = sortable.Remove(0, searchLower.Length + 1); - } - // Remove from middle if surrounded by spaces - sortable = sortable.Replace(" " + searchLower + " ", " "); - - // Remove from end if followed by a space - if (sortable.EndsWith(" " + searchLower)) - { - sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1)); - } - } - item.SortName = sortable; - } - - return true; - } - - } -}