Browse Source

Reduce allocations in visitors. (#618)

pull/616/head
Sebastian Stehle 5 years ago
committed by GitHub
parent
commit
a6fd374976
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
  2. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs
  3. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs
  4. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs
  5. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs
  6. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
  7. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs
  8. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs
  9. 24
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs
  10. 24
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs
  11. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs
  12. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs
  13. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs
  14. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs
  15. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs
  16. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs
  17. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs
  18. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs
  19. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs
  20. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/UIFieldProperties.cs
  21. 69
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs
  22. 72
      backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs
  23. 43
      backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs
  24. 84
      backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs
  25. 89
      backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs
  26. 6
      backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs
  27. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmSchemaExtensions.cs
  28. 54
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs
  29. 3
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs
  30. 63
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs
  31. 73
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs
  32. 28
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/FieldBagValidatorsFactory.cs
  33. 78
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs
  34. 1
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ObjectPath.cs
  35. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs
  36. 7
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs
  37. 61
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/GraphQLTypeVisitor.cs
  38. 61
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/InputFieldVisitor.cs
  39. 27
      backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs
  40. 27
      backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs
  41. 1
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs
  42. 54
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs
  43. 4
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs

1
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs

@ -16,14 +16,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public int? MaxItems { get; set; } public int? MaxItems { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IArrayField)field); return visitor.Visit((IArrayField)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs

@ -52,14 +52,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public ReadOnlyCollection<string>? AllowedExtensions { get; set; } public ReadOnlyCollection<string>? AllowedExtensions { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<AssetsFieldProperties>)field); return visitor.Visit((IField<AssetsFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs

@ -18,14 +18,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public BooleanFieldEditor Editor { get; set; } public BooleanFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<BooleanFieldProperties>)field); return visitor.Visit((IField<BooleanFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs

@ -24,14 +24,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public DateTimeFieldEditor Editor { get; set; } public DateTimeFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<DateTimeFieldProperties>)field); return visitor.Visit((IField<DateTimeFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

4
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs

@ -24,9 +24,9 @@ namespace Squidex.Domain.Apps.Core.Schemas
public ReadOnlyCollection<string>? Tags { get; set; } public ReadOnlyCollection<string>? Tags { get; set; }
public abstract T Accept<T>(IFieldPropertiesVisitor<T> visitor); public abstract T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args);
public abstract T Accept<T>(IFieldVisitor<T> visitor, IField field); public abstract T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args);
public abstract RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null); public abstract RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null);

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs

@ -12,14 +12,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
public GeolocationFieldEditor Editor { get; set; } public GeolocationFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<GeolocationFieldProperties>)field); return visitor.Visit((IField<GeolocationFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs

@ -15,6 +15,6 @@ namespace Squidex.Domain.Apps.Core.Schemas
FieldProperties RawProperties { get; } FieldProperties RawProperties { get; }
T Accept<T>(IFieldVisitor<T> visitor); T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, TArgs args);
} }
} }

24
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs

@ -7,28 +7,28 @@
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
public interface IFieldPropertiesVisitor<out T> public interface IFieldPropertiesVisitor<out T, in TArgs>
{ {
T Visit(ArrayFieldProperties properties); T Visit(ArrayFieldProperties properties, TArgs args);
T Visit(AssetsFieldProperties properties); T Visit(AssetsFieldProperties properties, TArgs args);
T Visit(BooleanFieldProperties properties); T Visit(BooleanFieldProperties properties, TArgs args);
T Visit(DateTimeFieldProperties properties); T Visit(DateTimeFieldProperties properties, TArgs args);
T Visit(GeolocationFieldProperties properties); T Visit(GeolocationFieldProperties properties, TArgs args);
T Visit(JsonFieldProperties properties); T Visit(JsonFieldProperties properties, TArgs args);
T Visit(NumberFieldProperties properties); T Visit(NumberFieldProperties properties, TArgs args);
T Visit(ReferencesFieldProperties properties); T Visit(ReferencesFieldProperties properties, TArgs args);
T Visit(StringFieldProperties properties); T Visit(StringFieldProperties properties, TArgs args);
T Visit(TagsFieldProperties properties); T Visit(TagsFieldProperties properties, TArgs args);
T Visit(UIFieldProperties properties); T Visit(UIFieldProperties properties, TArgs args);
} }
} }

24
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs

@ -7,28 +7,28 @@
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
public interface IFieldVisitor<out T> public interface IFieldVisitor<out T, in TArgs>
{ {
T Visit(IArrayField field); T Visit(IArrayField field, TArgs args);
T Visit(IField<AssetsFieldProperties> field); T Visit(IField<AssetsFieldProperties> field, TArgs args);
T Visit(IField<BooleanFieldProperties> field); T Visit(IField<BooleanFieldProperties> field, TArgs args);
T Visit(IField<DateTimeFieldProperties> field); T Visit(IField<DateTimeFieldProperties> field, TArgs args);
T Visit(IField<GeolocationFieldProperties> field); T Visit(IField<GeolocationFieldProperties> field, TArgs args);
T Visit(IField<JsonFieldProperties> field); T Visit(IField<JsonFieldProperties> field, TArgs args);
T Visit(IField<NumberFieldProperties> field); T Visit(IField<NumberFieldProperties> field, TArgs args);
T Visit(IField<ReferencesFieldProperties> field); T Visit(IField<ReferencesFieldProperties> field, TArgs args);
T Visit(IField<StringFieldProperties> field); T Visit(IField<StringFieldProperties> field, TArgs args);
T Visit(IField<TagsFieldProperties> field); T Visit(IField<TagsFieldProperties> field, TArgs args);
T Visit(IField<UIFieldProperties> field); T Visit(IField<UIFieldProperties> field, TArgs args);
} }
} }

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs

@ -10,14 +10,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
[Equals(DoNotAddEqualityOperators = true)] [Equals(DoNotAddEqualityOperators = true)]
public sealed class JsonFieldProperties : FieldProperties public sealed class JsonFieldProperties : FieldProperties
{ {
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<JsonFieldProperties>)field); return visitor.Visit((IField<JsonFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs

@ -131,7 +131,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
}); });
} }
public abstract T Accept<T>(IFieldVisitor<T> visitor); public abstract T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, TArgs args);
public abstract NestedField Update(FieldProperties newProperties); public abstract NestedField Update(FieldProperties newProperties);
} }

4
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs

@ -67,9 +67,9 @@ namespace Squidex.Domain.Apps.Core.Schemas
return typedProperties; return typedProperties;
} }
public override TResult Accept<TResult>(IFieldVisitor<TResult> visitor) public override TResult Accept<TResult, TArgs>(IFieldVisitor<TResult, TArgs> visitor, TArgs args)
{ {
return properties.Accept(visitor, this); return properties.Accept(visitor, this, args);
} }
} }
} }

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs

@ -28,14 +28,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public NumberFieldEditor Editor { get; set; } public NumberFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<NumberFieldProperties>)field); return visitor.Visit((IField<NumberFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs

@ -52,14 +52,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public ReadOnlyCollection<DomainId>? SchemaIds { get; set; } public ReadOnlyCollection<DomainId>? SchemaIds { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<ReferencesFieldProperties>)field); return visitor.Visit((IField<ReferencesFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs

@ -140,7 +140,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
}); });
} }
public abstract T Accept<T>(IFieldVisitor<T> visitor); public abstract T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, TArgs args);
public abstract RootField Update(FieldProperties newProperties); public abstract RootField Update(FieldProperties newProperties);
} }

4
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs

@ -65,9 +65,9 @@ namespace Squidex.Domain.Apps.Core.Schemas
return typedProperties; return typedProperties;
} }
public override TResult Accept<TResult>(IFieldVisitor<TResult> visitor) public override TResult Accept<TResult, TArgs>(IFieldVisitor<TResult, TArgs> visitor, TArgs args)
{ {
return properties.Accept(visitor, this); return properties.Accept(visitor, this, args);
} }
} }
} }

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs

@ -42,14 +42,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public StringFieldEditor Editor { get; set; } public StringFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<StringFieldProperties>)field); return visitor.Visit((IField<StringFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs

@ -26,14 +26,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
public TagsFieldNormalization Normalization { get; set; } public TagsFieldNormalization Normalization { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<TagsFieldProperties>)field); return visitor.Visit((IField<TagsFieldProperties>)field, args);
} }
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/UIFieldProperties.cs

@ -12,14 +12,14 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
public UIFieldEditor Editor { get; set; } public UIFieldEditor Editor { get; set; }
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T, TArgs>(IFieldPropertiesVisitor<T, TArgs> visitor, TArgs args)
{ {
return visitor.Visit(this); return visitor.Visit(this, args);
} }
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) public override T Accept<T, TArgs>(IFieldVisitor<T, TArgs> visitor, IField field, TArgs args)
{ {
return visitor.Visit((IField<UIFieldProperties>)field); return visitor.Visit((IField<UIFieldProperties>)field, args);
} }
public override NestedField CreateNestedField(long id, string name, IFieldSettings? settings = null) public override NestedField CreateNestedField(long id, string name, IFieldSettings? settings = null)

69
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs

