mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
17 changed files with 1392 additions and 756 deletions
@ -0,0 +1,51 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class AddSchemaNames : IContentItemConverter |
|||
{ |
|||
private readonly ResolvedComponents components; |
|||
|
|||
public AddSchemaNames(ResolvedComponents components) |
|||
{ |
|||
this.components = components; |
|||
} |
|||
|
|||
public JsonObject ConvertItem(IField field, JsonObject source) |
|||
{ |
|||
if (field is IArrayField) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
if (source.ContainsKey("schemaName")) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
if (!Component.IsValid(source, out var discriminator)) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
var id = DomainId.Create(discriminator); |
|||
|
|||
if (components.TryGetValue(id, out var schema)) |
|||
{ |
|||
source["schemaName"] = schema.Name; |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.ValidateContent; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class ExcludeChangedTypes : IContentFieldConverter, IContentValueConverter |
|||
{ |
|||
private readonly IJsonSerializer jsonSerializer; |
|||
|
|||
public ExcludeChangedTypes(IJsonSerializer jsonSerializer) |
|||
{ |
|||
this.jsonSerializer = jsonSerializer; |
|||
} |
|||
|
|||
public ContentFieldData? ConvertField(IRootField field, ContentFieldData source) |
|||
{ |
|||
foreach (var (_, value) in source) |
|||
{ |
|||
if (value.Value == default) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (IsChangedType(field, value)) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
|
|||
public (bool Remove, JsonValue) ConvertValue(IField field, JsonValue source, IField? parent) |
|||
{ |
|||
if (parent == null || source == default) |
|||
{ |
|||
return (false, source); |
|||
} |
|||
|
|||
return (IsChangedType(field, source), source); |
|||
} |
|||
|
|||
private bool IsChangedType(IField field, JsonValue source) |
|||
{ |
|||
try |
|||
{ |
|||
return !JsonValueValidator.IsValid(field, source, jsonSerializer); |
|||
} |
|||
catch |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class ExcludeHidden : IContentFieldConverter, IContentValueConverter |
|||
{ |
|||
public static readonly ExcludeHidden Instance = new ExcludeHidden(); |
|||
|
|||
private ExcludeHidden() |
|||
{ |
|||
} |
|||
|
|||
public ContentFieldData? ConvertField(IRootField field, ContentFieldData source) |
|||
{ |
|||
return field.IsForApi() ? source : null; |
|||
} |
|||
|
|||
public (bool Remove, JsonValue) ConvertValue(IField field, JsonValue source, IField? parent) |
|||
{ |
|||
return field.IsForApi() ? (false, source) : (true, default); |
|||
} |
|||
} |
|||
} |
|||
@ -1,403 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.ValidateContent; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
#pragma warning disable MA0048 // File name must match type name
|
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public delegate ContentFieldData? FieldConverter(ContentFieldData data, IRootField field); |
|||
|
|||
public static class FieldConverters |
|||
{ |
|||
public static readonly FieldConverter Noop = (data, _) => data; |
|||
|
|||
public static readonly FieldConverter ExcludeHidden = (data, field) => |
|||
{ |
|||
return field.IsForApi() ? data : null; |
|||
}; |
|||
|
|||
public static FieldConverter ExcludeChangedTypes(IJsonSerializer jsonSerializer) |
|||
{ |
|||
return (data, field) => |
|||
{ |
|||
foreach (var (_, value) in data) |
|||
{ |
|||
if (value.Value == default) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
if (!JsonValueValidator.IsValid(field, value, jsonSerializer)) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
return data; |
|||
}; |
|||
} |
|||
|
|||
public static FieldConverter ResolveInvariant(LanguagesConfig languages) |
|||
{ |
|||
var iv = InvariantPartitioning.Key; |
|||
|
|||
return (data, field) => |
|||
{ |
|||
if (field.Partitioning.Equals(Partitioning.Invariant) && !data.TryGetNonNull(iv, out _)) |
|||
{ |
|||
var result = new ContentFieldData(1); |
|||
|
|||
if (data.TryGetNonNull(languages.Master, out var value)) |
|||
{ |
|||
result[iv] = value; |
|||
} |
|||
else if (data.Count > 0) |
|||
{ |
|||
result[iv] = data.First().Value; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
return data; |
|||
}; |
|||
} |
|||
|
|||
public static FieldConverter ResolveLanguages(LanguagesConfig languages) |
|||
{ |
|||
var iv = InvariantPartitioning.Key; |
|||
|
|||
return (data, field) => |
|||
{ |
|||
if (field.Partitioning.Equals(Partitioning.Language)) |
|||
{ |
|||
if (data.TryGetNonNull(iv, out var value)) |
|||
{ |
|||
var result = new ContentFieldData |
|||
{ |
|||
[languages.Master] = value |
|||
}; |
|||
|
|||
return result; |
|||
} |
|||
|
|||
while (true) |
|||
{ |
|||
var isRemoved = false; |
|||
|
|||
foreach (var (key, _) in data) |
|||
{ |
|||
if (!languages.AllKeys.Contains(key)) |
|||
{ |
|||
data.Remove(key); |
|||
isRemoved = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!isRemoved) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return data; |
|||
}; |
|||
} |
|||
|
|||
public static FieldConverter ResolveFallbackLanguages(LanguagesConfig languages) |
|||
{ |
|||
return (data, field) => |
|||
{ |
|||
if (field.Partitioning.Equals(Partitioning.Language)) |
|||
{ |
|||
foreach (var languageCode in languages.AllKeys) |
|||
{ |
|||
if (data.TryGetNonNull(languageCode, out _)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var fallback in languages.GetPriorities(languageCode)) |
|||
{ |
|||
if (data.TryGetNonNull(fallback, out var value)) |
|||
{ |
|||
data[languageCode] = value; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return data; |
|||
}; |
|||
} |
|||
|
|||
public static FieldConverter FilterLanguages(LanguagesConfig config, IEnumerable<Language>? languages) |
|||
{ |
|||
if (languages?.Any() != true) |
|||
{ |
|||
return Noop; |
|||
} |
|||
|
|||
var languageSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); |
|||
|
|||
foreach (var language in languages) |
|||
{ |
|||
if (config.Contains(language.Iso2Code)) |
|||
{ |
|||
languageSet.Add(language.Iso2Code); |
|||
} |
|||
} |
|||
|
|||
if (languageSet.Count == 0) |
|||
{ |
|||
languageSet.Add(config.Master); |
|||
} |
|||
|
|||
return (data, field) => |
|||
{ |
|||
if (field.Partitioning.Equals(Partitioning.Language)) |
|||
{ |
|||
while (true) |
|||
{ |
|||
var isRemoved = false; |
|||
|
|||
foreach (var (key, _) in data) |
|||
{ |
|||
if (!languageSet.Contains(key)) |
|||
{ |
|||
data.Remove(key); |
|||
isRemoved = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!isRemoved) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return data; |
|||
}; |
|||
} |
|||
|
|||
public static FieldConverter ForValues(ResolvedComponents components, params ValueConverter[] converters) |
|||
{ |
|||
return (data, field) => |
|||
{ |
|||
ContentFieldData? newData = null; |
|||
|
|||
foreach (var (key, value) in data) |
|||
{ |
|||
var newValue = ConvertByType(field, value, null, converters, components); |
|||
|
|||
if (newValue == null) |
|||
{ |
|||
newData ??= new ContentFieldData(data); |
|||
newData.Remove(key); |
|||
} |
|||
else if (!ReferenceEquals(newValue.Value.Value, value.Value)) |
|||
{ |
|||
newData ??= new ContentFieldData(data); |
|||
newData[key] = newValue.Value; |
|||
} |
|||
} |
|||
|
|||
return newData ?? data; |
|||
}; |
|||
} |
|||
|
|||
private static JsonValue? ConvertByType<T>(T field, JsonValue value, IArrayField? parent, ValueConverter[] converters, |
|||
ResolvedComponents components) where T : IField |
|||
{ |
|||
switch (field) |
|||
{ |
|||
case IArrayField arrayField: |
|||
return ConvertArray(arrayField, value, converters, components); |
|||
|
|||
case IField<ComponentFieldProperties>: |
|||
return ConvertComponent(value, converters, components); |
|||
|
|||
case IField<ComponentsFieldProperties>: |
|||
return ConvertComponents(value, converters, components); |
|||
|
|||
default: |
|||
return ConvertValue(field, value, parent, converters); |
|||
} |
|||
} |
|||
|
|||
private static JsonValue? ConvertArray(IArrayField field, JsonValue value, ValueConverter[] converters, |
|||
ResolvedComponents components) |
|||
{ |
|||
if (value.Value is JsonArray a) |
|||
{ |
|||
JsonArray? result = null; |
|||
|
|||
for (int i = 0, j = 0; i < a.Count; i++, j++) |
|||
{ |
|||
var oldValue = a[i]; |
|||
|
|||
var newValue = ConvertArrayItem(field, oldValue, converters, components); |
|||
|
|||
if (newValue == null) |
|||
{ |
|||
result ??= new JsonArray(a); |
|||
result.RemoveAt(j); |
|||
j--; |
|||
} |
|||
else if (!ReferenceEquals(newValue.Value.Value, oldValue.Value)) |
|||
{ |
|||
result ??= new JsonArray(a); |
|||
result[j] = newValue.Value; |
|||
} |
|||
} |
|||
|
|||
return result ?? value; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private static JsonValue? ConvertComponents(JsonValue? value, ValueConverter[] converters, |
|||
ResolvedComponents components) |
|||
{ |
|||
if (value?.Value is JsonArray a) |
|||
{ |
|||
JsonArray? result = null; |
|||
|
|||
for (int i = 0, j = 0; i < a.Count; i++, j++) |
|||
{ |
|||
var oldValue = a[i]; |
|||
|
|||
var newValue = ConvertComponent(oldValue, converters, components); |
|||
|
|||
if (newValue == null) |
|||
{ |
|||
result ??= new JsonArray(a); |
|||
result.RemoveAt(j); |
|||
j--; |
|||
} |
|||
else if (!ReferenceEquals(newValue.Value.Value, a[i].Value)) |
|||
{ |
|||
result ??= new JsonArray(a); |
|||
result[j] = newValue.Value; |
|||
} |
|||
} |
|||
|
|||
return result ?? value; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private static JsonValue? ConvertComponent(JsonValue? value, ValueConverter[] converters, |
|||
ResolvedComponents components) |
|||
{ |
|||
if (value?.Value is JsonObject o && o.TryGetValue(Component.Discriminator, out var found) && found.Value is string s) |
|||
{ |
|||
var id = DomainId.Create(s); |
|||
|
|||
if (components.TryGetValue(id, out var schema)) |
|||
{ |
|||
return ConvertNested(schema.FieldCollection, value.Value, null, converters, components); |
|||
} |
|||
else |
|||
{ |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private static JsonValue? ConvertArrayItem(IArrayField field, JsonValue value, ValueConverter[] converters, |
|||
ResolvedComponents components) |
|||
{ |
|||
if (value.Value is JsonObject) |
|||
{ |
|||
return ConvertNested(field.FieldCollection, value, field, converters, components); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private static JsonValue ConvertNested<T>(FieldCollection<T> fields, JsonValue source, IArrayField? parent, ValueConverter[] converters, |
|||
ResolvedComponents components) where T : IField |
|||
{ |
|||
JsonObject? result = null; |
|||
|
|||
var obj = source.AsObject; |
|||
|
|||
foreach (var (key, value) in obj) |
|||
{ |
|||
JsonValue? newValue = value; |
|||
|
|||
if (fields.ByName.TryGetValue(key, out var field)) |
|||
{ |
|||
newValue = ConvertByType(field, value, parent, converters, components); |
|||
} |
|||
else if (key != Component.Discriminator) |
|||
{ |
|||
newValue = null; |
|||
} |
|||
|
|||
if (newValue == null) |
|||
{ |
|||
result ??= new JsonObject(obj); |
|||
result.Remove(key); |
|||
} |
|||
else if (!ReferenceEquals(newValue.Value.Value, value.Value)) |
|||
{ |
|||
result ??= new JsonObject(obj); |
|||
result[key] = newValue.Value; |
|||
} |
|||
} |
|||
|
|||
return result ?? source; |
|||
} |
|||
|
|||
private static JsonValue? ConvertValue(IField field, JsonValue value, IArrayField? parent, ValueConverter[] converters) |
|||
{ |
|||
var newValue = value; |
|||
|
|||
for (var i = 0; i < converters.Length; i++) |
|||
{ |
|||
var candidate = converters[i](newValue!, field, parent); |
|||
|
|||
if (candidate == null) |
|||
{ |
|||
return null; |
|||
} |
|||
else |
|||
{ |
|||
newValue = candidate.Value; |
|||
} |
|||
} |
|||
|
|||
return newValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
#pragma warning disable MA0048 // File name must match type name
|
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public interface IConverter |
|||
{ |
|||
} |
|||
|
|||
public interface IContentFieldAfterConverter : IConverter |
|||
{ |
|||
ContentFieldData? ConvertFieldAfter(IRootField field, ContentFieldData source); |
|||
} |
|||
|
|||
public interface IContentFieldConverter : IConverter |
|||
{ |
|||
ContentFieldData? ConvertField(IRootField field, ContentFieldData source); |
|||
} |
|||
|
|||
public interface IContentItemConverter : IConverter |
|||
{ |
|||
JsonObject ConvertItem(IField field, JsonObject source); |
|||
} |
|||
|
|||
public interface IContentValueConverter : IConverter |
|||
{ |
|||
(bool Remove, JsonValue) ConvertValue(IField field, JsonValue source, IField? parent); |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class ResolveAssetUrls : IContentValueConverter |
|||
{ |
|||
private readonly NamedId<DomainId> appId; |
|||
private readonly IUrlGenerator urlGenerator; |
|||
private readonly Func<IField, IField?, bool> shouldHandle; |
|||
|
|||
public ResolveAssetUrls(NamedId<DomainId> appId, IUrlGenerator urlGenerator, IReadOnlyCollection<string>? fields) |
|||
{ |
|||
this.appId = appId; |
|||
|
|||
if (fields == null || fields.Count == 0) |
|||
{ |
|||
shouldHandle = (field, parent) => false; |
|||
} |
|||
else if (fields.Contains("*")) |
|||
{ |
|||
shouldHandle = (field, parent) => true; |
|||
} |
|||
else |
|||
{ |
|||
var paths = fields.Select(x => x.Split('.')).ToList(); |
|||
|
|||
shouldHandle = (field, parent) => |
|||
{ |
|||
for (var i = 0; i < paths.Count; i++) |
|||
{ |
|||
var path = paths[i]; |
|||
|
|||
if (parent != null) |
|||
{ |
|||
if (path.Length == 2 && path[0] == parent.Name && path[1] == field.Name) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (path.Length == 1 && path[0] == field.Name) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
}; |
|||
} |
|||
|
|||
this.urlGenerator = urlGenerator; |
|||
} |
|||
|
|||
public (bool Remove, JsonValue) ConvertValue(IField field, JsonValue source, IField? parent) |
|||
{ |
|||
if (field is IField<AssetsFieldProperties> && source.Value is JsonArray a && shouldHandle(field, parent)) |
|||
{ |
|||
for (var i = 0; i < a.Count; i++) |
|||
{ |
|||
a[i] = urlGenerator.AssetContent(appId, a[i].ToString()); |
|||
} |
|||
} |
|||
|
|||
return (false, source); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class ResolveInvariant : IContentFieldAfterConverter |
|||
{ |
|||
private readonly LanguagesConfig languages; |
|||
|
|||
public ResolveInvariant(LanguagesConfig languages) |
|||
{ |
|||
this.languages = languages; |
|||
} |
|||
|
|||
public ContentFieldData? ConvertFieldAfter(IRootField field, ContentFieldData source) |
|||
{ |
|||
if (!field.Partitioning.Equals(Partitioning.Invariant)) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
if (source.TryGetNonNull(InvariantPartitioning.Key, out _)) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
if (source.TryGetNonNull(languages.Master, out var value)) |
|||
{ |
|||
source.Clear(); |
|||
source[InvariantPartitioning.Key] = value; |
|||
|
|||
return source; |
|||
} |
|||
|
|||
if (source.Count > 0) |
|||
{ |
|||
var first = source.First().Value; |
|||
|
|||
source.Clear(); |
|||
source[InvariantPartitioning.Key] = first; |
|||
|
|||
return source; |
|||
} |
|||
|
|||
source.Clear(); |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,104 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public sealed class ResolveLanguages : IContentFieldAfterConverter |
|||
{ |
|||
private readonly LanguagesConfig languages; |
|||
private readonly bool resolveFallback; |
|||
private readonly HashSet<string> languageCodes; |
|||
|
|||
public ResolveLanguages(LanguagesConfig languages, bool resolveFallback = true, params Language[] filteredLanguages) |
|||
{ |
|||
this.languages = languages; |
|||
|
|||
if (filteredLanguages?.Length > 0) |
|||
{ |
|||
languageCodes = languages.AllKeys.Intersect(filteredLanguages.Select(x => x.Iso2Code)).ToHashSet(); |
|||
} |
|||
else |
|||
{ |
|||
languageCodes = languages.AllKeys.ToHashSet(); |
|||
} |
|||
|
|||
if (languageCodes.Count == 0) |
|||
{ |
|||
languageCodes.Add(languages.Master); |
|||
} |
|||
|
|||
this.resolveFallback = resolveFallback; |
|||
} |
|||
|
|||
public ContentFieldData? ConvertFieldAfter(IRootField field, ContentFieldData source) |
|||
{ |
|||
if (!field.Partitioning.Equals(Partitioning.Language)) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
if (source.TryGetNonNull(InvariantPartitioning.Key, out var value)) |
|||
{ |
|||
var result = new ContentFieldData |
|||
{ |
|||
[languages.Master] = value |
|||
}; |
|||
|
|||
return result; |
|||
} |
|||
|
|||
while (true) |
|||
{ |
|||
var isRemoved = false; |
|||
|
|||
foreach (var (key, _) in source) |
|||
{ |
|||
if (!languageCodes.Contains(key)) |
|||
{ |
|||
source.Remove(key); |
|||
isRemoved = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!isRemoved) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!resolveFallback) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
foreach (var languageCode in languageCodes) |
|||
{ |
|||
if (source.TryGetNonNull(languageCode, out _)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var fallback in languages.GetPriorities(languageCode)) |
|||
{ |
|||
if (source.TryGetNonNull(fallback, out var fallbackValue)) |
|||
{ |
|||
source[languageCode] = fallbackValue; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -1,111 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.ValidateContent; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
#pragma warning disable MA0048 // File name must match type name
|
|||
|
|||
namespace Squidex.Domain.Apps.Core.ConvertContent |
|||
{ |
|||
public delegate JsonValue? ValueConverter(JsonValue value, IField field, IArrayField? parent); |
|||
|
|||
public static class ValueConverters |
|||
{ |
|||
public static readonly ValueConverter Noop = (value, field, parent) => value; |
|||
|
|||
public static readonly ValueConverter ExcludeHidden = (value, field, parent) => |
|||
{ |
|||
return field.IsForApi() ? (JsonValue?)value : null; |
|||
}; |
|||
|
|||
public static ValueConverter ExcludeChangedTypes(IJsonSerializer jsonSerializer) |
|||
{ |
|||
return (value, field, parent) => |
|||
{ |
|||
if (value == default) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
if (!JsonValueValidator.IsValid(field, value, jsonSerializer)) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return value; |
|||
}; |
|||
} |
|||
|
|||
public static ValueConverter ResolveAssetUrls(NamedId<DomainId> appId, IReadOnlyCollection<string>? fields, IUrlGenerator urlGenerator) |
|||
{ |
|||
if (fields?.Any() != true) |
|||
{ |
|||
return Noop; |
|||
} |
|||
|
|||
Func<IField, IField?, bool> shouldHandle; |
|||
|
|||
if (fields.Contains("*")) |
|||
{ |
|||
shouldHandle = (field, parent) => true; |
|||
} |
|||
else |
|||
{ |
|||
var paths = fields.Select(x => x.Split('.')).ToList(); |
|||
|
|||
shouldHandle = (field, parent) => |
|||
{ |
|||
for (var i = 0; i < paths.Count; i++) |
|||
{ |
|||
var path = paths[i]; |
|||
|
|||
if (parent != null) |
|||
{ |
|||
if (path.Length == 2 && path[0] == parent.Name && path[1] == field.Name) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (path.Length == 1 && path[0] == field.Name) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
}; |
|||
} |
|||
|
|||
return (value, field, parent) => |
|||
{ |
|||
if (field is IField<AssetsFieldProperties> && value.Value is JsonArray a && shouldHandle(field, parent)) |
|||
{ |
|||
for (var i = 0; i < a.Count; i++) |
|||
{ |
|||
a[i] = urlGenerator.AssetContent(appId, a[i].ToString()); |
|||
} |
|||
} |
|||
|
|||
return value; |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue