< Summary - Jellyfin

Information
Class: Jellyfin.Server.Implementations.Item.FolderAwareFilterExtensions
Assembly: Jellyfin.Server.Implementations
File(s): /srv/git/jellyfin/Jellyfin.Server.Implementations/Item/FolderAwareFilterExtensions.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 24
Coverable lines: 24
Total lines: 83
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 5/4/2026 - 12:15:16 AM Line coverage: 0% (0/24) Total lines: 83

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
WhereItemOrDescendantMatches(...)100%210%
WhereNeitherItemNorDescendantMatches(...)100%210%

File(s)

/srv/git/jellyfin/Jellyfin.Server.Implementations/Item/FolderAwareFilterExtensions.cs

#LineLine coverage
 1#pragma warning disable RS0030 // Do not use banned APIs
 2
 3using System;
 4using System.Linq;
 5using System.Linq.Expressions;
 6using Jellyfin.Database.Implementations;
 7using Jellyfin.Database.Implementations.Entities;
 8
 9namespace Jellyfin.Server.Implementations.Item;
 10
 11/// <summary>
 12/// Extension methods for applying folder-aware filters that check items and their descendants.
 13/// </summary>
 14internal static class FolderAwareFilterExtensions
 15{
 16    /// <summary>
 17    /// Filters items where either the item matches the condition (for non-folders)
 18    /// or any descendant matches (for folders). Uses reverse traversal through AncestorIds.
 19    /// </summary>
 20    /// <param name="query">The query to filter.</param>
 21    /// <param name="context">The database context.</param>
 22    /// <param name="condition">The condition to check on BaseItemEntity.</param>
 23    /// <returns>Filtered query.</returns>
 24    public static IQueryable<BaseItemEntity> WhereItemOrDescendantMatches(
 25        this IQueryable<BaseItemEntity> query,
 26        JellyfinDbContext context,
 27        Expression<Func<BaseItemEntity, bool>> condition)
 28    {
 29        // Get IDs of items that directly match the condition
 030        var directMatchIds = context.BaseItems.Where(condition).Select(b => b.Id);
 31
 32        // Get parent IDs where a descendant (via AncestorIds) matches
 033        var ancestorMatchIds = context.AncestorIds
 034            .Where(a => directMatchIds.Contains(a.ItemId))
 035            .Select(a => a.ParentItemId);
 36
 37        // Get parent IDs where a linked child matches
 038        var linkedMatchIds = context.LinkedChildren
 039            .Where(lc => directMatchIds.Contains(lc.ChildId))
 040            .Select(lc => lc.ParentId);
 41
 042        var allMatchingIds = directMatchIds
 043            .Concat(ancestorMatchIds)
 044            .Concat(linkedMatchIds)
 045            .Distinct();
 46
 047        return query.Where(e => allMatchingIds.Contains(e.Id));
 48    }
 49
 50    /// <summary>
 51    /// Filters items where neither the item matches the condition (for non-folders)
 52    /// nor any descendant matches (for folders). Uses reverse traversal for infinite depth.
 53    /// </summary>
 54    /// <param name="query">The query to filter.</param>
 55    /// <param name="context">The database context.</param>
 56    /// <param name="condition">The condition that should NOT match.</param>
 57    /// <returns>Filtered query.</returns>
 58    public static IQueryable<BaseItemEntity> WhereNeitherItemNorDescendantMatches(
 59        this IQueryable<BaseItemEntity> query,
 60        JellyfinDbContext context,
 61        Expression<Func<BaseItemEntity, bool>> condition)
 62    {
 63        // Get IDs of items that directly match the condition
 064        var directMatchIds = context.BaseItems.Where(condition).Select(b => b.Id);
 65
 66        // Get parent IDs where a descendant (via AncestorIds) matches
 067        var ancestorMatchIds = context.AncestorIds
 068            .Where(a => directMatchIds.Contains(a.ItemId))
 069            .Select(a => a.ParentItemId);
 70
 71        // Get parent IDs where a linked child matches
 072        var linkedMatchIds = context.LinkedChildren
 073            .Where(lc => directMatchIds.Contains(lc.ChildId))
 074            .Select(lc => lc.ParentId);
 75
 076        var allMatchingIds = directMatchIds
 077            .Concat(ancestorMatchIds)
 078            .Concat(linkedMatchIds)
 079            .Distinct();
 80
 081        return query.Where(e => !allMatchingIds.Contains(e.Id));
 82    }
 83}