< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.FilterController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/FilterController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 107
Coverable lines: 107
Total lines: 218
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 48
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetQueryFiltersLegacy(...)0%272160%
GetQueryFilters(...)0%1056320%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/FilterController.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3using Jellyfin.Api.Helpers;
 4using Jellyfin.Api.ModelBinders;
 5using Jellyfin.Data.Enums;
 6using Jellyfin.Extensions;
 7using MediaBrowser.Controller.Dto;
 8using MediaBrowser.Controller.Entities;
 9using MediaBrowser.Controller.Library;
 10using MediaBrowser.Model.Dto;
 11using MediaBrowser.Model.Querying;
 12using Microsoft.AspNetCore.Authorization;
 13using Microsoft.AspNetCore.Http;
 14using Microsoft.AspNetCore.Mvc;
 15
 16namespace Jellyfin.Api.Controllers;
 17
 18/// <summary>
 19/// Filters controller.
 20/// </summary>
 21[Route("")]
 22[Authorize]
 23public class FilterController : BaseJellyfinApiController
 24{
 25    private readonly ILibraryManager _libraryManager;
 26    private readonly IUserManager _userManager;
 27
 28    /// <summary>
 29    /// Initializes a new instance of the <see cref="FilterController"/> class.
 30    /// </summary>
 31    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 32    /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
 033    public FilterController(ILibraryManager libraryManager, IUserManager userManager)
 34    {
 035        _libraryManager = libraryManager;
 036        _userManager = userManager;
 037    }
 38
 39    /// <summary>
 40    /// Gets legacy query filters.
 41    /// </summary>
 42    /// <param name="userId">Optional. User id.</param>
 43    /// <param name="parentId">Optional. Parent id.</param>
 44    /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows 
 45    /// <param name="mediaTypes">Optional. Filter by MediaType. Allows multiple, comma delimited.</param>
 46    /// <response code="200">Legacy filters retrieved.</response>
 47    /// <returns>Legacy query filters.</returns>
 48    [HttpGet("Items/Filters")]
 49    [ProducesResponseType(StatusCodes.Status200OK)]
 50    public ActionResult<QueryFiltersLegacy> GetQueryFiltersLegacy(
 51        [FromQuery] Guid? userId,
 52        [FromQuery] Guid? parentId,
 53        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
 54        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] MediaType[] mediaTypes)
 55    {
 056        userId = RequestHelpers.GetUserId(User, userId);
 057        var user = userId.IsNullOrEmpty()
 058            ? null
 059            : _userManager.GetUserById(userId.Value);
 60
 061        BaseItem? item = null;
 062        if (includeItemTypes.Length != 1
 063            || !(includeItemTypes[0] == BaseItemKind.BoxSet
 064                 || includeItemTypes[0] == BaseItemKind.Playlist
 065                 || includeItemTypes[0] == BaseItemKind.Trailer
 066                 || includeItemTypes[0] == BaseItemKind.Program))
 67        {
 068            item = _libraryManager.GetParentItem(parentId, user?.Id);
 69        }
 70
 071        var query = new InternalItemsQuery
 072        {
 073            User = user,
 074            MediaTypes = mediaTypes,
 075            IncludeItemTypes = includeItemTypes,
 076            Recursive = true,
 077            EnableTotalRecordCount = false,
 078            DtoOptions = new DtoOptions
 079            {
 080                Fields = new[] { ItemFields.Genres, ItemFields.Tags },
 081                EnableImages = false,
 082                EnableUserData = false
 083            }
 084        };
 85
 086        if (item is not Folder folder)
 87        {
 088            return new QueryFiltersLegacy();
 89        }
 90
 091        var itemList = folder.GetItemList(query);
 092        return new QueryFiltersLegacy
 093        {
 094            Years = itemList.Select(i => i.ProductionYear ?? -1)
 095                .Where(i => i > 0)
 096                .Distinct()
 097                .Order()
 098                .ToArray(),
 099
 0100            Genres = itemList.SelectMany(i => i.Genres)
 0101                .DistinctNames()
 0102                .Order()
 0103                .ToArray(),
 0104
 0105            Tags = itemList
 0106                .SelectMany(i => i.Tags)
 0107                .Distinct(StringComparer.OrdinalIgnoreCase)
 0108                .Order()
 0109                .ToArray(),
 0110
 0111            OfficialRatings = itemList
 0112                .Select(i => i.OfficialRating)
 0113                .Where(i => !string.IsNullOrWhiteSpace(i))
 0114                .Distinct(StringComparer.OrdinalIgnoreCase)
 0115                .Order()
 0116                .ToArray()
 0117        };
 118    }
 119
 120    /// <summary>
 121    /// Gets query filters.
 122    /// </summary>
 123    /// <param name="userId">Optional. User id.</param>
 124    /// <param name="parentId">Optional. Specify this to localize the search to a specific item or folder. Omit to use t
 125    /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows 
 126    /// <param name="isAiring">Optional. Is item airing.</param>
 127    /// <param name="isMovie">Optional. Is item movie.</param>
 128    /// <param name="isSports">Optional. Is item sports.</param>
 129    /// <param name="isKids">Optional. Is item kids.</param>
 130    /// <param name="isNews">Optional. Is item news.</param>
 131    /// <param name="isSeries">Optional. Is item series.</param>
 132    /// <param name="recursive">Optional. Search recursive.</param>
 133    /// <response code="200">Filters retrieved.</response>
 134    /// <returns>Query filters.</returns>
 135    [HttpGet("Items/Filters2")]
 136    [ProducesResponseType(StatusCodes.Status200OK)]
 137    public ActionResult<QueryFilters> GetQueryFilters(
 138        [FromQuery] Guid? userId,
 139        [FromQuery] Guid? parentId,
 140        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
 141        [FromQuery] bool? isAiring,
 142        [FromQuery] bool? isMovie,
 143        [FromQuery] bool? isSports,
 144        [FromQuery] bool? isKids,
 145        [FromQuery] bool? isNews,
 146        [FromQuery] bool? isSeries,
 147        [FromQuery] bool? recursive)
 148    {
 0149        userId = RequestHelpers.GetUserId(User, userId);
 0150        var user = userId.IsNullOrEmpty()
 0151            ? null
 0152            : _userManager.GetUserById(userId.Value);
 153
 0154        BaseItem? parentItem = null;
 0155        if (includeItemTypes.Length == 1
 0156            && (includeItemTypes[0] == BaseItemKind.BoxSet
 0157                || includeItemTypes[0] == BaseItemKind.Playlist
 0158                || includeItemTypes[0] == BaseItemKind.Trailer
 0159                || includeItemTypes[0] == BaseItemKind.Program))
 160        {
 0161            parentItem = null;
 162        }
 0163        else if (parentId.HasValue)
 164        {
 0165            parentItem = _libraryManager.GetItemById<BaseItem>(parentId.Value);
 166        }
 167
 0168        var filters = new QueryFilters();
 0169        var genreQuery = new InternalItemsQuery(user)
 0170        {
 0171            IncludeItemTypes = includeItemTypes,
 0172            DtoOptions = new DtoOptions
 0173            {
 0174                Fields = Array.Empty<ItemFields>(),
 0175                EnableImages = false,
 0176                EnableUserData = false
 0177            },
 0178            IsAiring = isAiring,
 0179            IsMovie = isMovie,
 0180            IsSports = isSports,
 0181            IsKids = isKids,
 0182            IsNews = isNews,
 0183            IsSeries = isSeries
 0184        };
 185
 0186        if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
 187        {
 0188            genreQuery.AncestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id };
 189        }
 190        else
 191        {
 0192            genreQuery.Parent = parentItem;
 193        }
 194
 0195        if (includeItemTypes.Length == 1
 0196            && (includeItemTypes[0] == BaseItemKind.MusicAlbum
 0197                || includeItemTypes[0] == BaseItemKind.MusicVideo
 0198                || includeItemTypes[0] == BaseItemKind.MusicArtist
 0199                || includeItemTypes[0] == BaseItemKind.Audio))
 200        {
 0201            filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
 0202            {
 0203                Name = i.Item.Name,
 0204                Id = i.Item.Id
 0205            }).ToArray();
 206        }
 207        else
 208        {
 0209            filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
 0210            {
 0211                Name = i.Item.Name,
 0212                Id = i.Item.Id
 0213            }).ToArray();
 214        }
 215
 0216        return filters;
 217    }
 218}