< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Entities.InternalItemsQuery
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
Line coverage
75%
Covered lines: 77
Uncovered lines: 25
Coverable lines: 102
Total lines: 499
Line coverage: 75.4%
Branch coverage
35%
Covered branches: 11
Total branches: 31
Branch coverage: 35.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 2/11/2026 - 12:13:19 AM Line coverage: 98.4% (64/65) Branch coverage: 83.3% (5/6) Total lines: 3923/14/2026 - 12:13:58 AM Line coverage: 73.9% (71/96) Branch coverage: 38.7% (12/31) Total lines: 4635/4/2026 - 12:15:16 AM Line coverage: 74.7% (74/99) Branch coverage: 38.7% (12/31) Total lines: 4845/16/2026 - 12:15:55 AM Line coverage: 75.2% (76/101) Branch coverage: 38.7% (12/31) Total lines: 4925/20/2026 - 12:15:44 AM Line coverage: 75.2% (76/101) Branch coverage: 35.4% (11/31) Total lines: 4925/22/2026 - 12:15:17 AM Line coverage: 75.4% (77/102) Branch coverage: 35.4% (11/31) Total lines: 499 2/11/2026 - 12:13:19 AM Line coverage: 98.4% (64/65) Branch coverage: 83.3% (5/6) Total lines: 3923/14/2026 - 12:13:58 AM Line coverage: 73.9% (71/96) Branch coverage: 38.7% (12/31) Total lines: 4635/4/2026 - 12:15:16 AM Line coverage: 74.7% (74/99) Branch coverage: 38.7% (12/31) Total lines: 4845/16/2026 - 12:15:55 AM Line coverage: 75.2% (76/101) Branch coverage: 38.7% (12/31) Total lines: 4925/20/2026 - 12:15:44 AM Line coverage: 75.2% (76/101) Branch coverage: 35.4% (11/31) Total lines: 4925/22/2026 - 12:15:17 AM Line coverage: 75.4% (77/102) Branch coverage: 35.4% (11/31) Total lines: 499

Coverage delta

Coverage delta 45 -45

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
.ctor(...)50%22100%
set_Parent(...)100%22100%
SetUser(...)50%2294.11%
ApplyFilters(...)28%3152522.58%

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Entities/InternalItemsQuery.cs

