At yesterdays Nordic Sitecore Conference, I was asked about how we deal with clone notifications in Sitecore. So here I’ll try to do a brief blog post of my thoughts on this and how we’ve solved it. It may be gaps in here and room for improvements, but perhaps it’s a start to get your solution work well in this area.
Clones in Sitecore has been around for quite some time now and they are really powerful and important, but also causes a lot of pain. The default implementation is quite generic but still quite well thought through. To us, this means it’s a toolbox that is mostly useless until it’s adjusted to the specific project needs. I won’t go into all those details in this post.
Clones uses a Notification concept to notify editors when things happens to related items. For example, when a child item is created of a cloned item, a ChildCreatedNotification is sent to all item clones. When the source of a non-inherited field of a cloned item is changed, a FieldChangedNotification is sent and so on. There are tons of post about this already, so just google it if you need more info about it.
To make the notification behave the way we want them to, I usually find implementing a custom NotificaitonProvider to be the best way. You can simply inherit the SqlServerNotificationProvider and override the AddNotification method. This method will be called for every notification created in the system, so we can tapp into how those are handled before the enter database. There are tons of examples already about this as well.
From the notification object we can decide if we should accept, reject or just pass through the notification. Typically like this:
public override void AddNotification(Notification notification) { var item = ItemManager.GetItem(notification.Uri.ItemID, notification.Uri.Language, notification.Uri.Version, Database.GetDatabase(notification.Uri.DatabaseName)); if (ShouldAutomaticallyAcceptChanges(notification, item)) { notification.Accept(item); } else if (ShouldAutomaticallyRejectChanges(notification, item)) { notification.Reject(item); } else { base.AddNotification(notification); } }
The two methods, ShouldAutomaticallyAcceptChanges and ShouldAutomaticallyRejectChanges, you can implement logic that suits your site. For example, certain changes should be automatically be accepted, such as centrally managed content. Local content, such as news or integrated content, you may want to automatically reject notifications and so on.
We can do this with any custom code, or we can do this in a very generic way or a combination of the two. I added some Tristate fields on my templates and fields, such as ItemCreatedNotification and FieldChangedNotification. The first I added to templates so I can set this value on the template standard values. The other is an extension to the Fields template so that I can control each individual field.
Clone Notifications section added to website templates standard values:
Field clone notifications setting added to “Template field” template:
With this, we get much more control over our notifications and the amount notifications actually sent to users becomes a much more manageable volume.
However, there is one more problem with the nature of Notifications. They are of a fire-and-forget type. When an editor receives a notification, he or she would just answer accept or reject and there is really no way to naturally change that decision. Sometimes there is a need to “re-create” those, or perhaps clean up some that has been created accidentally.
So, say hi to DevOps best friend SPE, Sitecore PowerShell Extensions!
With SPE we can easily correct notifications at any time, even on the fly in a production environment without fiddle with code deployments etc. You can even make custom commands in the UI that would synchronize parts of a clone branch with certain rules etc. The possibilities are endless.
# Below is basically just fake data. Don't even try this. It's incorrect. It won't work. # See it as a sample to start working from. $parent = Get-Item master:/content $item = Get-Item master:/content/Home $clone = New-ItemClone -Item $item -Destination $parent -Name HomeClone $provider = $clone.Database.NotificationProvider $notification = New-Object Sitecore.Data.Clones.ChildCreatedNotification $notification.ID = [Sitecore.Data.ID]::NewID $notification.Processed = $false $notification.Uri = New-Object Sitecore.Data.ItemUri($item.ID, $item.Database) $notification.ChildId = New-Object Sitecore.Data.ID("{DCF23BA5-7A42-431F-BD29-076E3A02B91F}") $provider.AddNotification($notification)
I have made some extensions to SPE that makes it easier to handle notifications, but at the time this is being written, I haven’t made pull request for it yet. But you can probably get the above to work, but keep an eye on the Notifications table in the database. Creating new notifications and actually get the right values into the database isn’t trivial. (Tips: a ItemUri will typically save the item language in the Notifications table. A ChildCreatedNotification with a non-empty language won’t show up in the editor.)
With the (maybe) upcoming addition, you’d be able to do things like the sample below. I just have to find some time to finish it and hope it gets accepted.
Get-Item master:/content/HomeClone | Get-ItemNotification | Format-Table Type, ID, Uri
That’s a great idea! I didn’t fully understood what you meant when we originally talked about it as we don’t use clones much, but this post makes it perfectly clear!
Can’t wait for your commit and to start using it in our projects!
Accepting notification while adding them won`t work with ChildCreatedNotification type.
Child item is created, but it is versionless, therefore _Source field isn`t filled and item isn`t considered as clone.
By time notifications are added, origin item doesn`t contain any versions. You should consider accept notifications later, when item:created event is called.