Building on some of the information Dan Sinclair's answer provided, I reached the following solution:
I needed a way to capture the "Delete" event, but only when it was triggered from inside the content editor, so after some research I found the "uiDeleteItems" processor in the Sitecore.config file, which does exactly what I want.
<uiDeleteItems>
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="CheckPermissions" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="Confirm" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="CheckTemplateLinks" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="CheckCloneLinks" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="CheckLinks" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="CheckLanguage" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="UncloneItems" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="Execute" />
<processor mode="on" type="Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel" method="PostAction" />
</uiDeleteItems>
To use this processor, I added a config patch that looked like this, the [2]
is to ensure it triggers after the "Confirm" is clicked in the default delete item popup check in Sitecore.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<processors>
<uiDeleteItems>
<processor mode="on" type="YourAbortDeleteFunctionClass, YourNamespace" method="AbortDelete" patch:after="processor[@type='Sitecore.Shell.Framework.Pipelines.DeleteItems,Sitecore.Kernel'][2]"/>
</uiDeleteItems>
</processors>
</sitecore>
</configuration>
In my workflow, I added 2 states: "(awaiting) Deletion Approval" and "Deletion Approved"
and I made it so that, on clicking "Delete" from the content editor, I would "interrupt" that process and set my current item's workflow state to "Deletion Approval" instead, making it enter my workflow cycle.
Afterwards, if this item's deletion approval is accepted, it would move to the "Deletion Approved" state, and the item would get recycled/deleted in my custom code for "Delete Item" action.
Next, I added my AbortDelete()
function, which would set the state of my item to "Awaiting deletion" and not delete it, and it looked something like this:
public void AbortDelete(ClientPipelineArgs args)
{
using (new Sitecore.SecurityModel.SecurityDisabler())
{
try
{
item.Editing.BeginEdit();
item.Fields["__Workflow"].Value = YourWorkflowID;
item.Fields["__Workflow State"].Value = YourDeletionStateID;
item.Editing.EndEdit(true, false);
}
catch (Exception ex)
{
Sitecore.Diagnostics.Log.SingleError("Error in workflow state set on deleteui" + ex, ex);
}
}
args.AbortPipeline();
}
The last thing you need to do is write some code to actually delete the items that get "Deletion approved", and add it to your "Delete Item" action, should be something along these lines
public class DeleteApproved
{
public void Process(WorkflowPipelineArgs args)
{
Assert.ArgumentNotNull(args, "args");
ProcessorItem processorItem = args.ProcessorItem;
Item currentItem = args.DataItem;
if (currentItem != null)
{
Item innerItem = currentItem;
innerItem.Recycle(); //send to recyclebin from master db
var webDB = Sitecore.Configuration.Factory.GetDatabase("web");
Item webItem = webDB.GetItem(currentItem.ID);
webItem.Recycle(); //send to recyclebin from web db
}
}
}
Hope this helps!