Skip to content

Instantly share code, notes, and snippets.

@casper-rasmussen
Last active May 22, 2016 13:57
Show Gist options
  • Save casper-rasmussen/954671c8385cd2ab44d805a44451399b to your computer and use it in GitHub Desktop.
Save casper-rasmussen/954671c8385cd2ab44d805a44451399b to your computer and use it in GitHub Desktop.
class InheritedCatalogPropertyLoader : CatalogPropertyLoader
{
private string[] _localReservedNames = new string[] { "Epi_StartPublish", "Epi_IsPublished", "Epi_StopPublish" };
private readonly MetaDataPropertyConfiguration _metaDataPropertyConfiguration;
private readonly MetaDataPropertyMapper _metaDataPropertyMapper;
/// <summary>
/// Initializes a new instance of the <see cref="T:EPiServer.Commerce.Catalog.Provider.Construction.CatalogPropertyLoader"/> class.
///
/// </summary>
/// <param name="metaDataPropertyMapper">The meta data property mapper.</param><param name="localizationService">The service used to get localized string resources.</param><param name="metaDataPropertyConfiguration">The catalog meta data property configuration.</param><param name="permanentLinkMapper">The permanent link mapper.</param>
[DefaultConstructor]
public InheritedCatalogPropertyLoader(MetaDataPropertyMapper metaDataPropertyMapper, LocalizationService localizationService, MetaDataPropertyConfiguration metaDataPropertyConfiguration, IPermanentLinkMapper permanentLinkMapper)
: base(metaDataPropertyMapper, localizationService, metaDataPropertyConfiguration, permanentLinkMapper)
{
this._metaDataPropertyConfiguration = metaDataPropertyConfiguration;
this._metaDataPropertyMapper = metaDataPropertyMapper;
}
public override void LoadMetaDataContentProperties(MetaObjectAccessor accessor, CatalogContentBase content)
{
if (content.Status == VersionStatus.CheckedOut && content.IsPendingPublish && !content.Language.Equals(content.MasterLanguage))
{
//If its a draft
AddInheritedMetaDataAttributePropertyValues(accessor, content);
return;
}
base.LoadMetaDataContentProperties(accessor, content);
}
public override void LoadMetaDataContentProperties(MetaObjectAccessor accessor, EntryContentBase content)
{
if (content.Status == VersionStatus.CheckedOut && content.IsPendingPublish && !content.Language.Equals(content.MasterLanguage))
{
//If its a draft then add inherited meta data
AddInheritedMetaDataAttributePropertyValues(accessor, content);
return;
}
base.LoadMetaDataContentProperties(accessor, (EntryContentBase)content);
}
private void AddInheritedMetaDataAttributePropertyValues(MetaObjectAccessor accessor, CatalogContentBase content)
{
//Load values for the current language branch - e.g. fr-LU
Hashtable existingFieldValues = accessor.GetFieldValues(content.Language.Name);
//Load values for the Master Language of the Content - e.g. fr-FR
Hashtable fieldValues = accessor.GetFieldValues(content.MasterLanguage.Name);
if (fieldValues == null)
return;
//Get the Meta Class for our Content Type
MetaClass metaClass = accessor.GetMetaClass();
//Get the list of Reserved Commerce Fields that we do not want to map
HashSet<string> reservedNames = this._metaDataPropertyConfiguration.GetReservedNames(content.GetType());
foreach (MetaField metaField in metaClass.MetaFields.Where(f => f.IsUser))
{
//Skip if the field is reserved. We don't want to map e.g. Published Date and other internal fields
if (reservedNames.Contains(metaField.Name) || this._localReservedNames.Contains(metaField.Name))
{
//Skip and do nothing if its a reserved name
}
else
{
object existingValue = existingFieldValues[metaField.Name];
//If there already are a value in Commerce for the language branch
if (existingValue != null)
continue;
//Load the Property associated with our field
PropertyData property = content.Property[metaField.Name];
//If the Property is a in-line Block
if (IsBlock(metaField.Name))
{
string blockName = GetBlockName(metaField.Name);
property = content.Property[blockName];
//Get all the metafieldnames associated with the block we are creating
IList<MetaField> metaFields = GetMetaFieldsForBlock(metaClass, blockName);
BlockData block = property.Value as BlockData;
if (block != null)
{
//Map all the Properties for this block now
foreach (MetaField blockMetaField in metaFields)
{
//Get the PropertyName on our Block for meta field
string propertyName = GetPropertyNameForBlockName(blockMetaField.Name, blockName);
PropertyData blockProperty = block.Property[propertyName];
if(blockProperty == null || !blockProperty.IsNull)
continue;
//Assign the value we've mapped out to the Block
this._metaDataPropertyMapper.AssignMetaFieldValueToProperty(property, fieldValues[blockMetaField.Name],
blockMetaField.DataType, blockMetaField.Name);
}
}
}
if (property != null)
{
if (!property.IsNull)
continue;
//Assign the fallback value to our Property
this._metaDataPropertyMapper.AssignMetaFieldValueToProperty(property, fieldValues[metaField.Name], metaField.DataType, metaField.Name);
}
}
}
}
internal static string GetBlockName(string metaFieldName)
{
//First segment that are not EPiBlock
return metaFieldName.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
.First(segment => segment != "EPiBlock");
}
internal static string GetPropertyNameForBlockName(string metaFieldName, string blockName)
{
//First segment that are not EPiBlock
return metaFieldName.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
.First(segment => segment != "EPiBlock" && segment != blockName);
}
internal static bool IsBlock(string metaFieldName)
{
return metaFieldName.StartsWith("EPiBlock");
}
internal static IList<MetaField> GetMetaFieldsForBlock(MetaClass metaClass, string blockName)
{
IList<MetaField> propertyNames = new List<MetaField>();
//Get all fields
foreach (MetaField metaField in metaClass.MetaFields.Where(f => f.IsUser))
{
//Verify if this field belongs to the Block
if (IsBlock(metaField.Name))
{
//If its a Property to the same block type
if(!blockName.Equals(GetBlockName(metaField.Name)))
continue;
propertyNames.Add(metaField);
}
}
return propertyNames;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment