Skip to content

Commit

Permalink
Enrich required fields. (#1119)
Browse files Browse the repository at this point in the history
* Enrich required fields.

* Remove unused properties.

* Fix tests

* Update tests
  • Loading branch information
SebastianStehle committed Aug 19, 2024
1 parent 3a30b63 commit 9733e8f
Show file tree
Hide file tree
Showing 27 changed files with 300 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ private async Task<App> PrepareAsync(App app)
}

// Do not use cancellation here as we already so far.
await appCache.AddAsync(new[]
{
await appCache.AddAsync(
[
new KeyValuePair<string, object?>(GetCacheKey(app.Id), app),
new KeyValuePair<string, object?>(GetCacheKey(app.Name), app),
}, options.CacheDuration);
], options.CacheDuration);

return app;
}
Expand All @@ -244,10 +244,10 @@ private Task InvalidateItAsync(DomainId id, string name)
}

// Do not use cancellation here as we already so far.
return appCache.RemoveAsync(new[]
{
return appCache.RemoveAsync(
[
GetCacheKey(id),
GetCacheKey(name)
});
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Squidex.Domain.Apps.Entities.Assets;

public static class AssetSlug
{
private static readonly HashSet<char> Dot = new HashSet<char>(new[] { '.' });
private static readonly HashSet<char> Dot = new HashSet<char>(['.']);

public static string ToAssetSlug(this string value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@ public sealed class BulkUpdateContents : SquidexCommand, IAppCommand, ISchemaCom

public bool OptimizeValidation { get; set; }

public bool EnrichRequiredFields { get; set; }

public BulkUpdateJob[]? Jobs { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ namespace Squidex.Domain.Apps.Entities.Contents.Commands;

public sealed class EnrichContentDefaults : ContentCommand
{
public bool EnrichRequiredFields { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public sealed class UpsertContent : ContentDataCommand, ISchemaCommand

public bool EnrichDefaults { get; set; }

public bool EnrichRequiredFields { get; set; }

public UpsertContent()
{
ContentId = DomainId.NewGuid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class ContentHeaders
public const string KeyLanguages = "X-Languages";
public const string KeyNoCleanup = "X-NoCleanup";
public const string KeyNoEnrichment = "X-NoEnrichment";
public const string KeyNoDefaults = "X-NoDefaults";
public const string KeyNoResolveLanguages = "X-NoResolveLanguages";
public const string KeyResolveFlow = "X-ResolveFlow";
public const string KeyResolveUrls = "X-ResolveUrls";
Expand All @@ -32,6 +33,7 @@ public static void AddCacheHeaders(this Context context, IRequestCache cache)
cache.AddHeader(KeyLanguages);
cache.AddHeader(KeyNoCleanup);
cache.AddHeader(KeyNoEnrichment);
cache.AddHeader(KeyNoDefaults);
cache.AddHeader(KeyNoResolveLanguages);
cache.AddHeader(KeyResolveFlow);
cache.AddHeader(KeyResolveUrls);
Expand Down Expand Up @@ -63,6 +65,16 @@ public static ICloneBuilder WithNoEnrichment(this ICloneBuilder builder, bool va
return builder.WithBoolean(KeyNoEnrichment, value);
}

public static bool NoDefaults(this Context context)
{
return context.AsBoolean(KeyNoDefaults);
}

public static ICloneBuilder WithNoDefaults(this ICloneBuilder builder, bool value = true)
{
return builder.WithBoolean(KeyNoDefaults, value);
}

public static bool Unpublished(this Context context)
{
return context.AsBoolean(KeyUnpublished);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public override Task<CommandResult> ExecuteAsync(IAggregateCommand command,
{
var operation = await ContentOperation.CreateAsync(serviceProvider, c, () => Snapshot);
var newData = operation.GenerateDefaultValues(Snapshot.EditingData.Clone());
var newData = operation.GenerateDefaultValues(Snapshot.EditingData.Clone(), !c.EnrichRequiredFields);
if (!newData.Equals(Snapshot.EditingData))
{
Expand Down Expand Up @@ -263,7 +263,7 @@ private async Task CreateCore(CreateContent c, ContentOperation operation,
c.Data = await operation.ExecuteCreateScriptAsync(c.Data, status, ct);
}

c.Data = operation.GenerateDefaultValues(c.Data);
c.Data = operation.GenerateDefaultValues(c.Data, false);

if (!c.DoNotValidate)
{
Expand Down Expand Up @@ -336,7 +336,7 @@ private async Task UpdateCore(UpdateContent c, ContentOperation operation,

if (c.EnrichDefaults)
{
newData = operation.GenerateDefaultValues(newData);
newData = operation.GenerateDefaultValues(newData, true);
}

if (newData.Equals(Snapshot.EditingData))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public static void MustHaveData(this ContentOperation operation, ContentData? da
operation.ThrowOnErrors();
}

public static async Task ValidateInputAsync(this ContentOperation operation, ContentData data, bool optimize, bool published,
public static async Task ValidateInputAsync(this ContentOperation operation,
ContentData data, bool optimize, bool published,
CancellationToken ct)
{
var validator = GetValidator(operation, optimize, published);
Expand All @@ -57,7 +58,8 @@ public static async Task ValidateInputAsync(this ContentOperation operation, Con
operation.AddErrors(validator.Errors).ThrowOnErrors();
}

public static async Task ValidateInputPartialAsync(this ContentOperation operation, ContentData data, bool optimize, bool published,
public static async Task ValidateInputPartialAsync(this ContentOperation operation,
ContentData data, bool optimize, bool published,
CancellationToken ct)
{
var validator = GetValidator(operation, optimize, published);
Expand All @@ -67,7 +69,8 @@ public static async Task ValidateInputPartialAsync(this ContentOperation operati
operation.AddErrors(validator.Errors).ThrowOnErrors();
}

public static async Task ValidateContentAsync(this ContentOperation operation, ContentData data, bool optimize, bool published,
public static async Task ValidateContentAsync(this ContentOperation operation,
ContentData data, bool optimize, bool published,
CancellationToken ct)
{
var validator = GetValidator(operation, optimize, published);
Expand All @@ -77,7 +80,8 @@ public static async Task ValidateContentAsync(this ContentOperation operation, C
operation.AddErrors(validator.Errors).ThrowOnErrors();
}

public static async Task ValidateContentAndInputAsync(this ContentOperation operation, ContentData data, bool optimize, bool published,
public static async Task ValidateContentAndInputAsync(this ContentOperation operation,
ContentData data, bool optimize, bool published,
CancellationToken ct)
{
var validator = GetValidator(operation, optimize, published);
Expand All @@ -87,18 +91,20 @@ public static async Task ValidateContentAndInputAsync(this ContentOperation oper
operation.AddErrors(validator.Errors).ThrowOnErrors();
}

public static ContentData GenerateDefaultValues(this ContentOperation operation, ContentData data)
public static ContentData GenerateDefaultValues(this ContentOperation operation,
ContentData data, bool ignoreRequired)
{
var converter =
new ContentConverter(
operation.Components,
operation.Schema);
converter.Add(new AddDefaultValues(operation.Partition()) { IgnoreRequiredFields = true });
converter.Add(new AddDefaultValues(operation.Partition()) { IgnoreRequiredFields = ignoreRequired });

return converter.Convert(data);
}

public static ContentData InvokeUpdates(this ContentOperation operation, ContentData data, ContentData currentData, bool canUnset)
public static ContentData InvokeUpdates(this ContentOperation operation, ContentData data,
ContentData currentData, bool canUnset)
{
var converter =
new ContentConverter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private async Task<IReadOnlyList<EnrichedContent>> EnrichInternalAsync(IEnumerab
{
var result = SimpleMapper.Map(content, new EnrichedContent());

// Clone the data to keep the existing value intact (for example when cached in memory).
if (cloneData)
{
using (Telemetry.Activities.StartActivity("ContentEnricher/CloneData"))
Expand All @@ -86,12 +87,8 @@ private async Task<IReadOnlyList<EnrichedContent>> EnrichInternalAsync(IEnumerab
{
return schemaCache.GetOrAdd(id, async x =>
{
var schema = await appProvider.GetSchemaAsync(context.App.Id, x, false, ct);
if (schema == null)
{
throw new DomainObjectNotFoundException(x.ToString());
}
var schema = await appProvider.GetSchemaAsync(context.App.Id, x, false, ct)
?? throw new DomainObjectNotFoundException(x.ToString());
var components = await appProvider.GetComponentsAsync(schema, ct);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private ContentConverter GenerateConverter(Context context, ResolvedComponents c

converter.Add(new ResolveFromPreviousPartitioning(context.App.Languages));

if (!context.IsFrontendClient)
if (!context.IsFrontendClient && !context.NoDefaults())
{
converter.Add(new AddDefaultValues(context.App.PartitionResolver())
{
Expand Down
2 changes: 1 addition & 1 deletion backend/src/Squidex.Domain.Apps.Entities/Jobs/JobWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public JobWorker(IServiceProvider serviceProvider)

processorFactory = key =>
{
return (JobProcessor)objectFactory(serviceProvider, new object[] { key });
return (JobProcessor)objectFactory(serviceProvider, [key]);
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ private async Task<Schema> PrepareAsync(Schema schema)
}

// Do not use cancellation here as we already so far.
await schemaCache.AddAsync(new[]
{
await schemaCache.AddAsync(
[
new KeyValuePair<string, object?>(GetCacheKey(schema.AppId.Id, schema.Id), schema),
new KeyValuePair<string, object?>(GetCacheKey(schema.AppId.Id, schema.Name), schema),
}, options.CacheDuration);
], options.CacheDuration);

return schema;
}
Expand All @@ -235,10 +235,10 @@ private Task InvalidateItAsync(DomainId appId, DomainId id, string name)
}

// Do not use cancellation here as we already so far.
return schemaCache.RemoveAsync(new[]
{
return schemaCache.RemoveAsync(
[
GetCacheKey(appId, id),
GetCacheKey(appId, name)
});
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -464,9 +464,9 @@ public async Task<IActionResult> PutContent(string app, string schema, DomainId
[AcceptHeader.Unpublished]
[AcceptHeader.Languages]
[ApiCosts(1)]
public async Task<IActionResult> PutContentDefaults(string app, string schema, DomainId id)
public async Task<IActionResult> PutContentDefaults(string app, string schema, DomainId id, EnrichContentDefaultsDto request)
{
var command = new EnrichContentDefaults { ContentId = id };
var command = request.ToCommand(id);

var response = await InvokeCommandAsync(command);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public sealed class BulkUpdateContentsDto
/// </summary>
public bool DoNotScript { get; set; } = true;

/// <summary>
/// True, to also enrich required fields. Default: false.
/// </summary>
public bool EnrichRequiredFields { get; set; }

/// <summary>
/// True to turn off validation for faster inserts. Default: false.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================

using Microsoft.AspNetCore.Mvc;
using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;

namespace Squidex.Areas.Api.Controllers.Contents.Models;

public class EnrichContentDefaultsDto
{
/// <summary>
/// True, to also enrich required fields. Default: false.
/// </summary>
[FromQuery(Name = "enrichRequiredFields")]
public bool EnrichRequiredFields { get; set; }

public EnrichContentDefaults ToCommand(DomainId id)
{
var command = SimpleMapper.Map(this, new EnrichContentDefaults { ContentId = id });

return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public async Task Should_add_cache_headers()
"X-Languages",
"X-NoCleanup",
"X-NoEnrichment",
"X-NoDefaults",
"X-NoResolveLanguages",
"X-ResolveFlow",
"X-ResolveUrls",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public async Task Should_add_cache_headers()
"X-Languages",
"X-NoCleanup",
"X-NoEnrichment",
"X-NoDefaults",
"X-NoResolveLanguages",
"X-ResolveFlow",
"X-ResolveUrls",
Expand Down
3 changes: 3 additions & 0 deletions tools/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ dotnet_diagnostic.IDE0305.severity = none
# CA1707: Identifiers should not contain underscores
dotnet_diagnostic.CA1707.severity = none

# CA1861: Avoid constant arrays as arguments
dotnet_diagnostic.CA1861.severity = none

# CA2016: Forward the 'CancellationToken' parameter to methods
dotnet_diagnostic.CA2016.severity = none

Expand Down
2 changes: 1 addition & 1 deletion tools/TestSuite/TestSuite.ApiTests/AssetFoldersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public async Task Should_create_and_query_nested_folders()
// STEP 3: Query by nested id.
var folders2 = await _.Client.Assets.GetAssetFoldersAsync(folder1.Id);

Assert.Equal(new[] { folder2.Id }, folders2.Items.Select(x => x.Id));
Assert.Equal([folder2.Id], folders2.Items.Select(x => x.Id));


// STEP 3: Query all
Expand Down
2 changes: 1 addition & 1 deletion tools/TestSuite/TestSuite.ApiTests/ContentQueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ query ContentsQuery($filter: String!) {
}
};

var results = await _.Client.SharedDynamicContents.GraphQlAsync<QueryResult>(new[] { query1, query2 });
var results = await _.Client.SharedDynamicContents.GraphQlAsync<QueryResult>([query1, query2]);

var items1 = results.ElementAt(0).Data.Items;
var items2 = results.ElementAt(1).Data.Items;
Expand Down
Loading

0 comments on commit 9733e8f

Please sign in to comment.