The other day I saw a post in one of the SDN forums asking how one could go about building a solution to unlock items locked by a user when he/she logs out of Sitecore.
What immediately came to mind was building a new processor for the logout pipeline — this pipeline can be found at /configuration/sitecore/processors/logout in your Sitecore instance’s Web.config — but had to research how one would programmatically get all Sitecore items locked by the current user.
After a bit of fishing in Sitecore.Kernel.dll and Sitecore.Client.dll, I found a query in Sitecore.Client.dll that will give me all locked items for the current user:
Now all we need to do is add it into a custom logout pipeline processor:
using System; using System.Collections.Generic; using System.Linq; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.Pipelines.Logout; namespace Sitecore.Sandbox.Pipelines.Logout { public class UnlockMyItems { public void Process(LogoutArgs args) { Assert.ArgumentNotNull(args, "args"); UnlockMyItemsIfAny(); } private void UnlockMyItemsIfAny() { IEnumerable<Item> lockedItems = GetMyLockedItems(); if (!CanProcess(lockedItems)) { return; } foreach (Item lockedItem in lockedItems) { Unlock(lockedItem); } } private static IEnumerable<Item> GetMyLockedItems() { return Context.ContentDatabase.SelectItems(GetMyLockedItemsQuery()); } private static string GetMyLockedItemsQuery() { return string.Format("fast://*[@__lock='%\"{0}\"%']", Context.User.Name); } private static bool CanProcess(IEnumerable<Item> lockedItems) { return lockedItems != null && lockedItems.Any() && lockedItems.Select(item => item.Locking.HasLock()).Any(); } private void Unlock(Item item) { Assert.ArgumentNotNull(item, "item"); if (!item.Locking.HasLock()) { return; } try { item.Editing.BeginEdit(); item.Locking.Unlock(); item.Editing.EndEdit(); } catch (Exception ex) { Log.Error(this.ToString(), ex, this); } } } }
The class above grabs all items locked by the current user in the context content database. If none are found, we don’t move forward on processing.
When there are locked items for the current user, the code checks to see if each item is locked before unlocking, just in case some other account unlocks the item before we unlock it — I don’t know what would happen if we try to unlock an item that isn’t locked. If you know, please share in a comment.
I then injected the above pipeline processor into the logout pipeline using the following patch configuration file:
<?xml version="1.0" encoding="utf-8" ?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <processors> <logout> <processor patch:after="*[@type='Sitecore.Pipelines.Logout.CheckModified, Sitecore.Kernel']" type="Sitecore.Sandbox.Pipelines.Logout.UnlockMyItems, Sitecore.Sandbox"/> </logout> </processors> </sitecore> </configuration>
Let’s test-drive this.
I first logged into Sitecore using my ‘mike’ account, and chose the Home item to lock:
It is now locked:
In another session, I logged in using another account, and saw that ‘mike’ had locked the Home item:
I switched back to the other session under the ‘mike’ user, and logged out:
When I logged back in, I saw that the Home item was no longer locked:
If you have any thoughts or suggestions on making this better, please share in a comment below.
