Remove warnings from MediaBrowser.LocalMetadata

pull/3334/head
crobibero 4 years ago
parent 403cd3205f
commit 14f32b4927

@ -7,12 +7,43 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata namespace MediaBrowser.LocalMetadata
{ {
/// <summary>
/// The BaseXmlProvider.
/// </summary>
/// <typeparam name="T">Type of provider.</typeparam>
public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasItemChangeMonitor, IHasOrder public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasItemChangeMonitor, IHasOrder
where T : BaseItem, new() where T : BaseItem, new()
{ {
protected IFileSystem FileSystem; /// <summary>
/// Initializes a new instance of the <see cref="BaseXmlProvider{T}"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
protected BaseXmlProvider(IFileSystem fileSystem)
{
this.FileSystem = fileSystem;
}
/// <inheritdoc />
public string Name => XmlProviderUtils.Name;
public Task<MetadataResult<T>> GetMetadata(ItemInfo info, /// After Nfo
/// <inheritdoc />
public virtual int Order => 1;
/// <summary>
/// Gets the IFileSystem.
/// </summary>
protected IFileSystem FileSystem { get; }
/// <summary>
/// Gets metadata for item.
/// </summary>
/// <param name="info">The item info.</param>
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The metadata for item.</returns>
public Task<MetadataResult<T>> GetMetadata(
ItemInfo info,
IDirectoryService directoryService, IDirectoryService directoryService,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
@ -46,15 +77,23 @@ namespace MediaBrowser.LocalMetadata
return Task.FromResult(result); return Task.FromResult(result);
} }
/// <summary>
/// Get metadata from path.
/// </summary>
/// <param name="result">Resulting metadata.</param>
/// <param name="path">The path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
protected abstract void Fetch(MetadataResult<T> result, string path, CancellationToken cancellationToken); protected abstract void Fetch(MetadataResult<T> result, string path, CancellationToken cancellationToken);
protected BaseXmlProvider(IFileSystem fileSystem) /// <summary>
{ /// Get metadata from xml file.
FileSystem = fileSystem; /// </summary>
} /// <param name="info">Item inf.</param>
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
/// <returns>The file system metadata.</returns>
protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService);
/// <inheritdoc />
public bool HasChanged(BaseItem item, IDirectoryService directoryService) public bool HasChanged(BaseItem item, IDirectoryService directoryService)
{ {
var file = GetXmlFile(new ItemInfo(item), directoryService); var file = GetXmlFile(new ItemInfo(item), directoryService);
@ -66,15 +105,5 @@ namespace MediaBrowser.LocalMetadata
return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved;
} }
public string Name => XmlProviderUtils.Name;
//After Nfo
public virtual int Order => 1;
}
static class XmlProviderUtils
{
public static string Name => "Emby Xml";
} }
} }

@ -5,30 +5,41 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images namespace MediaBrowser.LocalMetadata.Images
{ {
/// <summary>
/// Collection folder local image provider.
/// </summary>
public class CollectionFolderLocalImageProvider : ILocalImageProvider, IHasOrder public class CollectionFolderLocalImageProvider : ILocalImageProvider, IHasOrder
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="CollectionFolderLocalImageProvider"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
public CollectionFolderLocalImageProvider(IFileSystem fileSystem) public CollectionFolderLocalImageProvider(IFileSystem fileSystem)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
/// <inheritdoc />
public string Name => "Collection Folder Images"; public string Name => "Collection Folder Images";
/// Run after LocalImageProvider
/// <inheritdoc />
public int Order => 1;
/// <inheritdoc />
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
return item is CollectionFolder && item.SupportsLocalMetadata; return item is CollectionFolder && item.SupportsLocalMetadata;
} }
// Run after LocalImageProvider /// <inheritdoc />
public int Order => 1;
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
{ {
var collectionFolder = (CollectionFolder)item; var collectionFolder = (CollectionFolder)item;
return new LocalImageProvider(_fileSystem).GetImages(item, collectionFolder.PhysicalLocations, true, directoryService); return new LocalImageProvider(_fileSystem).GetImages(item, collectionFolder.PhysicalLocations, directoryService);
} }
} }
} }

@ -10,24 +10,35 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images namespace MediaBrowser.LocalMetadata.Images
{ {
public class EpisodeLocalLocalImageProvider : ILocalImageProvider, IHasOrder /// <summary>
/// Episode local local local image provider.
/// </summary>
public class EpisodeLocalImageProvider : ILocalImageProvider, IHasOrder
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
public EpisodeLocalLocalImageProvider(IFileSystem fileSystem) /// <summary>
/// Initializes a new instance of the <see cref="EpisodeLocalImageProvider"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
public EpisodeLocalImageProvider(IFileSystem fileSystem)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
/// <inheritdoc />
public string Name => "Local Images"; public string Name => "Local Images";
/// <inheritdoc />
public int Order => 0; public int Order => 0;
/// <inheritdoc />
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
return item is Episode && item.SupportsLocalMetadata; return item is Episode && item.SupportsLocalMetadata;
} }
/// <inheritdoc />
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
{ {
var parentPath = Path.GetDirectoryName(item.Path); var parentPath = Path.GetDirectoryName(item.Path);
@ -58,23 +69,15 @@ namespace MediaBrowser.LocalMetadata.Images
if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{ {
list.Add(new LocalImageInfo list.Add(new LocalImageInfo { FileInfo = i, Type = ImageType.Primary });
{
FileInfo = i,
Type = ImageType.Primary
});
} }
else if (string.Equals(thumbName, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) else if (string.Equals(thumbName, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{ {
list.Add(new LocalImageInfo list.Add(new LocalImageInfo { FileInfo = i, Type = ImageType.Primary });
{
FileInfo = i,
Type = ImageType.Primary
});
} }
} }
} }
return list; return list;
} }
} }

