As I was walking along a beach near my apartment tonight, I thought “wouldn’t it be nifty to have a button in the Sitecore ribbon to accept all notifications on clones of an Item instead of having to accept these manually on each clone?”
I immediately returned home, and whipped up the following command class:
using System.Collections.Generic; using System.Linq; using Sitecore.Data.Clones; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.Shell.Framework.Commands; namespace Sitecore.Sandbox.Shell.Framework.Commands { public class AcceptAllNotificationsOnClones : Command { public override CommandState QueryState(CommandContext context) { Assert.ArgumentNotNull(context, "context"); IEnumerable<Item> clones = GetClonesWithNotifications(GetItem(context)); if(!clones.Any()) { return CommandState.Hidden; } return CommandState.Enabled; } public override void Execute(CommandContext context) { Assert.ArgumentNotNull(context, "context"); Item item = GetItem(context); IEnumerable<Item> clones = GetClonesWithNotifications(item); if(!clones.Any()) { return; } foreach (Item clone in clones) { AcceptAllNotifications(item.Database.NotificationProvider, clone); } } protected virtual Item GetItem(CommandContext context) { Assert.ArgumentNotNull(context, "context"); return context.Items.FirstOrDefault(); } protected virtual IEnumerable<Item> GetClonesWithNotifications(Item item) { Assert.ArgumentNotNull(item, "item"); IEnumerable<Item> clones = item.GetClones(); if(!clones.Any()) { return new List<Item>(); } IEnumerable<Item> clonesWithNotifications = GetClonesWithNotifications(item.Database.NotificationProvider, clones); if(!clonesWithNotifications.Any()) { return new List<Item>(); } return clonesWithNotifications; } protected virtual IEnumerable<Item> GetClonesWithNotifications(NotificationProvider notificationProvider, IEnumerable<Item> clones) { Assert.ArgumentNotNull(notificationProvider, "notificationProvider"); Assert.ArgumentNotNull(clones, "clones"); return (from clone in clones let notifications = notificationProvider.GetNotifications(clone) where notifications.Any() select clone).ToList(); } protected virtual void AcceptAllNotifications(NotificationProvider notificationProvider, Item clone) { Assert.ArgumentNotNull(notificationProvider, "notificationProvider"); Assert.ArgumentNotNull(clone, "clone"); foreach (Notification notification in notificationProvider.GetNotifications(clone)) { notification.Accept(clone); } } } }
The code in the command above ensures the command is only visible when the selected Item in the Sitecore content tree has clones, and those clones have notifications — this visibility logic is contained in the QueryState() method.
When the command is invoked — this happens through the Execute() method — all clones with notifications of the selected Item are retrieved, and iterated over — each are passed to the AcceptAllNotifications() method which contains logic to accept all notifications on them via the Accept() method on a NotificationProvider instance: this NotificationProvider instance comes from the source Item’s Database property.
I then registered the above command class in Sitecore using the following configuration file:
<?xml version="1.0" encoding="utf-8" ?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <commands> <command name="item:AcceptAllNotificationsOnClones" type="Sitecore.Sandbox.Shell.Framework.Commands.AcceptAllNotificationsOnClones, Sitecore.Sandbox"/> </commands> </sitecore> </configuration>
We need a way to invoke this command. I created a new button to go into the ‘Item Clones’ chunk in the ribbon:
Let’s take this for a test drive!
I first created some clones:
I then changed a field value on one of those clones:
On the clone’s source Item, I changed the same field’s value with something completely different, and added a new child item — the new button appeared after saving the Item:
Now, the clone has notifications on it:
I went back to the source Item, clicked the ‘Accept Notifications On Clones’ button in the ribbon, and navigated back to the clone:
As you can see, the notifications were accepted.
If you have any thoughts on this, please share in a comment.