Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.Text.Json.Nodes;

using Umbraco.Cms.Core;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Services;

using uSync.Core.Extensions;

namespace uSync.Core.DataTypes.DataTypeSerializers;


/// <summary>
/// migrates nested content to a block list element.
/// </summary>

internal class NestedContentMigratingConfig : ConfigurationSerializerBase, IConfigurationSerializer
{
private readonly IContentTypeService _contentTypeService;

public NestedContentMigratingConfig(IContentTypeService contentTypeService)
{
this._contentTypeService = contentTypeService;
}

public string Name => nameof(NestedContentMigratingConfig);
public string[] Editors => [SyncLegacyTypes.NestedContent, SyncLegacyTypes.OurNestedContent];

public string? GetEditorAlias() => Constants.PropertyEditors.Aliases.BlockList;
public string? GetEditorUIAlias() => "Umb.PropertyEditorUi.BlockList";

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
{
var config = new BlockListConfiguration();

if (configuration.TryGetValue("minItems", out var min) && int.TryParse(min?.ToString(), out var minItems))
config.ValidationLimit.Min = minItems;

if (configuration.TryGetValue("maxItems", out var max) && int.TryParse(max?.ToString(), out var maxItems))
config.ValidationLimit.Max = maxItems;

if (configuration.TryGetValue("contentTypes", out var contentTypes) && contentTypes is JsonArray contentTypesArray)
{
var blocks = new List<BlockListConfiguration.BlockConfiguration>();
foreach (var contentType in contentTypesArray.Cast<JsonObject>())
{
if (contentType["ncAlias"]?.ToString() is not string alias) continue;
Comment thread
KevinJump marked this conversation as resolved.
var contentTypeItem = _contentTypeService.Get(alias);
if (contentTypeItem is null) continue;
blocks.Add(new BlockListConfiguration.BlockConfiguration
{
ContentElementTypeKey = contentTypeItem.Key,
});
}

config.Blocks = [.. blocks];
}

var result = config.SerializeJsonString().DeserializeJson<Dictionary<string, object>>() ?? configuration;
return result;
}
Comment thread
KevinJump marked this conversation as resolved.
}
83 changes: 83 additions & 0 deletions uSync.Core/Mapping/Mappers/NestedContentToBlockListHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Text;

using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Services;

using uSync.Core.Extensions;

namespace uSync.Core.Mapping.Mappers;

/// <summary>
/// helper methods that can convert nested content to block list values.
/// </summary>
internal class NestedContentToBlockListHelper
{
private readonly IContentTypeService _contentTypeService;

public NestedContentToBlockListHelper(IContentTypeService contentTypeService)
{
_contentTypeService = contentTypeService;
}

private static string[] _reservedProperties = ["ncContentTypeAlias", "key", "name"];

/// <summary>
/// converts a nested content value to a block list value. This is used when we are converting a nested content property to a block list property.
/// </summary>
/// <param name="nestedContentValue">the nested content value to convert</param>
/// <returns>the converted block list value</returns>
public string ConvertNestedContentToBlockList(string nestedContentValue)
{
if (nestedContentValue.Contains("ncContentTypeAlias") is false) return nestedContentValue;

var nestedContent = nestedContentValue.DeserializeJson<List<Dictionary<string, object>>>();
Comment thread
KevinJump marked this conversation as resolved.
Outdated
if (nestedContent == null) return nestedContentValue;

BlockListValue blockListValue = new BlockListValue();

foreach (var item in nestedContent)
{
var contentTypeAlias = item.TryGetValue("ncContentTypeAlias", out var alias) ? alias?.ToString() : null;
if (contentTypeAlias == null) continue;

var contentType = _contentTypeService.Get(contentTypeAlias);
if (contentType == null) continue;

var blockItemData = new BlockItemData
{
ContentTypeKey = contentType.Key,
Key = item.TryGetValue("key", out var key) && Guid.TryParse(key?.ToString(), out var guidKey) ? guidKey : Guid.NewGuid(),
};

foreach (var value in item.Keys)
{
if (_reservedProperties.Contains(value)) continue;
blockItemData.Values.Add(new BlockPropertyValue
{
Alias = value,
Value = item[value]
});
}

blockListValue.ContentData.Add(blockItemData);
}

blockListValue.Expose = [.. blockListValue.ContentData.Select(x => new BlockItemVariation(x.Key, null, null))];
blockListValue.Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
{
{
"Umbraco.BlockList",
blockListValue.ContentData.Select(
x => new BlockListLayoutItem
{
ContentKey = x.Key,
SettingsKey = null,
})
}
};

return blockListValue.SerializeJsonString() ?? nestedContentValue;
}
}
9 changes: 8 additions & 1 deletion uSync.Core/Mapping/SyncBlockMapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.Collections;
using System.Text.Json.Nodes;

using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Blocks;
Expand All @@ -10,6 +11,7 @@

using uSync.Core.Dependency;
using uSync.Core.Extensions;
using uSync.Core.Mapping.Mappers;

namespace uSync.Core.Mapping;

Expand Down Expand Up @@ -70,7 +72,12 @@ public SyncBlockMapperBase(
private async Task<string?> ProcessBlockValuesAsync(string value, Func<object?, string, Task<object?>> GetValueMethod)
{
var blockValue = SyncBlockMapperBase<TBlockValue>.GetBlockValue(value);
if (blockValue == null) return value;
if (blockValue == null)
{
if (value.Contains("ncContentTypeAlias") is false) return value;
var nestedContentHelper = new NestedContentToBlockListHelper(_contentTypeService);
return nestedContentHelper.ConvertNestedContentToBlockList(value);
}

List<BlockItemData> blocks = [
..blockValue.ContentData,
Expand Down
8 changes: 4 additions & 4 deletions uSync.Core/Serialization/Serializers/DataTypeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ protected override async Task<SyncAttempt<IDataType>> DeserializeCoreAsync(XElem
// config
if (ShouldDesterilizeConfig(name, editorAlias, options))
{
details.AddRange(DeserializeConfiguration(item, node));
details.AddRange(DeserializeConfiguration(item, node, editorAlias));
}

details.AddNotNull(await SetFolderFromElementAsync(item, info?.Element("Folder")));
Expand Down Expand Up @@ -174,7 +174,7 @@ private static ValueStorageType GetEditorValueStorageType(IDataEditor? editor)
return null;
}

private List<uSyncChange> DeserializeConfiguration(IDataType item, XElement node)
private List<uSyncChange> DeserializeConfiguration(IDataType item, XElement node, string editorAlias)
{
var config = node.Element("Config").ValueOrDefault(string.Empty);
if (string.IsNullOrEmpty(config)) return [];
Expand All @@ -191,10 +191,10 @@ private List<uSyncChange> DeserializeConfiguration(IDataType item, XElement node
importData = importData.ConvertToCamelCase();

// multiple serializers can run per property.
var serializers = _configurationSerializers.GetSerializers(item.EditorAlias);
var serializers = _configurationSerializers.GetSerializers(editorAlias);
foreach (var serializer in serializers)
{
logger.LogDebug("Running Configuration Serializer : {name} for {type}", serializer.Name, item.EditorAlias);
logger.LogDebug("Running Configuration Serializer : {name} for {type}", serializer.Name, editorAlias);
importData = serializer.GetConfigurationImport(importData);
}

Expand Down
14 changes: 11 additions & 3 deletions uSync.Core/Serialization/Serializers/MediaSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,17 @@ private static string GetFilePath(string? value)
{
return uSyncTaskHelper.FromResultOf(() =>
{
var parentId = parent != null ? parent.Id : -1;
var item = _mediaService.CreateMedia(alias, parentId, itemType);
return Attempt.Succeed((IMedia)item);
try
{
var parentId = parent != null ? parent.Id : -1;
var item = _mediaService.CreateMedia(alias, parentId, itemType);
return Attempt.Succeed((IMedia)item);
}
catch (Exception ex)
{
logger.LogError(ex, "Error creating media item with alias {alias} and parent {parentId}", alias, parent?.Id);
Comment thread
KevinJump marked this conversation as resolved.
throw;
}

});
}
Expand Down