@ -9,12 +9,21 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Images namespace MediaBrowser.LocalMetadata.Images
{ {
/// <summary>
/// Internal metadata folder image provider.
/// </summary>
public class InternalMetadataFolderImageProvider : ILocalImageProvider, IHasOrder public class InternalMetadataFolderImageProvider : ILocalImageProvider, IHasOrder
{ {
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILogger<InternalMetadataFolderImageProvider> _logger; private readonly ILogger<InternalMetadataFolderImageProvider> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="InternalMetadataFolderImageProvider"/> class.
/// </summary>
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{InternalMetadataFolderImageProvider}"/> interface.</param>
public InternalMetadataFolderImageProvider( public InternalMetadataFolderImageProvider(
IServerConfigurationManager config, IServerConfigurationManager config,
IFileSystem fileSystem, IFileSystem fileSystem,
@ -25,8 +34,14 @@ namespace MediaBrowser.LocalMetadata.Images
_logger = logger; _logger = logger;
} }
/// Make sure this is last so that all other locations are scanned first
/// <inheritdoc />
public int Order => 1000;
/// <inheritdoc />
public string Name => "Internal Images"; public string Name => "Internal Images";
/// <inheritdoc />
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
if (item is Photo) if (item is Photo)
@ -52,9 +67,8 @@ namespace MediaBrowser.LocalMetadata.Images
return true; return true;
} }
// Make sure this is last so that all other locations are scanned first
public int Order => 1000;
/// <inheritdoc />
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
{ {
var path = item.GetInternalMetadataPath(); var path = item.GetInternalMetadataPath();
@ -66,7 +80,7 @@ namespace MediaBrowser.LocalMetadata.Images
try try
{ {
return new LocalImageProvider(_fileSystem).GetImages(item, path, false, directoryService); return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
} }
catch (IOException ex) catch (IOException ex)
{ {

@ -13,19 +13,71 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images namespace MediaBrowser.LocalMetadata.Images
{ {
/// <summary>
/// Local image provider.
/// </summary>
public class LocalImageProvider : ILocalImageProvider, IHasOrder public class LocalImageProvider : ILocalImageProvider, IHasOrder
{ {
private static readonly string[] _commonImageFileNames =
{
"poster",
"folder",
"cover",
"default"
};
private static readonly string[] _musicImageFileNames =
{
"folder",
"poster",
"cover",
"default"
};
private static readonly string[] _personImageFileNames =
{
"folder",
"poster"
};
private static readonly string[] _seriesImageFileNames =
{
"poster",
"folder",
"cover",
"default",
"show"
};
private static readonly string[] _videoImageFileNames =
{
"poster",
"folder",
"cover",
"default",
"movie"
};
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary>
/// Initializes a new instance of the <see cref="LocalImageProvider"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
public LocalImageProvider(IFileSystem fileSystem) public LocalImageProvider(IFileSystem fileSystem)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
/// <inheritdoc />
public string Name => "Local Images"; public string Name => "Local Images";
/// <inheritdoc />
public int Order => 0; public int Order => 0;
/// <inheritdoc />
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
if (item.SupportsLocalMetadata) if (item.SupportsLocalMetadata)
@ -42,17 +94,12 @@ namespace MediaBrowser.LocalMetadata.Images
if (item.LocationType == LocationType.Virtual) if (item.LocationType == LocationType.Virtual)
{ {
var season = item as Season; var season = item as Season;
var series = season?.Series;
if (season != null)
{
var series = season.Series;
if (series != null && series.IsFileProtocol) if (series != null && series.IsFileProtocol)
{ {
return true; return true;
} }
} }
}
return false; return false;
} }
@ -85,6 +132,7 @@ namespace MediaBrowser.LocalMetadata.Images
.OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty)); .OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty));
} }
/// <inheritdoc />
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
{ {
var files = GetFiles(item, true, directoryService).ToList(); var files = GetFiles(item, true, directoryService).ToList();
@ -96,12 +144,26 @@ namespace MediaBrowser.LocalMetadata.Images
return list; return list;
} }
public List<LocalImageInfo> GetImages(BaseItem item, string path, bool isPathInMediaFolder, IDirectoryService directoryService) /// <summary>
/// Get images for item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="path">The images path.</param>
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
/// <returns>The local image info.</returns>
public List<LocalImageInfo> GetImages(BaseItem item, string path, IDirectoryService directoryService)
{ {
return GetImages(item, new[] { path }, isPathInMediaFolder, directoryService); return GetImages(item, new[] { path }, directoryService);
} }
public List<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, bool arePathsInMediaFolders, IDirectoryService directoryService) /// <summary>
/// Get images for item from multiple paths.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="paths">The image paths.</param>
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
/// <returns>The local image info.</returns>
public List<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, IDirectoryService directoryService)
{ {
IEnumerable<FileSystemMetadata> files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false)); IEnumerable<FileSystemMetadata> files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false));
@ -196,7 +258,7 @@ namespace MediaBrowser.LocalMetadata.Images
if (!isEpisode && !isSong && !isPerson) if (!isEpisode && !isSong && !isPerson)
{ {
PopulateBackdrops(item, images, files, imagePrefix, isInMixedFolder, directoryService); PopulateBackdrops(item, images, files, imagePrefix, isInMixedFolder);
} }
if (item is IHasScreenshots) if (item is IHasScreenshots)
@ -205,46 +267,6 @@ namespace MediaBrowser.LocalMetadata.Images
} }
} }
private static readonly string[] CommonImageFileNames = new[]
{
"poster",
"folder",
"cover",
"default"
};
private static readonly string[] MusicImageFileNames = new[]
{
"folder",
"poster",
"cover",
"default"
};
private static readonly string[] PersonImageFileNames = new[]
{
"folder",
"poster"
};
private static readonly string[] SeriesImageFileNames = new[]
{
"poster",
"folder",
"cover",
"default",
"show"
};
private static readonly string[] VideoImageFileNames = new[]
{
"poster",
"folder",
"cover",
"default",
"movie"
};
private void PopulatePrimaryImages(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder) private void PopulatePrimaryImages(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder)
{ {
string[] imageFileNames; string[] imageFileNames;
@ -252,24 +274,24 @@ namespace MediaBrowser.LocalMetadata.Images
if (item is MusicAlbum || item is MusicArtist || item is PhotoAlbum) if (item is MusicAlbum || item is MusicArtist || item is PhotoAlbum)
{ {
// these prefer folder // these prefer folder
imageFileNames = MusicImageFileNames; imageFileNames = _musicImageFileNames;
} }
else if (item is Person) else if (item is Person)
{ {
// these prefer folder // these prefer folder
imageFileNames = PersonImageFileNames; imageFileNames = _personImageFileNames;
} }
else if (item is Series) else if (item is Series)
{ {
imageFileNames = SeriesImageFileNames; imageFileNames = _seriesImageFileNames;
} }
else if (item is Video && !(item is Episode)) else if (item is Video && !(item is Episode))
{ {
imageFileNames = VideoImageFileNames; imageFileNames = _videoImageFileNames;
} }
else else
{ {
imageFileNames = CommonImageFileNames; imageFileNames = _commonImageFileNames;
} }
var fileNameWithoutExtension = item.FileNameWithoutExtension; var fileNameWithoutExtension = item.FileNameWithoutExtension;
@ -301,7 +323,7 @@ namespace MediaBrowser.LocalMetadata.Images
} }
} }
private void PopulateBackdrops(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder, IDirectoryService directoryService) private void PopulateBackdrops(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder)
{ {
if (!string.IsNullOrEmpty(item.Path)) if (!string.IsNullOrEmpty(item.Path))
{ {
@ -328,13 +350,13 @@ namespace MediaBrowser.LocalMetadata.Images
if (extraFanartFolder != null) if (extraFanartFolder != null)
{ {
PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images, directoryService); PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images);
} }
PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop); PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop);
} }
private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images, IDirectoryService directoryService) private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images)
{ {
var imageFiles = _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, false); var imageFiles = _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, false);
@ -395,8 +417,6 @@ namespace MediaBrowser.LocalMetadata.Images
} }
} }
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private void PopulateSeasonImagesFromSeriesFolder(Season season, List<LocalImageInfo> images, IDirectoryService directoryService) private void PopulateSeasonImagesFromSeriesFolder(Season season, List<LocalImageInfo> images, IDirectoryService directoryService)
{ {
var seasonNumber = season.IndexNumber; var seasonNumber = season.IndexNumber;
@ -410,7 +430,7 @@ namespace MediaBrowser.LocalMetadata.Images
var seriesFiles = GetFiles(series, false, directoryService).ToList(); var seriesFiles = GetFiles(series, false, directoryService).ToList();
// Try using the season name // Try using the season name
var prefix = season.Name.ToLowerInvariant().Replace(" ", string.Empty); var prefix = season.Name.Replace(" ", string.Empty, StringComparison.Ordinal).ToLowerInvariant();
var filenamePrefixes = new List<string> { prefix }; var filenamePrefixes = new List<string> { prefix };

@ -10,14 +10,28 @@
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs" />
</ItemGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

@ -14,24 +14,21 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Parsers namespace MediaBrowser.LocalMetadata.Parsers
{ {
/// <summary> /// <summary>
/// Provides a base class for parsing metadata xml /// Provides a base class for parsing metadata xml.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T">Type of item xml parser.</typeparam>
public class BaseItemXmlParser<T> public class BaseItemXmlParser<T>
where T : BaseItem where T : BaseItem
{ {
/// <summary> private readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// The logger
/// </summary>
protected ILogger<BaseItemXmlParser<T>> Logger { get; private set; }
protected IProviderManager ProviderManager { get; private set; }
private Dictionary<string, string> _validProviderIds; private Dictionary<string, string>? _validProviderIds;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class. /// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class.
/// </summary> /// </summary>
/// <param name="logger">The logger.</param> /// <param name="logger">Instance of the <see cref="ILogger{BaseItemXmlParser}"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
public BaseItemXmlParser(ILogger<BaseItemXmlParser<T>> logger, IProviderManager providerManager) public BaseItemXmlParser(ILogger<BaseItemXmlParser<T>> logger, IProviderManager providerManager)
{ {
Logger = logger; Logger = logger;
@ -39,12 +36,22 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
/// <summary> /// <summary>
/// Fetches metadata for an item from one xml file /// Gets the logger.
/// </summary>
protected ILogger<BaseItemXmlParser<T>> Logger { get; private set; }
/// <summary>
/// Gets the provider manager.
/// </summary>
protected IProviderManager ProviderManager { get; private set; }
/// <summary>
/// Fetches metadata for an item from one xml file.
/// </summary> /// </summary>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <param name="metadataFile">The metadata file.</param> /// <param name="metadataFile">The metadata file.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentNullException">Item is null.</exception>
public void Fetch(MetadataResult<T> item, string metadataFile, CancellationToken cancellationToken) public void Fetch(MetadataResult<T> item, string metadataFile, CancellationToken cancellationToken)
{ {
if (item == null) if (item == null)
@ -57,7 +64,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
throw new ArgumentException("The metadata file was empty or null.", nameof(metadataFile)); throw new ArgumentException("The metadata file was empty or null.", nameof(metadataFile));
} }
var settings = new XmlReaderSettings() var settings = new XmlReaderSettings
{ {
ValidationType = ValidationType.None, ValidationType = ValidationType.None,
CheckCharacters = false, CheckCharacters = false,
@ -97,10 +104,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.ResetPeople(); item.ResetPeople();
using (var fileStream = File.OpenRead(metadataFile)) using var fileStream = File.OpenRead(metadataFile);
using (var streamReader = new StreamReader(fileStream, encoding)) using var streamReader = new StreamReader(fileStream, encoding);
using (var reader = XmlReader.Create(streamReader, settings)) using var reader = XmlReader.Create(streamReader, settings);
{
reader.MoveToContent(); reader.MoveToContent();
reader.Read(); reader.Read();
@ -119,12 +125,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
} }
} }
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary> /// <summary>
/// Fetches metadata from one Xml Element /// Fetches metadata from one Xml Element.
/// </summary> /// </summary>
/// <param name="reader">The reader.</param> /// <param name="reader">The reader.</param>
/// <param name="itemResult">The item result.</param> /// <param name="itemResult">The item result.</param>
@ -150,6 +153,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
Logger.LogWarning("Invalid Added value found: " + val); Logger.LogWarning("Invalid Added value found: " + val);
} }
} }
break; break;
} }
@ -161,6 +165,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.OriginalTitle = val; item.OriginalTitle = val;
} }
break; break;
} }
@ -191,6 +196,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.ForcedSortName = val; item.ForcedSortName = val;
} }
break; break;
} }
@ -231,10 +237,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
if (!string.IsNullOrWhiteSpace(val)) if (!string.IsNullOrWhiteSpace(val))
{ {
var person = item as Person; if (item is Person person)
if (person != null)
{ {
person.ProductionLocations = new string[] { val }; person.ProductionLocations = new[] { val };
} }
} }
@ -255,8 +260,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
return null; return null;
}).Where(i => i.HasValue).Select(i => i!.Value).ToArray();
}).Where(i => i.HasValue).Select(i => i.Value).ToArray();
} }
break; break;
@ -275,6 +279,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -284,13 +289,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
using (var subtree = reader.ReadSubtree()) using (var subtree = reader.ReadSubtree())
{ {
FetchFromCountriesNode(subtree, item); FetchFromCountriesNode(subtree);
} }
} }
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -303,6 +309,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.OfficialRating = rating; item.OfficialRating = rating;
} }
break; break;
} }
@ -314,6 +321,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.CustomRating = val; item.CustomRating = val;
} }
break; break;
} }
@ -328,6 +336,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks;
} }
} }
break; break;
} }
@ -340,6 +349,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
hasAspectRatio.AspectRatio = val; hasAspectRatio.AspectRatio = val;
} }
break; break;
} }
@ -351,6 +361,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
} }
break; break;
} }
@ -362,8 +373,10 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
item.AddStudio(name); item.AddStudio(name);
} }
break; break;
} }
@ -375,10 +388,13 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
itemResult.AddPerson(p); itemResult.AddPerson(p);
} }
break; break;
} }
case "Writer": case "Writer":
{ {
foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer })) foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer }))
@ -387,21 +403,23 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
itemResult.AddPerson(p); itemResult.AddPerson(p);
} }
break; break;
} }
case "Actors": case "Actors":
{ {
var actors = reader.ReadInnerXml(); var actors = reader.ReadInnerXml();
if (actors.Contains("<")) if (actors.Contains("<", StringComparison.Ordinal))
{ {
// This is one of the mis-named "Actors" full nodes created by MB2 // This is one of the mis-named "Actors" full nodes created by MB2
// Create a reader and pass it to the persons node processor // Create a reader and pass it to the persons node processor
FetchDataFromPersonsNode(XmlReader.Create(new StringReader("<Persons>" + actors + "</Persons>")), itemResult); using var xmlReader = XmlReader.Create(new StringReader($"<Persons>{actors}</Persons>"));
FetchDataFromPersonsNode(xmlReader, itemResult);
} }
else else
{ {
@ -412,9 +430,11 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
itemResult.AddPerson(p); itemResult.AddPerson(p);
} }
} }
break; break;
} }
@ -426,8 +446,10 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
itemResult.AddPerson(p); itemResult.AddPerson(p);
} }
break; break;
} }
@ -439,6 +461,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.AddTrailerUrl(val); item.AddTrailerUrl(val);
} }
break; break;
} }
@ -454,6 +477,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
hasDisplayOrder.DisplayOrder = val; hasDisplayOrder.DisplayOrder = val;
} }
} }
break; break;
} }
@ -461,15 +485,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{
FetchDataFromTrailersNode(subtree, item); FetchDataFromTrailersNode(subtree, item);
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -491,7 +514,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
case "Rating": case "Rating":
case "IMDBrating": case "IMDBrating":
{ {
var rating = reader.ReadElementContentAsString(); var rating = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(rating)) if (!string.IsNullOrWhiteSpace(rating))
@ -502,6 +524,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
item.CommunityRating = val; item.CommunityRating = val;
} }
} }
break; break;
} }
@ -545,21 +568,21 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.SetProviderId(MetadataProvider.TmdbCollection, tmdbCollection); item.SetProviderId(MetadataProvider.TmdbCollection, tmdbCollection);
} }
break; break;
case "Genres": case "Genres":
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{
FetchFromGenresNode(subtree, item); FetchFromGenresNode(subtree, item);
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -567,15 +590,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{
FetchFromTagsNode(subtree, item); FetchFromTagsNode(subtree, item);
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -583,15 +605,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{
FetchDataFromPersonsNode(subtree, itemResult); FetchDataFromPersonsNode(subtree, itemResult);
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -599,15 +620,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{
FetchFromStudiosNode(subtree, item); FetchFromStudiosNode(subtree, item);
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -615,19 +635,17 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
if (!reader.IsEmptyElement) if (!reader.IsEmptyElement)
{ {
using (var subtree = reader.ReadSubtree()) using var subtree = reader.ReadSubtree();
{ if (item is IHasShares hasShares)
var hasShares = item as IHasShares;
if (hasShares != null)
{ {
FetchFromSharesNode(subtree, hasShares); FetchFromSharesNode(subtree, hasShares);
} }
} }
}
else else
{ {
reader.Read(); reader.Read();
} }
break; break;
} }
@ -635,9 +653,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
var val = reader.ReadElementContentAsString(); var val = reader.ReadElementContentAsString();
var video = item as Video; if (item is Video video)
if (video != null)
{ {
if (string.Equals("HSBS", val, StringComparison.OrdinalIgnoreCase)) if (string.Equals("HSBS", val, StringComparison.OrdinalIgnoreCase))
{ {
@ -660,13 +676,14 @@ namespace MediaBrowser.LocalMetadata.Parsers
video.Video3DFormat = Video3DFormat.MVC; video.Video3DFormat = Video3DFormat.MVC;
} }
} }
break; break;
} }
default: default:
{ {
string readerName = reader.Name; string readerName = reader.Name;
if (_validProviderIds.TryGetValue(readerName, out string providerIdValue)) if (_validProviderIds!.TryGetValue(readerName, out string providerIdValue))
{ {
var id = reader.ReadElementContentAsString(); var id = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(id)) if (!string.IsNullOrWhiteSpace(id))
@ -680,10 +697,10 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
break; break;
} }
} }
} }
private void FetchFromSharesNode(XmlReader reader, IHasShares item) private void FetchFromSharesNode(XmlReader reader, IHasShares item)
{ {
var list = new List<Share>(); var list = new List<Share>();
@ -718,6 +735,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
break; break;
} }
default: default:
{ {
reader.Skip(); reader.Skip();
@ -756,7 +774,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
case "CanEdit": case "CanEdit":
{ {
share.CanEdit = string.Equals(reader.ReadElementContentAsString(), true.ToString(), StringComparison.OrdinalIgnoreCase); share.CanEdit = string.Equals(reader.ReadElementContentAsString(), true.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase);
break; break;
} }
@ -774,7 +792,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
return share; return share;
} }
private void FetchFromCountriesNode(XmlReader reader, T item) private void FetchFromCountriesNode(XmlReader reader)
{ {
reader.MoveToContent(); reader.MoveToContent();
reader.Read(); reader.Read();
@ -793,6 +811,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
if (!string.IsNullOrWhiteSpace(val)) if (!string.IsNullOrWhiteSpace(val))
{ {
} }
break; break;
} }
@ -833,8 +852,10 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.Tagline = val; item.Tagline = val;
} }
break; break;
} }
default: default:
reader.Skip(); reader.Skip();
break; break;
@ -872,6 +893,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.AddGenre(genre); item.AddGenre(genre);
} }
break; break;
} }
@ -909,6 +931,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
tags.Add(tag); tags.Add(tag);
} }
break; break;
} }
@ -951,6 +974,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
reader.Read(); reader.Read();
continue; continue;
} }
using (var subtree = reader.ReadSubtree()) using (var subtree = reader.ReadSubtree())
{ {
foreach (var person in GetPersonsFromXmlNode(subtree)) foreach (var person in GetPersonsFromXmlNode(subtree))
@ -959,9 +983,11 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
continue; continue;
} }
item.AddPerson(person); item.AddPerson(person);
} }
} }
break; break;
} }
@ -997,6 +1023,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.AddTrailerUrl(val); item.AddTrailerUrl(val);
} }
break; break;
} }
@ -1037,6 +1064,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
item.AddStudio(studio); item.AddStudio(studio);
} }
break; break;
} }
@ -1086,6 +1114,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
type = val; type = val;
} }
break; break;
} }
@ -1097,8 +1126,10 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
role = val; role = val;
} }
break; break;
} }
case "SortOrder": case "SortOrder":
{ {
var val = reader.ReadElementContentAsString(); var val = reader.ReadElementContentAsString();
@ -1110,6 +1141,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
sortOrder = intVal; sortOrder = intVal;
} }
} }
break; break;
} }
@ -1124,23 +1156,19 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
} }
var personInfo = new PersonInfo var personInfo = new PersonInfo { Name = name.Trim(), Role = role, Type = type, SortOrder = sortOrder };
{
Name = name.Trim(),
Role = role,
Type = type,
SortOrder = sortOrder
};
return new[] { personInfo }; return new[] { personInfo };
} }
protected LinkedChild GetLinkedChild(XmlReader reader) /// <summary>
{ /// Get linked child.
var linkedItem = new LinkedChild /// </summary>
/// <param name="reader">The xml reader.</param>
/// <returns>The linked child.</returns>
protected LinkedChild? GetLinkedChild(XmlReader reader)
{ {
Type = LinkedChildType.Manual var linkedItem = new LinkedChild { Type = LinkedChildType.Manual };
};
reader.MoveToContent(); reader.MoveToContent();
reader.Read(); reader.Read();
@ -1157,6 +1185,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
linkedItem.Path = reader.ReadElementContentAsString(); linkedItem.Path = reader.ReadElementContentAsString();
break; break;
} }
case "ItemId": case "ItemId":
{ {
linkedItem.LibraryItemId = reader.ReadElementContentAsString(); linkedItem.LibraryItemId = reader.ReadElementContentAsString();
@ -1183,7 +1212,12 @@ namespace MediaBrowser.LocalMetadata.Parsers
return null; return null;
} }
protected Share GetShare(XmlReader reader) /// <summary>
/// Get share.
/// </summary>
/// <param name="reader">The xml reader.</param>
/// <returns>The share.</returns>
protected Share? GetShare(XmlReader reader)
{ {
var item = new Share(); var item = new Share();
@ -1208,6 +1242,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase); item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase);
break; break;
} }
default: default:
{ {
reader.Skip(); reader.Skip();
@ -1230,19 +1265,19 @@ namespace MediaBrowser.LocalMetadata.Parsers
return null; return null;
} }
/// <summary> /// <summary>
/// Used to split names of comma or pipe delimeted genres and people /// Used to split names of comma or pipe delimited genres and people.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns>IEnumerable{System.String}.</returns> /// <returns>IEnumerable{System.String}.</returns>
private IEnumerable<string> SplitNames(string value) private IEnumerable<string> SplitNames(string value)
{ {
value = value ?? string.Empty; value ??= string.Empty;
// Only split by comma if there is no pipe in the string // Only split by comma if there is no pipe in the string
// We have to be careful to not split names like Matthew, Jr. // We have to be careful to not split names like Matthew, Jr.
var separator = value.IndexOf('|') == -1 && value.IndexOf(';') == -1 ? new[] { ',' } : new[] { '|', ';' }; var separator = value.IndexOf('|', StringComparison.Ordinal) == -1
&& value.IndexOf(';', StringComparison.Ordinal) == -1 ? new[] { ',' } : new[] { '|', ';' };
value = value.Trim().Trim(separator); value = value.Trim().Trim(separator);
@ -1250,7 +1285,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
} }
/// <summary> /// <summary>
/// Provides an additional overload for string.split /// Provides an additional overload for string.split.
/// </summary> /// </summary>
/// <param name="val">The val.</param> /// <param name="val">The val.</param>
/// <param name="separators">The separators.</param> /// <param name="separators">The separators.</param>
@ -1260,6 +1295,5 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
return val.Split(separators, options); return val.Split(separators, options);
} }
} }
} }

