Sitecore 8:保存时同步存储桶项目

时间:2015-09-16 15:02:01

标签: sitecore sitecore7 sitecore7.2 bucket sitecore8

我已经了解了如何为新创建的存储桶项提供默认条件和默认操作。我也知道我们可以根据自定义日期字段创建自定义规则来构建路径。

但是,如何在日期字段和保存时设置项目路径。 考虑一个例子。我们有一个桶项目模板说“新闻”,其日期字段说“发布日期”。我们有项目创建的设置,项目路径的创建日期如“/ News / 2015/09/16 / item1”。现在,我们需要有一些逻辑,我们可以在更新“item1”的“发布日期”并且项目已保存时更改路径。

如果项目的发布日期更新且项目已保存,我们如何更新项目路径!!我需要在OnItemSaved()方法中实现一些逻辑吗?

我已经浏览了GeekHive

上的帖子

5 个答案:

答案 0 :(得分:5)

最简单的方法是挂钩项目:保存事件并在那里同步存储桶。以下代码未经测试:

public class ItemSavedEventHandler
{
    public void Execute(object sender, ItemSavedEventArgs args)
    {
        Assert.IsNotNull(sender, "sender is null");
        Assert.IsNotNull(args, "args is null");

        using (new EventsDisabler())
        {
            var parameter = args.Item;
            if (!BucketManager.IsItemContainedWithinBucket(paremeter))
            {
                return;
            }

            var bucketItem = parameter.GetParentBucketItemOrParent();
            if (!bucketItem.IsABucket())
            {
                return;
            }

            BucketManager.Sync(bucketItem);
        }
    }
}

在包含大量物品的水桶上,这将大大减慢保存过程。

答案 1 :(得分:3)

如果我理解正确,您希望您的存储桶项目路径基于日期更新而不是创建?我是对的吗?

如果是的话,这不是一件简单的事情。我看到了以下方法来实现它。

  1. 将您的存储桶配置为按更新日期进行组织,而不是创建(您提到您已经知道如何配置该行为)。从标准模板派生的每个Sitecore项都应具有统计部分,其中 __更新字段(两个下划线为开头),每个项目自动更新,并保存相应的事件。你应该使用那个字段。

  2. 完成后,同步所有现有项目以应用该分段项目路径。

  3. 处理项目:已保存事件

  4. 项目:已保存事件处理程序中:取消该特定项目并再次重新打包该项目(使用项目:unbucket 项目:存储桶命令)

  5. 您的特定项目将会实施您的分段路径规则。

  6. 希望有所帮助!

答案 2 :(得分:1)

在某些答案的基础上,这是大多数情况下最易读/性能最佳的解决方案:

using Sitecore.Buckets.Extensions;
using Sitecore.Buckets.Managers;
using Sitecore.Data.Events;
using Sitecore.Diagnostics;
using System;
using Sitecore.Data.Items;
using Sitecore.Events;

namespace XXXX.Project.Web.Infrastructure.Pipelines
{
    public class MoveItemIntoBucketOnSave
    {
        public void OnItemSaved(object sender, EventArgs args)
        {
            Assert.IsNotNull(sender, "sender is null");
            Assert.IsNotNull(args, "args is null");

            var savedItem = Event.ExtractParameter(args, 0) as Item;

            if (savedItem == null || savedItem.Database.Name.ToLower() != "master" || !savedItem.IsItemBucketable())
            {
                return;
            }

            using (new EventDisabler())
            {
                if (!BucketManager.IsItemContainedWithinBucket(savedItem))
                {
                    return;
                }

                var bucketItem = savedItem.GetParentBucketItemOrParent();
                if (!bucketItem.IsABucket())
                {
                    return;
                }

                // If you want to sync the entire bucket
                // BucketManager.Sync(bucketItem);

                BucketManager.MoveItemIntoBucket(savedItem, bucketItem);
            }
        }
    }
}

我不担心此操作后是否有空的存储桶文件夹,因为它们将在完整的存储桶同步期间被清理,并且内容作者通常不会遍历存储桶树,因为他们应该使用搜索。

