Created
April 10, 2015 21:46
-
-
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...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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\":[]}"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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