@ -11,16 +11,25 @@ using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Core.ConvertContent namespace Squidex.Domain.Apps.Core.ConvertContent
{ {
public sealed class StringFormatter : IFieldVisitor<string> public sealed class StringFormatter : IFieldPropertiesVisitor<string, StringFormatter.Args>
{ {
private readonly IJsonValue value; private static readonly StringFormatter Instance = new StringFormatter();
private StringFormatter(IJsonValue value) public readonly struct Args
{
public readonly IJsonValue Value;
public Args(IJsonValue value)
{
Value = value;
}
}
private StringFormatter()
{ {
this.value = value;
} }
public static string Format(IJsonValue? value, IField field) public static string Format(IField field, IJsonValue? value)
{ {
Guard.NotNull(field, nameof(field)); Guard.NotNull(field, nameof(field));
@ -29,22 +38,24 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
return string.Empty; return string.Empty;
} }
return field.Accept(new StringFormatter(value)); var args = new Args(value ?? JsonValue.Null);
return field.RawProperties.Accept(Instance, args);
} }
public string Visit(IArrayField field) public string Visit(ArrayFieldProperties properties, Args args)
{ {
return FormatArray("Item", "Items"); return FormatArray(args.Value, "Item", "Items");
} }
public string Visit(IField<AssetsFieldProperties> field) public string Visit(AssetsFieldProperties properties, Args args)
{ {
return FormatArray("Asset", "Assets"); return FormatArray(args.Value, "Asset", "Assets");
} }
public string Visit(IField<BooleanFieldProperties> field) public string Visit(BooleanFieldProperties properties, Args args)
{ {
if (value is JsonBoolean boolean && boolean.Value) if (args.Value is JsonBoolean boolean && boolean.Value)
{ {
return "Yes"; return "Yes";
} }
@ -54,14 +65,16 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
} }
} }
public string Visit(IField<DateTimeFieldProperties> field) public string Visit(DateTimeFieldProperties properties, Args args)
{ {
return value.ToString(); return args.Value.ToString();
} }
public string Visit(IField<GeolocationFieldProperties> field) public string Visit(GeolocationFieldProperties properties, Args args)
{ {
if (value is JsonObject obj && obj.TryGetValue("latitude", out var lat) && obj.TryGetValue("longitude", out var lon)) if (args.Value is JsonObject jsonObject &&
jsonObject.TryGetValue("latitude", out var lat) &&
jsonObject.TryGetValue("longitude", out var lon))
{ {
return $"{lat}, {lon}"; return $"{lat}, {lon}";
} }
@ -71,36 +84,36 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
} }
} }
public string Visit(IField<JsonFieldProperties> field) public string Visit(JsonFieldProperties properties, Args args)
{ {
return "<Json />"; return "<Json />";
} }
public string Visit(IField<NumberFieldProperties> field) public string Visit(NumberFieldProperties properties, Args args)
{ {
return value.ToString(); return args.Value.ToString();
} }
public string Visit(IField<ReferencesFieldProperties> field) public string Visit(ReferencesFieldProperties properties, Args args)
{ {
return FormatArray("Reference", "References"); return FormatArray(args.Value, "Reference", "References");
} }
public string Visit(IField<StringFieldProperties> field) public string Visit(StringFieldProperties properties, Args args)
{ {
if (field.Properties.Editor == StringFieldEditor.StockPhoto) if (properties.Editor == StringFieldEditor.StockPhoto)
{ {
return "[Photo]"; return "[Photo]";
} }
else else
{ {
return value.ToString(); return args.Value.ToString();
} }
} }
public string Visit(IField<TagsFieldProperties> field) public string Visit(TagsFieldProperties properties, Args args)
{ {
if (value is JsonArray array) if (args.Value is JsonArray array)
{ {
return string.Join(", ", array); return string.Join(", ", array);
} }
@ -110,12 +123,12 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
} }
} }
public string Visit(IField<UIFieldProperties> field) public string Visit(UIFieldProperties properties, Args args)
{ {
return string.Empty; return string.Empty;
} }
private string FormatArray(string singularName, string pluralName) private static string FormatArray(IJsonValue value, string singularName, string pluralName)
{ {
if (value is JsonArray array) if (value is JsonArray array)
{ {

72
backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs

@ -13,104 +13,116 @@ using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Core.DefaultValues namespace Squidex.Domain.Apps.Core.DefaultValues
{ {
public sealed class DefaultValueFactory : IFieldVisitor<IJsonValue> public sealed class DefaultValueFactory : IFieldPropertiesVisitor<IJsonValue, DefaultValueFactory.Args>
{ {
private readonly Instant now; private static readonly DefaultValueFactory Instance = new DefaultValueFactory();
private readonly string partition;
private DefaultValueFactory(Instant now, string partition) public readonly struct Args
{
public readonly Instant Now;
public readonly string Partition;
public Args(Instant now, string partition)
{
Now = now;
Partition = partition;
}
}
private DefaultValueFactory()
{ {
this.now = now;
this.partition = partition;
} }
public static IJsonValue CreateDefaultValue(IField field, Instant now, string partition) public static IJsonValue CreateDefaultValue(IField field, Instant now, string partition)
{ {
Guard.NotNull(field, nameof(field)); Guard.NotNull(field, nameof(field));
Guard.NotNull(partition, nameof(partition));
return field.Accept(new DefaultValueFactory(now, partition)); return field.RawProperties.Accept(Instance, new Args(now, partition));
} }
public IJsonValue Visit(IArrayField field) public IJsonValue Visit(ArrayFieldProperties properties, Args args)
{ {
return JsonValue.Array(); return JsonValue.Array();
} }
public IJsonValue Visit(IField<AssetsFieldProperties> field) public IJsonValue Visit(AssetsFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return Array(value); return Array(value);
} }
public IJsonValue Visit(IField<BooleanFieldProperties> field) public IJsonValue Visit(BooleanFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return JsonValue.Create(value); return JsonValue.Create(value);
} }
public IJsonValue Visit(IField<GeolocationFieldProperties> field) public IJsonValue Visit(GeolocationFieldProperties properties, Args args)
{ {
return JsonValue.Null; return JsonValue.Null;
} }
public IJsonValue Visit(IField<JsonFieldProperties> field) public IJsonValue Visit(JsonFieldProperties properties, Args args)
{ {
return JsonValue.Null; return JsonValue.Null;
} }
public IJsonValue Visit(IField<NumberFieldProperties> field) public IJsonValue Visit(NumberFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return JsonValue.Create(value); return JsonValue.Create(value);
} }
public IJsonValue Visit(IField<ReferencesFieldProperties> field) public IJsonValue Visit(ReferencesFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return Array(value); return Array(value);
} }
public IJsonValue Visit(IField<StringFieldProperties> field) public IJsonValue Visit(StringFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return JsonValue.Create(value); return JsonValue.Create(value);
} }
public IJsonValue Visit(IField<TagsFieldProperties> field) public IJsonValue Visit(TagsFieldProperties properties, Args args)
{ {
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return Array(value); return Array(value);
} }
public IJsonValue Visit(IField<UIFieldProperties> field) public IJsonValue Visit(UIFieldProperties properties, Args args)
{ {
return JsonValue.Null; return JsonValue.Null;
} }
public IJsonValue Visit(IField<DateTimeFieldProperties> field) public IJsonValue Visit(DateTimeFieldProperties properties, Args args)
{ {
if (field.Properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Now) if (properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Now)
{ {
return JsonValue.Create(now); return JsonValue.Create(args.Now);
} }
if (field.Properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Today) if (properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Today)
{ {
return JsonValue.Create($"{now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}T00:00:00Z"); return JsonValue.Create($"{args.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}T00:00:00Z");
} }
var value = GetDefaultValue(field.Properties.DefaultValue, field.Properties.DefaultValues); var value = GetDefaultValue(properties.DefaultValue, properties.DefaultValues, args.Partition);
return JsonValue.Create(value); return JsonValue.Create(value);
} }
private T GetDefaultValue<T>(T value, LocalizedValue<T>? values) private static T GetDefaultValue<T>(T value, LocalizedValue<T>? values, string partition)
{ {
if (values != null && values.TryGetValue(partition, out var @default)) if (values != null && values.TryGetValue(partition, out var @default))
{ {

43
backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs

@ -20,57 +20,52 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
{ {
Guard.NotNull(schema, nameof(schema)); Guard.NotNull(schema, nameof(schema));
var extractor = new ReferencesExtractor(new HashSet<DomainId>(), referencesPerField); var result = new HashSet<DomainId>();
AddReferencedIds(source, schema.Fields, extractor); AddReferencedIds(source, schema.Fields, result, referencesPerField);
return extractor.Result; return result;
} }
public static void AddReferencedIds(this NamedContentData source, Schema schema, HashSet<DomainId> result, int referencesPerField = int.MaxValue) public static void AddReferencedIds(this NamedContentData source, Schema schema, HashSet<DomainId> result, int referencesPerField = int.MaxValue)
{ {
Guard.NotNull(schema, nameof(schema)); Guard.NotNull(schema, nameof(schema));
var extractor = new ReferencesExtractor(result, referencesPerField); AddReferencedIds(source, schema.Fields, result, referencesPerField);
AddReferencedIds(source, schema.Fields, extractor);
} }
public static void AddReferencedIds(this NamedContentData source, IEnumerable<IField> fields, HashSet<DomainId> result, int referencesPerField = int.MaxValue) public static void AddReferencedIds(this NamedContentData source, IEnumerable<IField> fields, HashSet<DomainId> result, int referencesPerField = int.MaxValue)
{ {
Guard.NotNull(fields, nameof(fields)); Guard.NotNull(fields, nameof(fields));
Guard.NotNull(result, nameof(result));
var extractor = new ReferencesExtractor(result, referencesPerField); foreach (var field in fields)
{
AddReferencedIds(source, fields, extractor); AddReferencedIds(source, result, referencesPerField, field);
}
} }
public static void AddReferencedIds(this NamedContentData source, IField field, HashSet<DomainId> result, int referencesPerField = int.MaxValue) public static void AddReferencedIds(this NamedContentData source, IField field, HashSet<DomainId> result, int referencesPerField = int.MaxValue)
{ {
Guard.NotNull(field, nameof(field)); Guard.NotNull(field, nameof(field));
Guard.NotNull(result, nameof(result));
var extractor = new ReferencesExtractor(result, referencesPerField); if (source.TryGetValue(field.Name, out var fieldData) && fieldData != null)
AddReferencedIds(source, field, extractor);
}
private static void AddReferencedIds(NamedContentData source, IEnumerable<IField> fields, ReferencesExtractor extractor)
{ {
foreach (var field in fields) foreach (var partitionValue in fieldData)
{ {
AddReferencedIds(source, field, extractor); ReferencesExtractor.Extract(field, partitionValue.Value, result, referencesPerField);
}
} }
} }
private static void AddReferencedIds(NamedContentData source, IField field, ReferencesExtractor extractor) private static void AddReferencedIds(NamedContentData source, HashSet<DomainId> result, int referencesPerField, IField field)
{ {
if (source.TryGetValue(field.Name, out var fieldData) && fieldData != null) if (source.TryGetValue(field.Name, out var fieldData) && fieldData != null)
{ {
foreach (var partitionValue in fieldData) foreach (var partitionValue in fieldData)
{ {
extractor.SetValue(partitionValue.Value); ReferencesExtractor.Extract(field, partitionValue.Value, result, referencesPerField);
field.Accept(extractor);
} }
} }
} }
@ -81,11 +76,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
if (value != null) if (value != null)
{ {
var extractor = new ReferencesExtractor(result, referencesPerField); ReferencesExtractor.Extract(field, value, result, referencesPerField);
extractor.SetValue(value);
field.Accept(extractor);
} }
return result; return result;

84
backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs

@ -12,87 +12,99 @@ using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Core.ExtractReferenceIds namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
{ {
public sealed class ReferencesCleaner : IFieldVisitor<IJsonValue> internal sealed class ReferencesCleaner : IFieldVisitor<IJsonValue, ReferencesCleaner.Args>
{ {
private readonly HashSet<DomainId> validIds; private static readonly ReferencesCleaner Instance = new ReferencesCleaner();
private IJsonValue value;
public ReferencesCleaner(HashSet<DomainId> validIds) public readonly struct Args
{ {
Guard.NotNull(validIds, nameof(validIds)); public readonly IJsonValue Value;
this.validIds = validIds; public readonly HashSet<DomainId> ValidIds;
public Args(IJsonValue value, HashSet<DomainId> validIds)
{
Value = value;
ValidIds = validIds;
}
} }
public void SetValue(IJsonValue newValue) private ReferencesCleaner()
{ {
value = newValue;
} }
public IJsonValue Visit(IField<AssetsFieldProperties> field) public static IJsonValue Cleanup(IField field, IJsonValue? value, HashSet<DomainId> validIds)
{
var args = new Args(value ?? JsonValue.Null, validIds);
return field.Accept(Instance, args);
}
public IJsonValue Visit(IField<AssetsFieldProperties> field, Args args)
{ {
return CleanIds(); return CleanIds(args);
} }
public IJsonValue Visit(IField<ReferencesFieldProperties> field) public IJsonValue Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
return CleanIds(); return CleanIds(args);
} }
public IJsonValue Visit(IField<BooleanFieldProperties> field) public IJsonValue Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<DateTimeFieldProperties> field) public IJsonValue Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<GeolocationFieldProperties> field) public IJsonValue Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<JsonFieldProperties> field) public IJsonValue Visit(IField<JsonFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<NumberFieldProperties> field) public IJsonValue Visit(IField<NumberFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<StringFieldProperties> field) public IJsonValue Visit(IField<StringFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<TagsFieldProperties> field) public IJsonValue Visit(IField<TagsFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IField<UIFieldProperties> field) public IJsonValue Visit(IField<UIFieldProperties> field, Args args)
{ {
return value; return args.Value;
} }
public IJsonValue Visit(IArrayField field) public IJsonValue Visit(IArrayField field, Args args)
{ {
return value; return args.Value;
} }
private IJsonValue CleanIds() private static IJsonValue CleanIds(Args args)
{ {
if (value is JsonArray array) if (args.Value is JsonArray array)
{ {
var result = array; var result = array;
for (var i = 0; i < result.Count; i++) for (var i = 0; i < result.Count; i++)
{ {
if (!IsValidReference(result[i])) if (!IsValidReference(result[i], args))
{ {
if (ReferenceEquals(result, array)) if (ReferenceEquals(result, array))
{ {
@ -107,12 +119,12 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
return result; return result;
} }
return value; return args.Value;
} }
private bool IsValidReference(IJsonValue item) private static bool IsValidReference(IJsonValue item, Args args)
{ {
return item is JsonString s && validIds.Contains(DomainId.Create(s.Value)); return item is JsonString s && args.ValidIds.Contains(DomainId.Create(s.Value));
} }
} }
} }

89
backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs

@ -13,34 +13,40 @@ using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Core.ExtractReferenceIds namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
{ {
internal sealed class ReferencesExtractor : IFieldVisitor<None> internal sealed class ReferencesExtractor : IFieldVisitor<None, ReferencesExtractor.Args>
{ {
private readonly HashSet<DomainId> result; private static readonly ReferencesExtractor Instance = new ReferencesExtractor();
private readonly int take;
private IJsonValue? value;
public HashSet<DomainId> Result public readonly struct Args
{ {
get { return result; } public readonly IJsonValue Value;
}
public ReferencesExtractor(HashSet<DomainId> result, int take) public readonly HashSet<DomainId> Result;
{
Guard.NotNull(result, nameof(result)); public readonly int ResultLimit;
this.result = result; public Args(IJsonValue value, HashSet<DomainId> result, int take)
{
Value = value;
Result = result;
ResultLimit = take;
}
}
this.take = take; private ReferencesExtractor()
{
} }
public void SetValue(IJsonValue? newValue) public static None Extract(IField field, IJsonValue? value, HashSet<DomainId> result, int take)
{ {
value = newValue; var args = new Args(value ?? JsonValue.Null, result, take);
return field.Accept(Instance, args);
} }
public None Visit(IArrayField field) public None Visit(IArrayField field, Args args)
{ {
if (value is JsonArray array) if (args.Value is JsonArray array)
{ {
foreach (var item in array.OfType<JsonObject>()) foreach (var item in array.OfType<JsonObject>())
{ {
@ -48,9 +54,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
{ {
if (item.TryGetValue(nestedField.Name, out var nestedValue)) if (item.TryGetValue(nestedField.Name, out var nestedValue))
{ {
SetValue(nestedValue); nestedField.Accept(this, new Args(nestedValue, args.Result, args.ResultLimit));
nestedField.Accept(this);
} }
} }
} }
@ -59,58 +63,81 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
return None.Value; return None.Value;
} }
public None Visit(IField<AssetsFieldProperties> field) public None Visit(IField<AssetsFieldProperties> field, Args args)
{ {
value.AddIds(result, take); AddIds(ref args);
return None.Value; return None.Value;
} }
public None Visit(IField<ReferencesFieldProperties> field) public None Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
value.AddIds(result, take); AddIds(ref args);
return None.Value; return None.Value;
} }
public None Visit(IField<BooleanFieldProperties> field) public None Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<DateTimeFieldProperties> field) public None Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<GeolocationFieldProperties> field) public None Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<JsonFieldProperties> field) public None Visit(IField<JsonFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<NumberFieldProperties> field) public None Visit(IField<NumberFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<StringFieldProperties> field) public None Visit(IField<StringFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<TagsFieldProperties> field) public None Visit(IField<TagsFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
public None Visit(IField<UIFieldProperties> field) public None Visit(IField<UIFieldProperties> field, Args args)
{ {
return None.Value; return None.Value;
} }
private static void AddIds(ref Args args)
{
var added = 0;
if (args.Value is JsonArray array)
{
foreach (var id in array)
{
if (id is JsonString s)
{
args.Result.Add(DomainId.Create(s.Value));
added++;
if (added >= args.ResultLimit)
{
break;
}
}
}
}
}
} }
} }

6
backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs

@ -21,8 +21,6 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
return ValueConverters.Noop; return ValueConverters.Noop;
} }
var cleaner = new ReferencesCleaner(validIds);
return (value, field, parent) => return (value, field, parent) =>
{ {
if (value.Type == JsonValueType.Null) if (value.Type == JsonValueType.Null)
@ -30,9 +28,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
return value; return value;
} }
cleaner.SetValue(value); return ReferencesCleaner.Cleanup(field, value, validIds);
return field.Accept(cleaner);
}; };
} }
} }

4
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmSchemaExtensions.cs

@ -33,8 +33,6 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
var (edmType, _) = typeFactory("Data"); var (edmType, _) = typeFactory("Data");
var visitor = new EdmTypeVisitor(typeFactory);
foreach (var field in schema.FieldsByName.Values) foreach (var field in schema.FieldsByName.Values)
{ {
if (!field.IsForApi(withHidden)) if (!field.IsForApi(withHidden))
@ -42,7 +40,7 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
continue; continue;
} }
var fieldEdmType = field.Accept(visitor); var fieldEdmType = EdmTypeVisitor.BuildType(field, typeFactory);
if (fieldEdmType == null) if (fieldEdmType == null)
{ {

54
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs

@ -11,30 +11,46 @@ using Squidex.Text;
namespace Squidex.Domain.Apps.Core.GenerateEdmSchema namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
{ {
public sealed class EdmTypeVisitor : IFieldVisitor<IEdmTypeReference?> internal sealed class EdmTypeVisitor : IFieldVisitor<IEdmTypeReference?, EdmTypeVisitor.Args>
{ {
private static readonly EdmComplexType JsonType = new EdmComplexType("Squidex", "Json", null, false, true); private static readonly EdmComplexType JsonType = new EdmComplexType("Squidex", "Json", null, false, true);
private readonly EdmTypeFactory typeFactory; private static readonly EdmTypeVisitor Instance = new EdmTypeVisitor();
internal EdmTypeVisitor(EdmTypeFactory typeFactory) public readonly struct Args
{ {
this.typeFactory = typeFactory; public readonly EdmTypeFactory Factory;
public Args(EdmTypeFactory factory)
{
Factory = factory;
}
}
private EdmTypeVisitor()
{
}
public static IEdmTypeReference? BuildType(IField field, EdmTypeFactory factory)
{
var args = new Args(factory);
return field.Accept(Instance, args);
} }
public IEdmTypeReference? CreateEdmType(IField field) public IEdmTypeReference? CreateEdmType(IField field, Args args)
{ {
return field.Accept(this); return field.Accept(this, args);
} }
public IEdmTypeReference? Visit(IArrayField field) public IEdmTypeReference? Visit(IArrayField field, Args args)
{ {
var (fieldEdmType, created) = typeFactory($"Data.{field.Name.ToPascalCase()}.Item"); var (fieldEdmType, created) = args.Factory($"Data.{field.Name.ToPascalCase()}.Item");
if (created) if (created)
{ {
foreach (var nestedField in field.Fields) foreach (var nestedField in field.Fields)
{ {
var nestedEdmType = nestedField.Accept(this); var nestedEdmType = nestedField.Accept(this, args);
if (nestedEdmType != null) if (nestedEdmType != null)
{ {
@ -46,52 +62,52 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
return new EdmComplexTypeReference(fieldEdmType, false); return new EdmComplexTypeReference(fieldEdmType, false);
} }
public IEdmTypeReference? Visit(IField<AssetsFieldProperties> field) public IEdmTypeReference? Visit(IField<AssetsFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.String, field); return CreatePrimitive(EdmPrimitiveTypeKind.String, field);
} }
public IEdmTypeReference? Visit(IField<BooleanFieldProperties> field) public IEdmTypeReference? Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.Boolean, field); return CreatePrimitive(EdmPrimitiveTypeKind.Boolean, field);
} }
public IEdmTypeReference? Visit(IField<DateTimeFieldProperties> field) public IEdmTypeReference? Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.DateTimeOffset, field); return CreatePrimitive(EdmPrimitiveTypeKind.DateTimeOffset, field);
} }
public IEdmTypeReference? Visit(IField<GeolocationFieldProperties> field) public IEdmTypeReference? Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
return null; return null;
} }
public IEdmTypeReference? Visit(IField<JsonFieldProperties> field) public IEdmTypeReference? Visit(IField<JsonFieldProperties> field, Args args)
{ {
return new EdmComplexTypeReference(JsonType, !field.RawProperties.IsRequired); return new EdmComplexTypeReference(JsonType, !field.RawProperties.IsRequired);
} }
public IEdmTypeReference? Visit(IField<NumberFieldProperties> field) public IEdmTypeReference? Visit(IField<NumberFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.Double, field); return CreatePrimitive(EdmPrimitiveTypeKind.Double, field);
} }
public IEdmTypeReference? Visit(IField<ReferencesFieldProperties> field) public IEdmTypeReference? Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.String, field); return CreatePrimitive(EdmPrimitiveTypeKind.String, field);
} }
public IEdmTypeReference? Visit(IField<StringFieldProperties> field) public IEdmTypeReference? Visit(IField<StringFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.String, field); return CreatePrimitive(EdmPrimitiveTypeKind.String, field);
} }
public IEdmTypeReference? Visit(IField<TagsFieldProperties> field) public IEdmTypeReference? Visit(IField<TagsFieldProperties> field, Args args)
{ {
return CreatePrimitive(EdmPrimitiveTypeKind.String, field); return CreatePrimitive(EdmPrimitiveTypeKind.String, field);
} }
public IEdmTypeReference? Visit(IField<UIFieldProperties> field) public IEdmTypeReference? Visit(IField<UIFieldProperties> field, Args args)
{ {
return null; return null;
} }