这是配置:

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <events>
      <event name="item:saved">
        <handler type="XXXX.Project.Web.Infrastructure.Pipelines.MoveItemIntoBucketOnSave, XXXX.Project.Web" method="OnItemSaved" />
      </event>
    </events>
  </sitecore>
</configuration>

答案 3 :(得分:0)

您需要实现管道处理器。 您可以通过将以下内容添加到App_Code / Include文件夹中的.config文件中来完成此操作。

<processors>
    <saveUI>
        <processor mode="on" type="Namespace.ClassName, Your.Assembly" patch:after="processor[last()]" />
    </saveUI>
</processor

你还需要实现那个类 - 除了它必须有一个带有Sitecore.Pipelines.Save.SaveArgs参数的公共Process方法之外没什么特别的。

namespace CustomFunctions
{
    public class SaveAction
    {
        public void Process(SaveArgs args)
        {
            // There's a collection of items
            // I'm not sure what the situation where there's more than one item is though.
            var items = args.SavedItems;

            var bucket = SomeFunctionToGetParent(items);

            BucketManager.Sync(items);
        }
    }
}

我从来没有真正实现过这个,但我认为我的代码应该让你知道如何开始 - 虽然这个管道处理器会在每次保存项目时被调用,所以你需要有效的检查以确保该项目需要使用您的存储桶同步处理器。

答案 4 :(得分:0)

您可以通过使用BucketManager将存储桶中的项目以编程方式移动到存储桶的根中来实现。这样做将迫使它重新评估存储桶规则并重新组织它:

BucketManager.MoveItemIntoBucket(bucketedItem, bucketItem);

请注意,这与BucketManager.Sync(bucketItem)不同,因为它不同步整个存储桶,而是仅处理已更改的单个项目。

在我们的解决方案中,我们通常创建一个item:saved事件处理程序以自动执行此操作:

using Sitecore.Buckets.Managers;
using Sitecore.Buckets.Util;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Events;
using System;
using System.Text.RegularExpressions;

namespace Custom.Events.ItemSaved
{
    public class ReorganizeBucketedItemInBucket
    {
        public void OnItemSaved(object sender, EventArgs args)
        {
            var bucketedItem = Event.ExtractParameter(args, 0) as Item;

            // If we don't have an item or we're not saving in the master DB, ignore this save
            if (bucketedItem == null || !"master".Equals(bucketedItem.Database?.Name, StringComparison.OrdinalIgnoreCase))
                return;

            if (!bucketedItem.TemplateID.Equals(new ID("{bucketed-item-template-id}"))) return;

            var itemChanges = Event.ExtractParameter(args, 1) as ItemChanges;

            // If there were no changes or the changes didn't include the date field, ignore this save
            if (itemChanges == null || !itemChanges.HasFieldsChanged || !itemChanges.IsFieldModified(new ID("{field-id-of-date-field}")))
                return;

            Item bucketItem = bucketedItem.Axes.SelectSingleItem($"{EscapePath(bucketedItem.Paths.FullPath)}/ancestor-or-self::*[@@templateid = '{{bucket-container-template-id}}']");

            // If this item isn't in a bucket (or is in a bucket of another, unexpected type), ignore it
            if (bucketItem == null) return;

            Item parent = bucketedItem.Parent;
            BucketManager.MoveItemIntoBucket(bucketedItem, bucketItem);

            // Delete empty ancestor bucket folders
            while (parent != null && !parent.HasChildren && parent.TemplateID == BucketConfigurationSettings.BucketTemplateId)
            {
                Item tempParent = parent.Parent;
                parent.Delete();
                parent = tempParent;
            }
        }

        /// <summary>
        /// Wraps each segment of a sitecore path with "#"'s
        /// </summary>
        public string EscapePath(string path)
        {
            return Regex.Replace(path, @"([^/]+)", "#$1#").Replace("#*#", "*");
        }
    }
}

当然,不要忘记您的补丁配置:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <events>
            <event name="item:saved">
                <handler type="Custom.Events.ItemSaved.ReorganizeBucketedItemInBucket, Custom.Events" method="OnItemSaved"></handler>
            </event>
        </events>
    </sitecore>
</configuration>