#LineLine coverage
 1#pragma warning disable CA1044, CA1819, CA2227, CS1591
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using Diacritics.Extensions;
 7using Jellyfin.Data;
 8using Jellyfin.Data.Enums;
 9using Jellyfin.Database.Implementations.Entities;
 10using Jellyfin.Database.Implementations.Enums;
 11using MediaBrowser.Controller.Dto;
 12using MediaBrowser.Model.Entities;
 13using MediaBrowser.Model.Querying;
 14
 15namespace MediaBrowser.Controller.Entities
 16{
 17    public class InternalItemsQuery
 18    {
 19        public InternalItemsQuery()
 20        {
 57021            AlbumArtistIds = [];
 57022            AlbumIds = [];
 57023            AncestorIds = [];
 57024            LinkedChildAncestorIds = [];
 57025            ArtistIds = [];
 57026            BlockUnratedItems = [];
 57027            BoxSetLibraryFolders = [];
 57028            ChannelIds = [];
 57029            ContributingArtistIds = [];
 57030            DtoOptions = new DtoOptions();
 57031            EnableTotalRecordCount = true;
 57032            ExcludeArtistIds = [];
 57033            ExcludeInheritedTags = [];
 57034            IncludeInheritedTags = [];
 57035            ExcludeItemIds = [];
 57036            ExcludeItemTypes = [];
 57037            ExcludeTags = [];
 57038            GenreIds = [];
 57039            Genres = [];
 57040            GroupByPresentationUniqueKey = true;
 57041            ImageTypes = [];
 57042            IncludeItemTypes = [];
 57043            ItemIds = [];
 57044            OwnerIds = [];
 57045            ExtraTypes = [];
 57046            MediaTypes = [];
 57047            OfficialRatings = [];
 57048            OrderBy = [];
 57049            OwnerIds = [];
 57050            PersonIds = [];
 57051            PersonTypes = [];
 57052            PresetViews = [];
 57053            SeriesStatuses = [];
 57054            SourceTypes = [];
 57055            StudioIds = [];
 57056            Tags = [];
 57057            TopParentIds = [];
 57058            TrailerTypes = [];
 57059            VideoTypes = [];
 57060            Years = [];
 57061            SkipDeserialization = false;
 57062            AudioLanguages = [];
 57063            SubtitleLanguages = [];
 57064        }
 65
 66        public InternalItemsQuery(User? user)
 267            : this()
 68        {
 269            if (user is not null)
 70            {
 271                SetUser(user);
 72            }
 273        }
 74
 75        public bool Recursive { get; set; }
 76
 77        public int? StartIndex { get; set; }
 78
 79        public int? Limit { get; set; }
 80
 81        public User? User { get; set; }
 82
 83        public bool? IsFolder { get; set; }
 84
 85        public bool? IsFavorite { get; set; }
 86
 87        public bool? IsFavoriteOrLiked { get; set; }
 88
 89        public bool? IsLiked { get; set; }
 90
 91        public bool? IsPlayed { get; set; }
 92
 93        public bool? IsResumable { get; set; }
 94
 95        public bool? IncludeItemsByName { get; set; }
 96
 97        public MediaType[] MediaTypes { get; set; }
 98
 99        public BaseItemKind[] IncludeItemTypes { get; set; }
 100
 101        public BaseItemKind[] ExcludeItemTypes { get; set; }
 102
 103        public string[] ExcludeTags { get; set; }
 104
 105        public string[] ExcludeInheritedTags { get; set; }
 106
 107        public string[] IncludeInheritedTags { get; set; }
 108
 109        public IReadOnlyList<string> Genres { get; set; }
 110
 111        public bool? IsSpecialSeason { get; set; }
 112
 113        public bool? IsMissing { get; set; }
 114
 115        public bool? IsUnaired { get; set; }
 116
 117        public bool? CollapseBoxSetItems { get; set; }
 118
 119        /// <summary>
 120        /// Gets or sets the item types that should be collapsed into box sets.
 121        /// When empty, all types are collapsed. When set, only items of these types are replaced by their parent box se
 122        /// </summary>
 123        public BaseItemKind[] CollapseBoxSetItemTypes { get; set; } = [];
 124
 125        public string? NameStartsWithOrGreater { get; set; }
 126
 127        public string? NameStartsWith { get; set; }
 128
 129        public string? NameLessThan { get; set; }
 130
 131        public string? NameContains { get; set; }
 132
 133        public string? MinSortName { get; set; }
 134
 135        public string? PresentationUniqueKey { get; set; }
 136
 137        public string? Path { get; set; }
 138
 139        public string? Name { get; set; }
 140
 141        public bool? UseRawName { get; set; }
 142
 143        public string? Person { get; set; }
 144
 145        public Guid[] PersonIds { get; set; }
 146
 147        public Guid[] ItemIds { get; set; }
 148
 149        public Guid[] OwnerIds { get; set; }
 150
 151        public ExtraType[] ExtraTypes { get; set; }
 152
 153        public Guid[] ExcludeItemIds { get; set; }
 154
 155        public Guid? AdjacentTo { get; set; }
 156
 157        public string[] PersonTypes { get; set; }
 158
 159        public bool? Is3D { get; set; }
 160
 161        public bool? IsHD { get; set; }
 162
 163        public bool? IsLocked { get; set; }
 164
 165        public bool? IsPlaceHolder { get; set; }
 166
 167        public bool? HasImdbId { get; set; }
 168
 169        public bool? HasOverview { get; set; }
 170
 171        public bool? HasTmdbId { get; set; }
 172
 173        public bool? HasOfficialRating { get; set; }
 174
 175        public bool? HasTvdbId { get; set; }
 176
 177        public bool? HasThemeSong { get; set; }
 178
 179        public bool? HasThemeVideo { get; set; }
 180
 181        public bool? HasSubtitles { get; set; }
 182
 183        public bool? HasSpecialFeature { get; set; }
 184
 185        public bool? HasTrailer { get; set; }
 186
 187        public bool? HasParentalRating { get; set; }
 188
 189        public Guid[] StudioIds { get; set; }
 190
 191        public IReadOnlyList<Guid> GenreIds { get; set; }
 192
 193        public ImageType[] ImageTypes { get; set; }
 194
 195        public VideoType[] VideoTypes { get; set; }
 196
 197        public UnratedItem[] BlockUnratedItems { get; set; }
 198
 199        public int[] Years { get; set; }
 200
 201        public string[] Tags { get; set; }
 202
 203        public string[] OfficialRatings { get; set; }
 204
 205        public DateTime? MinPremiereDate { get; set; }
 206
 207        public DateTime? MaxPremiereDate { get; set; }
 208
 209        public DateTime? MinStartDate { get; set; }
 210
 211        public DateTime? MaxStartDate { get; set; }
 212
 213        public DateTime? MinEndDate { get; set; }
 214
 215        public DateTime? MaxEndDate { get; set; }
 216
 217        public bool? IsAiring { get; set; }
 218
 219        public bool? IsMovie { get; set; }
 220
 221        public bool? IsSports { get; set; }
 222
 223        public bool? IsKids { get; set; }
 224
 225        public bool? IsNews { get; set; }
 226
 227        public bool? IsSeries { get; set; }
 228
 229        public int? MinIndexNumber { get; set; }
 230
 231        /// <summary>
 232        /// Gets or sets the minimum ParentIndexNumber and IndexNumber.
 233        /// </summary>
 234        /// <remarks>
 235        /// It produces this where clause:
 236        /// <para>(ParentIndexNumber = X and IndexNumber >= Y) or ParentIndexNumber > X.
 237        /// </para>
 238        /// </remarks>
 239        public (int ParentIndexNumber, int IndexNumber)? MinParentAndIndexNumber { get; set; }
 240
 241        public int? AiredDuringSeason { get; set; }
 242
 243        public double? MinCriticRating { get; set; }
 244
 245        public double? MinCommunityRating { get; set; }
 246
 247        public IReadOnlyList<Guid> ChannelIds { get; set; }
 248
 249        public int? ParentIndexNumber { get; set; }
 250
 251        public int? ParentIndexNumberNotEquals { get; set; }
 252
 253        public int? IndexNumber { get; set; }
 254
 255        public ParentalRatingScore? MinParentalRating { get; set; }
 256
 257        public ParentalRatingScore? MaxParentalRating { get; set; }
 258
 259        public bool? HasDeadParentId { get; set; }
 260
 261        public bool? IsVirtualItem { get; set; }
 262
 263        public Guid ParentId { get; set; }
 264
 265        public BaseItemKind? ParentType { get; set; }
 266
 267        public Guid[] AncestorIds { get; set; }
 268
 269        /// <summary>
 270        /// Gets or sets a list of ancestor ids that the item's linked children must descend from.
 271        /// Useful for filtering BoxSets/Playlists to only those that contain items from a specific library.
 272        /// </summary>
 273        public Guid[] LinkedChildAncestorIds { get; set; }
 274
 275        public Guid[] TopParentIds { get; set; }
 276
 277        public CollectionType?[] PresetViews { get; set; }
 278
 279        public TrailerType[] TrailerTypes { get; set; }
 280
 281        public SourceType[] SourceTypes { get; set; }
 282
 283        public SeriesStatus[] SeriesStatuses { get; set; }
 284
 285        public string? ExternalSeriesId { get; set; }
 286
 287        public string? ExternalId { get; set; }
 288
 289        public Guid[] AlbumIds { get; set; }
 290
 291        public Guid[] ArtistIds { get; set; }
 292
 293        public Guid[] ExcludeArtistIds { get; set; }
 294
 295        public string? AncestorWithPresentationUniqueKey { get; set; }
 296
 297        public string? SeriesPresentationUniqueKey { get; set; }
 298
 299        public bool GroupByPresentationUniqueKey { get; set; }
 300
 301        public bool GroupBySeriesPresentationUniqueKey { get; set; }
 302
 303        public bool EnableTotalRecordCount { get; set; }
 304
 305        public bool ForceDirect { get; set; }
 306
 307        public Dictionary<string, string>? ExcludeProviderIds { get; set; }
 308
 309        public bool EnableGroupByMetadataKey { get; set; }
 310
 311        public bool? HasChapterImages { get; set; }
 312
 313        public IReadOnlyList<(ItemSortBy OrderBy, SortOrder SortOrder)> OrderBy { get; set; }
 314
 315        public DateTime? MinDateCreated { get; set; }
 316
 317        public DateTime? MinDateLastSaved { get; set; }
 318
 319        public DateTime? MinDateLastSavedForUser { get; set; }
 320
 321        public DtoOptions DtoOptions { get; set; }
 322
 323        public string? HasNoAudioTrackWithLanguage { get; set; }
 324
 325        public string? HasNoInternalSubtitleTrackWithLanguage { get; set; }
 326
 327        public string? HasNoExternalSubtitleTrackWithLanguage { get; set; }
 328
 329        public string? HasNoSubtitleTrackWithLanguage { get; set; }
 330
 331        public bool? IsDeadArtist { get; set; }
 332
 333        public bool? IsDeadStudio { get; set; }
 334
 335        public bool? IsDeadGenre { get; set; }
 336
 337        public bool? IsDeadPerson { get; set; }
 338
 339        /// <summary>
 340        /// Gets or sets a value indicating whether album sub-folders should be returned if they exist.
 341        /// </summary>
 342        public bool? DisplayAlbumFolders { get; set; }
 343
 344        public BaseItem? Parent
 345        {
 346            set
 347            {
 259348                if (value is null)
 349                {
 58350                    ParentId = Guid.Empty;
 58351                    ParentType = null;
 352                }
 353                else
 354                {
 201355                    ParentId = value.Id;
 201356                    ParentType = value.GetBaseItemKind();
 357                }
 201358            }
 359        }
 360
 361        public Dictionary<string, string>? HasAnyProviderId { get; set; }
 362
 363        public Dictionary<string, string[]>? HasAnyProviderIds { get; set; }
 364
 365        public Guid[] AlbumArtistIds { get; set; }
 366
 367        public Guid[] BoxSetLibraryFolders { get; set; }
 368
 369        public Guid[] ContributingArtistIds { get; set; }
 370
 371        public bool? HasAired { get; set; }
 372
 373        public bool? HasOwnerId { get; set; }
 374
 375        /// <summary>
 376        /// Gets or sets a value indicating whether to include items with an OwnerId
 377        /// (additional parts, alternate versions) that are normally excluded from general queries.
 378        /// </summary>
 379        public bool IncludeOwnedItems { get; set; }
 380
 381        public bool? Is4K { get; set; }
 382
 383        public int? MaxHeight { get; set; }
 384
 385        public int? MaxWidth { get; set; }
 386
 387        public int? MinHeight { get; set; }
 388
 389        public int? MinWidth { get; set; }
 390
 391        public string? SearchTerm { get; set; }
 392
 393        public string? SeriesTimerId { get; set; }
 394
 395        public bool SkipDeserialization { get; set; }
 396
 397        public bool IncludeExtras { get; set; }
 398
 399        public IReadOnlyList<string> AudioLanguages { get; set; }
 400
 401        public IReadOnlyList<string> SubtitleLanguages { get; set; }
 402
 403        public void SetUser(User user)
 404        {
 2405            var maxRating = user.MaxParentalRatingScore;
 2406            if (maxRating.HasValue)
 407            {
 0408                MaxParentalRating = new(maxRating.Value, user.MaxParentalRatingSubScore);
 409            }
 410
 2411            var other = UnratedItem.Other.ToString();
 2412            BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
 2413                .Where(i => i != other)
 2414                .Select(e => Enum.Parse<UnratedItem>(e, true)).ToArray();
 415
 2416            ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags)
 2417                .Where(tag => !string.IsNullOrWhiteSpace(tag))
 2418                .Select(tag => tag.RemoveDiacritics().ToLowerInvariant())
 2419                .ToArray();
 420
 2421            IncludeInheritedTags = user.GetPreference(PreferenceKind.AllowedTags)
 2422                .Where(tag => !string.IsNullOrWhiteSpace(tag))
 2423                .Select(tag => tag.RemoveDiacritics().ToLowerInvariant())
 2424                .ToArray();
 425
 2426            User = user;
 2427        }
 428
 429        public void ApplyFilters(ItemFilter[] filters)
 430        {
 431            static void ThrowConflictingFilters()
 432                => throw new ArgumentException("Conflicting filters", nameof(filters));
 433
 9434            foreach (var filter in filters)
 435            {
 436                switch (filter)
 437                {
 438                    case ItemFilter.IsFolder:
 1439                        if (filters.Contains(ItemFilter.IsNotFolder))
 440                        {
 1441                            ThrowConflictingFilters();
 442                        }
 443
 0444                        IsFolder = true;
 0445                        break;
 446                    case ItemFilter.IsNotFolder:
 0447                        if (filters.Contains(ItemFilter.IsFolder))
 448                        {
 0449                            ThrowConflictingFilters();
 450                        }
 451
 0452                        IsFolder = false;
 0453                        break;
 454                    case ItemFilter.IsUnplayed:
 0455                        if (filters.Contains(ItemFilter.IsPlayed))
 456                        {
 0457                            ThrowConflictingFilters();
 458                        }
 459
 0460                        IsPlayed = false;
 0461                        break;
 462                    case ItemFilter.IsPlayed:
 1463                        if (filters.Contains(ItemFilter.IsUnplayed))
 464                        {
 1465                            ThrowConflictingFilters();
 466                        }
 467
 0468                        IsPlayed = true;
 0469                        break;
 470                    case ItemFilter.IsFavorite:
 0471                        IsFavorite = true;
 0472                        break;
 473                    case ItemFilter.IsResumable:
 0474                        IsResumable = true;
 0475                        break;
 476                    case ItemFilter.Likes:
 1477                        if (filters.Contains(ItemFilter.Dislikes))
 478                        {
 1479                            ThrowConflictingFilters();
 480                        }
 481
 0482                        IsLiked = true;
 0483                        break;
 484                    case ItemFilter.Dislikes:
 0485                        if (filters.Contains(ItemFilter.Likes))
 486                        {
 0487                            ThrowConflictingFilters();
 488                        }
 489
 0490                        IsLiked = false;
 0491                        break;
 492                    case ItemFilter.IsFavoriteOrLikes:
 0493                        IsFavoriteOrLiked = true;
 494                        break;
 495                }
 496            }
 0497        }
 498    }
 499}