Skip to content

Commit

Permalink
Hook into DataType saving event to convert legacy editor data to Meganav
Browse files Browse the repository at this point in the history
  • Loading branch information
callumbwhyte committed Sep 14, 2021
1 parent 50152c2 commit a5e4b72
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Our.Umbraco.Meganav/Migrations/LegacyEditors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace Our.Umbraco.Meganav.Migrations
{
public static class LegacyEditors
{
public static List<string> Aliases => new List<string>
{
"Meganav",
"Cogworks.Meganav"
};
}
}
47 changes: 47 additions & 0 deletions src/Our.Umbraco.Meganav/Migrations/LegacyMigrationComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;

namespace Our.Umbraco.Meganav.Migrations
{
internal class LegacyMigrationComponent : IComponent
{
private readonly LegacyValueMigrator _legacyValueMigrator;

public LegacyMigrationComponent(LegacyValueMigrator legacyValueMigrator)
{
_legacyValueMigrator = legacyValueMigrator;
}

public void Initialize()
{
DataTypeService.Saving += DataTypeService_Saving;
}

public void Terminate()
{
DataTypeService.Saving -= DataTypeService_Saving;
}

private void DataTypeService_Saving(IDataTypeService sender, SaveEventArgs<IDataType> e)
{
var dataTypes = e.SavedEntities
.Where(x => x.EditorAlias == Constants.PropertyEditorAlias)
.Where(x =>
{
var existingEntity = sender.GetDataType(x.Id);

return existingEntity != null && LegacyEditors.Aliases.Any(existingEntity.EditorAlias.InvariantContains);
});

foreach (var dataType in dataTypes)
{
_legacyValueMigrator.MigrateContentValues(dataType);
}
}
}
}
15 changes: 15 additions & 0 deletions src/Our.Umbraco.Meganav/Migrations/LegacyMigrationComposer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Umbraco.Core;
using Umbraco.Core.Composing;

namespace Our.Umbraco.Meganav.Migrations
{
public class LegacyMigrationComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<LegacyValueMigrator>();

composition.Components().Append<LegacyMigrationComponent>();
}
}
}
138 changes: 138 additions & 0 deletions src/Our.Umbraco.Meganav/Migrations/LegacyValueMigrator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Our.Umbraco.Meganav.Models;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;

namespace Our.Umbraco.Meganav.Migrations
{
internal class LegacyValueMigrator
{
private readonly IContentTypeService _contentTypeService;
private readonly IContentService _contentService;
private readonly ILogger _logger;

public LegacyValueMigrator(IContentTypeService contentTypeService, IContentService contentService, ILogger logger)
{
_contentTypeService = contentTypeService;
_contentService = contentService;
_logger = logger;
}

public void MigrateContentValues(IDataType dataType)
{
var contentTypes = _contentTypeService.GetAll()
.Where(x => x.PropertyTypes.Any(p => p.DataTypeId == dataType.Id))
.ToList();

var contentTypeIds = contentTypes.Select(x => x.Id).ToArray();

var contentItems = _contentService.GetPagedOfTypes(contentTypeIds, 0, int.MaxValue, out long totalRecords, null);

var propertyAliases = contentTypes
.SelectMany(x => x.PropertyTypes)
.Where(x => x.DataTypeId == dataType.Id)
.Select(x => x.Alias)
.Distinct()
.ToArray();

MigrateContentValues(contentItems, propertyAliases);
}

public void MigrateContentValues(IEnumerable<IContent> contentItems, string[] propertyAliases)
{
foreach (var content in contentItems)
{
var properties = content.Properties.Where(x => propertyAliases.InvariantContains(x.Alias));

foreach (var property in properties)
{
foreach (var propertyValue in property.Values)
{
try
{
var entities = ConvertToEntity(propertyValue.EditedValue);

var value = JsonConvert.SerializeObject(entities);

property.SetValue(value, propertyValue.Culture, propertyValue.Segment);
}
catch (Exception ex)
{
_logger.Error<LegacyValueMigrator>(ex, "Failed to migrate Meganav values for {alias} on content {id}", property.Alias, content.Id);
}
}
}

_contentService.Save(content);
}
}

private IEnumerable<MeganavEntity> ConvertToEntity(object value)
{
if (!(value is JToken data))
{
if (value is string stringValue)
{
data = JToken.Parse(stringValue);
}
else
{
yield break;
}
}

foreach (var item in data.Children())
{
var entity = new MeganavEntity
{
Title = item.Value<string>("title"),
Target = item.Value<string>("target"),
Visible = !item.Value<bool>("naviHide")
};

var id = item.Value<int>("id");

GuidUdi.TryParse(item.Value<string>("udi"), out GuidUdi udi);

if (id > 0 || udi?.Guid != Guid.Empty)
{
var contentItem = udi != null
? _contentService.GetById(udi.Guid)
: _contentService.GetById(id);

if (contentItem != null)
{
entity.Udi = contentItem.GetUdi();
}
}
else
{
entity.Url = item.Value<string>("url");
}

var children = item.Value<JArray>("children");

if (children != null)
{
entity.Children = ConvertToEntity(children);
}

var ignoreProperties = new[] { "id", "key", "udi", "name", "title", "description", "target", "url", "children", "icon", "published", "naviHide", "culture" };

var settings = item.ToObject<IDictionary<string, object>>();

settings.RemoveAll(x => ignoreProperties.InvariantContains(x.Key));

entity.Settings = settings;

yield return entity;
}
}
}
}

0 comments on commit a5e4b72

Please sign in to comment.