private static object LiquidizeChildren( this object myObject, int levelsDeep = 0, RockContext rockContext = null, Dictionary<int, List<int>> entityHistory = null, string parentElement = "" )
{
// Add protection for stack-overflow if property attributes are not set correctly resulting in child/parent objects being evaluated in loop
levelsDeep++;
if ( levelsDeep > 6)
{
return string.Empty;
}
// If the object is liquidable, get the object return by its ToLiquid() method.
if ( myObject is DotLiquid.ILiquidizable )
{
myObject = ( (DotLiquid.ILiquidizable)myObject ).ToLiquid();
}
// If the object is null, return an empty string
if ( myObject == null )
{
return string.Empty;
}
// If the object is a string, return its value converted to HTML and truncated
if ( myObject is string )
{
return myObject.ToString().Truncate( 50 ).EncodeHtml();
}
// If the object is a guid, return its string representation
if ( myObject is Guid )
{
return myObject.ToString();
}
// Get the object's type ( checking for a proxy object )
Type entityType = myObject.GetType();
if ( entityType.IsDynamicProxyType() )
{
entityType = entityType.BaseType;
}
// If this is an IEntity, check to see if it's already been liquidized in prev heirarchy. If so, just return string indicating "--See Previous Entry--"
if ( myObject is IEntity )
{
var entity = myObject as IEntity;
var entityTypeCache = EntityTypeCache.Read( entityType, false, rockContext );
if ( entity != null && entityTypeCache != null )
{
if ( entityHistory == null )
{
entityHistory = new Dictionary<int, List<int>>();
}
entityHistory.AddOrIgnore( entityTypeCache.Id, new List<int>() );
if ( entityHistory[entityTypeCache.Id].Contains( entity.Id ) )
{
return "--See Previous Entry--";
}
else
{
entityHistory[entityTypeCache.Id].Add( entity.Id );
}
}
}
// If the object is a Liquid Drop object, return a list of all of the object's properties
if ( myObject is Drop )
{
var result = new Dictionary<string, object>();
foreach ( var propInfo in entityType.GetProperties(
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly ) )
{
if ( propInfo != null )
{
try
{
result.Add( propInfo.Name, propInfo.GetValue( myObject, null ).LiquidizeChildren( levelsDeep, rockContext, entityHistory ) );
}
catch ( Exception ex )
{
result.Add( propInfo.Name, ex.ToString() );
}
}
}
return result;
}
// If the object has the [LiquidType] attribute, enumerate the allowed properties and return a list of those properties
if ( entityType.GetCustomAttributes( typeof( LiquidTypeAttribute ), false ).Any() )
{
var result = new Dictionary<string, object>();
var attr = (LiquidTypeAttribute)entityType.GetCustomAttributes( typeof( LiquidTypeAttribute ), false ).First();
foreach ( string propName in attr.AllowedMembers )
{
var propInfo = entityType.GetProperty( propName );
{
if ( propInfo != null )
{
try
{
result.Add( propInfo.Name, propInfo.GetValue( myObject, null ).LiquidizeChildren( levelsDeep, rockContext, entityHistory, parentElement + "." + propName ) );
}
catch ( Exception ex )
{
result.Add( propInfo.Name, ex.ToString() );
}
}
}
}
return result;
}
// If the object is a Rock Liquidizable object, call the object's AvailableKeys method to determine the properties available.
if ( myObject is Lava.ILiquidizable )
{
var liquidObject = (Lava.ILiquidizable)myObject;
var result = new Dictionary<string, object>();
foreach ( var key in liquidObject.AvailableKeys )
{
// Ignore the person property of the person's primary alias (prevent unnecessary recursion)
if ( key == "Person" && parentElement.Contains( ".PrimaryAlias" ) )
{
result.AddOrIgnore( key, string.Empty );
}
else
{
try
{
object propValue = liquidObject[key];
if ( propValue != null )
{
result.Add( key, propValue.LiquidizeChildren( levelsDeep, rockContext, entityHistory, parentElement + "." + key ) );
}
else
{
result.AddOrIgnore( key, string.Empty );
}
}
catch ( Exception ex )
{
result.AddOrIgnore( key, ex.ToString() );
}
}
}
// Add the attributes if this object has attributes
if ( liquidObject is Rock.Attribute.IHasAttributes )
{
var objWithAttrs = (Rock.Attribute.IHasAttributes)liquidObject;
if ( objWithAttrs.Attributes == null )
{
rockContext = rockContext ?? new RockContext();
objWithAttrs.LoadAttributes( rockContext );
}
var objAttrs = new Dictionary<string, object>();
foreach ( var objAttr in objWithAttrs.Attributes )
{
var attributeCache = objAttr.Value;
string value = attributeCache.FieldType.Field.FormatValue( null, objWithAttrs.GetAttributeValue( attributeCache.Key ), attributeCache.QualifierValues, false );
objAttrs.Add( attributeCache.Key, value.Truncate( 50 ).EncodeHtml() );
}
if ( objAttrs.Any() )
{
result.Add( string.Format( "Attributes <p class='attributes'>Below is a list of attributes that can be retrieved using <code>{{{{ {0} | Attribute:'[AttributeKey]' }}}}</code>.</p>", parentElement ), objAttrs );
}
}
return result;
}
if ( myObject is IDictionary<string, object> )
{
var result = new Dictionary<string, object>();
foreach ( var keyValue in ( (IDictionary<string, object>)myObject ) )
{
try
{
result.Add( keyValue.Key, keyValue.Value.LiquidizeChildren( levelsDeep, rockContext, entityHistory, keyValue.Key ) );
}
catch ( Exception ex )
{
result.Add( keyValue.Key, ex.ToString() );
}
}
return result;
}
if ( myObject is Newtonsoft.Json.Linq.JObject )
{
var result = new Dictionary<string, object>();
var jObject = myObject as Newtonsoft.Json.Linq.JObject;
foreach ( var keyValue in jObject )
{
try
{
result.Add( keyValue.Key, keyValue.Value.LiquidizeChildren( levelsDeep, rockContext, entityHistory, keyValue.Key ) );
}
catch ( Exception ex )
{
result.Add( keyValue.Key, ex.ToString() );
}
}
return result;
}
if ( myObject is Newtonsoft.Json.Linq.JValue )
{
var jValue = ( myObject as Newtonsoft.Json.Linq.JValue );
if ( jValue != null && jValue.Value != null )
{
return jValue.Value.ToString();
}
else
{
return string.Empty;
}
}
if ( myObject is IEnumerable )
{
var result = new List<object>();
// Only show first two items in an enumerable list
int iEnumCount = 1;
foreach ( var value in ( (IEnumerable)myObject ) )
{
if ( iEnumCount > 2 )
{
result.Add( "..." );
break;
}
iEnumCount++;
try
{
result.Add( value.LiquidizeChildren( levelsDeep, rockContext, entityHistory, parentElement ) );
}
catch { }
}
return result;
}
return myObject.ToStringSafe();
}