Automatically cleanup placeholder content after resource gallery items have been deleted
A problem I have been confronted serveral times is that authors have problems to save pages because the content of the page is refering to a resource gallery item that has been deleted in the past.
Usually deleting such resource gallery items should not happen as this means that the site contains broken images or invalid attachment links.
But on huge systems with many authors and different department this can happen quite often.
The best solution would be to deny the deletion of a resource gallery item if it is still in use. Unfortunatelly MCMS does not provide such a feature.
Whenever an author tries to update a posting that contains a reference to a deleted resource gallery item he will see the following error message:
Save Placeholder Failed
-----------------------------------------------------------
Error Details:
The current user does not have rights to edit the requested item. If you are seeing this exception when a MCMS template is executing, it means that you have removed the CmsAuthorizationModule from the HttpModules section of your web.config. You can only remove this module if: 1. All requests for every MCMS template in the web application will only be accessed by anonymous users 2. Guest access is enabled in MCMS (via the SCA) 3. The MCMS guest user has access to all postings based on templates in the web application If any of these requirements are not met, you MUST register the CmsAuthorizationModule in your web.config.
-----------------------------------------------------------
This error message is missleading and also does not give the author a hint about which item is causing the problem.
To bypass this problem cleanup code can be inserted in the MCMS workflow to remove all references to resource gallery items which no longer exist in the MCMS repository.
Here is sample code that can be added to the global.asax.cs to achieve this:
private bool DeletedResource(string link)
{
// Extract Resource GUID from URL
string[] splt = link.Split('/');
string GUID = splt[3];
// create new context with admin rights to be able to see deleted items
CmsApplicationContext appContext = new CmsApplicationContext();
appContext.AuthenticateAsUser("WinNT://servername/cmsAdmin", "cmsAdminPassword", PublishingMode.Unpublished);
object o = appContext.Searches.GetByGuid("{"+GUID+"}");
// Test item for being deleted
bool isDeleted= false;
if (o != null)
{
isDeleted = ((o is Resource) & (((Resource)o).Path.StartsWith("/Archive Folder")));
}
// dispose admin context
appContext.Dispose();
appContext = null;
// return result
return isDeleted;
}
private static int FindTag(string text, string tag, int start, string recursecompare)
{
int pos = text.ToLower().IndexOf(tag.ToLower(),start);
int check = text.ToLower().IndexOf(recursecompare.ToLower(),start+1);
if ((check >= 0) & (check < pos))
{
check = FindTag(text,tag,check,recursecompare);
pos = text.ToLower().IndexOf(tag.ToLower(), check+1);
}
return pos;
}
private static string RemoveTagPair(string text, string tag, string endtag, string recursecompare)
{
int start = text.ToLower().IndexOf(tag.ToLower());
int end = -1;
while (start >= 0)
{
end = FindTag(text,endtag,start,recursecompare);
if (end > start)
text = text.Remove(end,endtag.Length);
text = text.Remove(start,tag.Length);
start = text.ToLower().IndexOf(tag.ToLower());
}
return text;
}
private string HandleImgAndAttPlaceholderTypes(string propValue)
{
if (propValue.ToLower().StartsWith("/nr/rdonlyres"))
{
if (DeletedResource(propValue))
{
propValue = "";
}
}
return propValue;
}
private string HandleImageTags(string propValue)
{
int start=propValue.ToLower().IndexOf("<img ");
while (start >= 0)
{
int end = propValue.IndexOf(">",start);
if (end > start)
{
string tag = propValue.Substring(start,end-start+1);
int linkStart = tag.ToLower().IndexOf("\"/nr/rdonlyres");
if (linkStart >= 0)
{
int linkEnd = tag.IndexOf("\"",linkStart+1);
if (linkEnd > linkStart)
{
string linkStr = tag.Substring(linkStart,linkEnd-linkStart+1);
if (DeletedResource(linkStr))
{
propValue = propValue.Replace(tag,"");
tag = "";
}
}
}
start = propValue.ToLower().IndexOf("<img ",start+tag.Length);
}
}
return propValue;
}
private string HandleAnchorTags(string propValue)
{
int start=propValue.ToLower().IndexOf("<a ");
while (start >= 0)
{
int end = propValue.IndexOf(">",start);
if (end > start)
{
string tag = propValue.Substring(start,end-start+1);
int linkStart = tag.ToLower().IndexOf("\"/nr/rdonlyres");
if (linkStart >= 0)
{
int linkEnd = tag.IndexOf("\"",linkStart+1);
if (linkEnd > linkStart)
{
string linkStr = tag.Substring(linkStart,linkEnd-linkStart+1);
if (DeletedResource(linkStr))
{
propValue = RemoveTagPair(propValue,tag,"</a>","<a");
tag = "";
}
}
}
start = propValue.ToLower().IndexOf("<a ",start+tag.Length);
}
}
return propValue;
}
public void CmsPosting_PlaceholderPropertyChanging( Object sender, PropertyChangingEventArgs e )
{
string propName = e.PropertyName;
string propValue = e.PropertyValue as string;
switch (propName)
{
case "Html" : // handle HtmlPlaceholder
{
propValue = HandleImageTags(propValue);
propValue = HandleAnchorTags(propValue);
break;
}
case "Src" : // handle ImagePlaceholder
case "Url" : // handle AttachmentPlaceholder
{
propValue = HandleImgAndAttPlaceholderTypes(propValue);
break;
}
}
e.PropertyValue = propValue;
}