Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Classic to Spire CMS conversion tool customizations

Describes how to convert custom pages and widgets from Classic to Spire CMS in Optimizely Configured Commerce.

See the user guide for an overview of the Classic to Spire CMS conversion tool and its limitations. Here is a basic overview of how it can be extended to convert custom pages and widgets.

Custom pages

Imagine that you have a custom page in the Classic code:

public class MyCustomPage : AbstractPage { ... }

To create a converter for this custom page, you must create a new class that meets two conditions:

  1. Implements IPageConverter interface.
  2. Has DependencyName attribute with your custom page class name.
[DependencyName("MyCustomPage")]
public class MyCustomPageConverter : IPageConverter
{
    public Node Convert(PageConvertParameter parameter) { ... }
 
    public string GetNodeType(PageConvertParameter parameter, Node spireNode) { ... }
}

This gives you full control over how your Classic custom page converts to a Spire page. However, you must account for the nuances associated with the differences in the architecture of the Classic and Spire pages, which can be a long process. Instead, you should inherit your converter from GenericPageConverter class. This is the generic OOTB converter that handles all the nuances with converting Classic page to Spire page. It contains two dozen methods that you can override and add/replace with your custom logic at each stage of the page conversion.

[DependencyName("MyCustomPage")]
public class MyCustomPageConverter : GenericPageConverter
{
    public MyCustomPageConverter(IUnitOfWorkFactory unitOfWorkFactory, IRetrievalService retrievalService) : base(unitOfWorkFactory, retrievalService) { }
 
    public override Node Convert(PageConvertParameter parameter) { ... }
 
    protected override Node CreateSpireNode(PageConvertParameter parameter) { ... }
 
    protected override void PopulateNodeFields(PageConvertParameter parameter, Node spireNode) { ... }
 
    public override string GetNodeType(PageConvertParameter parameter, Node spireNode) { ... }
 
    protected override IList<Page> CreateSpirePages(PageConvertParameter parameter, Node spireNode) { ... }
 
    protected override void PopulatePageFields(PageConvertParameter parameter, Node spireNode, Page spirePage) { ... }
 
    protected override IList<PageVersion> CreateSpirePageVersions(PageConvertParameter parameter, Node spireNode, Page spirePage) { ... }
 
    protected override void PopulateContentModelFields(ContentModelConvertParameter parameter, Node spireNode, Page spirePage, ContentModel contentModel) { ... }
 
    protected override IList<ContentItemField> GetContentItemFieldsForContentItem(ContentModelConvertParameter parameter) { ... }
 
    protected override void PopulateContentModelField(ContentModelConvertParameter parameter, Node spireNode, Page spirePage, ContentModel contentModel, ContentItemField itemField) { ... }
 
    protected override string GetContentModelFieldName(ContentItemField itemField, ContentItem item) { ... }
 
    protected override IDictionary<string, string> GetContentModelFieldNameMapping() { ... }
 
    protected override object GetContentModelFieldValue(ContentItemField itemField, ContentItem item) { ... }
 
    protected override bool IsContextualField(ContentItemField itemField, ContentItem item) { ... }
 
    protected override PageModel CreatePageModel(PageConvertParameter parameter, Node spireNode, Page spirePage) { ... }
 
    protected override IList<WidgetModel> GetWidgets(PageConvertParameter parameter, Node spireNode, Page spirePage) { ... }
 
    protected override IList<WidgetModel> GetWidgetModels(PageConvertParameter parameter, Node spireNode, Page spirePage, AbstractWidget classicWidget) { ... }
}

Most have the PageConvertParameter, which contains useful data you may need for the conversion.

public class PageConvertParameter
{
    public ContentItem ContentItem { get; set; }
 
    public IList<ContentItemField> AllContentItemFields { get; set; }
 
    public ContentTreeNodeModel ClassicNode { get; set; }
 
    public IList<ContentTreeNodeModel> AllClassicNodes { get; set; }
 
    public IList<ContentItem> AllContentItems { get; set; }
 
    public Guid WebsiteId { get; set; }
 
    public Dictionary<int, Guid> ContentKeyToIdMap { get; set; }
 
    public List<PageModel> LayoutPageModels { get; set; }
}

Custom widgets

Imagine that you have a custom widget in the Classic code:

public class MyCustomWidget : AbstractWidget { ... }

To create a converter for this custom widget, you must create new class that meets two conditions:

  1. Implements IWidgetConverter interface.
  2. Has DependencyName attribute with your custom widget class name.
[DependencyName("MyCustomWidget")]
public class MyCustomWidgetConverter : IWidgetConverter
{
    public IList<WidgetModel> Convert(WidgetConvertParameter parameter) { ... }
 
    public string GetWidgetType(WidgetConvertParameter parameter) { ... }
 
    public string ConvertZone(string zone) { ... }
}

Similar for custom pages, you have full control over how your Classic custom widget converts to a Spire widget. However, Optimizely recommends you inherit your converter from GenericWidgetConverter class. This is the generic OOTB converter that handles all the nuances with converting Classic widget to Spire widget. It contains dozen methods that you can override and add/replace with your custom logic at each stage of the widget conversion.

[DependencyName("MyCustomWidget")]
public class MyCustomWidgetConverter : GenericWidgetConverter
{
    public override IList<WidgetModel> Convert(WidgetConvertParameter parameter) { ... }
 
    protected override void PopulateContentModelFields(ContentModelConvertParameter parameter, Node spireNode, Page spirePage, ContentModel contentModel) { ... }
 
    protected override IList<ContentItemField> GetContentItemFieldsForContentItem(ContentModelConvertParameter parameter) { ... }
 
    protected override void PopulateContentModelField(ContentModelConvertParameter parameter, Node spireNode, Page spirePage, ContentModel contentModel, ContentItemField itemField) { ... }
 
    protected override string GetContentModelFieldName(ContentItemField itemField, ContentItem item) { ... }
 
    protected override IDictionary<string, string> GetContentModelFieldNameMapping() { ... }
 
    protected override object GetContentModelFieldValue(ContentItemField itemField, ContentItem item) { ... }
 
    protected override bool IsContextualField(ContentItemField itemField, ContentItem item) { ... }
 
    protected override Guid GetParentId(WidgetConvertParameter parameter) { ... }
 
    public override string GetWidgetType(WidgetConvertParameter parameter) { ... }
 
    protected override string GetZone(WidgetConvertParameter parameter) { ... }
 
    public override string ConvertZone(string zone) { ... }
}

Some have the WidgetConvertParameter, which contains useful data you may need for the widget conversion:

public class WidgetConvertParameter
{
    public ContentItem ContentItem { get; set; }
 
    public IList<ContentItemField> AllContentItemFields { get; set; }
 
    public AbstractWidget ClassicWidget { get; set; }
 
    public Guid WebsiteId { get; set; }
 
    public Dictionary<int, Guid> ContentKeyToIdMap { get; set; }
 
    public Node SpireNode { get; set; }
 
    public Page SpirePage { get; set; }
 
    public ContentItem ParentContentItem { get; set; }
 
    public List<PageModel> LayoutPageModels { get; set; }
}