November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Hi Goran,
Honestly, I think this is the cleanest way of solving this problem, I'm fairly sure there is no nice, one-stop RemoveReferencesToContent()
method! 😄
Couple of comments, based on your code comments:
Although the SaveAction enum is not decorated with the flags attribute it is a collection of "primary commands (CheckIn, Publish, Schedule) that defines the main action and option flags (ForceNewVersion, ForceCurrentVersion) that provide additional information about the save operation" (directly from the documentation). So you can do, for example:
contentRepository.Save(content, SaveAction.Publish | SaveAction.ForceNewVersion | SaveAction.SkipValidation, AccessLevel.NoAccess);
Also, how are you removing the content from the content area? It should be automatically updating the SoftLinks when you publish which happens in the DefaultContentProviderDatabase (although it first checks if any PropertyData have IsModified set to true).
I made some quick modifications to your code and the following seems to work:
var contentType = contentTypeRepository.Load<MyBlockType>();
var contentUsages = contentModelUsage.ListContentOfContentType(contentType);
var contentReferences = contentUsages.Select(x => x.ContentLink.ToReferenceWithoutVersion())
.Distinct().ToList();
foreach (var contentLink in contentReferences)
{
if (!contentRepository.TryGet(contentLink, out IContent content))
{
continue;
}
var versionable = content as IVersionable;
if (versionable?.StopPublish == null || versionable.StopPublish.Value > DateTime.Now)
{
continue;
}
var refInfos = contentRepository.GetReferencesToContent(contentLink, true);
foreach (var refInfo in refInfos)
{
if (!contentRepository.TryGet(refInfo.OwnerID, refInfo.OwnerLanguage, out ContentData owner))
{
continue;
}
owner = (ContentData)owner.CreateWritableClone();
if (owner == null)
{
continue;
}
bool updated = false;
foreach (var property in owner.Property.Where(x => x.PropertyValueType == typeof(ContentArea)))
{
var contentArea = owner[property.Name] as ContentArea;
var item = contentArea?.Items.FirstOrDefault(x =>
x.ContentLink.CompareToIgnoreWorkID(contentLink));
if (item == null)
{
continue;
}
contentArea.Items.Remove(item);
updated = true;
}
if (updated)
{
contentRepository.Save((IContent)owner, SaveAction.Publish | SaveAction.ForceNewVersion, AccessLevel.NoAccess);
}
}
}
I only checked with content areas but XHtmlStrings should work very similarly.
/Jake
I am trying to make a scheduled job that will remove expired content from content area or xhtml string to clean up the edit mode of unused blocks, but not move it to the recycle bin because maybe someday it will be used again.
I found many posts here on World and on various blogs about getting the references to specified content but nothing that would show me the way to actually remove them. I am close but something is still missing. I also think there is more cleaner way of sloving this but couldn't find any Repository or Service that would clean up list of ReferenceInformation returned by GetReferencesToContent method.
Here is the code: