Ok, this was what worked in the end, I decided the category and picture images were what we actually wanted to have with localized names. The reverse product name and category name looks ups are not great performance wise but lookups could be decreased by having the picture entity have an image type. Hope this helps others looking for the same functionality until the work item is completed, thanks Stefan for all your help! Best D
#region GetPictureUrl
/// <summary>
/// Get a picture URL
/// </summary>
/// <param name="picture">Picture instance</param>
/// <param name="targetSize">The target picture size (longest side)</param>
/// <param name="showDefaultPicture">A value indicating whether the default picture is shown</param>
/// <param name="storeLocation">Store location URL; null to use determine the current store location automatically</param>
/// <param name="defaultPictureType">Default picture type</param>
/// <returns>Picture URL</returns>
public virtual string GetPictureUrl(Picture picture, int targetSize = 0, bool showDefaultPicture = true, string storeLocation = null, PictureType defaultPictureType = PictureType.Entity)
{
string url = string.Empty;
byte[] pictureBinary = null;
if (picture != null)
pictureBinary = LoadPictureBinary(picture);
if (picture == null || pictureBinary == null || pictureBinary.Length == 0)
{
if (showDefaultPicture)
{
url = GetDefaultPictureUrl(targetSize, defaultPictureType, storeLocation);
}
return url;
}
var lastPart = GetFileExtensionFromMimeType(picture.MimeType);
var currentThumbFileName = string.Empty;
if (picture.IsNew)
{
DeletePictureThumbs(picture);
//we do not validate picture binary here to ensure that no exception ("Parameter is not valid") will be thrown
picture = UpdatePicture(picture.Id,
pictureBinary,
picture.MimeType,
picture.SeoFilename,
picture.AltAttribute,
picture.TitleAttribute,
false,
false);
}
foreach (var language in _languageService.GetAllLanguages())
{
string seoFileName;
var localizedName = GetLocalizedNameByPicture(picture, language);
if (!string.IsNullOrEmpty(localizedName))
{
seoFileName = localizedName;
}
else
{
seoFileName = GetPictureSeName(picture.SeoFilename);
}
lock (s_lock)
{
string thumbFileName;
if (targetSize == 0)
{
//original size (no resizing required)
thumbFileName = !string.IsNullOrEmpty(seoFileName)
? string.Format("{0}_{1}.{2}", picture.Id.ToString("0000000"), seoFileName, lastPart)
: string.Format("{0}.{1}", picture.Id.ToString("0000000"), lastPart);
var thumbFilePath = GetThumbLocalPath(thumbFileName);
if (!GeneratedThumbExists(thumbFilePath, thumbFileName))
{
SaveThumb(thumbFilePath, thumbFileName, pictureBinary);
}
}
else
{
//resizing required
thumbFileName = !string.IsNullOrEmpty(seoFileName)
? string.Format("{0}_{1}_{2}.{3}", picture.Id.ToString("0000000"), seoFileName, targetSize, lastPart)
: string.Format("{0}_{1}.{2}", picture.Id.ToString("0000000"), targetSize, lastPart);
var thumbFilePath = GetThumbLocalPath(thumbFileName);
if (!GeneratedThumbExists(thumbFilePath, thumbFileName))
{
using (var stream = new MemoryStream(pictureBinary))
{
Bitmap b = null;
try
{
//try-catch to ensure that picture binary is really OK. Otherwise, we can get "Parameter is not valid" exception if binary is corrupted for some reasons
b = new Bitmap(stream);
}
catch (ArgumentException exc)
{
_logger.Error(string.Format("Error generating picture thumb. ID={0}", picture.Id), exc);
}
if (b == null)
{
//bitmap could not be loaded for some reasons
return url;
}
using (var destStream = new MemoryStream())
{
var newSize = CalculateDimensions(b.Size, targetSize);
ImageBuilder.Current.Build(b, destStream, new ResizeSettings
{
Width = newSize.Width,
Height = newSize.Height,
Scale = ScaleMode.Both,
Quality = _mediaSettings.DefaultImageQuality
});
var destBinary = destStream.ToArray();
SaveThumb(thumbFilePath, thumbFileName, destBinary);
b.Dispose();
}
}
}
}
if (_workContext.WorkingLanguage == language)
{
currentThumbFileName = thumbFileName;
}
}
}
url = GetThumbUrl(currentThumbFileName, storeLocation);
return url;
}
#endregion
#region GetLocalizedNameByPicture
/// <summary>
/// Gets the localized name by picture.
/// </summary>
/// <param name="picture">The picture.</param>
/// <param name="language">The language.</param>
/// <returns></returns>
public virtual string GetLocalizedNameByPicture(Picture picture, Language language)
{
if (language.Name == "English") return GetPictureSeName(picture.SeoFilename);
var category = (from c in _categoryRepository.Table
where c.PictureId == picture.Id
select c).FirstOrDefault();
if (category != null)
return SeoExtensions.GetSeName(category.GetLocalized(x => x.Name, language.Id), true, true);
var product = (from p in _productRepository.Table
join pp in _productPictureRepository.Table on p.Id equals pp.ProductId
orderby pp.DisplayOrder
where pp.PictureId == picture.Id
select p).FirstOrDefault();
if (product != null)
return SeoExtensions.GetSeName(product.GetLocalized(x => x.Name, language.Id), true, true);
var seoFileName = GetPictureSeName(picture.SeoFilename);
return seoFileName ?? string.Empty;
}
#endregion