3

I've written a custom bucket action to set the path based on a template date field, rather than the created date. I based this information off this blog: http://techitpro.com/uncategorized/sitecore-bucket-structure-item-field-value-based/

On creation, the template date field is set via a standard value to today's date, but this could be changed on edit. I found an old article asking about this: https://stackoverflow.com/questions/32612278/sitecore-8-sync-a-bucket-item-on-save. The original answer mentioned using the BucketManager.Sync function, which would sync the entire bucket, but a comment suggested there was a way to sync a single item and have its path alter like the entire bucket sync had been done.

Since this bucket is going to contain thousands of items, I'd like to avoid syncing the whole bucket on save each time. Is syncing a single item a feasible option in Sitecore 9.1.1, or is that not advisable?

1 Answer 1

3

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.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;
            }
        }
    }
}

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>
4
  • 1
    Just implemented this, Dan, and it works great. One tweak I made from something I saw before, instead of using ancestor or self, I found this extension to get the top level bucket item: Item bucketItem = bucketedItem.GetParentBucketItemOrParent(); Commented Sep 27, 2019 at 1:35
  • Thanks for that little detail! I've updated the code to simplify it. Commented Sep 27, 2019 at 2:34
  • Dan, I may blog about this in the near future and I'll be sure to reference this for credit. I made an additional change to make the template/field configurable via the config. Which led me to branching out to updating my custom bucket rules to add those kinds of features as well. Thanks again for your help! Commented Sep 27, 2019 at 19:04
  • Note the following important points about BucketManager.MoveItemIntoBucket. 1) Unlike Sync, as items are moved around within the bucket, empty folders may be left behind, which may be annoying to some content authors. 2) MoveItemIntoBucket breaks some implementations, so be sure to test it. Commented Aug 27 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.