mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.2 KiB
111 lines
4.2 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using Squidex.Domain.Apps.Core.Contents;
|
|
using Squidex.Domain.Apps.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<IContentEntity>();
|
|
|
|
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<JsonArray>().SelectMany(x => x).SingleOrDefault()?.ToString();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|