diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs index 6a68882af..758840b1f 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs @@ -38,6 +38,49 @@ namespace Squidex.Domain.Apps.Core.Contents return this; } + public ContentData UseSameFields(ContentData? other) + { + if (other == null || other.Count == 0) + { + return this; + } + + foreach (var (fieldName, fieldData) in this.ToList()) + { + if (fieldData == null) + { + continue; + } + + if (!other.TryGetValue(fieldName, out var otherField) || otherField == null) + { + continue; + } + + if (otherField.Equals(fieldData)) + { + this[fieldName] = otherField; + } + else + { + foreach (var (language, value) in fieldData.ToList()) + { + if (!otherField.TryGetValue(language, out var otherValue) || otherValue == null) + { + continue; + } + + if (otherValue.Equals(value)) + { + fieldData[language] = otherValue; + } + } + } + } + + return this; + } + private static ContentData MergeTo(ContentData target, params ContentData[] sources) { Guard.NotEmpty(sources, nameof(sources)); @@ -49,19 +92,23 @@ namespace Squidex.Domain.Apps.Core.Contents foreach (var source in sources) { - foreach (var (key, contentFieldData) in source) + foreach (var (fieldName, sourceFieldData) in source) { - if (contentFieldData != null) + if (sourceFieldData == null) { - var fieldValue = target.GetOrAdd(key, _ => new ContentFieldData()); + continue; + } - if (fieldValue != null) - { - foreach (var (fieldName, value) in contentFieldData) - { - fieldValue[fieldName] = value; - } - } + var targetFieldData = target.GetOrAdd(fieldName, _ => new ContentFieldData()); + + if (targetFieldData == null) + { + continue; + } + + foreach (var (partition, value) in sourceFieldData) + { + targetFieldData[partition] = value; } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs index f67fdb192..1d48d217e 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs @@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Core.Contents Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(value, nameof(value)); - geoJSON = null!; + geoJSON = null; if (value is JsonObject obj) { @@ -42,6 +42,8 @@ namespace Squidex.Domain.Apps.Core.Contents } geoJSON = new Point(new Position(lat.Value, lon.Value)); + + return GeoJsonParseResult.Success; } return GeoJsonParseResult.InvalidValue; diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs index c08bf5562..c3c654eeb 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs @@ -19,14 +19,19 @@ namespace Squidex.Domain.Apps.Core.ConvertContent var result = new ContentData(content.Count); - foreach (var (fieldName, data) in content) + if (converters == null || converters.Length == 0) { - if (data == null || !schema.FieldsByName.TryGetValue(fieldName, out var field)) + return result; + } + + foreach (var (fieldName, fieldData) in content) + { + if (fieldData == null || !schema.FieldsByName.TryGetValue(fieldName, out var field)) { continue; } - ContentFieldData? newData = data; + ContentFieldData? newData = fieldData; if (newData != null) { @@ -44,16 +49,18 @@ namespace Squidex.Domain.Apps.Core.ConvertContent private static ContentFieldData? ConvertData(IRootField field, ContentFieldData data, FieldConverter[] converters) { - if (converters != null) + if (converters == null || converters.Length == 0) { - for (var i = 0; i < converters.Length; i++) - { - data = converters[i](data!, field)!; + return data; + } + + for (var i = 0; i < converters.Length; i++) + { + data = converters[i](data!, field)!; - if (data == null) - { - break; - } + if (data == null) + { + break; } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs index d528202a3..c8e1523ef 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs @@ -119,15 +119,17 @@ namespace Squidex.Domain.Apps.Core.ConvertContent { foreach (var languageCode in languages.AllKeys) { - if (!data.TryGetNonNull(languageCode, out _)) + if (data.TryGetNonNull(languageCode, out _)) { - foreach (var fallback in languages.GetPriorities(languageCode)) + continue; + } + + foreach (var fallback in languages.GetPriorities(languageCode)) + { + if (data.TryGetNonNull(fallback, out var value)) { - if (data.TryGetNonNull(fallback, out var value)) - { - data[languageCode] = value; - break; - } + data[languageCode] = value; + break; } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs index 4c93c19e0..43a79334e 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs @@ -71,7 +71,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject case ContentDraftCreated e: { - NewVersion = new ContentVersion(e.Status, e.MigratedData ?? CurrentVersion.Data); + var newData = e.MigratedData?.UseSameFields(Data) ?? CurrentVersion.Data; + + NewVersion = new ContentVersion(e.Status, newData); ScheduleJob = null; @@ -95,7 +97,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject { if (e.Status == Status.Published) { - CurrentVersion = new ContentVersion(e.Status, NewVersion.Data); + CurrentVersion = new ContentVersion(e.Status, NewVersion.Data.UseSameFields(Data)); NewVersion = null; } @@ -130,11 +132,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject { if (NewVersion != null) { - NewVersion = NewVersion.WithData(e.Data); + NewVersion = NewVersion.WithData(e.Data.UseSameFields(Data)); } else { - CurrentVersion = CurrentVersion.WithData(e.Data); + CurrentVersion = CurrentVersion.WithData(e.Data.UseSameFields(Data)); } break; diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs index d836e986e..85faeac76 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs @@ -159,5 +159,55 @@ namespace Squidex.Domain.Apps.Core.Model.Contents Assert.NotSame(value, source[key]); } } + + [Fact] + public void Should_copy_fields_from_other_data_if_they_are_equal() + { + var oldData = + new ContentData() + .AddField("field1", + new ContentFieldData() + .AddInvariant(1)) + .AddField("field2", + new ContentFieldData() + .AddInvariant(2)); + + var newData = + new ContentData() + .AddField("field1", + new ContentFieldData() + .AddInvariant(1)) + .AddField("field2", + new ContentFieldData() + .AddInvariant(3)); + + newData.UseSameFields(oldData); + + Assert.Same(newData["field1"], oldData["field1"]); + Assert.NotSame(newData["field2"], oldData["field2"]); + } + + [Fact] + public void Should_copy_field_values_from_other_data_if_they_are_equal() + { + var oldData = + new ContentData() + .AddField("field1", + new ContentFieldData() + .AddLocalized("en", 1) + .AddLocalized("de", 2)); + var newData = + new ContentData() + .AddField("field1", + new ContentFieldData() + .AddLocalized("en", 1) + .AddLocalized("de", 3)); + + newData.UseSameFields(oldData); + + Assert.Same(newData["field1"]!["en"], oldData["field1"]!["en"]); + Assert.NotSame(newData["field1"]!["de"], oldData["field1"]!["de"]); + Assert.NotSame(newData["field1"], oldData["field1"]); + } } }