Search code examples
sitecoresitecore6

Track Sitecore item history


Sitecore tracks the item changes with last updated by, Created by information. Is it possible to track changes made to "fields" in an item against the person who changed them? And retrive the list of changes made to fields of an item.


Solution

  • You can create a custom handler and add it to item:saving event in Sitecore events/event configuration:

    <sitecore>
      <events>
        <event name="item:saving">
          <handler type="My.Assembly.Namespace.CreateHistoryEntryHandler, My.Assembly" method="OnItemSaving" />
        </event>
      </events>
    </sitecore>
    

    The class below saves the information to the Workflow History Store so you can see it using History menu from ribbon (see screenshot), but you can save it to any other place

    Sitecore Workflow History Store - changes of the item fields

    namespace My.Assembly.Namespace
    {
        public class CreateHistoryEntryHandler
        {
            protected void OnItemSaving(object sender, EventArgs args)
            {
                Item newItem = Event.ExtractParameter(args, 0) as Item;
    
                if (newItem == null || newItem.Database.DataManager.GetWorkflowInfo(newItem) == null)
                {
                    return;
                }
    
                Item originalItem = newItem.Database.GetItem(newItem.ID, newItem.Language, newItem.Version);
    
                newItem.Fields.ReadAll();
    
                IEnumerable<string> fieldNames = newItem.Fields.Select(f => f.Name);
    
                IEnumerable<string> differences = fieldNames.Where(fieldName => newItem[fieldName] != originalItem[fieldName]).ToList();
    
                if (differences.Any())
                {
                    string message = String.Format("Item content changed [{0}]", differences.Aggregate((s1, s2) => s1 + ", " + s2));
                    AddHistoryEntry(newItem, message);
                }
            }
    
            public static void AddHistoryEntry(Item item, string text)
            {
                WorkflowProvider workflowProvider = (item.Database.WorkflowProvider as WorkflowProvider);
                if (workflowProvider != null && workflowProvider.HistoryStore != null)
                {
                    string workflowState = GetWorkflowState(item);
                    workflowProvider.HistoryStore.AddHistory(item, workflowState, workflowState, text);
                }
            }
    
            private static string GetWorkflowState(Item item)
            {
                WorkflowInfo info = item.Database.DataManager.GetWorkflowInfo(item);
                return (info != null) ? info.StateID : String.Empty;
            }
        }
    }