Skip to main content
Simplifying the code to use `GetParentBucketItemOrParent()` instead
Source Link
Dan Sinclair
  • 5.5k
  • 2
  • 20
  • 44
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($"{EscapePathGetParentBucketItemOrParent(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("#*#", "*");
        }
    }
}
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("#*#", "*");
        }
    }
}
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.GetParentBucketItemOrParent();

            // 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;
            }
        }
    }
}
Source Link
Dan Sinclair
  • 5.5k
  • 2
  • 20
  • 44

You can achieve this by programmatically moving the bucketed item to the root of the bucket with the BucketManager. Doing this will force it to reevaluate the bucket rules and reorganize it:

BucketManager.MoveItemIntoBucket(bucketedItem, bucketItem);

In our solutions, we typically create an item:saved event handler to do this automatically:

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("#*#", "*");
        }
    }
}

And don't forget your patch config, of course:

<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>