diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 90f03995e8..797990d296 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4020,34 +4020,116 @@ namespace Emby.Server.Implementations.Data whereClauses.Add(clause); } - if (query.MinParentalRating.HasValue) + var ratingClause = "("; + if (query.HasParentalRating.HasValue && query.HasParentalRating.Value) { - whereClauses.Add("InheritedParentalRatingValue>=@MinParentalRating"); - if (statement is not null) + ratingClause += "InheritedParentalRatingValue not null"; + if (query.MinParentalRating.HasValue) { - statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); + ratingClause += " AND InheritedParentalRatingValue >= @MinParentalRating"; + if (statement is not null) + { + statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); + } } - } - if (query.MaxParentalRating.HasValue) - { - whereClauses.Add("InheritedParentalRatingValue<=@MaxParentalRating"); - if (statement is not null) + if (query.MaxParentalRating.HasValue) { - statement.TryBind("@MaxParentalRating", query.MaxParentalRating.Value); + ratingClause += " AND InheritedParentalRatingValue <= @MaxParentalRating"; + if (statement is not null) + { + statement.TryBind("@MaxParentalRating", query.MaxParentalRating.Value); + } } } + else if (query.BlockUnratedItems.Length > 0) + { + var paramName = "@UnratedType"; + var index = 0; + string blockedUnratedItems = string.Join(',', query.BlockUnratedItems.Select(_ => paramName + index++)); + ratingClause += "(InheritedParentalRatingValue is null AND UnratedType not in (" + blockedUnratedItems + "))"; + + if (statement != null) + { + for (var ind = 0; ind < query.BlockUnratedItems.Length; ind++) + { + statement.TryBind(paramName + ind, query.BlockUnratedItems[ind].ToString()); + } + } + + if (query.MinParentalRating.HasValue || query.MaxParentalRating.HasValue) + { + ratingClause += " OR ("; + } - if (query.HasParentalRating.HasValue) + if (query.MinParentalRating.HasValue) + { + ratingClause += "InheritedParentalRatingValue >= @MinParentalRating"; + if (statement != null) + { + statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); + } + } + + if (query.MaxParentalRating.HasValue) + { + if (query.MinParentalRating.HasValue) + { + ratingClause += " AND "; + } + + ratingClause += "InheritedParentalRatingValue <= @MaxParentalRating"; + if (statement != null) + { + statement.TryBind("@MaxParentalRating", query.MaxParentalRating.Value); + } + } + + if (query.MinParentalRating.HasValue || query.MaxParentalRating.HasValue) + { + ratingClause += ")"; + } + + if (!(query.MinParentalRating.HasValue || query.MaxParentalRating.HasValue)) + { + ratingClause += " OR InheritedParentalRatingValue not null"; + } + } + else if (query.MinParentalRating.HasValue) { - if (query.HasParentalRating.Value) + ratingClause += "InheritedParentalRatingValue is null OR (InheritedParentalRatingValue >= @MinParentalRating"; + if (statement != null) { - whereClauses.Add("InheritedParentalRatingValue > 0"); + statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); } - else + + if (query.MaxParentalRating.HasValue) { - whereClauses.Add("InheritedParentalRatingValue = 0"); + ratingClause += " AND InheritedParentalRatingValue <= @MaxParentalRating"; + if (statement != null) + { + statement.TryBind("@MaxParentalRating", query.MaxParentalRating.Value); + } } + + ratingClause += ")"; + } + else if (query.MaxParentalRating.HasValue) + { + ratingClause += "InheritedParentalRatingValue is null OR InheritedParentalRatingValue <= @MaxParentalRating"; + if (statement != null) + { + statement.TryBind("@MaxParentalRating", query.MaxParentalRating.Value); + } + } + else if (query.HasParentalRating.HasValue && !query.HasParentalRating.Value) + { + ratingClause += "InheritedParentalRatingValue is null"; + } + + if (!string.Equals(ratingClause, "(", StringComparison.OrdinalIgnoreCase)) + { + whereClauses.Add(ratingClause + ")"); } if (query.HasOfficialRating.HasValue) @@ -4312,7 +4394,7 @@ namespace Emby.Server.Implementations.Data } // TODO this seems to be an idea for a better schema where ProviderIds are their own table - // buut this is not implemented + // but this is not implemented // hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); // TODO this is a really BAD way to do it since the pair: @@ -4440,25 +4522,6 @@ namespace Emby.Server.Implementations.Data } } - if (query.BlockUnratedItems.Length == 1) - { - whereClauses.Add("(InheritedParentalRatingValue > 0 or UnratedType <> @UnratedType)"); - if (statement is not null) - { - statement.TryBind("@UnratedType", query.BlockUnratedItems[0].ToString()); - } - } - - if (query.BlockUnratedItems.Length > 1) - { - var inClause = string.Join(',', query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'")); - whereClauses.Add( - string.Format( - CultureInfo.InvariantCulture, - "(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", - inClause)); - } - if (query.ExcludeInheritedTags.Length > 0) { var paramName = "@ExcludeInheritedTags"; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 5e22e78867..0e19e80a88 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.Localization } } - // TODO: Further improve by normalizing out all spaces and dashes + // TODO: Further improve when necessary return null; } diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 57d446dbd0..9c71482413 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -147,7 +147,7 @@ public class ItemUpdateController : BaseJellyfinApiController var info = new MetadataEditorInfo { - ParentalRatingOptions = _localizationManager.GetParentalRatings().ToArray(), + ParentalRatingOptions = _localizationManager.GetParentalRatings().ToList(), ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(), Countries = _localizationManager.GetCountries().ToArray(), Cultures = _localizationManager.GetCultures().ToArray() diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 728e628109..377526729a 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -411,6 +411,13 @@ public class ItemsController : BaseJellyfinApiController query.SeriesStatuses = seriesStatus; } + // Exclude Blocked Unrated Items + var blockedUnratedItems = user?.GetPreferenceValues(PreferenceKind.BlockUnratedItems); + if (blockedUnratedItems is not null) + { + query.BlockUnratedItems = blockedUnratedItems; + } + // ExcludeLocationTypes if (excludeLocationTypes.Any(t => t == LocationType.Virtual)) {