From 145469d032468487709fa47e5ca1e76efc93323a Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 17 Sep 2021 16:47:17 +0200 Subject: [PATCH] Test for double linked middleware. --- .../DoubleLinkedContentMiddleware.cs | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 backend/extensions/Squidex.Extensions/Samples/Middleware/DoubleLinkedContentMiddleware.cs diff --git a/backend/extensions/Squidex.Extensions/Samples/Middleware/DoubleLinkedContentMiddleware.cs b/backend/extensions/Squidex.Extensions/Samples/Middleware/DoubleLinkedContentMiddleware.cs new file mode 100644 index 000000000..ed09dc2f2 --- /dev/null +++ b/backend/extensions/Squidex.Extensions/Samples/Middleware/DoubleLinkedContentMiddleware.cs @@ -0,0 +1,113 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Linq; +using System.Threading.Tasks; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Entities.Contents; +using Squidex.Domain.Apps.Entities.Contents.Commands; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Commands; +using Squidex.Infrastructure.Json.Objects; + +namespace Squidex.Extensions.Samples.Middleware +{ + public sealed class DoubleLinkedContentMiddleware : ICustomCommandMiddleware + { + private readonly IContentLoader contentLoader; + + public DoubleLinkedContentMiddleware(IContentLoader contentLoader) + { + this.contentLoader = contentLoader; + } + + public async Task HandleAsync(CommandContext context, NextDelegate next) + { + await next(context); + + if (context.Command is UpdateContent update && context.IsCompleted && update.SchemaId.Name == "source") + { + // After a change is made, the content is put to the command context. + var content = context.Result(); + + var contentPrevious = + await contentLoader.GetAsync( + content.AppId.Id, + content.Id, + content.Version - 1); + + // The data might have been changed within the domain object. Therefore we do not use the data fro mthe command. + var oldReferenceId = GetReference(contentPrevious?.Data); + var newReferenceId = GetReference(content.Data); + + // If nothing has been changed we can just stop here. + if (newReferenceId == oldReferenceId) + { + return; + } + + if (oldReferenceId != null) + { + var oldReferenced = await contentLoader.GetAsync(content.AppId.Id, DomainId.Create(oldReferenceId)); + + if (oldReferenced != null) + { + var data = oldReferenced.Data.Clone(); + + // Remove the reference from the old referenced content. + data.Remove("referencing"); + + await UpdateReferencing(context, oldReferenced, data); + } + } + + if (newReferenceId != null) + { + var newReferenced = await contentLoader.GetAsync(content.AppId.Id, DomainId.Create(newReferenceId)); + + if (newReferenced != null) + { + var data = newReferenced.Data.Clone(); + + // Add the reference to the new referenced content. + data["referencing"] = new ContentFieldData + { + ["iv"] = JsonValue.Array(content.Id) + }; + + await UpdateReferencing(context, newReferenced, data); + } + } + } + } + + private static async Task UpdateReferencing(CommandContext context, IContentEntity reference, ContentData data) + { + await context.CommandBus.PublishAsync(new UpdateContent + { + AppId = reference.AppId, + SchemaId = reference.SchemaId, + ContentId = reference.Id, + DoNotScript = true, + DoNotValidate = true, + Data = data, + // Also set the expected version, otherwise it will be overriden with the version from the request. + ExpectedVersion = reference.Version + }); + } + + private static string GetReference(ContentData data) + { + if (data != null && data.TryGetValue("reference", out ContentFieldData fieldData)) + { + return fieldData.Values.OfType().SelectMany(x => x).SingleOrDefault()?.ToString(); + } + + return null; + } + } +}