Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Hi All, I resolved this by hooking into the page saving event.
The following code will automatically add (
As the page saves:
You could do this onPublish, but I chose onSaving as I wanted the editor/approvers to see exactly what the page would look like.
First install the HTMLAgilityPack from here I just put the dll in the bin folder and referenced it.
Here is the initialization code:
[InitializableModule]
[ModuleDependency(typeof (EPiServer.Web.InitializationModule))]
public class InitializationModule : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
if (!_eventsAttached)
{
DataFactory.Instance.SavingPage += PageSavingPageHandler;
_eventsAttached = true;
}
}
private void PageSavingPageHandler(object sender, PageEventArgs e)
{
// Go through each property looking for xhtmlString properties
foreach (var prop in e.Page.Property)
{
if (prop.PropertyValueType.FullName == "EPiServer.Core.XhtmlString")
{
// Use the HTML agility pack to find links within the HTML
HtmlAgilityPack.HtmlDocument theHtml = new HtmlDocument();
theHtml.LoadHtml(prop.Value.ToString());
var rootVal = theHtml.DocumentNode;
var linksInHtml = rootVal.SelectNodes("//*/a/@href");
if (linksInHtml != null && linksInHtml.Count > 0)
{
foreach (var fullLink in linksInHtml)
{
// Get the link. Internal link is in format:
// link/.aspx?id=
Match match =
new Regex(@"/link/.*?.aspx\?id=([0-9].*)\&").Match(fullLink.Attributes["href"].Value);
var docId = 0;
if (match.Success)
{
int.TryParse(match.Groups[1].Value, out docId);
}
// if we have a document ID then get the document and check extension
if (docId > 0)
{
var contRef = new ContentReference(docId);
var contentRepository = ServiceLocator.Current.GetInstance();
var media = contentRepository.Get(contRef);
var isPdf = media.RouteSegment.ToLower().EndsWith(".pdf");
var isDoc = media.RouteSegment.ToLower().EndsWith(".doc");
var isDocX = media.RouteSegment.ToLower().EndsWith(".docx");
if (isDoc || isPdf || isDocX)
{
// check if it already has a size and type and remove it
// as the link may have been re-linked or the document updated
// having a different size.
fullLink.InnerHtml = Regex.Replace(fullLink.InnerHtml,
@"\([A-Za-z]{3,4} [0-9]*[A-Za-z]{0,2}\)$",
string.Empty);
if (contRef.ID > 0)
{
int size = 0;
if (media.BinaryData!=null)
{
using (var stream = media.BinaryData.OpenRead())
{
size = (int) stream.Length;
}
}
if (size > 0)
{
if (isDoc)
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (DOC {0:fs})", size);
}
else if (isPdf)
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (PDF {0:fs})", size);
}
else
{
fullLink.InnerHtml +=
string.Format(new FileSizeFormatProvider(),
" (DOCX {0:fs})", size);
}
}
}
}
}
}
}
// reset the property value to the new value
e.Page.Property[prop.Name].Value = theHtml.DocumentNode.InnerHtml;
}
}
}
}
Here is the FileSizeFormatProvider class (This is from the net, slightly modified, original and kudos here)
public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter)) return this;
return null;
}
private const string fileSizeFormat = "fs";
private const Decimal OneKiloByte = 1024M;
private const Decimal OneMegaByte = OneKiloByte * 1024M;
private const Decimal OneGigaByte = OneMegaByte * 1024M;
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (format == null || !format.StartsWith(fileSizeFormat))
{
return defaultFormat(format, arg, formatProvider);
}
if (arg is string)
{
return defaultFormat(format, arg, formatProvider);
}
Decimal size;
try
{
size = Convert.ToDecimal(arg);
}
catch (InvalidCastException)
{
return defaultFormat(format, arg, formatProvider);
}
string suffix;
if (size > OneGigaByte)
{
size /= OneGigaByte;
suffix = "Gb";
}
else if (size > OneMegaByte)
{
size /= OneMegaByte;
suffix = "Mb";
}
else if (size > OneKiloByte)
{
size /= OneKiloByte;
suffix = "Kb";
}
else
{
suffix = "b";
}
return String.Format("{0}" + "{1}", Convert.ToInt32(size), suffix);
}
private static string defaultFormat(string format, object arg, IFormatProvider formatProvider)
{
IFormattable formattableArg = arg as IFormattable;
if (formattableArg != null)
{
return formattableArg.ToString(format, formatProvider);
}
return arg.ToString();
}
}
That's it.
Potentially, a similar method could be used to add other automated content when saving the page.
Hope it helps someone!
Cheers,
Paul
Hi All,
I have a requirement to automatically attach the file type and size to links that are inserted via an editor in an editable area.
For example: change:my link
To: my link (PDF 230kb)
What do you think is the best way to do this?
I've thought of:
All seem to have a lot of negatives!
Can anyone think of a better way?
Cheers,
Paul