Skip to content

Instantly share code, notes, and snippets.

@robertjf
Last active April 5, 2018 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertjf/c6d9122d90b4406b19ec to your computer and use it in GitHub Desktop.
Save robertjf/c6d9122d90b4406b19ec to your computer and use it in GitHub Desktop.
NestedContentCreator - generate a NestedContent Property Value based on a Property Type and a list of dictionary items.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors;
namespace RMS.Extensions.Importers
{
public static class NestedContentCreator
{
public static List<object> GenerateNestedContentList(PropertyType property, IEnumerable<Dictionary<string, object>> data)
{
var contentType = GetContentType(property.DataTypeDefinitionId);
List<object> nodes = new List<object>();
foreach (var item in data)
{
nodes.Add(GenerateNestedContentItem(contentType, item));
}
return nodes;
}
public static string GenerateNestedContentValue(PropertyType property, IEnumerable<Dictionary<string, object>> data)
{
return JsonConvert.SerializeObject(GenerateNestedContentList(property, data));
}
public static object GenerateNestedContentItem(IContentType contentType, Dictionary<string, object> propertyData)
{
// Update template and populate.
var propValues = new JObject();
foreach (var propKey in propertyData.Keys)
{
var propType = contentType.PropertyTypes.FirstOrDefault(x => x.Alias == propKey);
if (propType == null)
{
if (propKey != "name")
{
// Property missing so just delete the value
propValues[propKey] = null;
}
}
else
{
// Fetch the property types prevalue
var propPreValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propType.DataTypeDefinitionId);
// Lookup the property editor
var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias);
// Create a fake content property data object
var contentPropData = new ContentPropertyData(
propertyData[propKey] == null ? null : propertyData[propKey].ToString(), propPreValues,
new Dictionary<string, object>());
// Get the property editor to do it's conversion
var newValue = propEditor.ValueEditor.ConvertEditorToDb(contentPropData, propValues[propKey]);
// Add the property
propValues[propKey] = (newValue == null) ? null : JToken.FromObject(newValue);
}
}
return propValues;
}
private static IContentType GetContentType(int propertyDefinitionId)
{
var preValueCollection = (PreValueCollection)ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
string.Concat("Our.Umbraco.NestedContent.GetPreValuesCollectionByDataTypeId_", propertyDefinitionId),
() => ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propertyDefinitionId));
var preValuesDict = preValueCollection.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);
Guid contentTypeGuid;
if (!preValuesDict.ContainsKey("docTypeGuid") || !Guid.TryParse(preValuesDict["docTypeGuid"], out contentTypeGuid))
return null;
var contentTypeAlias = GetContentTypeAliasByGuid(Guid.Parse(preValuesDict["docTypeGuid"]));
return ApplicationContext.Current.Services.ContentTypeService.GetContentType(contentTypeAlias);
}
private static string GetContentTypeAliasByGuid(Guid id)
{
return (string)ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
string.Concat("Our.Umbraco.NestedContent.GetContentTypeAliasByGuid_", id),
() => ApplicationContext.Current.DatabaseContext.Database
.ExecuteScalar<string>("SELECT [cmsContentType].[alias] FROM [cmsContentType] INNER JOIN [umbracoNode] ON [cmsContentType].[nodeId] = [umbracoNode].[id] WHERE [umbracoNode].[uniqueID] = @0", id));
}
}
}
// showbag is of type IContent.
var pt = showbag.PropertyTypes.FirstOrDefault(p => p.Alias == "locations");
// db is an EntityFramework CodeFirst database, with a table rasv_ShowbagStallLocation.
// In this example I want to take all locations related to the showbag and import them as a NestedContent list.
// Create and serialise the Showbag Locations
showbag.SetValue(pt.Alias, NestedContentCreator.GenerateNestedContentValue(pt,
db.rasv_ShowbagStallLocation
.Where(i => i.ShowbagId == showbagId)
.ToList()
.Select(location => new Dictionary<string, object>
{
{"location", location.ShowbagLocationHTML},
// EnsureEventPrecinct is another method that effectively
// maps the EvenTPrecinctId to a Content Node.
{"eventPrecinct", EnsureEventPrecinct(location.EventPrecinctId).Id}
}
)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment