diff --git a/uSync.Migrations.Migrators/Community/Meganav/MeganavToMeganavMigrator.cs b/uSync.Migrations.Migrators/Community/Meganav/MeganavToMeganavMigrator.cs new file mode 100644 index 00000000..e32817f1 --- /dev/null +++ b/uSync.Migrations.Migrators/Community/Meganav/MeganavToMeganavMigrator.cs @@ -0,0 +1,121 @@ +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; +using Umbraco.Cms.Core; +using Umbraco.Extensions; +using static Umbraco.Cms.Core.Models.Property; + +namespace uSync.Migrations.Migrators.Community.Meganav; + +/// +/// Based on https://github.com/callumbwhyte/meganav/tree/v9/dev/src/Our.Umbraco.Meganav/Migrations +/// +[SyncMigrator("Cogworks.Meganav")] +[SyncMigrator("Meganav")] +[SyncDefaultMigrator] +public class MeganavToMeganavMigrator : SyncPropertyMigratorBase +{ + public override string GetEditorAlias(SyncMigrationDataTypeProperty dataTypeProperty, SyncMigrationContext context) + => "Our.Umbraco.Meganav"; + + public override string? GetContentValue(SyncMigrationContentProperty contentProperty, SyncMigrationContext context) + { + var oldStringValue = base.GetContentValue(contentProperty, context); + var data = JToken.Parse(string.IsNullOrEmpty(oldStringValue) ? "{}" : oldStringValue); + + var entities = ConvertToEntity(data, context); + var value = JsonConvert.SerializeObject(entities, new JsonSerializerSettings() { }); + + return value; + } + + private IEnumerable ConvertToEntity(JToken data, SyncMigrationContext context) + { + foreach (var item in data.Children()) + { + var entity = new MeganavEntity + { + Title = item.Value("title"), + Target = item.Value("target"), + Visible = !item.Value("naviHide") + }; + + + var id = item.Value("id"); + + UdiParser.TryParse(item.Value("udi"), out Udi udi); + + if (id > 0 || udi != null) + { + if (udi is GuidUdi guidUdi) + { + // UDI is healthy + + // UNDONE: the original source still obtains the object here but I think it's not needed. + // All I can see it'd do is check the node still exists, which is handled by the editor anyway. + } + else + { + // convert ID to key + guidUdi = new GuidUdi(UmbConstants.UdiEntityType.Document, context.GetKey(id)); + } + + entity.Udi = guidUdi; + } + else + { + entity.Url = item.Value("url"); + } + + var children = item.Value("children"); + + if (children != null) + { + entity.Children = ConvertToEntity(children, context); + } + + var ignoreProperties = new[] + { + "id", "key", "udi", "name", "title", "description", "target", "url", "children", "icon", "published", + "naviHide", "culture" + }; + + var settings = item.ToObject>(); + + settings.RemoveAll(x => ignoreProperties.InvariantContains(x.Key)); + + entity.Settings = settings; + + yield return entity; + } + } + + [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))] + internal class MeganavEntity + { + [DataMember(Name = "title")] + public string Title { get; set; } + + [DataMember(Name = "url")] + public string Url { get; set; } + + [DataMember(Name = "target")] + public string Target { get; set; } + + [DataMember(Name = "visible")] + public bool Visible { get; set; } = true; + + [DataMember(Name = "udi")] + public GuidUdi Udi { get; set; } + + [DataMember(Name = "itemTypeId")] + public Guid? ItemTypeId { get; set; } + + [DataMember(Name = "settings")] + public IDictionary Settings { get; set; } + + [DataMember(Name = "children")] + public IEnumerable Children { get; set; } = new List(); + } +}