@ -7,8 +7,22 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Parsers namespace MediaBrowser.LocalMetadata.Parsers
{ {
/// <summary>
/// The box set xml parser.
/// </summary>
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet> public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="BoxSetXmlParser"/> class.
/// </summary>
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParset}"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
public BoxSetXmlParser(ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
: base(logger, providerManager)
{
}
/// <inheritdoc />
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item) protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item)
{ {
switch (reader.Name) switch (reader.Name)
@ -26,6 +40,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
reader.Read(); reader.Read();
} }
break; break;
default: default:
@ -69,6 +84,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
break; break;
} }
default: default:
{ {
reader.Skip(); reader.Skip();
@ -84,10 +100,5 @@ namespace MediaBrowser.LocalMetadata.Parsers
item.Item.LinkedChildren = list.ToArray(); item.Item.LinkedChildren = list.ToArray();
} }
public BoxSetXmlParser(ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
: base(logger, providerManager)
{
}
} }
} }

@ -7,8 +7,22 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Parsers namespace MediaBrowser.LocalMetadata.Parsers
{ {
/// <summary>
/// Playlist xml parser.
/// </summary>
public class PlaylistXmlParser : BaseItemXmlParser<Playlist> public class PlaylistXmlParser : BaseItemXmlParser<Playlist>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="PlaylistXmlParser"/> class.
/// </summary>
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlParser}"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
public PlaylistXmlParser(ILogger<PlaylistXmlParser> logger, IProviderManager providerManager)
: base(logger, providerManager)
{
}
/// <inheritdoc />
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result) protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result)
{ {
var item = result.Item; var item = result.Item;
@ -35,6 +49,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
{ {
reader.Read(); reader.Read();
} }
break; break;
default: default:
@ -77,6 +92,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
break; break;
} }
default: default:
{ {
reader.Skip(); reader.Skip();
@ -92,10 +108,5 @@ namespace MediaBrowser.LocalMetadata.Parsers
item.LinkedChildren = list.ToArray(); item.LinkedChildren = list.ToArray();
} }
public PlaylistXmlParser(ILogger<PlaylistXmlParser> logger, IProviderManager providerManager)
: base(logger, providerManager)
{
}
} }
} }

