Merge pull request #49 from leekelleher/feature-patch-courier-dataresolver

Tweaks to support a Courier DataResolver
This commit is contained in:
Kevin Giszewski
2014-02-14 09:29:57 -05:00
10 changed files with 249 additions and 138 deletions
@@ -184,6 +184,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Constants.cs" />
<Compile Include="Extensions\Extensions.cs" />
<Compile Include="Models\Archetype.cs" />
<Compile Include="Models\ArchetypePreValue.cs" />
@@ -0,0 +1,9 @@
namespace Archetype.Umbraco
{
public static class Constants
{
public const string PropertyEditorAlias = "Imulus.Archetype";
public const string PreValueAlias = "archetypeConfig";
}
}
@@ -15,7 +15,7 @@ namespace Archetype.Umbraco.Extensions
public static bool IsArchetype(this Property prop)
{
return prop.PropertyEditorAlias.InvariantEquals("Imulus.Archetype");
return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias);
}
}
}
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Archetype.Umbraco.Models
{
public class Archetype
{
public IEnumerable<Fieldset> Fieldsets { get; set; }
[JsonProperty("fieldsets")]
public IEnumerable<Fieldset> Fieldsets { get; set; }
public Archetype()
{
@@ -1,9 +1,44 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Archetype.Umbraco.Models
{
internal class ArchetypePreValue
{
internal IEnumerable<ArchetypePreValueFieldset> Fieldsets { get; set; }
}
public class ArchetypePreValue
{
[JsonProperty("showAdvancedOptions")]
public bool ShowAdvancedOptions { get; set; }
[JsonProperty("hideFieldsetToolbar")]
public bool HideFieldsetToolbar { get; set; }
[JsonProperty("enableMultipleFieldsets")]
public bool EnableMultipleFieldsets { get; set; }
[JsonProperty("hideFieldsetControls")]
public bool HideFieldsetControls { get; set; }
[JsonProperty("hidePropertyLabel")]
public bool HidePropertyLabel { get; set; }
[JsonProperty("maxFieldsets", NullValueHandling = NullValueHandling.Ignore)]
public int MaxFieldsets { get; set; }
[JsonProperty("fieldsets")]
public IEnumerable<ArchetypePreValueFieldset> Fieldsets { get; set; }
[JsonProperty("hidePropertyLabels")]
public bool HidePropertyLabels { get; set; }
[JsonProperty("customCssClass")]
public string CustomCssClass { get; set; }
[JsonProperty("customCssPath")]
public string CustomCssPath { get; set; }
[JsonProperty("customJsPath")]
public string CustomJsPath { get; set; }
[JsonProperty("developerMode")]
public bool DeveloperMode { get; set; }
}
}
@@ -1,10 +1,29 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Archetype.Umbraco.Models
{
internal class ArchetypePreValueFieldset
{
internal string Alias { get; set; }
internal IEnumerable<ArchetypePreValueProperty> Properties { get; set; }
}
}
public class ArchetypePreValueFieldset
{
[JsonProperty("alias")]
public string Alias { get; set; }
[JsonProperty("remove")]
public bool Remove { get; set; }
[JsonProperty("collapse")]
public bool Collapse { get; set; }
[JsonProperty("labelTemplate")]
public string LabelTemplate { get; set; }
[JsonProperty("icon")]
public string Icon { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("properties")]
public IEnumerable<ArchetypePreValueProperty> Properties { get; set; }
}
}
@@ -1,9 +1,37 @@
namespace Archetype.Umbraco.Models
using Newtonsoft.Json;
namespace Archetype.Umbraco.Models
{
internal class ArchetypePreValueProperty
{
internal string Alias { get; set; }
internal int DataTypeId { get; set; }
internal string PropertyEditorAlias { get; set; }
}
public class ArchetypePreValueProperty
{
[JsonProperty("alias")]
public string Alias { get; set; }
[JsonProperty("remove")]
public bool Remove { get; set; }
[JsonProperty("collapse")]
public bool Collapse { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("helpText")]
public string HelpText { get; set; }
[JsonProperty("dataTypeId")]
public int DataTypeId { get; set; }
[JsonProperty("dataTypeGuid")]
public string DataTypeGuid { get; set; }
[JsonProperty("propertyEditorAlias")]
public string PropertyEditorAlias { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("required")]
public bool Required { get; set; }
}
}
@@ -1,23 +1,26 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
namespace Archetype.Umbraco.Models
{
public class Fieldset
{
[JsonProperty("alias")]
public string Alias { get; set; }
public IEnumerable<Property> Properties;
[JsonProperty("properties")]
public IEnumerable<Property> Properties;
public Fieldset()
{
Properties = new List<Property>();
}
#region Helper Methods
#region Helper Methods
public string GetValue(string propertyAlias)
public string GetValue(string propertyAlias)
{
return GetValue<string>(propertyAlias);
}
@@ -26,18 +29,18 @@ namespace Archetype.Umbraco.Models
{
var property = GetProperty(propertyAlias);
if (property == null || string.IsNullOrEmpty(property.Value.ToString()))
return default(T);
if (property == null || string.IsNullOrEmpty(property.Value.ToString()))
return default(T);
return property.GetValue<T>();
return property.GetValue<T>();
}
private Property GetProperty(string propertyAlias)
{
return Properties.FirstOrDefault(p => p.Alias.InvariantEquals(propertyAlias));
}
}
#endregion
#endregion
}
}
@@ -1,4 +1,5 @@
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
@@ -6,66 +7,72 @@ using Umbraco.Core.PropertyEditors;
namespace Archetype.Umbraco.Models
{
public class Property
public class Property
{
public string Alias { get; internal set; }
public object Value { get; internal set; }
[JsonProperty("alias")]
public string Alias { get; internal set; }
[JsonProperty("value")]
public object Value { get; set; }
[JsonProperty("propertyEditorAlias")]
public string PropertyEditorAlias { get; internal set; }
internal int DataTypeId { get; set; }
[JsonProperty("dataTypeId")]
public int DataTypeId { get; internal set; }
public T GetValue<T>()
{
// If the value is of type T, just return it
if (Value is T)
return (T)Value;
public T GetValue<T>()
{
// If the value is of type T, just return it
if (Value is T)
return (T)Value;
// Umbraco has the concept of a IPropertyEditorValueConverter which it
// also queries for property resolvers. However I'm not sure what these
// are for, nor can I find any implementations in core, so am currently
// just ignoring these when looking up converters.
// NB: IPropertyEditorValueConverter not to be confused with
// IPropertyValueConverter which are the ones most people are creating
var properyType = CreateDummyPropertyType(DataTypeId, PropertyEditorAlias);
var converters = PropertyValueConvertersResolver.Current.Converters.ToArray();
// Umbraco has the concept of a IPropertyEditorValueConverter which it
// also queries for property resolvers. However I'm not sure what these
// are for, nor can I find any implementations in core, so am currently
// just ignoring these when looking up converters.
// NB: IPropertyEditorValueConverter not to be confused with
// IPropertyValueConverter which are the ones most people are creating
var properyType = CreateDummyPropertyType(DataTypeId, PropertyEditorAlias);
var converters = PropertyValueConvertersResolver.Current.Converters.ToArray();
// In umbraco, there are default value converters that try to convert the
// value if all else fails. The problem is, they are also in the list of
// converters, and the means for filtering these out is internal, so
// we currently have to try ALL converters to see if they can convert
// rather than just finding the most appropreate. If the ability to filter
// out default value converters becomes public, the following logic could
// and probably should be changed.
foreach (var converter in converters.Where(x => x.IsConverter(properyType)))
{
// Convert the type using a found value converter
var value2 = converter.ConvertDataToSource(properyType, Value, false);
// In umbraco, there are default value converters that try to convert the
// value if all else fails. The problem is, they are also in the list of
// converters, and the means for filtering these out is internal, so
// we currently have to try ALL converters to see if they can convert
// rather than just finding the most appropreate. If the ability to filter
// out default value converters becomes public, the following logic could
// and probably should be changed.
foreach (var converter in converters.Where(x => x.IsConverter(properyType)))
{
// Convert the type using a found value converter
var value2 = converter.ConvertDataToSource(properyType, Value, false);
// If the value is of type T, just return it
if (value2 is T)
return (T)value2;
// If the value is of type T, just return it
if (value2 is T)
return (T)value2;
// Value is not final value type, so try a regular type conversion aswell
var convertAttempt = value2.TryConvertTo<T>();
if (convertAttempt.Success)
return convertAttempt.Result;
}
// Value is not final value type, so try a regular type conversion aswell
var convertAttempt = value2.TryConvertTo<T>();
if (convertAttempt.Success)
return convertAttempt.Result;
}
// Value is not final value type, so try a regular type conversion
var convertAttempt2 = Value.TryConvertTo<T>();
if (convertAttempt2.Success)
return convertAttempt2.Result;
// Value is not final value type, so try a regular type conversion
var convertAttempt2 = Value.TryConvertTo<T>();
if (convertAttempt2.Success)
return convertAttempt2.Result;
return default(T);
}
return default(T);
}
private PublishedPropertyType CreateDummyPropertyType(int dataTypeId, string propertyEditorAlias)
{
return new PublishedPropertyType(null,
new PropertyType(new DataTypeDefinition(-1, propertyEditorAlias)
{
Id = dataTypeId
}));
}
private PublishedPropertyType CreateDummyPropertyType(int dataTypeId, string propertyEditorAlias)
{
return new PublishedPropertyType(null,
new PropertyType(new DataTypeDefinition(-1, propertyEditorAlias)
{
Id = dataTypeId
}));
}
}
}
@@ -1,11 +1,11 @@
using System;
using System.Linq;
using Archetype.Umbraco.Extensions;
using Archetype.Umbraco.Models;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Models.PublishedContent;
using Archetype.Umbraco.Models;
using Archetype.Umbraco.Extensions;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Archetype.Umbraco.PropertyConverters
@@ -15,58 +15,65 @@ namespace Archetype.Umbraco.PropertyConverters
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class ArchetypeValueConverter : PropertyValueConverterBase
{
protected JsonSerializerSettings _jsonSettings;
protected JsonSerializerSettings _jsonSettings;
public ArchetypeValueConverter()
{
var dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
public ArchetypeValueConverter()
{
var dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
_jsonSettings = new JsonSerializerSettings { ContractResolver = dcr };
}
_jsonSettings = new JsonSerializerSettings { ContractResolver = dcr };
}
public ServiceContext Services
{
get { return ApplicationContext.Current.Services; }
}
public ServiceContext Services
{
get { return ApplicationContext.Current.Services; }
}
public override bool IsConverter(PublishedPropertyType propertyType)
{
return propertyType.PropertyEditorAlias.Equals("Imulus.Archetype");
return propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias);
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null) return null;
var sourceString = source.ToString();
if (source == null)
return null;
var sourceString = source.ToString();
if (sourceString.DetectIsJson())
{
try
{
// Deserialize value to archetype model
var archetype = JsonConvert.DeserializeObject<Models.Archetype>(sourceString, _jsonSettings);
// Deserialize value to archetype model
var archetype = JsonConvert.DeserializeObject<Models.Archetype>(sourceString, _jsonSettings);
// Get list of configured properties and their types
// and map them to the deserialized archetype model
var preValue = GetArchetypePreValueFromDataTypeId(propertyType.DataTypeId);
foreach (var fieldset in preValue.Fieldsets)
{
var fieldsetAlias = fieldset.Alias;
foreach (var fieldsetInst in archetype.Fieldsets.Where(x => x.Alias == fieldsetAlias))
{
foreach (var property in fieldset.Properties)
{
var propertyAlias = property.Alias;
foreach (var propertyInst in fieldsetInst.Properties.Where(x => x.Alias == propertyAlias))
{
propertyInst.DataTypeId = property.DataTypeId;
propertyInst.PropertyEditorAlias = property.PropertyEditorAlias;
}
}
}
}
try
{
// Get list of configured properties and their types
// and map them to the deserialized archetype model
var preValue = GetArchetypePreValueFromDataTypeId(propertyType.DataTypeId);
foreach (var fieldset in preValue.Fieldsets)
{
var fieldsetAlias = fieldset.Alias;
foreach (var fieldsetInst in archetype.Fieldsets.Where(x => x.Alias == fieldsetAlias))
{
foreach (var property in fieldset.Properties)
{
var propertyAlias = property.Alias;
foreach (var propertyInst in fieldsetInst.Properties.Where(x => x.Alias == propertyAlias))
{
propertyInst.DataTypeId = property.DataTypeId;
propertyInst.PropertyEditorAlias = property.PropertyEditorAlias;
}
}
}
}
}
catch (Exception ex)
{
}
return archetype;
}
@@ -79,32 +86,32 @@ namespace Archetype.Umbraco.PropertyConverters
return sourceString;
}
internal ArchetypePreValue GetArchetypePreValueFromDataTypeId(int dataTypeId)
{
var preValues = Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId);
internal ArchetypePreValue GetArchetypePreValueFromDataTypeId(int dataTypeId)
{
var preValues = Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId);
var configJson = preValues.IsDictionaryBased
? preValues.PreValuesAsDictionary["archetypeConfig"].Value
: preValues.PreValuesAsArray.First().Value;
var configJson = preValues.IsDictionaryBased
? preValues.PreValuesAsDictionary[Constants.PreValueAlias].Value
: preValues.PreValuesAsArray.First().Value;
var config = JsonConvert.DeserializeObject<Models.ArchetypePreValue>(configJson, _jsonSettings);
var config = JsonConvert.DeserializeObject<Models.ArchetypePreValue>(configJson, _jsonSettings);
foreach (var fieldset in config.Fieldsets)
{
foreach (var property in fieldset.Properties)
{
// Lookup the properties property editor alias
// (See if we've already looked it up first though to save a database hit)
var propertyWithSameDataType = config.Fieldsets.SelectMany(x => x.Properties)
.FirstOrDefault(x => x.DataTypeId == property.DataTypeId && !string.IsNullOrWhiteSpace(x.PropertyEditorAlias));
foreach (var fieldset in config.Fieldsets)
{
foreach (var property in fieldset.Properties)
{
// Lookup the properties property editor alias
// (See if we've already looked it up first though to save a database hit)
var propertyWithSameDataType = config.Fieldsets.SelectMany(x => x.Properties)
.FirstOrDefault(x => x.DataTypeId == property.DataTypeId && !string.IsNullOrWhiteSpace(x.PropertyEditorAlias));
property.PropertyEditorAlias = propertyWithSameDataType != null
? propertyWithSameDataType.PropertyEditorAlias
: Services.DataTypeService.GetDataTypeDefinitionById(property.DataTypeId).PropertyEditorAlias;
}
}
property.PropertyEditorAlias = propertyWithSameDataType != null
? propertyWithSameDataType.PropertyEditorAlias
: Services.DataTypeService.GetDataTypeDefinitionById(property.DataTypeId).PropertyEditorAlias;
}
}
return config;
}
return config;
}
}
}