2

Hej 伙计们

我有一个相当大的问题,我的任务是创建一个自定义数据提供程序,用于从 SOLR 数据库中提取库存单位 (SKU) 到 sitecore,而无需实际使用项目填充数据库。

我创建了一个数据提供程序,它成功地从 SOLR 数据库中提取数据,并使用以下代码在 sitecore 中“创建”项目:

public class SkuDataProvider : DataProvider, ISkuDataProvider
{
        private readonly string _targetDatabaseName = "master";
        private readonly string _idTablePrefix = "Skus";
        private readonly ID _skuTemplateId = new ID("{F806B403-BDAF-4C60-959D-E706A82FC1DC}");
        private readonly ID _skuRootTemplateId = new ID("{9767BC47-0A95-40E9-A2DE-3766FF241411}");

        private readonly IEnumerable<SkuItemInfo> _skus;

        public SkuDataProvider(/*IProductPageService productPageService*/)
        {
            _skus = new MockDataForSkuDataProvider().GetSimpleSkuCollection();
        }


        public override ItemDefinition GetItemDefinition(ID itemId, CallContext context)
        {
            Assert.ArgumentNotNull(itemId, "itemID");

            // Retrieve the sku id from Sitecore's IDTable
            var skuId = GetSkuIdFromIdTable(itemId);

            if (!string.IsNullOrEmpty(skuId))
            {
                // Retrieve the sku data from the skus collection
                var sku = _skus.FirstOrDefault(o => o.SkuId == skuId);

                if (sku != null)
                {
                    // Ensure the sku item name is valid for the Sitecore content tree
                    var itemName = ItemUtil.ProposeValidItemName($"{sku.SkuId}_{sku.Name}");

                    // Return a Sitecore item definition for the sku using the sku template
                    return new ItemDefinition(itemId, itemName, ID.Parse(_skuTemplateId), ID.Null);
                }
            }

            return null;
        }

        private string GetSkuIdFromIdTable(ID itemId)
        {
            var idTableEntries = IDTable.GetKeys(_idTablePrefix, itemId);

            if (idTableEntries.Any())
                return idTableEntries[0].Key.ToString();

            return null;
        }

        public override IDList GetChildIDs(ItemDefinition parentItem, CallContext context)
        {
            if (CanProcessParent(parentItem.ID))
            {
                var itemIdList = new IDList();

                foreach (var sku in _skus)
                {
                    var skuId = sku.SkuId;

                    // Retrieve the Sitecore item ID mapped to his sku
                    IDTableEntry mappedId = IDTable.GetID(_idTablePrefix, skuId) ??
                                            IDTable.GetNewID(_idTablePrefix, skuId, parentItem.ID);

                    itemIdList.Add(mappedId.ID);
                }

                context.DataManager.Database.Caches.DataCache.Clear();

                return itemIdList;
            }

            return base.GetChildIDs(parentItem, context);
        }


        private bool CanProcessParent(ID id)
        {
            var item = Factory.GetDatabase(_targetDatabaseName).Items[id];

            bool canProcess = item.Paths.IsContentItem && item.TemplateID == _skuRootTemplateId && item.ID == new ID("{F37753A0-BC79-4FF7-B975-A8F142AACD76}");

            return canProcess;
        }


        public override ID GetParentID(ItemDefinition itemDefinition, CallContext context)
        {
            var idTableEntries = IDTable.GetKeys(_idTablePrefix, itemDefinition.ID);

            if (idTableEntries.Any())
            {
                return idTableEntries.First().ParentID;
            }

            return base.GetParentID(itemDefinition, context);
        }


        public override FieldList GetItemFields(ItemDefinition itemDefinition, VersionUri version, CallContext context)
        {
            var fields = new FieldList();

            var idTableEntries = IDTable.GetKeys(_idTablePrefix, itemDefinition.ID);

            if (idTableEntries.Any())
            {
                if (context.DataManager.DataSource.ItemExists(itemDefinition.ID))
                {
                    ReflectionUtil.CallMethod(typeof(ItemCache), CacheManager.GetItemCache(context.DataManager.Database), "RemoveItem", true, true, new object[] { itemDefinition.ID });
                }

                var template = TemplateManager.GetTemplate(_skuTemplateId, Factory.GetDatabase(_targetDatabaseName));

                if (template != null)
                {
                    var skuId = GetSkuIdFromIdTable(itemDefinition.ID);

                    if (!string.IsNullOrEmpty(skuId))
                    {
                        var sku = _skus.FirstOrDefault(o => o.SkuId == skuId);

                        if (sku != null)
                        {
                            foreach (var field in GetDataFields(template))
                            {
                                fields.Add(field.ID, GetFieldValue(field, sku));
                            }
                        }
                    }
                }
            }

            return fields;
        }

        protected virtual IEnumerable<TemplateField> GetDataFields(Template template)
        {
            return template.GetFields().Where(ItemUtil.IsDataField);
        }

        private string GetFieldValue(TemplateField field, SkuItemInfo sku)
        {
            string fieldValue = string.Empty;

            switch (field.Name)
            {
                case "Name":
                    fieldValue = sku.Name;
                    break;
                case "SkuId":
                    fieldValue = sku.SkuId;
                    break;
                default:
                    break;
            }
            return fieldValue;
        }
    }
} 

访问 Sitecore 后端时会出现问题,其中所有项目都以分层方式显示在存储桶项目下方。

我检查了 Root 项目是否设置了一个存储桶,并且使用的模板是可存储的。此外,在后端手动插入时,该项目已正确插入存储桶中。

有没有人对我有想法,如何解决这个问题?

最好的问候尼古拉

4

1 回答 1

1

您需要Is Bucketable在模板项的标准值而不是模板项本身上设置标志。

此外,项目被“分桶”的方式是通过创建或保存项目时的事件。Sitecore 然后创建存储桶文件夹来存储项目。在您的情况下,因为您有虚拟项目,您需要通过数据提供程序处理它们的路径。

如果您只是希望它们以与标准存储桶中相同的方式隐藏,那么我建议在您的 SKU 根文件夹下创建一个存储桶文件夹,并将该项目用作所有 SKU 虚拟项目的父项。这样,存储桶文件夹将被 sitecore 隐藏,您将获得与标准存储桶相同的视图。

这是要使用的模板: 存储桶文件夹模板

于 2016-04-18T12:08:01.870 回答