@ -16,6 +16,12 @@ namespace MediaBrowser.LocalMetadata.Providers
private readonly ILogger<BoxSetXmlParser> _logger; private readonly ILogger<BoxSetXmlParser> _logger;
private readonly IProviderManager _providerManager; private readonly IProviderManager _providerManager;
/// <summary>
/// Initializes a new instance of the <see cref="BoxSetXmlProvider"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParser}"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
public BoxSetXmlProvider(IFileSystem fileSystem, ILogger<BoxSetXmlParser> logger, IProviderManager providerManager) public BoxSetXmlProvider(IFileSystem fileSystem, ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
: base(fileSystem) : base(fileSystem)
{ {
@ -23,11 +29,13 @@ namespace MediaBrowser.LocalMetadata.Providers
_providerManager = providerManager; _providerManager = providerManager;
} }
/// <inheritdoc />
protected override void Fetch(MetadataResult<BoxSet> result, string path, CancellationToken cancellationToken) protected override void Fetch(MetadataResult<BoxSet> result, string path, CancellationToken cancellationToken)
{ {
new BoxSetXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken); new BoxSetXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
} }
/// <inheritdoc />
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
{ {
return directoryService.GetFile(Path.Combine(info.Path, "collection.xml")); return directoryService.GetFile(Path.Combine(info.Path, "collection.xml"));

@ -8,11 +8,20 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Providers namespace MediaBrowser.LocalMetadata.Providers
{ {
/// <summary>
/// Playlist xml provider.
/// </summary>
public class PlaylistXmlProvider : BaseXmlProvider<Playlist> public class PlaylistXmlProvider : BaseXmlProvider<Playlist>
{ {
private readonly ILogger<PlaylistXmlParser> _logger; private readonly ILogger<PlaylistXmlParser> _logger;
private readonly IProviderManager _providerManager; private readonly IProviderManager _providerManager;
/// <summary>
/// Initializes a new instance of the <see cref="PlaylistXmlProvider"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlParser}"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
public PlaylistXmlProvider( public PlaylistXmlProvider(
IFileSystem fileSystem, IFileSystem fileSystem,
ILogger<PlaylistXmlParser> logger, ILogger<PlaylistXmlParser> logger,
@ -23,14 +32,16 @@ namespace MediaBrowser.LocalMetadata.Providers
_providerManager = providerManager; _providerManager = providerManager;
} }
/// <inheritdoc />
protected override void Fetch(MetadataResult<Playlist> result, string path, CancellationToken cancellationToken) protected override void Fetch(MetadataResult<Playlist> result, string path, CancellationToken cancellationToken)
{ {
new PlaylistXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken); new PlaylistXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
} }
/// <inheritdoc />
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
{ {
return directoryService.GetFile(PlaylistXmlSaver.GetSavePath(info.Path, FileSystem)); return directoryService.GetFile(PlaylistXmlSaver.GetSavePath(info.Path));
} }
} }
} }

@ -17,10 +17,25 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Savers namespace MediaBrowser.LocalMetadata.Savers
{ {
/// <inheritdoc />
public abstract class BaseXmlSaver : IMetadataFileSaver public abstract class BaseXmlSaver : IMetadataFileSaver
{ {
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// <summary>
/// Gets the date added format.
/// </summary>
public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
private static readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary>
/// Initializes a new instance of the <see cref="BaseXmlSaver"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{BaseXmlSaver}"/> interface.</param>
public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger) public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger)
{ {
FileSystem = fileSystem; FileSystem = fileSystem;
@ -31,15 +46,40 @@ namespace MediaBrowser.LocalMetadata.Savers
Logger = logger; Logger = logger;
} }
/// <summary>
/// Gets the file system.
/// </summary>
protected IFileSystem FileSystem { get; private set; } protected IFileSystem FileSystem { get; private set; }
/// <summary>
/// Gets the configuration manager.
/// </summary>
protected IServerConfigurationManager ConfigurationManager { get; private set; } protected IServerConfigurationManager ConfigurationManager { get; private set; }
/// <summary>
/// Gets the library manager.
/// </summary>
protected ILibraryManager LibraryManager { get; private set; } protected ILibraryManager LibraryManager { get; private set; }
/// <summary>
/// Gets the user manager.
/// </summary>
protected IUserManager UserManager { get; private set; } protected IUserManager UserManager { get; private set; }
/// <summary>
/// Gets the user data manager.
/// </summary>
protected IUserDataManager UserDataManager { get; private set; } protected IUserDataManager UserDataManager { get; private set; }
/// <summary>
/// Gets the logger.
/// </summary>
protected ILogger<BaseXmlSaver> Logger { get; private set; } protected ILogger<BaseXmlSaver> Logger { get; private set; }
/// <inheritdoc />
public string Name => XmlProviderUtils.Name; public string Name => XmlProviderUtils.Name;
/// <inheritdoc />
public string GetSavePath(BaseItem item) public string GetSavePath(BaseItem item)
{ {
return GetLocalSavePath(item); return GetLocalSavePath(item);
@ -70,13 +110,13 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType); public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType);
/// <inheritdoc />
public void Save(BaseItem item, CancellationToken cancellationToken) public void Save(BaseItem item, CancellationToken cancellationToken)
{ {
var path = GetSavePath(item); var path = GetSavePath(item);
using (var memoryStream = new MemoryStream()) using var memoryStream = new MemoryStream();
{ Save(item, memoryStream);
Save(item, memoryStream, path);
memoryStream.Position = 0; memoryStream.Position = 0;
@ -84,7 +124,6 @@ namespace MediaBrowser.LocalMetadata.Savers
SaveToFile(memoryStream, path); SaveToFile(memoryStream, path);
} }
}
private void SaveToFile(Stream stream, string path) private void SaveToFile(Stream stream, string path)
{ {
@ -115,7 +154,7 @@ namespace MediaBrowser.LocalMetadata.Savers
} }
} }
private void Save(BaseItem item, Stream stream, string xmlPath) private void Save(BaseItem item, Stream stream)
{ {
var settings = new XmlWriterSettings var settings = new XmlWriterSettings
{ {
@ -136,7 +175,7 @@ namespace MediaBrowser.LocalMetadata.Savers
if (baseItem != null) if (baseItem != null)
{ {
AddCommonNodes(baseItem, writer, LibraryManager, UserManager, UserDataManager, FileSystem, ConfigurationManager); AddCommonNodes(baseItem, writer, LibraryManager);
} }
WriteCustomElements(item, writer); WriteCustomElements(item, writer);
@ -147,22 +186,27 @@ namespace MediaBrowser.LocalMetadata.Savers
} }
} }
/// <summary>
/// Write custom elements.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
protected abstract void WriteCustomElements(BaseItem item, XmlWriter writer); protected abstract void WriteCustomElements(BaseItem item, XmlWriter writer);
public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
/// <summary> /// <summary>
/// Adds the common nodes. /// Adds common notes.
/// </summary> /// </summary>
/// <returns>Task.</returns> /// <param name="item">The item.</param>
public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) /// <param name="writer">The xml writer.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager)
{ {
if (!string.IsNullOrEmpty(item.OfficialRating)) if (!string.IsNullOrEmpty(item.OfficialRating))
{ {
writer.WriteElementString("ContentRating", item.OfficialRating); writer.WriteElementString("ContentRating", item.OfficialRating);
} }
writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G")); writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G", CultureInfo.InvariantCulture));
writer.WriteElementString("LockData", item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); writer.WriteElementString("LockData", item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
@ -173,7 +217,7 @@ namespace MediaBrowser.LocalMetadata.Savers
if (item.CriticRating.HasValue) if (item.CriticRating.HasValue)
{ {
writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(UsCulture)); writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(_usCulture));
} }
if (!string.IsNullOrEmpty(item.Overview)) if (!string.IsNullOrEmpty(item.Overview))
@ -185,6 +229,7 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
writer.WriteElementString("OriginalTitle", item.OriginalTitle); writer.WriteElementString("OriginalTitle", item.OriginalTitle);
} }
if (!string.IsNullOrEmpty(item.CustomRating)) if (!string.IsNullOrEmpty(item.CustomRating))
{ {
writer.WriteElementString("CustomRating", item.CustomRating); writer.WriteElementString("CustomRating", item.CustomRating);
@ -205,11 +250,11 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
if (item is Person) if (item is Person)
{ {
writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")); writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
} }
else if (!(item is Episode)) else if (!(item is Episode))
{ {
writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")); writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
} }
} }
@ -217,11 +262,11 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
if (item is Person) if (item is Person)
{ {
writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd")); writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
} }
else if (!(item is Episode)) else if (!(item is Episode))
{ {
writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd")); writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
} }
} }
@ -257,12 +302,12 @@ namespace MediaBrowser.LocalMetadata.Savers
if (item.CommunityRating.HasValue) if (item.CommunityRating.HasValue)
{ {
writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(UsCulture)); writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(_usCulture));
} }
if (item.ProductionYear.HasValue && !(item is Person)) if (item.ProductionYear.HasValue && !(item is Person))
{ {
writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(UsCulture)); writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture));
} }
var hasAspectRatio = item as IHasAspectRatio; var hasAspectRatio = item as IHasAspectRatio;
@ -278,6 +323,7 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
writer.WriteElementString("Language", item.PreferredMetadataLanguage); writer.WriteElementString("Language", item.PreferredMetadataLanguage);
} }
if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode)) if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode))
{ {
writer.WriteElementString("CountryCode", item.PreferredMetadataCountryCode); writer.WriteElementString("CountryCode", item.PreferredMetadataCountryCode);
@ -288,9 +334,9 @@ namespace MediaBrowser.LocalMetadata.Savers
if (runTimeTicks.HasValue) if (runTimeTicks.HasValue)
{ {
var timespan = TimeSpan.FromTicks(runTimeTicks.Value); var timespan = TimeSpan.FromTicks(runTimeTicks!.Value);
writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(UsCulture)); writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(_usCulture));
} }
if (item.ProviderIds != null) if (item.ProviderIds != null)
@ -363,7 +409,7 @@ namespace MediaBrowser.LocalMetadata.Savers
if (person.SortOrder.HasValue) if (person.SortOrder.HasValue)
{ {
writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(UsCulture)); writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(_usCulture));
} }
writer.WriteEndElement(); writer.WriteEndElement();
@ -393,6 +439,11 @@ namespace MediaBrowser.LocalMetadata.Savers
AddMediaInfo(item, writer); AddMediaInfo(item, writer);
} }
/// <summary>
/// Add shares.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
public static void AddShares(IHasShares item, XmlWriter writer) public static void AddShares(IHasShares item, XmlWriter writer)
{ {
writer.WriteStartElement("Shares"); writer.WriteStartElement("Shares");
@ -415,13 +466,13 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <summary> /// <summary>
/// Appends the media info. /// Appends the media info.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
/// <typeparam name="T">Type of item.</typeparam>
public static void AddMediaInfo<T>(T item, XmlWriter writer) public static void AddMediaInfo<T>(T item, XmlWriter writer)
where T : BaseItem where T : BaseItem
{ {
var video = item as Video; if (item is Video video)
if (video != null)
{ {
if (video.Video3DFormat.HasValue) if (video.Video3DFormat.HasValue)
{ {
@ -447,6 +498,13 @@ namespace MediaBrowser.LocalMetadata.Savers
} }
} }
/// <summary>
/// ADd linked children.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
/// <param name="pluralNodeName">The plural node name.</param>
/// <param name="singularNodeName">The singular node name.</param>
public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName) public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
{ {
var items = item.LinkedChildren var items = item.LinkedChildren

@ -9,8 +9,26 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Savers namespace MediaBrowser.LocalMetadata.Savers
{ {
/// <summary>
/// Box set xml saver.
/// </summary>
public class BoxSetXmlSaver : BaseXmlSaver public class BoxSetXmlSaver : BaseXmlSaver
{ {
/// <summary>
/// Initializes a new instance of the <see cref="BoxSetXmlSaver"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlSaver}"/> interface.</param>
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BoxSetXmlSaver> logger)
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
{
}
/// <inheritdoc />
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
{ {
if (!item.SupportsLocalMetadata) if (!item.SupportsLocalMetadata)
@ -21,18 +39,15 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is BoxSet && updateType >= ItemUpdateType.MetadataDownload; return item is BoxSet && updateType >= ItemUpdateType.MetadataDownload;
} }
/// <inheritdoc />
protected override void WriteCustomElements(BaseItem item, XmlWriter writer) protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
{ {
} }
/// <inheritdoc />
protected override string GetLocalSavePath(BaseItem item) protected override string GetLocalSavePath(BaseItem item)
{ {
return Path.Combine(item.Path, "collection.xml"); return Path.Combine(item.Path, "collection.xml");
} }
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BoxSetXmlSaver> logger)
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
{
}
} }
} }

@ -9,6 +9,9 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Savers namespace MediaBrowser.LocalMetadata.Savers
{ {
/// <summary>
/// Playlist xml saver.
/// </summary>
public class PlaylistXmlSaver : BaseXmlSaver public class PlaylistXmlSaver : BaseXmlSaver
{ {
/// <summary> /// <summary>
@ -16,6 +19,21 @@ namespace MediaBrowser.LocalMetadata.Savers
/// </summary> /// </summary>
public const string DefaultPlaylistFilename = "playlist.xml"; public const string DefaultPlaylistFilename = "playlist.xml";
/// <summary>
/// Initializes a new instance of the <see cref="PlaylistXmlSaver"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlSaver}"/> interface.</param>
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<PlaylistXmlSaver> logger)
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
{
}
/// <inheritdoc />
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
{ {
if (!item.SupportsLocalMetadata) if (!item.SupportsLocalMetadata)
@ -26,6 +44,7 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is Playlist && updateType >= ItemUpdateType.MetadataImport; return item is Playlist && updateType >= ItemUpdateType.MetadataImport;
} }
/// <inheritdoc />
protected override void WriteCustomElements(BaseItem item, XmlWriter writer) protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
{ {
var game = (Playlist)item; var game = (Playlist)item;
@ -36,12 +55,18 @@ namespace MediaBrowser.LocalMetadata.Savers
} }
} }
/// <inheritdoc />
protected override string GetLocalSavePath(BaseItem item) protected override string GetLocalSavePath(BaseItem item)
{ {
return GetSavePath(item.Path, FileSystem); return GetSavePath(item.Path);
} }
public static string GetSavePath(string itemPath, IFileSystem fileSystem) /// <summary>
/// Get the save path.
/// </summary>
/// <param name="itemPath">The item path.</param>
/// <returns>The save path.</returns>
public static string GetSavePath(string itemPath)
{ {
var path = itemPath; var path = itemPath;
@ -52,10 +77,5 @@ namespace MediaBrowser.LocalMetadata.Savers
return Path.Combine(path, DefaultPlaylistFilename); return Path.Combine(path, DefaultPlaylistFilename);
} }
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<PlaylistXmlSaver> logger)
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
{
}
} }
} }

@ -0,0 +1,13 @@
namespace MediaBrowser.LocalMetadata
{
/// <summary>
/// The xml provider utils.
/// </summary>
public static class XmlProviderUtils
{
/// <summary>
/// Gets the name.
/// </summary>
public static string Name => "Emby Xml";
}
}
Loading…
Cancel
Save