3
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs

@ -21,7 +21,6 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
var schemaName = schema.Name.ToPascalCase(); var schemaName = schema.Name.ToPascalCase();
var jsonTypeVisitor = new JsonTypeVisitor(schemaResolver, withHidden);
var jsonSchema = SchemaBuilder.Object(); var jsonSchema = SchemaBuilder.Object();
foreach (var field in schema.Fields.ForApi(withHidden)) foreach (var field in schema.Fields.ForApi(withHidden))
@ -31,7 +30,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
foreach (var partitionKey in partitioning.AllKeys) foreach (var partitionKey in partitioning.AllKeys)
{ {
var partitionItemProperty = field.Accept(jsonTypeVisitor); var partitionItemProperty = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden);
if (partitionItemProperty != null) if (partitionItemProperty != null)
{ {

63
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs

@ -13,25 +13,42 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{ {
public delegate JsonSchema SchemaResolver(string name, JsonSchema schema); public delegate JsonSchema SchemaResolver(string name, JsonSchema schema);
public sealed class JsonTypeVisitor : IFieldVisitor<JsonSchemaProperty?> internal sealed class JsonTypeVisitor : IFieldVisitor<JsonSchemaProperty?, JsonTypeVisitor.Args>
{ {
private readonly SchemaResolver schemaResolver; private static readonly JsonTypeVisitor Instance = new JsonTypeVisitor();
private readonly bool withHiddenFields;
public JsonTypeVisitor(SchemaResolver schemaResolver, bool withHiddenFields) public readonly struct Args
{ {
this.schemaResolver = schemaResolver; public readonly SchemaResolver SchemaResolver;
this.withHiddenFields = withHiddenFields; public readonly bool WithHiddenFields;
public Args(SchemaResolver schemaResolver, bool withHiddenFields)
{
SchemaResolver = schemaResolver;
WithHiddenFields = withHiddenFields;
}
}
private JsonTypeVisitor()
{
}
public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver schemaResolver, bool withHiddenFields)
{
var args = new Args(schemaResolver, withHiddenFields);
return field.Accept(Instance, args);
} }
public JsonSchemaProperty? Visit(IArrayField field) public JsonSchemaProperty? Visit(IArrayField field, Args args)
{ {
var itemSchema = SchemaBuilder.Object(); var itemSchema = SchemaBuilder.Object();
foreach (var nestedField in field.Fields.ForApi(withHiddenFields)) foreach (var nestedField in field.Fields.ForApi(args.WithHiddenFields))
{ {
var nestedProperty = nestedField.Accept(this); var nestedProperty = nestedField.Accept(this, args);
if (nestedProperty != null) if (nestedProperty != null)
{ {
@ -45,24 +62,24 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return SchemaBuilder.ArrayProperty(itemSchema); return SchemaBuilder.ArrayProperty(itemSchema);
} }
public JsonSchemaProperty? Visit(IField<AssetsFieldProperties> field) public JsonSchemaProperty? Visit(IField<AssetsFieldProperties> field, Args args)
{ {
var itemSchema = schemaResolver("AssetItem", SchemaBuilder.String()); var itemSchema = args.SchemaResolver("AssetItem", SchemaBuilder.String());
return SchemaBuilder.ArrayProperty(itemSchema); return SchemaBuilder.ArrayProperty(itemSchema);
} }
public JsonSchemaProperty? Visit(IField<BooleanFieldProperties> field) public JsonSchemaProperty? Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return SchemaBuilder.BooleanProperty(); return SchemaBuilder.BooleanProperty();
} }
public JsonSchemaProperty? Visit(IField<DateTimeFieldProperties> field) public JsonSchemaProperty? Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return SchemaBuilder.DateTimeProperty(); return SchemaBuilder.DateTimeProperty();
} }
public JsonSchemaProperty? Visit(IField<GeolocationFieldProperties> field) public JsonSchemaProperty? Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
var geolocationSchema = SchemaBuilder.Object(); var geolocationSchema = SchemaBuilder.Object();
@ -80,17 +97,17 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
Minimum = -180 Minimum = -180
}.SetRequired(true)); }.SetRequired(true));
var reference = schemaResolver("GeolocationDto", geolocationSchema); var reference = args.SchemaResolver("GeolocationDto", geolocationSchema);
return SchemaBuilder.ObjectProperty(reference); return SchemaBuilder.ObjectProperty(reference);
} }
public JsonSchemaProperty? Visit(IField<JsonFieldProperties> field) public JsonSchemaProperty? Visit(IField<JsonFieldProperties> field, Args args)
{ {
return SchemaBuilder.JsonProperty(); return SchemaBuilder.JsonProperty();
} }
public JsonSchemaProperty? Visit(IField<NumberFieldProperties> field) public JsonSchemaProperty? Visit(IField<NumberFieldProperties> field, Args args)
{ {
var property = SchemaBuilder.NumberProperty(); var property = SchemaBuilder.NumberProperty();
@ -107,14 +124,14 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return property; return property;
} }
public JsonSchemaProperty? Visit(IField<ReferencesFieldProperties> field) public JsonSchemaProperty? Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
var itemSchema = schemaResolver("ReferenceItem", SchemaBuilder.String()); var itemSchema = args.SchemaResolver("ReferenceItem", SchemaBuilder.String());
return SchemaBuilder.ArrayProperty(itemSchema); return SchemaBuilder.ArrayProperty(itemSchema);
} }
public JsonSchemaProperty? Visit(IField<StringFieldProperties> field) public JsonSchemaProperty? Visit(IField<StringFieldProperties> field, Args args)
{ {
var property = SchemaBuilder.StringProperty(); var property = SchemaBuilder.StringProperty();
@ -135,14 +152,14 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return property; return property;
} }
public JsonSchemaProperty? Visit(IField<TagsFieldProperties> field) public JsonSchemaProperty? Visit(IField<TagsFieldProperties> field, Args args)
{ {
var itemSchema = schemaResolver("ReferenceItem", SchemaBuilder.String()); var itemSchema = args.SchemaResolver("ReferenceItem", SchemaBuilder.String());
return SchemaBuilder.ArrayProperty(itemSchema); return SchemaBuilder.ArrayProperty(itemSchema);
} }
public JsonSchemaProperty? Visit(IField<UIFieldProperties> field) public JsonSchemaProperty? Visit(IField<UIFieldProperties> field, Args args)
{ {
return null; return null;
} }

