Skip to content

Instantly share code, notes, and snippets.

@KevinJump
Created April 10, 2015 21:46
Show Gist options
  • Save KevinJump/e1049ba83ec316e4ef55 to your computer and use it in GitHub Desktop.
Save KevinJump/e1049ba83ec316e4ef55 to your computer and use it in GitHub Desktop.
Data Migration code, when moving to umbraco 7 - some content may change structure, the ContentConverter walks through the code, and attempts to move the content from one type to another...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Xml;
using System.Xml.Linq;
public class ContentConverter
{
public ContentConverter()
{
}
/// <summary>
/// convert the property nameed value in all content
/// </summary>
/// <param name="propertyName"></param>
public void Convert(List<ConvertItem> items)
{
var _contentService = ApplicationContext.Current.Services.ContentService;
foreach(var rootNode in _contentService.GetRootContent())
{
Convert(items, rootNode);
}
}
private void Convert(List<ConvertItem> convertItems, IContent node)
{
var _contentService = ApplicationContext.Current.Services.ContentService;
LogHelper.Info<ContentConverter>("Checking: {0}{1}", () => new string('-', node.Level + 1), () => node.Name);
bool changesMade = false;
foreach (var convertItem in convertItems)
{
if (node.HasProperty(convertItem.PropertyName))
{
var propVal = node.GetValue<string>(convertItem.PropertyName);
if (!string.IsNullOrWhiteSpace(propVal))
{
// try a convert here...
LogHelper.Info<ContentConverter>("Found Property: {0}", ()=> convertItem.PropertyName);
// do the convert....
var newValue = propVal;
switch (convertItem.Conversion)
{
case ConversionTypes.EmbeddToArchetype:
newValue = ConvertEmbeddedContent(propVal);
break;
case ConversionTypes.MultiNodeTreePicker:
newValue = ConvertMNTPXmlToCSV(propVal);
break;
case ConversionTypes.OpeningTimes:
newValue = ConvertOpeningTimes(propVal);
break;
case ConversionTypes.DetailPanel:
newValue = ConvertRelatedPanel(propVal);
break;
default:
break;
}
if ( !string.IsNullOrWhiteSpace(newValue) && !newValue.Equals(propVal) )
{
try
{
LogHelper.Info<ContentConverter>("Setting Values: {0}", () => newValue);
node.SetValue(convertItem.PropertyName, newValue);
changesMade = true;
}
catch( Exception ex )
{
LogHelper.Info<ContentConverter>("Setting value - failed {0}", ()=> ex.Message);
}
}
}
}
}
if (changesMade)
{
try
{
_contentService.Save(node, raiseEvents: false);
}
catch(Exception ex)
{
LogHelper.Info<ContentConverter>("Saving value failed {0}", ()=> ex.Message);
}
}
foreach(var child in _contentService.GetChildren(node.Id))
{
Convert(convertItems, child);
}
}
/// <summary>
/// Converts Content Stored for Embedded Content into Content stored
/// in an Archetype datatype (where the names match)
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string ConvertEmbeddedContent(string data)
{
var ArchetypeItemAlias = "ListItem";
if (data.IsNullOrWhiteSpace())
return data;
if (!data.StartsWith("<data>"))
return data;
try
{
var jsonValue = string.Format("{{{{\"fieldsets\":[{{0}}]}}}}", ArchetypeItemAlias);
XElement node = XElement.Parse(data);
var jsonProps = new StringBuilder();
foreach(var item in node.Elements("item"))
{
jsonProps.Append("{\"properties\":[");
foreach(var property in item.Elements())
{
// LogHelper.Info<ContentConverter>("property: {0} {1}", () => property.Name, () => property.Value);
jsonProps.Append("{");
jsonProps.AppendFormat("\"alias\":\"{0}\",", property.Name);
string jsonPropValue = "" ;
if (string.IsNullOrWhiteSpace(property.Value))
{
// blank..
jsonPropValue = "null";
}
else
{
// interger or string ?
int intVal;
if (int.TryParse(property.Value, out intVal))
{
jsonPropValue = property.Value;
}
else
{
jsonPropValue = string.Format("\"{0}\"", property.Value);
}
}
jsonProps.AppendFormat("\"value\":{0}", jsonPropValue);
jsonProps.Append("},");
}
if (jsonProps.Length > 0)
jsonProps.Remove(jsonProps.Length - 1, 1);
jsonProps.AppendFormat("],");
jsonProps.AppendFormat("\"alias\":\"{0}\",", ArchetypeItemAlias);
jsonProps.Append("\"disabled\":false");
jsonProps.Append("},");
}
if (jsonProps.Length > 0)
jsonProps.Remove(jsonProps.Length - 1, 1);
jsonValue = string.Format(jsonValue, jsonProps.ToString());
LogHelper.Info<ContentConverter>("Archetype JSON: {0}", () => jsonValue);
return jsonValue;
}
catch(Exception ex)
{
LogHelper.Info<ContentConverter>("Error: {0}", ()=> ex.ToString());
return data;
}
}
/// <summary>
/// takes a MNTP that is storing things in XML, and stores them as CSV
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string ConvertMNTPXmlToCSV(string data)
{
if (!data.StartsWith("<MultiNodePicker"))
return data;
XElement node = XElement.Parse(data);
LogHelper.Info<ContentConverter>("Reading MNTP values: {0}", () => data);
var csvNodes = new StringBuilder();
// foreach (var mntp in node.Elements("multiNodePicker"))
// {
foreach (var nodeId in node.Elements("nodeid"))
{
csvNodes.AppendFormat("{0},", nodeId.Value);
}
foreach (var nodeId in node.Elements("nodeId"))
{
csvNodes.AppendFormat("{0},", nodeId.Value);
}
// }
if (csvNodes.Length > 0)
csvNodes.Remove(csvNodes.Length - 1, 1);
return csvNodes.ToString();
}
private string ConvertOpeningTimes(string data)
{
LogHelper.Info<ContentConverter>("Opening: {0}", () => data);
if (!data.StartsWith("<?xml version=\"1.0\"?><schedule"))
{
return data;
}
XElement node = XElement.Parse(data);
var jsonData = "[{0}]";
var firstset = "\"open\": \"{0}\", \"close\": \"{1}\"";
var secondset = "\"open2\": \"{0}\", \"close2\": \"{1}\"";
var dayformat = "{{ \"name\": \"{0}\", \"scheduled\": {1}, {2}, {3} }},";
var days = new StringBuilder();
foreach (var scheduleItem in node.Elements("scheduleItem"))
{
LogHelper.Info<ContentConverter>("Opening Item: {0}", ()=> scheduleItem.Element("weekDay").Value );
var day = scheduleItem.Element("weekDay");
var first = scheduleItem.Element("firstSet");
var second = scheduleItem.Element("secondSet");
var a = string.Format(firstset,
first.Element("hourStart").Value,
first.Element("hourEnd").Value).Replace("00:00", "");
var b = string.Format(secondset,
second.Element("hourStart").Value,
second.Element("hourEnd").Value).Replace("00:00", "");
days.AppendFormat(dayformat,
day.Value,
scheduleItem.Element("isScheduled").Value,
a, b);
}
if (days.Length > 0)
days.Remove(days.Length - 1, 1);
return string.Format(jsonData, days.ToString());
}
/// <summary>
///
/// converts:
/// <panel number="1">
/// <enabled>1</enabled>
/// <heading></heading>
/// <text><![CDATA[]]></text>
/// <image></image>
/// <link></link>
/// <xlinktext></xlinktext>
/// <xlink></xlink>
/// <autopanelid></autopanelid>
/// </panel>
///
/// to
/// {
/// "fieldsets":
/// [
/// {
/// "properties":
/// [
/// {"alias":"enbabled","value":1},
/// {"alias":"heading","value":"Are you looking for ?"},
/// {"alias":"link","value":null}
/// ],
/// "alias":"ListItem","disabled":false
/// }
/// ]
/// }
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string ConvertRelatedPanel(string data)
{
if ( data.IsNullOrWhiteSpace() )
return data ;
if (!data.StartsWith("<panel number="))
return data;
var jsonTail = "\"alias\":\"ListItem\",\"disabled\":false" ;
var jsonValue = string.Format("{{{{\"fieldsets\":[{{{{\"properties\":[{{0}}],{0}}}}}]}}}}", jsonTail );
XElement node = XElement.Parse(data);
var jsonProps = new StringBuilder();
if (node.Element("enabled") != null)
jsonProps.AppendFormat("{{\"alias\":\"enabled\",\"value\":{0}}},", node.Element("enabled").Value);
if (node.Element("heading") != null)
jsonProps.AppendFormat("{{\"alias\":\"heading\",\"value\":\"{0}\"}},", node.Element("heading").Value);
if (node.Element("link") != null)
jsonProps.AppendFormat("{{\"alias\":\"link\",\"value\":\"{0}\"}},", node.Element("link").Value);
if (jsonProps.Length > 0)
{
jsonProps.Remove(jsonProps.Length - 1, 1);
return string.Format(jsonValue, jsonProps.ToString());
}
return "{\"fieldsets\":[]}";
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using System.Diagnostics;
public class ConvertItem
{
public string PropertyName { get; set; }
public ConversionTypes Conversion { get; set; }
public string Options { get; set; }
}
public enum ConversionTypes
{
EmbeddToArchetype,
MultiNodeTreePicker,
TemplateUpdate,
OpeningTimes,
DetailPanel
}
private void DoDataMigration() {
Stopwatch sw = new Stopwatch();
sw.Start();
LogHelper.Info<UpgradeDash>("Starting Conversion Thing...");
var converter = new ContentConverter();
List<ConvertItem> conversions = new List<ConvertItem>();
// create a list of all the properties we want to convert here....
// embedded content to Archetype
conversions.Add(new ConvertItem { PropertyName = "relatedItems1", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "relatedItems2", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "relatedDetails1", Conversion = ConversionTypes.DetailPanel });
conversions.Add(new ConvertItem { PropertyName = "relatedDetails2", Conversion = ConversionTypes.DetailPanel });
conversions.Add(new ConvertItem { PropertyName = "relatedItems", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "carouselItems", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "homepageLinks", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "panels", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "spotlightList", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "footerIcons", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "homepageHighlights", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "homepageLinks", Conversion = ConversionTypes.EmbeddToArchetype });
conversions.Add(new ConvertItem { PropertyName = "socialLinks", Conversion = ConversionTypes.EmbeddToArchetype });
// some xml MNTP convert to CSV and then they will 'just work'
conversions.Add(new ConvertItem { PropertyName = "showcaseGallery", Conversion = ConversionTypes.MultiNodeTreePicker });
conversions.Add(new ConvertItem { PropertyName = "aTozRelatedPages", Conversion = ConversionTypes.MultiNodeTreePicker });
// OpeningHours to Opening Soon
conversions.Add(new ConvertItem { PropertyName = "openingHours", Conversion = ConversionTypes.OpeningTimes });
// do all the conversions
converter.Convert(conversions);
sw.Stop();
LogHelper.Info<UpgradeDash>("Converter Complete in about {0} Seconds", () => sw.Elapsed.TotalSeconds);
lbStatus.Text = string.Format("Converted Completed {0} seconds", sw.Elapsed.TotalSeconds);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment