mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 20:24:27 -04:00
The validate change should now works if the given data is good
This commit is contained in:
parent
6e61b21e9a
commit
8ce6e1cc1b
@ -15,6 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
6
Kyoo.Common/Models/Attributes/MergeAttributes.cs
Normal file
6
Kyoo.Common/Models/Attributes/MergeAttributes.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Kyoo.Models.Attributes
|
||||||
|
{
|
||||||
|
public class NotMergableAttribute : Attribute { }
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
{
|
{
|
||||||
@ -12,7 +13,7 @@ namespace Kyoo.Models
|
|||||||
public string Poster { get; set; }
|
public string Poster { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<CollectionLink> Links { get; set; }
|
[NotMergable] [JsonIgnore] public virtual IEnumerable<CollectionLink> Links { get; set; }
|
||||||
public virtual IEnumerable<Show> Shows
|
public virtual IEnumerable<Show> Shows
|
||||||
{
|
{
|
||||||
get => Links.Select(x => x.Show);
|
get => Links.Select(x => x.Show);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
@ -8,14 +11,34 @@ namespace Kyoo.Models
|
|||||||
[JsonIgnore] public long ID { get; set; }
|
[JsonIgnore] public long ID { get; set; }
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string[] Paths { get; set; }
|
public IEnumerable<string> Paths { get; set; }
|
||||||
public virtual IEnumerable<ProviderLink> Providers { get; set; }
|
|
||||||
[JsonIgnore] public virtual IEnumerable<Show> Shows { get; set; }
|
public IEnumerable<ProviderID> Providers
|
||||||
[JsonIgnore] public virtual IEnumerable<Collection> Collections { get; set; }
|
{
|
||||||
|
get => ProviderLinks.Select(x => x.Provider);
|
||||||
|
set => ProviderLinks = value.Select(x => new ProviderLink(x, this));
|
||||||
|
}
|
||||||
|
[NotMergable] [JsonIgnore] public virtual IEnumerable<ProviderLink> ProviderLinks { get; set; }
|
||||||
|
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> Links { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore] public IEnumerable<Show> Shows
|
||||||
|
{
|
||||||
|
get => Links.Where(x => x.Show != null).Select(x => x.Show);
|
||||||
|
set => Links = Utility.MergeLists(
|
||||||
|
value?.Select(x => new LibraryLink(this, x)),
|
||||||
|
Links?.Where(x => x.Show == null));
|
||||||
|
}
|
||||||
|
[JsonIgnore] public IEnumerable<Collection> Collections
|
||||||
|
{
|
||||||
|
get => Links.Where(x => x.Collection != null).Select(x => x.Collection);
|
||||||
|
set => Links = Utility.MergeLists(
|
||||||
|
value?.Select(x => new LibraryLink(this, x)),
|
||||||
|
Links?.Where(x => x.Collection == null));
|
||||||
|
}
|
||||||
|
|
||||||
public Library() { }
|
public Library() { }
|
||||||
|
|
||||||
public Library(string slug, string name, string[] paths, IEnumerable<ProviderLink> providers)
|
public Library(string slug, string name, IEnumerable<string> paths, IEnumerable<ProviderID> providers)
|
||||||
{
|
{
|
||||||
Slug = slug;
|
Slug = slug;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
@ -9,5 +9,19 @@ namespace Kyoo.Models
|
|||||||
public virtual Show Show { get; set; }
|
public virtual Show Show { get; set; }
|
||||||
public long? CollectionID { get; set; }
|
public long? CollectionID { get; set; }
|
||||||
public virtual Collection Collection { get; set; }
|
public virtual Collection Collection { get; set; }
|
||||||
|
|
||||||
|
public LibraryLink() { }
|
||||||
|
|
||||||
|
public LibraryLink(Library library, Show show)
|
||||||
|
{
|
||||||
|
Library = library;
|
||||||
|
Show = show;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryLink(Library library, Collection collection)
|
||||||
|
{
|
||||||
|
Library = library;
|
||||||
|
Collection = collection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,26 +16,5 @@ namespace Kyoo.Models
|
|||||||
Name = name;
|
Name = name;
|
||||||
Logo = logo;
|
Logo = logo;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool Equals(ProviderID other)
|
|
||||||
{
|
|
||||||
return Name == other.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, obj))
|
|
||||||
return false;
|
|
||||||
if (ReferenceEquals(this, obj))
|
|
||||||
return true;
|
|
||||||
if (obj.GetType() != this.GetType())
|
|
||||||
return false;
|
|
||||||
return Equals((ProviderID)obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return Name != null ? Name.GetHashCode() : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,30 +10,12 @@ namespace Kyoo.Models
|
|||||||
[JsonIgnore] public long? LibraryID { get; set; }
|
[JsonIgnore] public long? LibraryID { get; set; }
|
||||||
[JsonIgnore] public virtual Library Library { get; set; }
|
[JsonIgnore] public virtual Library Library { get; set; }
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => Provider?.Name;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Provider != null)
|
|
||||||
Provider.Name = value;
|
|
||||||
else
|
|
||||||
Provider = new ProviderID {Name = value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Logo
|
|
||||||
{
|
|
||||||
get => Provider?.Logo;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Provider != null)
|
|
||||||
Provider.Logo = value;
|
|
||||||
else
|
|
||||||
Provider = new ProviderID {Logo = value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProviderLink() { }
|
public ProviderLink() { }
|
||||||
|
|
||||||
|
public ProviderLink(ProviderID provider, Library library)
|
||||||
|
{
|
||||||
|
Provider = provider;
|
||||||
|
Library = library;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
{
|
{
|
||||||
@ -10,7 +11,7 @@ namespace Kyoo.Models
|
|||||||
|
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string[] Aliases { get; set; }
|
public IEnumerable<string> Aliases { get; set; }
|
||||||
[JsonIgnore] public string Path { get; set; }
|
[JsonIgnore] public string Path { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public Status? Status { get; set; }
|
public Status? Status { get; set; }
|
||||||
@ -31,10 +32,10 @@ namespace Kyoo.Models
|
|||||||
|
|
||||||
public virtual IEnumerable<Genre> Genres
|
public virtual IEnumerable<Genre> Genres
|
||||||
{
|
{
|
||||||
get { return GenreLinks?.Select(x => x.Genre).OrderBy(x => x.Name); }
|
get => GenreLinks?.Select(x => x.Genre);
|
||||||
set { GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); }
|
set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList();
|
||||||
}
|
}
|
||||||
[JsonIgnore] public virtual IEnumerable<GenreLink> GenreLinks { get; set; }
|
[NotMergable] [JsonIgnore] public virtual IEnumerable<GenreLink> GenreLinks { get; set; }
|
||||||
public virtual Studio Studio { get; set; }
|
public virtual Studio Studio { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<PeopleLink> People { get; set; }
|
[JsonIgnore] public virtual IEnumerable<PeopleLink> People { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
||||||
@ -55,7 +56,7 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
Slug = slug;
|
Slug = slug;
|
||||||
Title = title;
|
Title = title;
|
||||||
Aliases = aliases?.ToArray();
|
Aliases = aliases;
|
||||||
Path = path;
|
Path = path;
|
||||||
Overview = overview;
|
Overview = overview;
|
||||||
TrailerUrl = trailerUrl;
|
TrailerUrl = trailerUrl;
|
||||||
@ -83,7 +84,7 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
Slug = slug;
|
Slug = slug;
|
||||||
Title = title;
|
Title = title;
|
||||||
Aliases = aliases?.ToArray();
|
Aliases = aliases;
|
||||||
Path = path;
|
Path = path;
|
||||||
Overview = overview;
|
Overview = overview;
|
||||||
TrailerUrl = trailerUrl;
|
TrailerUrl = trailerUrl;
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
@ -64,9 +65,9 @@ namespace Kyoo
|
|||||||
return second;
|
return second;
|
||||||
if (second == null)
|
if (second == null)
|
||||||
return first;
|
return first;
|
||||||
List<T> list = first.ToList();
|
|
||||||
if (isEqual == null)
|
if (isEqual == null)
|
||||||
isEqual = (x, y) => x.Equals(y);
|
return first.Concat(second).ToList();
|
||||||
|
List<T> list = first.ToList();
|
||||||
return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))).ToList();
|
return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,9 +93,18 @@ namespace Kyoo
|
|||||||
|
|
||||||
public static T Merge<T>(T first, T second)
|
public static T Merge<T>(T first, T second)
|
||||||
{
|
{
|
||||||
|
// TODO During the merge, reference to the second values are not set to the first value (for child objects).
|
||||||
|
if (first == null)
|
||||||
|
return second;
|
||||||
|
if (second == null)
|
||||||
|
return first;
|
||||||
|
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
foreach (PropertyInfo property in type.GetProperties().Where(x => x.CanRead && x.CanWrite))
|
foreach (PropertyInfo property in type.GetProperties().Where(x => x.CanRead && x.CanWrite))
|
||||||
{
|
{
|
||||||
|
if (Attribute.GetCustomAttribute(property, typeof(NotMergableAttribute)) != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
object oldValue = property.GetValue(first);
|
object oldValue = property.GetValue(first);
|
||||||
object newValue = property.GetValue(second);
|
object newValue = property.GetValue(second);
|
||||||
object defaultValue = property.PropertyType.IsValueType
|
object defaultValue = property.PropertyType.IsValueType
|
||||||
@ -106,7 +116,11 @@ namespace Kyoo
|
|||||||
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType)
|
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType)
|
||||||
&& property.PropertyType != typeof(string))
|
&& property.PropertyType != typeof(string))
|
||||||
{
|
{
|
||||||
property.SetValue((IEnumerable<object>)oldValue, (IEnumerable<object>)newValue);
|
property.SetValue(first, RunGenericMethod(
|
||||||
|
typeof(Utility),
|
||||||
|
"MergeLists",
|
||||||
|
GetEnumerableType(property.PropertyType),
|
||||||
|
new []{ oldValue, newValue, null}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +144,26 @@ namespace Kyoo
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object RunGenericMethod([NotNull] object instance,
|
public static object RunGenericMethod(
|
||||||
|
[NotNull] Type owner,
|
||||||
|
[NotNull] string methodName,
|
||||||
|
[NotNull] Type type,
|
||||||
|
IEnumerable<object> args)
|
||||||
|
{
|
||||||
|
if (owner == null)
|
||||||
|
throw new ArgumentNullException(nameof(owner));
|
||||||
|
if (methodName == null)
|
||||||
|
throw new ArgumentNullException(nameof(methodName));
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
MethodInfo method = owner.GetMethod(methodName);
|
||||||
|
if (method == null)
|
||||||
|
throw new NullReferenceException($"A method named {methodName} could not be found on {owner.FullName}");
|
||||||
|
return method.MakeGenericMethod(type).Invoke(null, args?.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object RunGenericMethod(
|
||||||
|
[NotNull] object instance,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type type,
|
[NotNull] Type type,
|
||||||
IEnumerable<object> args)
|
IEnumerable<object> args)
|
||||||
@ -147,5 +180,24 @@ namespace Kyoo
|
|||||||
return method.MakeGenericMethod(type).Invoke(instance, args?.ToArray());
|
return method.MakeGenericMethod(type).Invoke(instance, args?.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Type GetEnumerableType([NoEnumeration] [NotNull] IEnumerable list)
|
||||||
|
{
|
||||||
|
if (list == null)
|
||||||
|
throw new ArgumentNullException(nameof(list));
|
||||||
|
Type type = list.GetType().GetInterfaces().FirstOrDefault(t => typeof(IEnumerable).IsAssignableFrom(t)
|
||||||
|
&& t.GetGenericArguments().Any()) ?? list.GetType();
|
||||||
|
return type.GetGenericArguments().First();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Type GetEnumerableType([NotNull] Type listType)
|
||||||
|
{
|
||||||
|
if (listType == null)
|
||||||
|
throw new ArgumentNullException(nameof(listType));
|
||||||
|
if (!typeof(IEnumerable).IsAssignableFrom(listType))
|
||||||
|
throw new InvalidOperationException($"The {nameof(listType)} parameter was not an IEnumerable.");
|
||||||
|
Type type = listType.GetInterfaces().FirstOrDefault(t => typeof(IEnumerable).IsAssignableFrom(t)
|
||||||
|
&& t.GetGenericArguments().Any()) ?? listType;
|
||||||
|
return type.GetGenericArguments().First();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -181,7 +181,28 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return;
|
return;
|
||||||
_database.Add(obj);
|
ValidateNewEntry(_database.Entry(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateNewEntry(EntityEntry entry)
|
||||||
|
{
|
||||||
|
if (entry.State != EntityState.Detached)
|
||||||
|
return;
|
||||||
|
entry.State = EntityState.Added;
|
||||||
|
foreach (NavigationEntry navigation in entry.Navigations)
|
||||||
|
{
|
||||||
|
ValidateNavigation(navigation);
|
||||||
|
if (navigation.CurrentValue == null)
|
||||||
|
continue;
|
||||||
|
if (navigation.Metadata.IsCollection())
|
||||||
|
{
|
||||||
|
IEnumerable entities = (IEnumerable)navigation.CurrentValue;
|
||||||
|
foreach (object childEntry in entities)
|
||||||
|
ValidateNewEntry(_database.Entry(childEntry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ValidateNewEntry(_database.Entry(navigation.CurrentValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterShowLinks(Library library, Collection collection, Show show)
|
public void RegisterShowLinks(Library library, Collection collection, Show show)
|
||||||
@ -212,7 +233,6 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
catch (DbUpdateException)
|
catch (DbUpdateException)
|
||||||
{
|
{
|
||||||
ValidateChanges();
|
|
||||||
if (retryCount < MaxSaveRetry)
|
if (retryCount < MaxSaveRetry)
|
||||||
await SaveChanges(retryCount + 1);
|
await SaveChanges(retryCount + 1);
|
||||||
else
|
else
|
||||||
@ -231,21 +251,7 @@ namespace Kyoo.Controllers
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (NavigationEntry navigation in sourceEntry.Navigations)
|
foreach (NavigationEntry navigation in sourceEntry.Navigations)
|
||||||
{
|
ValidateNavigation(navigation);
|
||||||
if (navigation.IsModified == false)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
object value = navigation.Metadata.PropertyInfo.GetValue(sourceEntry.Entity);
|
|
||||||
if (value == null)
|
|
||||||
continue;
|
|
||||||
object newValue = Validate(value);
|
|
||||||
if (newValue != value)
|
|
||||||
navigation.Metadata.PropertyInfo.SetValue(sourceEntry.Entity, newValue);
|
|
||||||
else
|
|
||||||
_database.Entry(value).State = EntityState.Detached;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -254,6 +260,22 @@ namespace Kyoo.Controllers
|
|||||||
_database.ChangeTracker.DetectChanges();
|
_database.ChangeTracker.DetectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ValidateNavigation(NavigationEntry navigation)
|
||||||
|
{
|
||||||
|
// if (navigation.IsModified == false)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
object oldValue = navigation.CurrentValue;
|
||||||
|
if (oldValue == null)
|
||||||
|
return;
|
||||||
|
object newValue = Validate(oldValue);
|
||||||
|
if (oldValue == newValue)
|
||||||
|
return;
|
||||||
|
navigation.CurrentValue = newValue;
|
||||||
|
if (!navigation.Metadata.IsCollection())
|
||||||
|
_database.Entry(oldValue).State = EntityState.Detached;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Edit
|
#region Edit
|
||||||
@ -465,16 +487,19 @@ namespace Kyoo.Controllers
|
|||||||
switch(obj)
|
switch(obj)
|
||||||
{
|
{
|
||||||
case ProviderLink link:
|
case ProviderLink link:
|
||||||
link.Provider = ValidateLink(() => link.Provider); //TODO Calling this methods make the obj in a deteached state. Don't know why.
|
link.Provider = ValidateLink(link.Provider);
|
||||||
link.Library = ValidateLink(() => link.Library);
|
link.Library = ValidateLink(link.Library);
|
||||||
|
_database.Entry(link).State = EntityState.Added;
|
||||||
return obj;
|
return obj;
|
||||||
case GenreLink link:
|
case GenreLink link:
|
||||||
link.Show = ValidateLink(() => link.Show);
|
link.Show = ValidateLink(link.Show);
|
||||||
link.Genre = ValidateLink(() => link.Genre);
|
link.Genre = ValidateLink(link.Genre);
|
||||||
|
_database.Entry(link).State = EntityState.Added;
|
||||||
return obj;
|
return obj;
|
||||||
case PeopleLink link:
|
case PeopleLink link:
|
||||||
link.Show = ValidateLink(() => link.Show);
|
link.Show = ValidateLink(link.Show);
|
||||||
link.People = ValidateLink(() => link.People);
|
link.People = ValidateLink(link.People);
|
||||||
|
_database.Entry(link).State = EntityState.Added;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,7 +516,7 @@ namespace Kyoo.Controllers
|
|||||||
ProviderID provider => GetProvider(provider.Name) ?? provider,
|
ProviderID provider => GetProvider(provider.Name) ?? provider,
|
||||||
|
|
||||||
IEnumerable<dynamic> list => Utility.RunGenericMethod(this, "ValidateList",
|
IEnumerable<dynamic> list => Utility.RunGenericMethod(this, "ValidateList",
|
||||||
list.GetType().GetGenericArguments().First(), new [] {list}),
|
Utility.GetEnumerableType(list), new [] {list}),
|
||||||
_ => obj
|
_ => obj
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -504,17 +529,38 @@ namespace Kyoo.Controllers
|
|||||||
if (tmp != x)
|
if (tmp != x)
|
||||||
_database.Entry(x).State = EntityState.Detached;
|
_database.Entry(x).State = EntityState.Detached;
|
||||||
return tmp ?? x;
|
return tmp ?? x;
|
||||||
}).Where(x => x != null).ToList();
|
}).GroupBy(GetSlug).Select(x => x.First()).Where(x => x != null).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private T ValidateLink<T>(Func<T> linkGet) where T : class
|
private static object GetSlug(object obj)
|
||||||
|
{
|
||||||
|
return obj switch
|
||||||
|
{
|
||||||
|
Library library => library.Slug,
|
||||||
|
LibraryLink link => (link.Library.Slug, link.Collection.Slug),
|
||||||
|
Collection collection => collection.Slug,
|
||||||
|
CollectionLink link => (link.Collection.Slug, link.Show.Slug),
|
||||||
|
Show show => show.Slug,
|
||||||
|
Season season => (season.Show.Slug, season.SeasonNumber),
|
||||||
|
Episode episode => (episode.Show.Slug, episode.SeasonNumber, episode.EpisodeNumber),
|
||||||
|
Track track => track.ID,
|
||||||
|
Studio studio => studio.Slug,
|
||||||
|
People people => people.Slug,
|
||||||
|
PeopleLink link => (link.Show.Slug, link.People.Slug),
|
||||||
|
Genre genre => genre.Slug,
|
||||||
|
GenreLink link => (link.Show.Slug, link.Genre.Slug),
|
||||||
|
MetadataID id => (id.ProviderID, id.ShowID, id.SeasonID, id.EpisodeID, id.PeopleID),
|
||||||
|
ProviderID id => id.Name,
|
||||||
|
ProviderLink link => (link.ProviderID, link.LibraryID),
|
||||||
|
_ => obj
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private T ValidateLink<T>(T oldValue) where T : class
|
||||||
{
|
{
|
||||||
if (linkGet == null)
|
|
||||||
throw new ArgumentNullException(nameof(linkGet));
|
|
||||||
T oldValue = linkGet();
|
|
||||||
T newValue = Validate(oldValue);
|
T newValue = Validate(oldValue);
|
||||||
if (!ReferenceEquals(oldValue, newValue))
|
if (!ReferenceEquals(oldValue, newValue))
|
||||||
_database.Entry(linkGet()).State = EntityState.Detached;
|
_database.Entry(oldValue).State = EntityState.Detached;
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,11 +568,11 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
if (library == null)
|
if (library == null)
|
||||||
return null;
|
return null;
|
||||||
library.Providers = library.Providers.Select(x =>
|
// library.Providers = library.Providers.Select(x =>
|
||||||
{
|
// {
|
||||||
x.Provider = _database.Providers.FirstOrDefault(y => y.Name == x.Name);
|
// x.Provider = _database.Providers.FirstOrDefault(y => y.Name == x.Name);
|
||||||
return x;
|
// return x;
|
||||||
}).Where(x => x.Provider != null).ToList();
|
// }).Where(x => x.Provider != null).ToList();
|
||||||
return library;
|
return library;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IdentityServer4.EntityFramework.Entities;
|
using IdentityServer4.EntityFramework.Entities;
|
||||||
@ -88,11 +89,13 @@ namespace Kyoo
|
|||||||
public DbSet<ProviderLink> ProviderLinks { get; set; }
|
public DbSet<ProviderLink> ProviderLinks { get; set; }
|
||||||
|
|
||||||
|
|
||||||
private ValueConverter<string[], string> stringArrayConverter = new ValueConverter<string[], string>(
|
private readonly ValueConverter<IEnumerable<string>, string> _stringArrayConverter =
|
||||||
|
new ValueConverter<IEnumerable<string>, string>(
|
||||||
arr => string.Join("|", arr),
|
arr => string.Join("|", arr),
|
||||||
str => str.Split("|", StringSplitOptions.None));
|
str => str.Split("|", StringSplitOptions.None));
|
||||||
|
|
||||||
private ValueComparer<string[]> stringArrayComparer = new ValueComparer<string[]>(
|
private readonly ValueComparer<IEnumerable<string>> _stringArrayComparer =
|
||||||
|
new ValueComparer<IEnumerable<string>>(
|
||||||
(l1, l2) => l1.SequenceEqual(l2),
|
(l1, l2) => l1.SequenceEqual(l2),
|
||||||
arr => arr.Aggregate(0, (i, s) => s.GetHashCode()));
|
arr => arr.Aggregate(0, (i, s) => s.GetHashCode()));
|
||||||
|
|
||||||
@ -101,8 +104,12 @@ namespace Kyoo
|
|||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity<Library>().Property(e => e.Paths).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
modelBuilder.Entity<Library>().Property(e => e.Paths)
|
||||||
modelBuilder.Entity<Show>().Property(e => e.Aliases).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
.HasConversion(_stringArrayConverter).Metadata
|
||||||
|
.SetValueComparer(_stringArrayComparer);
|
||||||
|
modelBuilder.Entity<Show>().Property(e => e.Aliases)
|
||||||
|
.HasConversion(_stringArrayConverter).Metadata
|
||||||
|
.SetValueComparer(_stringArrayComparer);
|
||||||
|
|
||||||
modelBuilder.Entity<Track>()
|
modelBuilder.Entity<Track>()
|
||||||
.Property(t => t.IsDefault)
|
.Property(t => t.IsDefault)
|
||||||
@ -114,21 +121,22 @@ namespace Kyoo
|
|||||||
|
|
||||||
modelBuilder.Entity<GenreLink>()
|
modelBuilder.Entity<GenreLink>()
|
||||||
.HasKey(x => new {x.ShowID, x.GenreID});
|
.HasKey(x => new {x.ShowID, x.GenreID});
|
||||||
|
|
||||||
modelBuilder.Entity<Show>()
|
|
||||||
.Ignore(x => x.Genres);
|
|
||||||
|
|
||||||
|
modelBuilder.Entity<Library>()
|
||||||
|
.Ignore(x => x.Shows)
|
||||||
|
.Ignore(x => x.Collections)
|
||||||
|
.Ignore(x => x.Providers);
|
||||||
|
|
||||||
modelBuilder.Entity<Collection>()
|
modelBuilder.Entity<Collection>()
|
||||||
.Ignore(x => x.Shows);
|
.Ignore(x => x.Shows);
|
||||||
|
|
||||||
|
modelBuilder.Entity<Show>()
|
||||||
|
.Ignore(x => x.Genres);
|
||||||
|
|
||||||
modelBuilder.Entity<PeopleLink>()
|
modelBuilder.Entity<PeopleLink>()
|
||||||
.Ignore(x => x.Slug)
|
.Ignore(x => x.Slug)
|
||||||
.Ignore(x => x.Name)
|
.Ignore(x => x.Name)
|
||||||
.Ignore(x => x.ExternalIDs);
|
.Ignore(x => x.ExternalIDs);
|
||||||
|
|
||||||
modelBuilder.Entity<ProviderLink>()
|
|
||||||
.Ignore(x => x.Name)
|
|
||||||
.Ignore(x => x.Logo);
|
|
||||||
|
|
||||||
|
|
||||||
modelBuilder.Entity<Collection>()
|
modelBuilder.Entity<Collection>()
|
||||||
|
@ -38,7 +38,7 @@ namespace Kyoo.Api
|
|||||||
return BadRequest(new {error = "The library's slug must be set and not empty"});
|
return BadRequest(new {error = "The library's slug must be set and not empty"});
|
||||||
if (string.IsNullOrEmpty(library.Name))
|
if (string.IsNullOrEmpty(library.Name))
|
||||||
return BadRequest(new {error = "The library's name must be set and not empty"});
|
return BadRequest(new {error = "The library's name must be set and not empty"});
|
||||||
if (library.Paths == null || library.Paths.Length == 0)
|
if (library.Paths == null || !library.Paths.Any())
|
||||||
return BadRequest(new {error = "The library should have a least one path."});
|
return BadRequest(new {error = "The library should have a least one path."});
|
||||||
if (_libraryManager.GetLibrary(library.Slug) != null)
|
if (_libraryManager.GetLibrary(library.Slug) != null)
|
||||||
return BadRequest(new {error = "Duplicated library slug"});
|
return BadRequest(new {error = "Duplicated library slug"});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user