73
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs

@ -10,37 +10,44 @@ using System.Collections.Generic;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.ValidateContent.Validators; using Squidex.Domain.Apps.Core.ValidateContent.Validators;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Core.ValidateContent namespace Squidex.Domain.Apps.Core.ValidateContent
{ {
internal sealed class DefaultFieldValueValidatorsFactory : IFieldVisitor<IEnumerable<IValidator>> internal sealed class DefaultFieldValueValidatorsFactory : IFieldVisitor<IEnumerable<IValidator>, DefaultFieldValueValidatorsFactory.Args>
{ {
private readonly ValidatorContext context; private static readonly DefaultFieldValueValidatorsFactory Instance = new DefaultFieldValueValidatorsFactory();
private readonly ValidatorFactory createFieldValidator;
private DefaultFieldValueValidatorsFactory(ValidatorContext context, ValidatorFactory createFieldValidator) public struct Args
{ {
this.context = context; public readonly ValidatorContext Context;
this.createFieldValidator = createFieldValidator;
public readonly ValidatorFactory Factory;
public Args(ValidatorContext context, ValidatorFactory factory)
{
Context = context;
Factory = factory;
}
} }
public static IEnumerable<IValidator> CreateValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) private DefaultFieldValueValidatorsFactory()
{ {
Guard.NotNull(context, nameof(context)); }
Guard.NotNull(field, nameof(field));
var visitor = new DefaultFieldValueValidatorsFactory(context, createFieldValidator); public static IEnumerable<IValidator> CreateValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator)
{
var args = new Args(context, createFieldValidator);
return field.Accept(visitor); return field.Accept(Instance, args);
} }
public IEnumerable<IValidator> Visit(IArrayField field) public IEnumerable<IValidator> Visit(IArrayField field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue) if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
{ {
@ -51,22 +58,22 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
foreach (var nestedField in field.Fields) foreach (var nestedField in field.Fields)
{ {
nestedValidators[nestedField.Name] = (false, createFieldValidator(nestedField)); nestedValidators[nestedField.Name] = (false, args.Factory(nestedField));
} }
yield return new CollectionItemValidator(new ObjectValidator<IJsonValue>(nestedValidators, false, "field")); yield return new CollectionItemValidator(new ObjectValidator<IJsonValue>(nestedValidators, false, "field"));
} }
public IEnumerable<IValidator> Visit(IField<AssetsFieldProperties> field) public IEnumerable<IValidator> Visit(IField<AssetsFieldProperties> field, Args args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<BooleanFieldProperties> field) public IEnumerable<IValidator> Visit(IField<BooleanFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -74,11 +81,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<DateTimeFieldProperties> field) public IEnumerable<IValidator> Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -91,11 +98,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<GeolocationFieldProperties> field) public IEnumerable<IValidator> Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -103,11 +110,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<JsonFieldProperties> field) public IEnumerable<IValidator> Visit(IField<JsonFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -115,11 +122,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<NumberFieldProperties> field) public IEnumerable<IValidator> Visit(IField<NumberFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -137,16 +144,16 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<ReferencesFieldProperties> field) public IEnumerable<IValidator> Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<StringFieldProperties> field) public IEnumerable<IValidator> Visit(IField<StringFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired) if (isRequired)
{ {
@ -193,11 +200,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
public IEnumerable<IValidator> Visit(IField<TagsFieldProperties> field) public IEnumerable<IValidator> Visit(IField<TagsFieldProperties> field, Args args)
{ {
var properties = field.Properties; var properties = field.Properties;
var isRequired = IsRequired(properties); var isRequired = IsRequired(properties, args.Context);
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue) if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
{ {
@ -212,7 +219,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
yield return new CollectionItemValidator(new RequiredStringValidator(true)); yield return new CollectionItemValidator(new RequiredStringValidator(true));
} }
public IEnumerable<IValidator> Visit(IField<UIFieldProperties> field) public IEnumerable<IValidator> Visit(IField<UIFieldProperties> field, Args args)
{ {
if (field is INestedField) if (field is INestedField)
{ {
@ -220,7 +227,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
} }
} }
private bool IsRequired(FieldProperties properties) private static bool IsRequired(FieldProperties properties, ValidatorContext context)
{ {
var isRequired = properties.IsRequired; var isRequired = properties.IsRequired;

28
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/FieldBagValidatorsFactory.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.ValidateContent namespace Squidex.Domain.Apps.Core.ValidateContent
{ {
public sealed class FieldBagValidatorsFactory : IFieldVisitor<IEnumerable<IValidator>> internal sealed class FieldBagValidatorsFactory : IFieldVisitor<IEnumerable<IValidator>, None>
{ {
private static readonly FieldBagValidatorsFactory Instance = new FieldBagValidatorsFactory(); private static readonly FieldBagValidatorsFactory Instance = new FieldBagValidatorsFactory();
@ -22,62 +22,60 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
public static IEnumerable<IValidator> CreateValidators(IField field) public static IEnumerable<IValidator> CreateValidators(IField field)
{ {
Guard.NotNull(field, nameof(field)); return field.Accept(Instance, None.Value);
return field.Accept(Instance);
} }
public IEnumerable<IValidator> Visit(IArrayField field) public IEnumerable<IValidator> Visit(IArrayField field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<AssetsFieldProperties> field) public IEnumerable<IValidator> Visit(IField<AssetsFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<BooleanFieldProperties> field) public IEnumerable<IValidator> Visit(IField<BooleanFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<DateTimeFieldProperties> field) public IEnumerable<IValidator> Visit(IField<DateTimeFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<GeolocationFieldProperties> field) public IEnumerable<IValidator> Visit(IField<GeolocationFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<JsonFieldProperties> field) public IEnumerable<IValidator> Visit(IField<JsonFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<NumberFieldProperties> field) public IEnumerable<IValidator> Visit(IField<NumberFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<ReferencesFieldProperties> field) public IEnumerable<IValidator> Visit(IField<ReferencesFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<StringFieldProperties> field) public IEnumerable<IValidator> Visit(IField<StringFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<TagsFieldProperties> field) public IEnumerable<IValidator> Visit(IField<TagsFieldProperties> field, None args)
{ {
yield break; yield break;
} }
public IEnumerable<IValidator> Visit(IField<UIFieldProperties> field) public IEnumerable<IValidator> Visit(IField<UIFieldProperties> field, None args)
{ {
yield return NoValueValidator.Instance; yield return NoValueValidator.Instance;
} }

78
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs

@ -16,43 +16,55 @@ using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Core.ValidateContent namespace Squidex.Domain.Apps.Core.ValidateContent
{ {
public sealed class JsonValueConverter : IFieldVisitor<(object? Result, JsonError? Error)> public sealed class JsonValueConverter : IFieldVisitor<(object? Result, JsonError? Error), JsonValueConverter.Args>
{ {
private readonly IJsonValue value; private static readonly JsonValueConverter Instance = new JsonValueConverter();
private JsonValueConverter(IJsonValue value) public readonly struct Args
{ {
this.value = value; public readonly IJsonValue Value;
public Args(IJsonValue value)
{
Value = value;
}
} }
public static (object? Result, JsonError? Error) ConvertValue(IField field, IJsonValue json) private JsonValueConverter()
{ {
return field.Accept(new JsonValueConverter(json));
} }
public (object? Result, JsonError? Error) Visit(IArrayField field) public static (object? Result, JsonError? Error) ConvertValue(IField field, IJsonValue value)
{
Guard.NotNull(field, nameof(field));
Guard.NotNull(value, nameof(value));
return field.Accept(Instance, new Args(value));
}
public (object? Result, JsonError? Error) Visit(IArrayField field, Args args)
{ {
return ConvertToObjectList(); return ConvertToObjectList(args.Value);
} }
public (object? Result, JsonError? Error) Visit(IField<AssetsFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<AssetsFieldProperties> field, Args args)
{ {
return ConvertToIdList(); return ConvertToIdList(args.Value);
} }
public (object? Result, JsonError? Error) Visit(IField<ReferencesFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
return ConvertToIdList(); return ConvertToIdList(args.Value);
} }
public (object? Result, JsonError? Error) Visit(IField<TagsFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<TagsFieldProperties> field, Args args)
{ {
return ConvertToStringList(); return ConvertToStringList(args.Value);
} }
public (object? Result, JsonError? Error) Visit(IField<BooleanFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<BooleanFieldProperties> field, Args args)
{ {
if (value is JsonBoolean b) if (args.Value is JsonBoolean b)
{ {
return (b.Value, null); return (b.Value, null);
} }
@ -60,9 +72,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidBoolean"))); return (null, new JsonError(T.Get("contents.invalidBoolean")));
} }
public (object? Result, JsonError? Error) Visit(IField<NumberFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<NumberFieldProperties> field, Args args)
{ {
if (value is JsonNumber n) if (args.Value is JsonNumber n)
{ {
return (n.Value, null); return (n.Value, null);
} }
@ -70,9 +82,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidNumber"))); return (null, new JsonError(T.Get("contents.invalidNumber")));
} }
public (object? Result, JsonError? Error) Visit(IField<StringFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<StringFieldProperties> field, Args args)
{ {
if (value is JsonString s) if (args.Value is JsonString s)
{ {
return (s.Value, null); return (s.Value, null);
} }
@ -80,16 +92,16 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidString"))); return (null, new JsonError(T.Get("contents.invalidString")));
} }
public (object? Result, JsonError? Error) Visit(IField<UIFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<UIFieldProperties> field, Args args)
{ {
return (value, null); return (args.Value, null);
} }
public (object? Result, JsonError? Error) Visit(IField<DateTimeFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
if (value.Type == JsonValueType.String) if (args.Value.Type == JsonValueType.String)
{ {
var parseResult = InstantPattern.General.Parse(value.ToString()); var parseResult = InstantPattern.General.Parse(args.Value.ToString());
if (!parseResult.Success) if (!parseResult.Success)
{ {
@ -102,9 +114,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidString"))); return (null, new JsonError(T.Get("contents.invalidString")));
} }
public (object? Result, JsonError? Error) Visit(IField<GeolocationFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
if (value is JsonObject geolocation) if (args.Value is JsonObject geolocation)
{ {
foreach (var propertyName in geolocation.Keys) foreach (var propertyName in geolocation.Keys)
{ {
@ -143,18 +155,18 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidGeolocation"))); return (null, new JsonError(T.Get("contents.invalidGeolocation")));
} }
return (value, null); return (args.Value, null);
} }
return (null, new JsonError(T.Get("contents.invalidGeolocation"))); return (null, new JsonError(T.Get("contents.invalidGeolocation")));
} }
public (object? Result, JsonError? Error) Visit(IField<JsonFieldProperties> field) public (object? Result, JsonError? Error) Visit(IField<JsonFieldProperties> field, Args args)
{ {
return (value, null); return (args.Value, null);
} }
private (object? Result, JsonError? Error) ConvertToIdList() private static (object? Result, JsonError? Error) ConvertToIdList(IJsonValue value)
{ {
if (value is JsonArray array) if (value is JsonArray array)
{ {
@ -178,7 +190,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError("Invalid json type, expected array of strings.")); return (null, new JsonError("Invalid json type, expected array of strings."));
} }
private (object? Result, JsonError? Error) ConvertToStringList() private static (object? Result, JsonError? Error) ConvertToStringList(IJsonValue value)
{ {
if (value is JsonArray array) if (value is JsonArray array)
{ {
@ -206,7 +218,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (null, new JsonError(T.Get("contents.invalidArrayOfStrings"))); return (null, new JsonError(T.Get("contents.invalidArrayOfStrings")));
} }
private (object? Result, JsonError? Error) ConvertToObjectList() private static (object? Result, JsonError? Error) ConvertToObjectList(IJsonValue value)
{ {
if (value is JsonArray array) if (value is JsonArray array)
{ {

1
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ObjectPath.cs

@ -17,6 +17,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
var sb = new StringBuilder(); var sb = new StringBuilder();
var index = 0; var index = 0;
foreach (var property in path) foreach (var property in path)
{ {
if (index == 0) if (index == 0)

2
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs

@ -138,7 +138,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
var value = GetValue(content.ReferenceData, field) ?? GetValue(content.Data, field); var value = GetValue(content.ReferenceData, field) ?? GetValue(content.Data, field);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
if (!string.IsNullOrWhiteSpace(formatted)) if (!string.IsNullOrWhiteSpace(formatted))
{ {

7
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs

@ -30,6 +30,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
private readonly IObjectGraphType assetType; private readonly IObjectGraphType assetType;
private readonly IGraphType assetListType; private readonly IGraphType assetListType;
private readonly GraphQLSchema graphQLSchema; private readonly GraphQLSchema graphQLSchema;
private readonly GraphQLTypeVisitor graphQLTypeVisitor;
private readonly ISemanticLog log; private readonly ISemanticLog log;
public bool CanGenerateAssetSourceUrl { get; } public bool CanGenerateAssetSourceUrl { get; }
@ -54,6 +55,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
assetType = new AssetGraphType(this); assetType = new AssetGraphType(this);
assetListType = new ListGraphType(new NonNullGraphType(assetType)); assetListType = new ListGraphType(new NonNullGraphType(assetType));
graphQLTypeVisitor = new GraphQLTypeVisitor(contentTypes, this, assetListType);
var allSchemas = schemas.Where(x => x.SchemaDef.IsPublished).ToList(); var allSchemas = schemas.Where(x => x.SchemaDef.IsPublished).ToList();
BuildSchemas(allSchemas); BuildSchemas(allSchemas);
@ -120,12 +123,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
public IGraphType? GetInputGraphType(ISchemaEntity schema, IField field, string fieldName) public IGraphType? GetInputGraphType(ISchemaEntity schema, IField field, string fieldName)
{ {
return field.Accept(new InputFieldVisitor(schema, this, fieldName)); return InputFieldVisitor.Build(field, this, schema, fieldName);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) GetGraphType(ISchemaEntity schema, IField field, string fieldName) public (IGraphType?, ValueResolver?, QueryArguments?) GetGraphType(ISchemaEntity schema, IField field, string fieldName)
{ {
return field.Accept(new QueryGraphTypeVisitor(schema, contentTypes, this, assetListType, fieldName)); return field.Accept(graphQLTypeVisitor, new GraphQLTypeVisitor.Args(schema, fieldName));
} }
public IGraphType GetAssetType() public IGraphType GetAssetType()

61
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs → backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/GraphQLTypeVisitor.cs

@ -18,81 +18,92 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
{ {
public delegate object ValueResolver(IJsonValue value, IResolveFieldContext context); public delegate object ValueResolver(IJsonValue value, IResolveFieldContext context);
public sealed class QueryGraphTypeVisitor : IFieldVisitor<(IGraphType?, ValueResolver?, QueryArguments?)> internal sealed class GraphQLTypeVisitor : IFieldVisitor<(IGraphType?, ValueResolver?, QueryArguments?), GraphQLTypeVisitor.Args>
{ {
private static readonly ValueResolver NoopResolver = (value, c) => value; private static readonly ValueResolver NoopResolver = (value, c) => value;
private readonly Dictionary<DomainId, ContentGraphType> schemaTypes; private readonly Dictionary<DomainId, ContentGraphType> schemaTypes;
private readonly ISchemaEntity schema;
private readonly IGraphModel model;
private readonly IGraphType assetListType; private readonly IGraphType assetListType;
private readonly string fieldName; private readonly IGraphModel model;
public readonly struct Args
{
public readonly ISchemaEntity Schema;
public readonly string SchemaField;
public QueryGraphTypeVisitor(ISchemaEntity schema, public Args(ISchemaEntity schema, string fieldName)
{
Schema = schema;
SchemaField = fieldName;
}
}
public GraphQLTypeVisitor(
Dictionary<DomainId, ContentGraphType> schemaTypes, Dictionary<DomainId, ContentGraphType> schemaTypes,
IGraphModel model, IGraphModel model,
IGraphType assetListType, IGraphType assetListType)
string fieldName)
{ {
this.model = model;
this.assetListType = assetListType; this.assetListType = assetListType;
this.schema = schema; this.model = model;
this.schemaTypes = schemaTypes; this.schemaTypes = schemaTypes;
this.fieldName = fieldName;
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IArrayField field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IArrayField field, Args args)
{ {
var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedGraphType(model, schema, field, fieldName))); var schemaFieldType =
new ListGraphType(
new NonNullGraphType(
new NestedGraphType(model, args.Schema, field, args.SchemaField)));
return (schemaFieldType, NoopResolver, null); return (schemaFieldType, NoopResolver, null);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<AssetsFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<AssetsFieldProperties> field, Args args)
{ {
return ResolveAssets(); return ResolveAssets();
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<BooleanFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopBoolean); return ResolveDefault(AllTypes.NoopBoolean);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<DateTimeFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopDate); return ResolveDefault(AllTypes.NoopDate);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<GeolocationFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopGeolocation); return ResolveDefault(AllTypes.NoopGeolocation);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<NumberFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<NumberFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopFloat); return ResolveDefault(AllTypes.NoopFloat);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<ReferencesFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
return ResolveReferences(field); return ResolveReferences(field, args);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<StringFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<StringFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopString); return ResolveDefault(AllTypes.NoopString);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<TagsFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<TagsFieldProperties> field, Args args)
{ {
return ResolveDefault(AllTypes.NoopTags); return ResolveDefault(AllTypes.NoopTags);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<UIFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<UIFieldProperties> field, Args args)
{ {
return (null, null, null); return (null, null, null);
} }
public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<JsonFieldProperties> field) public (IGraphType?, ValueResolver?, QueryArguments?) Visit(IField<JsonFieldProperties> field, Args args)
{ {
return (AllTypes.NoopJson, ContentActions.Json.Resolver, ContentActions.Json.Arguments); return (AllTypes.NoopJson, ContentActions.Json.Resolver, ContentActions.Json.Arguments);
} }
@ -114,13 +125,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
return (assetListType, resolver, null); return (assetListType, resolver, null);
} }
private (IGraphType?, ValueResolver?, QueryArguments?) ResolveReferences(IField<ReferencesFieldProperties> field) private (IGraphType?, ValueResolver?, QueryArguments?) ResolveReferences(IField<ReferencesFieldProperties> field, Args args)
{ {
IGraphType contentType = schemaTypes.GetOrDefault(field.Properties.SingleId()); IGraphType contentType = schemaTypes.GetOrDefault(field.Properties.SingleId());
if (contentType == null) if (contentType == null)
{ {
var union = new ContentUnionGraphType(fieldName, schemaTypes, field.Properties.SchemaIds); var union = new ContentUnionGraphType(args.SchemaField, schemaTypes, field.Properties.SchemaIds);
if (!union.PossibleTypes.Any()) if (!union.PossibleTypes.Any())
{ {

61
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/InputFieldVisitor.cs

@ -12,72 +12,93 @@ using Squidex.Domain.Apps.Entities.Schemas;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
{ {
public sealed class InputFieldVisitor : IFieldVisitor<IGraphType?> public sealed class InputFieldVisitor : IFieldVisitor<IGraphType?, InputFieldVisitor.Args>
{ {
private readonly ISchemaEntity schema; private static readonly InputFieldVisitor Instance = new InputFieldVisitor();
private readonly IGraphModel model;
private readonly string fieldName;
public InputFieldVisitor(ISchemaEntity schema, IGraphModel model, string fieldName) public readonly struct Args
{ {
this.model = model; public readonly IGraphModel Model;
this.schema = schema;
this.fieldName = fieldName; public readonly ISchemaEntity Schema;
public readonly string SchemaField;
public Args(IGraphModel model, ISchemaEntity schema, string fieldName)
{
Model = model;
Schema = schema;
SchemaField = fieldName;
}
}
private InputFieldVisitor()
{
}
public static IGraphType? Build(IField field, IGraphModel model, ISchemaEntity schema, string fieldName)
{
var args = new Args(model, schema, fieldName);
return field.Accept(Instance, args);
} }
public IGraphType? Visit(IArrayField field) public IGraphType? Visit(IArrayField field, Args args)
{ {
var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedInputGraphType(model, schema, field, fieldName))); var schemaFieldType =
new ListGraphType(
new NonNullGraphType(
new NestedInputGraphType(args.Model, args.Schema, field, args.SchemaField)));
return schemaFieldType; return schemaFieldType;
} }
public IGraphType? Visit(IField<AssetsFieldProperties> field) public IGraphType? Visit(IField<AssetsFieldProperties> field, Args args)
{ {
return AllTypes.References; return AllTypes.References;
} }
public IGraphType? Visit(IField<BooleanFieldProperties> field) public IGraphType? Visit(IField<BooleanFieldProperties> field, Args args)
{ {
return AllTypes.Boolean; return AllTypes.Boolean;
} }
public IGraphType? Visit(IField<DateTimeFieldProperties> field) public IGraphType? Visit(IField<DateTimeFieldProperties> field, Args args)
{ {
return AllTypes.Date; return AllTypes.Date;
} }
public IGraphType? Visit(IField<GeolocationFieldProperties> field) public IGraphType? Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
return GeolocationInputGraphType.Nullable; return GeolocationInputGraphType.Nullable;
} }
public IGraphType? Visit(IField<JsonFieldProperties> field) public IGraphType? Visit(IField<JsonFieldProperties> field, Args args)
{ {
return AllTypes.Json; return AllTypes.Json;
} }
public IGraphType? Visit(IField<NumberFieldProperties> field) public IGraphType? Visit(IField<NumberFieldProperties> field, Args args)
{ {
return AllTypes.Float; return AllTypes.Float;
} }
public IGraphType? Visit(IField<ReferencesFieldProperties> field) public IGraphType? Visit(IField<ReferencesFieldProperties> field, Args args)
{ {
return AllTypes.Json; return AllTypes.Json;
} }
public IGraphType? Visit(IField<StringFieldProperties> field) public IGraphType? Visit(IField<StringFieldProperties> field, Args args)
{ {
return AllTypes.String; return AllTypes.String;
} }
public IGraphType? Visit(IField<TagsFieldProperties> field) public IGraphType? Visit(IField<TagsFieldProperties> field, Args args)
{ {
return AllTypes.Tags; return AllTypes.Tags;
} }
public IGraphType? Visit(IField<UIFieldProperties> field) public IGraphType? Visit(IField<UIFieldProperties> field, Args args)
{ {
return null; return null;
} }

27
backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs

@ -9,12 +9,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations; using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation; using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
{ {
public sealed class FieldPropertiesValidator : IFieldPropertiesVisitor<IEnumerable<ValidationError>> public sealed class FieldPropertiesValidator : IFieldPropertiesVisitor<IEnumerable<ValidationError>, None>
{ {
private static readonly FieldPropertiesValidator Instance = new FieldPropertiesValidator(); private static readonly FieldPropertiesValidator Instance = new FieldPropertiesValidator();
@ -26,14 +27,14 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
{ {
if (properties != null) if (properties != null)
{ {
foreach (var error in properties.Accept(Instance)) foreach (var error in properties.Accept(Instance, None.Value))
{ {
yield return error; yield return error;
} }
} }
} }
public IEnumerable<ValidationError> Visit(ArrayFieldProperties properties) public IEnumerable<ValidationError> Visit(ArrayFieldProperties properties, None args)
{ {
if (IsMaxGreaterThanMin(properties.MaxItems, properties.MinItems)) if (IsMaxGreaterThanMin(properties.MaxItems, properties.MinItems))
{ {
@ -43,7 +44,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(AssetsFieldProperties properties) public IEnumerable<ValidationError> Visit(AssetsFieldProperties properties, None args)
{ {
if (IsMaxGreaterThanMin(properties.MaxItems, properties.MinItems)) if (IsMaxGreaterThanMin(properties.MaxItems, properties.MinItems))
{ {
@ -81,7 +82,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(BooleanFieldProperties properties) public IEnumerable<ValidationError> Visit(BooleanFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -90,7 +91,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(DateTimeFieldProperties properties) public IEnumerable<ValidationError> Visit(DateTimeFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -122,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(GeolocationFieldProperties properties) public IEnumerable<ValidationError> Visit(GeolocationFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -131,12 +132,12 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(JsonFieldProperties properties) public IEnumerable<ValidationError> Visit(JsonFieldProperties properties, None args)
{ {
yield break; yield break;
} }
public IEnumerable<ValidationError> Visit(NumberFieldProperties properties) public IEnumerable<ValidationError> Visit(NumberFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -165,7 +166,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(ReferencesFieldProperties properties) public IEnumerable<ValidationError> Visit(ReferencesFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -188,7 +189,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(StringFieldProperties properties) public IEnumerable<ValidationError> Visit(StringFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -243,7 +244,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(TagsFieldProperties properties) public IEnumerable<ValidationError> Visit(TagsFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {
@ -265,7 +266,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards
} }
} }
public IEnumerable<ValidationError> Visit(UIFieldProperties properties) public IEnumerable<ValidationError> Visit(UIFieldProperties properties, None args)
{ {
if (!properties.Editor.IsEnumValue()) if (!properties.Editor.IsEnumValue())
{ {

27
backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs

@ -7,11 +7,12 @@
using Squidex.Areas.Api.Controllers.Schemas.Models.Fields; using Squidex.Areas.Api.Controllers.Schemas.Models.Fields;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Converters namespace Squidex.Areas.Api.Controllers.Schemas.Models.Converters
{ {
public class FieldPropertiesDtoFactory : IFieldPropertiesVisitor<FieldPropertiesDto> internal sealed class FieldPropertiesDtoFactory : IFieldPropertiesVisitor<FieldPropertiesDto, None>
{ {
private static readonly FieldPropertiesDtoFactory Instance = new FieldPropertiesDtoFactory(); private static readonly FieldPropertiesDtoFactory Instance = new FieldPropertiesDtoFactory();
@ -21,60 +22,60 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Converters
public static FieldPropertiesDto Create(FieldProperties properties) public static FieldPropertiesDto Create(FieldProperties properties)
{ {
return properties.Accept(Instance); return properties.Accept(Instance, None.Value);
} }
public FieldPropertiesDto Visit(ArrayFieldProperties properties) public FieldPropertiesDto Visit(ArrayFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new ArrayFieldPropertiesDto()); return SimpleMapper.Map(properties, new ArrayFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(AssetsFieldProperties properties) public FieldPropertiesDto Visit(AssetsFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new AssetsFieldPropertiesDto()); return SimpleMapper.Map(properties, new AssetsFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(BooleanFieldProperties properties) public FieldPropertiesDto Visit(BooleanFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new BooleanFieldPropertiesDto()); return SimpleMapper.Map(properties, new BooleanFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(DateTimeFieldProperties properties) public FieldPropertiesDto Visit(DateTimeFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new DateTimeFieldPropertiesDto()); return SimpleMapper.Map(properties, new DateTimeFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(GeolocationFieldProperties properties) public FieldPropertiesDto Visit(GeolocationFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new GeolocationFieldPropertiesDto()); return SimpleMapper.Map(properties, new GeolocationFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(JsonFieldProperties properties) public FieldPropertiesDto Visit(JsonFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new JsonFieldPropertiesDto()); return SimpleMapper.Map(properties, new JsonFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(NumberFieldProperties properties) public FieldPropertiesDto Visit(NumberFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new NumberFieldPropertiesDto()); return SimpleMapper.Map(properties, new NumberFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(ReferencesFieldProperties properties) public FieldPropertiesDto Visit(ReferencesFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new ReferencesFieldPropertiesDto()); return SimpleMapper.Map(properties, new ReferencesFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(StringFieldProperties properties) public FieldPropertiesDto Visit(StringFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new StringFieldPropertiesDto()); return SimpleMapper.Map(properties, new StringFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(TagsFieldProperties properties) public FieldPropertiesDto Visit(TagsFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new TagsFieldPropertiesDto()); return SimpleMapper.Map(properties, new TagsFieldPropertiesDto());
} }
public FieldPropertiesDto Visit(UIFieldProperties properties) public FieldPropertiesDto Visit(UIFieldProperties properties, None args)
{ {
return SimpleMapper.Map(properties, new UIFieldPropertiesDto()); return SimpleMapper.Map(properties, new UIFieldPropertiesDto());
} }

1
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using FluentAssertions; using FluentAssertions;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Xunit; using Xunit;

54
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs

@ -19,7 +19,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
{ {
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(null, field); var formatted = StringFormatter.Format(field, null);
Assert.Empty(formatted); Assert.Empty(formatted);
} }
@ -29,7 +29,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
{ {
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(JsonValue.Null, field); var formatted = StringFormatter.Format(field, JsonValue.Null);
Assert.Empty(formatted); Assert.Empty(formatted);
} }
@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 Items", formatted); Assert.Equal("0 Items", formatted);
} }
@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("1 Item", formatted); Assert.Equal("1 Item", formatted);
} }
@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("2 Items", formatted); Assert.Equal("2 Items", formatted);
} }
@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Array(1, "field", Partitioning.Invariant); var field = Fields.Array(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 Items", formatted); Assert.Equal("0 Items", formatted);
} }
@ -89,7 +89,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Assets(1, "field", Partitioning.Invariant); var field = Fields.Assets(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 Assets", formatted); Assert.Equal("0 Assets", formatted);
} }
@ -101,7 +101,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Assets(1, "field", Partitioning.Invariant); var field = Fields.Assets(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("1 Asset", formatted); Assert.Equal("1 Asset", formatted);
} }
@ -113,7 +113,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Assets(1, "field", Partitioning.Invariant); var field = Fields.Assets(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("2 Assets", formatted); Assert.Equal("2 Assets", formatted);
} }
@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Assets(1, "field", Partitioning.Invariant); var field = Fields.Assets(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 Assets", formatted); Assert.Equal("0 Assets", formatted);
} }
@ -137,7 +137,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Boolean(1, "field", Partitioning.Invariant); var field = Fields.Boolean(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("Yes", formatted); Assert.Equal("Yes", formatted);
} }
@ -149,7 +149,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Boolean(1, "field", Partitioning.Invariant); var field = Fields.Boolean(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("No", formatted); Assert.Equal("No", formatted);
} }
@ -161,7 +161,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Boolean(1, "field", Partitioning.Invariant); var field = Fields.Boolean(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("No", formatted); Assert.Equal("No", formatted);
} }
@ -173,7 +173,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.DateTime(1, "field", Partitioning.Invariant); var field = Fields.DateTime(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("2019-01-19T12:00:00Z", formatted); Assert.Equal("2019-01-19T12:00:00Z", formatted);
} }
@ -185,7 +185,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Geolocation(1, "field", Partitioning.Invariant); var field = Fields.Geolocation(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("18.9, 10.9", formatted); Assert.Equal("18.9, 10.9", formatted);
} }
@ -197,7 +197,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Geolocation(1, "field", Partitioning.Invariant); var field = Fields.Geolocation(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Empty(formatted); Assert.Empty(formatted);
} }
@ -209,7 +209,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Geolocation(1, "field", Partitioning.Invariant); var field = Fields.Geolocation(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Empty(formatted); Assert.Empty(formatted);
} }
@ -221,7 +221,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Json(1, "field", Partitioning.Invariant); var field = Fields.Json(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("<Json />", formatted); Assert.Equal("<Json />", formatted);
} }
@ -233,7 +233,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Number(1, "field", Partitioning.Invariant); var field = Fields.Number(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("123", formatted); Assert.Equal("123", formatted);
} }
@ -245,7 +245,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.References(1, "field", Partitioning.Invariant); var field = Fields.References(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 References", formatted); Assert.Equal("0 References", formatted);
} }
@ -257,7 +257,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.References(1, "field", Partitioning.Invariant); var field = Fields.References(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("1 Reference", formatted); Assert.Equal("1 Reference", formatted);
} }
@ -269,7 +269,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.References(1, "field", Partitioning.Invariant); var field = Fields.References(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("2 References", formatted); Assert.Equal("2 References", formatted);
} }
@ -281,7 +281,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.References(1, "field", Partitioning.Invariant); var field = Fields.References(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("0 References", formatted); Assert.Equal("0 References", formatted);
} }
@ -293,7 +293,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.String(1, "field", Partitioning.Invariant); var field = Fields.String(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("hello", formatted); Assert.Equal("hello", formatted);
} }
@ -305,7 +305,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.String(1, "field", Partitioning.Invariant, new StringFieldProperties { Editor = StringFieldEditor.StockPhoto }); var field = Fields.String(1, "field", Partitioning.Invariant, new StringFieldProperties { Editor = StringFieldEditor.StockPhoto });
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("[Photo]", formatted); Assert.Equal("[Photo]", formatted);
} }
@ -317,7 +317,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Tags(1, "field", Partitioning.Invariant); var field = Fields.Tags(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Equal("hello, squidex, and, team", formatted); Assert.Equal("hello, squidex, and, team", formatted);
} }
@ -329,7 +329,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent
var field = Fields.Tags(1, "field", Partitioning.Invariant); var field = Fields.Tags(1, "field", Partitioning.Invariant);
var formatted = StringFormatter.Format(value, field); var formatted = StringFormatter.Format(field, value);
Assert.Empty(formatted); Assert.Empty(formatted);
} }

4
backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs

@ -6,10 +6,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
@ -17,7 +14,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Orleans; using Orleans;
using Orleans.Hosting; using Orleans.Hosting;
using Orleans.Runtime;
using Orleans.TestingHost; using Orleans.TestingHost;
using Squidex.Caching; using Squidex.Caching;
using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core;

Loading…
Cancel
Save