In Sitecore Commerce, a category/product entity associated with the different parents is treated as the different items in the Content Editor. Each item's fields are kept in the entity's ExternalSettings
component per entity relationship. So one item is edited, the others will not be updated. You can change this behavior by customizing the CatalogDataProvider
class.
To retrieve all items that share an entity, use the CatalogRepository
class. The implementation is the following.
public List<Item> GetEntityShareCatalogItems(Item item)
{
// Deterministic ID is an item's ID in the Content Editor.
var deterministicId = item.ID.Guid.ToString();
// Sitecore ID is an one-to-one GUID with the entity.
// This is used for mapping entity with items internally, so not visible in the Content Editor.
var catalogRepository = new CatalogRepository(item.Language.Name);
var sitecoreId = catalogRepository.GetSitecoreIdForDeterministicId(deterministicId);
if (string.IsNullOrWhiteSpace(sitecoreId))
{
return new List<Item> { item };
}
var entityId = catalogRepository.GetEntityIdFromMappings(sitecoreId);
if (string.IsNullOrWhiteSpace(entityId))
{
return new List<Item> { item };
}
// Get all items that share the entity ID.
var deterministicIds = catalogRepository.GetDeterministicIdsForEntityId(entityId, includeVariations: true);
if (deterministicIds == null || !deterministicIds.Any())
{
return new List<Item> { item };
}
return deterministicIds
.Select(id => ID.Parse(id, ID.Null))
.Select(item.Database.GetItem)
.Where(item => item?.Name == item.Name)
.Where(item => item.DescendsFrom(item.TemplateID))
.Where(item => item.Language == item.Language)
.ToList();
}
And apply field changes to all the items by customizing the CatalogDataProvider.SaveItem
method.
public class MyCatalogDataProvider : CatalogDataProvider
{
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context)
{
if (!CanProcessItem(itemDefinition, false))
{
return false;
}
using (new LanguageSwitcher(changes.Item.Language))
{
// Call the method here.
var catalogItems = GetEntityShareCatalogItems(changes.Item);
var success = true;
// Apply the same changes to all the items.
foreach (var item in catalogItems)
{
var definition = new ItemDefinition(item.ID, itemDefinition.Name, itemDefinition.TemplateID, itemDefinition.BranchId);
var clonedChanges = changes.Clone(item);
try
{
success &= base.SaveItem(definition, clonedChanges, context);
}
catch (Exception ex)
{
success = false;
}
}
return success;
}
}
}
Then replace the default data provider with the customized one.
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<dataProviders>
<catalogProvider type="Sitecore.Commerce.Engine.Connect.DataProvider.CatalogDataProvider, Sitecore.Commerce.Engine.Connect">
<patch:attribute name="type">Namespace.To.MyCatalogDataProvider, Assembly</patch:attribute>
</catalogProvider>
</dataProviders>
</sitecore>
</configuration>
Now when a catalog item is saved, all related items are updated together.
Top comments (0)