< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.Resolvers.PhotoResolver
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
Line coverage
22%
Covered lines: 10
Uncovered lines: 34
Coverable lines: 44
Total lines: 122
Line coverage: 22.7%
Branch coverage
27%
Covered branches: 6
Total branches: 22
Branch coverage: 27.2%
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
.cctor()100%210%
.ctor(...)100%11100%
Resolve(...)37.5%106.051629.41%
IsOwnedByMedia(...)0%620%
IsOwnedByResolvedMedia(...)100%210%
IsImageFile(...)0%2040%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs

#LineLine coverage
 1using System;
 2using System.IO;
 3using System.Linq;
 4using Emby.Naming.Common;
 5using Emby.Naming.Video;
 6using Jellyfin.Data.Enums;
 7using Jellyfin.Extensions;
 8using MediaBrowser.Controller.Drawing;
 9using MediaBrowser.Controller.Entities;
 10using MediaBrowser.Controller.Library;
 11using MediaBrowser.Controller.Providers;
 12using MediaBrowser.Controller.Resolvers;
 13using MediaBrowser.Model.Entities;
 14
 15namespace Emby.Server.Implementations.Library.Resolvers
 16{
 17    /// <summary>
 18    /// Class PhotoResolver.
 19    /// </summary>
 20    public class PhotoResolver : ItemResolver<Photo>
 21    {
 22        private readonly IImageProcessor _imageProcessor;
 23        private readonly NamingOptions _namingOptions;
 24        private readonly IDirectoryService _directoryService;
 25
 026        private static readonly string[] _ignoreFiles = new[]
 027        {
 028            "folder",
 029            "thumb",
 030            "landscape",
 031            "fanart",
 032            "backdrop",
 033            "poster",
 034            "cover",
 035            "logo",
 036            "default"
 037        };
 38
 39        /// <summary>
 40        /// Initializes a new instance of the <see cref="PhotoResolver"/> class.
 41        /// </summary>
 42        /// <param name="imageProcessor">The image processor.</param>
 43        /// <param name="namingOptions">The naming options.</param>
 44        /// <param name="directoryService">The directory service.</param>
 2245        public PhotoResolver(IImageProcessor imageProcessor, NamingOptions namingOptions, IDirectoryService directorySer
 46        {
 2247            _imageProcessor = imageProcessor;
 2248            _namingOptions = namingOptions;
 2249            _directoryService = directoryService;
 2250        }
 51
 52        /// <summary>
 53        /// Resolves the specified args.
 54        /// </summary>
 55        /// <param name="args">The args.</param>
 56        /// <returns>Trailer.</returns>
 57        protected override Photo? Resolve(ItemResolveArgs args)
 58        {
 4959            if (!args.IsDirectory)
 60            {
 61                // Must be an image file within a photo collection
 362                var collectionType = args.CollectionType;
 63
 364                if (collectionType == CollectionType.photos
 365                    || (collectionType == CollectionType.homevideos && args.LibraryOptions.EnablePhotos))
 66                {
 067                    if (IsImageFile(args.Path, _imageProcessor))
 68                    {
 069                        var filename = Path.GetFileNameWithoutExtension(args.Path.AsSpan());
 70
 71                        // Make sure the image doesn't belong to a video file
 072                        var files = _directoryService.GetFiles(Path.GetDirectoryName(args.Path)
 073                            ?? throw new InvalidOperationException("Path can't be a root directory."));
 74
 075                        foreach (var file in files)
 76                        {
 077                            if (IsOwnedByMedia(_namingOptions, file.FullName, filename))
 78                            {
 079                                return null;
 80                            }
 81                        }
 82
 083                        return new Photo
 084                        {
 085                            Path = args.Path
 086                        };
 87                    }
 88                }
 89            }
 90
 4991            return null;
 092        }
 93
 94        internal static bool IsOwnedByMedia(NamingOptions namingOptions, string file, ReadOnlySpan<char> imageFilename)
 95        {
 096            return VideoResolver.IsVideoFile(file, namingOptions) && IsOwnedByResolvedMedia(file, imageFilename);
 97        }
 98
 99        internal static bool IsOwnedByResolvedMedia(ReadOnlySpan<char> file, ReadOnlySpan<char> imageFilename)
 0100            => imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file), StringComparison.OrdinalIgnoreCase);
 101
 102        internal static bool IsImageFile(string path, IImageProcessor imageProcessor)
 103        {
 0104            ArgumentNullException.ThrowIfNull(path);
 105
 0106            var extension = Path.GetExtension(path.AsSpan()).TrimStart('.');
 0107            if (!imageProcessor.SupportedInputFormats.Contains(extension, StringComparison.OrdinalIgnoreCase))
 108            {
 0109                return false;
 110            }
 111
 0112            var filename = Path.GetFileNameWithoutExtension(path);
 113
 0114            if (_ignoreFiles.Any(i => filename.StartsWith(i, StringComparison.OrdinalIgnoreCase)))
 115            {
 0116                return false;
 117            }
 118
 0119            return true;
 120        }
 121    }
 122}