Sunday, 28 May 2023

Sitecore Content Hub: Finding Assets with Missing Renditions

 If you worked with Sitecore Content Hub, you must have worked with DAM module and in particular your worked with Renditions, if you don't know much about renditions I would suggest to go through my previous articles on it, just click here, In these previous posts I have explains renditions and how you can refresh renditions and how sometimes refresh rendition will be challenging, in this post I would like to provide some scripts samples of how you can find assets with missing renditions, keep reading! 



Imagine you would like a way to get a list of images with missing renditions, this could happen after you update the media processing set or specific flow, you may refresh renditions for assets through UI or through a mass edit job programmatically, some may fail, in any case, is there a way to get the Ids of assets of missing renditions? the answer is YES! keep reading. 

In the following script, I'm executing a query to get the media processing set / Media Matric that I would like to search my assets against, you can also see how I'm getting the renditions names that should be there when asset match this media processing set. 

public async Task<List<Flow>> GetMediaMatrix()
{
List<Flow> Flows = new List<Flow>();
MClient.Logger.Debug("GetMediaMatrix Prepare Query");
var query = Query.CreateQuery(entities =>
from e in entities
where
e.DefinitionName == "M.MediaMatrix" &&
e.Property("MediaMatrixName") == "content"
select e);
//Search to retrieve the MediaMatrix entity
MClient.Logger.Debug("GetMediaMatrix execute Query started");
var mediaMatrix = await MClient.Querying.QueryAsync(query);
MClient.Logger.Debug("GetMediaMatrix execute Query completed");
if (mediaMatrix == null)
{
throw new Exception("media Matrix retrieved is null, exit execution");
}
if (mediaMatrix.Items.Count == 0)
{
throw new Exception("media Matrix retrieved count is zero, exit execution");
}
MClient.Logger.Debug("GetMediaMatrix get first or default");
var contentMediaSettings = mediaMatrix.Items.FirstOrDefault();
MClient.Logger.Debug($"GetMediaMatrix get first or default {contentMediaSettings.Id.ToString()}");
MClient.Logger.Debug("GetMediaMatrix get contentMediaSettings started");
var fullContentMediaSettings = await MClient.Entities.GetAsync(contentMediaSettings.Id.Value, EntityLoadConfiguration.Full);
MClient.Logger.Debug("GetMediaMatrix get contentMediaSettings completed");
MClient.Logger.Debug("GetMediaMatrix getting/parsing Matrix started");
var matrix = fullContentMediaSettings.GetPropertyValue<Newtonsoft.Json.Linq.JArray>("Matrix");
MClient.Logger.Debug("GetMediaMatrix getting/parsing Matrix completed");
MClient.Logger.Debug("GetMediaMatrix loop flows started");
foreach (var flow in matrix)
{
var name = flow["name"].ToString();
if (name == "Default")
continue;
var fileTypes = flow["extensions"].ToString();
var renditions = (Newtonsoft.Json.Linq.JObject)flow["output"]["renditions"]["Renditions"];
if (renditions == null)
continue;
List<string> tasksNames = new List<string>();
foreach (var _rendition in renditions.Children())
{
tasksNames.Add(((Newtonsoft.Json.Linq.JProperty)_rendition).Name);
}
Flows.Add(new Flow
{
Name = name,
FileTypes = JArray.Parse(fileTypes).Select(e => e.ToString()).ToList(),
Renditions = tasksNames
});
}
MClient.Logger.Debug("GetMediaMatrix loop flows completed");
return Flows;
}
view raw gistfile1.txt hosted with ❤ by GitHub


Now once you have the flow(s) you're targeting, you can loop through the assets and get the assets with missing renditions, in the following script you can see I'm using an iterator to go through assets, then getting the file properties to get the extension and then compare with the right flow:  

public async Task<List<string>> getNextAssetsBlock(int Limit, List<Flow> Flows, List<string> BaseIdsList, int RoundNo)
{
MClient.Logger.Debug("getNextAssetsBlock started");
List<string> assetsIds = BaseIdsList;
var query = new Query
{
Filter = new CompositeQueryFilter()
{
Children = new QueryFilter[] {
new DefinitionQueryFilter {
Name = "M.Asset"
}
},
CombineMethod = CompositeFilterOperator.And
}
};
query.Take = 1000;
MClient.Logger.Debug("Query started");
var iterator = MClient.Querying.CreateEntityIdScroller(query, TimeSpan.FromSeconds(50));
MClient.Logger.Debug("Query completed");
// validate based on extension [match the flow with asset extension].
int counter = 0;
int assetsCount = 0;
while (await iterator.MoveNextAsync().ConfigureAwait(false))
{
assetsCount += iterator.Current.Items.Count;
// if (assetsIds.Count == Limit)
// break;
MClient.Logger.Debug("foreach started");
foreach (var Id in iterator.Current.Items)
{
// if (assetsIds.Count == Limit)
// break;
EntityLoadConfiguration assetLoadConfiguration = new EntityLoadConfiguration
{
PropertyLoadOption = new PropertyLoadOption("FileProperties", "Renditions"),
RelationLoadOption = RelationLoadOption.None,
CultureLoadOption = CultureLoadOption.None
};
try
{
var _asset = await MClient.Entities.GetAsync(Id, assetLoadConfiguration);//asset.Id.Value
var fileProperties = _asset.GetPropertyValue<Newtonsoft.Json.Linq.JObject>("FileProperties");
var assetCurrentRenditions = _asset.GetPropertyValue<Newtonsoft.Json.Linq.JObject>("Renditions");
if (fileProperties != null)
{
var assetExtension = Convert.ToString(fileProperties["properties"]["extension"]);
if (assetExtension != string.Empty)
{
if (Flows.Where(f => f.FileTypes.Contains(assetExtension)).Any())
{
var flow = Flows.Where(f => f.FileTypes.Contains(assetExtension)).FirstOrDefault();
if (flow.Renditions != null)
{
foreach (var rendition in flow.Renditions)
{
// This is not accurate, comment out for now.
//var _rendition = _asset.GetRendition(rendition);
if (assetCurrentRenditions == null || assetCurrentRenditions[rendition] == null)
{
assetsIds.Add(Id.ToString());
break;
}
}
}
else
{
//MClient.Logger.Debug($"renditions is null {Id.ToString()}");
}
}
else
{
//MClient.Logger.Debug($"flow is null {Id.ToString()}");
}
}
else
{
//MClient.Logger.Debug($"asset extension is empty {Id.ToString()}");
}
}
else
{
//MClient.Logger.Debug($"asset fileProperties is null {Id.ToString()}");
}
}
catch (Exception ex)
{
MClient.Logger.Error($"Error with Asset Id {Id.ToString()} exception {ex.Message}");
}
}
MClient.Logger.Debug($"iterator started {counter++}");
MClient.Logger.Debug($"Assets Count {assetsCount}");
MClient.Logger.Debug($"Assets with missing renditions {assetsIds.Count}");
MClient.Logger.Debug("foreach completed");
}
return assetsIds;
}
view raw gistfile1.txt hosted with ❤ by GitHub


Hope this helps someone, please do reach out through comments or email if you have comments or you need help/consultation. 

No comments:

Post a Comment