From 1aebce7ad666f82b461e9eb8a7f1793bbcd07e1c Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Sat, 29 Sep 2012 11:11:48 +0700 Subject: [PATCH] makes SystemDirectories and SystemFiles public. moves ResolveUrlsFromTextString to TemplateUtilities class and obsoletes other ones. Fixes an issue if content cache is stored in codegen folder and not in med trust. Updates the XmlDocument (IDocumentProperty) to always return a value with parsed {localLink} and resolved Urls and cache them so the parsing only happens once. --- src/Umbraco.Core/Dynamics/DynamicDocument.cs | 151 +++++------------- src/Umbraco.Core/Dynamics/PropertyResult.cs | 16 +- src/Umbraco.Core/IO/IOHelper.cs | 61 +++---- src/Umbraco.Core/IO/SystemDirectories.cs | 2 +- src/Umbraco.Core/IO/SystemFiles.cs | 6 +- src/Umbraco.Web/Models/XmlDocumentProperty.cs | 21 ++- src/Umbraco.Web/Mvc/RenderViewPage.cs | 5 - .../Templates/TemplateUtilities.cs | 48 +++++- src/Umbraco.Web/umbraco.presentation/macro.cs | 3 +- .../umbraco/nodeFactory/Page_Legacy.cs | 5 +- .../umbraco/nodeFactory/Property.cs | 4 +- .../umbraco/templateControls/ItemRenderer.cs | 3 +- src/umbraco.businesslogic/IO/IOHelper.cs | 2 +- 13 files changed, 158 insertions(+), 169 deletions(-) diff --git a/src/Umbraco.Core/Dynamics/DynamicDocument.cs b/src/Umbraco.Core/Dynamics/DynamicDocument.cs index 88a65dec8b..44e98fbc1e 100644 --- a/src/Umbraco.Core/Dynamics/DynamicDocument.cs +++ b/src/Umbraco.Core/Dynamics/DynamicDocument.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Dynamics /// public class DynamicDocument : DynamicObject { - private readonly IDocument _backingItem; + private readonly IDocument _document; private DynamicDocumentList _cachedChildren; private readonly ConcurrentDictionary _cachedMemberOutput = new ConcurrentDictionary(); @@ -28,7 +28,7 @@ namespace Umbraco.Core.Dynamics public DynamicDocument(IDocument node) { if (node == null) throw new ArgumentNullException("node"); - _backingItem = node; + _document = node; } /// @@ -107,82 +107,9 @@ namespace Umbraco.Core.Dynamics return DynamicDocumentWalker.Sibling(this, nodeTypeAlias); } - //public DynamicDocumentList XPath(string xPath) - //{ - // //if this DN was initialized with an underlying NodeFactory.Node - // if (n != null && n.Type == DynamicBackingItemType.Content) - // { - // //get the underlying xml content - // XmlDocument doc = umbraco.content.Instance.XmlContent; - // if (doc != null) - // { - // //get n as a XmlNode (to be used as the context point for the xpath) - // //rather than just applying the xPath to the root node, this lets us use .. etc from the DynamicNode point - - - // //in test mode, n.Id is 0, let this always succeed - // if (n.Id == 0) - // { - // List selfList = new List() { this }; - // return new DynamicDocumentList(selfList); - // } - // XmlNode node = doc.SelectSingleNode(string.Format("//*[@id='{0}']", n.Id)); - // if (node != null) - // { - // //got the current node (within the XmlContent instance) - // XmlNodeList nodes = node.SelectNodes(xPath); - // if (nodes.Count > 0) - // { - // //we got some resulting nodes - // List nodeFactoryNodeList = new List(); - // //attempt to convert each node in the set to a NodeFactory.Node - // foreach (XmlNode nodeXmlNode in nodes) - // { - // try - // { - // nodeFactoryNodeList.Add(new NodeFactory.Node(nodeXmlNode)); - // } - // catch (Exception) { } //swallow the exceptions - the returned nodes might not be full nodes, e.g. property - // } - // //Wanted to do this, but because we return DynamicDocumentList here, the only - // //common parent class is DynamicObject - // //maybe some future refactoring will solve this? - // //if (nodeFactoryNodeList.Count == 0) - // //{ - // // //if the xpath resulted in a node set, but none of them could be converted to NodeFactory.Node - // // XElement xElement = XElement.Parse(node.OuterXml); - // // //return - // // return new DynamicXml(xElement); - // //} - // //convert the NodeFactory nodelist to IEnumerable and return it as a DynamicDocumentList - // return new DynamicDocumentList(nodeFactoryNodeList.ConvertAll(nfNode => new DynamicNode((INode)nfNode))); - // } - // else - // { - // // XPath returned no nodes, return an empty DynamicDocumentList - // return new DynamicDocumentList(); - // } - // } - // else - // { - // throw new NullReferenceException("Couldn't locate the DynamicNode within the XmlContent"); - // } - // } - // else - // { - // throw new NullReferenceException("umbraco.content.Instance.XmlContent is null"); - // } - // } - // else - // { - // throw new NullReferenceException("DynamicNode wasn't initialized with an underlying NodeFactory.Node"); - // } - //} - - public bool HasProperty(string name) { - if (_backingItem != null) + if (_document != null) { try { @@ -240,7 +167,7 @@ namespace Umbraco.Core.Dynamics { try { - result = ExecuteExtensionMethod(args, binder.Name, false); + result = ExecuteExtensionMethod(args, binder.Name); return true; } catch (TargetInvocationException) @@ -269,7 +196,7 @@ namespace Umbraco.Core.Dynamics } - private object ExecuteExtensionMethod(object[] args, string name, bool argsContainsThis) + private object ExecuteExtensionMethod(object[] args, string name) { object result = null; @@ -350,7 +277,7 @@ namespace Umbraco.Core.Dynamics protected virtual Attempt TryGetChildrenByAlias(GetMemberBinder binder) { - var filteredTypeChildren = _backingItem.Children + var filteredTypeChildren = _document.Children .Where(x => x.DocumentTypeAlias.InvariantEquals(binder.Name) || x.DocumentTypeAlias.MakePluralName().InvariantEquals(binder.Name)) .ToArray(); if (filteredTypeChildren.Any()) @@ -403,7 +330,7 @@ namespace Umbraco.Core.Dynamics var result = userProperty.Value; - if (_backingItem.DocumentTypeAlias == null && userProperty.Alias == null) + if (_document.DocumentTypeAlias == null && userProperty.Alias == null) { throw new InvalidOperationException("No node alias or property alias available. Unable to look up the datatype of the property you are trying to fetch."); } @@ -496,7 +423,7 @@ namespace Umbraco.Core.Dynamics /// private PropertyResult GetReflectedProperty(string alias) { - return GetPropertyInternal(alias, _backingItem, false); + return GetPropertyInternal(alias, _document, false); } /// @@ -509,15 +436,15 @@ namespace Umbraco.Core.Dynamics { if (!recursive) { - return GetPropertyInternal(alias, _backingItem); + return GetPropertyInternal(alias, _document); } var context = this; - var prop = GetPropertyInternal(alias, _backingItem); + var prop = GetPropertyInternal(alias, _document); while (prop == null || !prop.HasValue()) { context = context.Parent; if (context == null) break; - prop = context.GetPropertyInternal(alias, context._backingItem); + prop = context.GetPropertyInternal(alias, context._document); } return prop; } @@ -830,7 +757,7 @@ namespace Umbraco.Core.Dynamics } internal DynamicDocumentList Descendants(Func func) { - var flattenedNodes = this._backingItem.Children.Map(func, (IDocument n) => n.Children); + var flattenedNodes = this._document.Children.Map(func, (IDocument n) => n.Children); return new DynamicDocumentList(flattenedNodes.ToList().ConvertAll(dynamicBackingItem => new DynamicDocument(dynamicBackingItem))); } public DynamicDocumentList DescendantsOrSelf(int level) @@ -847,14 +774,14 @@ namespace Umbraco.Core.Dynamics } internal DynamicDocumentList DescendantsOrSelf(Func func) { - if (this._backingItem != null) + if (this._document != null) { var thisNode = new List(); - if (func(this._backingItem)) + if (func(this._document)) { - thisNode.Add(this._backingItem); + thisNode.Add(this._document); } - var flattenedNodes = this._backingItem.Children.Map(func, (IDocument n) => n.Children); + var flattenedNodes = this._document.Children.Map(func, (IDocument n) => n.Children); return new DynamicDocumentList(thisNode.Concat(flattenedNodes).ToList().ConvertAll(dynamicBackingItem => new DynamicDocument(dynamicBackingItem))); } return new DynamicDocumentList(Enumerable.Empty()); @@ -906,11 +833,11 @@ namespace Umbraco.Core.Dynamics { get { - if (_backingItem.Parent != null) + if (_document.Parent != null) { - return new DynamicDocument(_backingItem.Parent); + return new DynamicDocument(_document.Parent); } - if (_backingItem != null && _backingItem.Id == 0) + if (_document != null && _document.Id == 0) { return this; } @@ -920,17 +847,17 @@ namespace Umbraco.Core.Dynamics public int TemplateId { - get { return _backingItem.TemplateId; } + get { return _document.TemplateId; } } public int SortOrder { - get { return _backingItem.SortOrder; } + get { return _document.SortOrder; } } public string Name { - get { return _backingItem.Name; } + get { return _document.Name; } } public bool Visible { @@ -948,66 +875,66 @@ namespace Umbraco.Core.Dynamics public string UrlName { - get { return _backingItem.UrlName; } + get { return _document.UrlName; } } public string DocumentTypeAlias { - get { return _backingItem.DocumentTypeAlias; } + get { return _document.DocumentTypeAlias; } } public string WriterName { - get { return _backingItem.WriterName; } + get { return _document.WriterName; } } public string CreatorName { - get { return _backingItem.CreatorName; } + get { return _document.CreatorName; } } public int WriterId { - get { return _backingItem.WriterId; } + get { return _document.WriterId; } } public int CreatorId { - get { return _backingItem.CreatorId; } + get { return _document.CreatorId; } } public string Path { - get { return _backingItem.Path; } + get { return _document.Path; } } public DateTime CreateDate { - get { return _backingItem.CreateDate; } + get { return _document.CreateDate; } } public int Id { - get { return _backingItem.Id; } + get { return _document.Id; } } public DateTime UpdateDate { - get { return _backingItem.UpdateDate; } + get { return _document.UpdateDate; } } public Guid Version { - get { return _backingItem.Version; } + get { return _document.Version; } } public int Level { - get { return _backingItem.Level; } + get { return _document.Level; } } public IEnumerable Properties { - get { return _backingItem.Properties; } + get { return _document.Properties; } } public IEnumerable Children @@ -1016,15 +943,15 @@ namespace Umbraco.Core.Dynamics { if (_cachedChildren == null) { - var children = _backingItem.Children; + var children = _document.Children; //testing, think this must be a special case for the root node ? - if (!children.Any() && _backingItem.Id == 0) + if (!children.Any() && _document.Id == 0) { - _cachedChildren = new DynamicDocumentList(new List { new DynamicDocument(this._backingItem) }); + _cachedChildren = new DynamicDocumentList(new List { new DynamicDocument(this._document) }); } else { - _cachedChildren = new DynamicDocumentList(_backingItem.Children.Select(x => new DynamicDocument(x))); + _cachedChildren = new DynamicDocumentList(_document.Children.Select(x => new DynamicDocument(x))); } } return _cachedChildren; diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs index ebefc76ea5..bcabfd05e4 100644 --- a/src/Umbraco.Core/Dynamics/PropertyResult.cs +++ b/src/Umbraco.Core/Dynamics/PropertyResult.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Dynamics { internal class PropertyResult : IDocumentProperty, IHtmlString { - public PropertyResult(IDocumentProperty source, PropertyResultType type) + internal PropertyResult(IDocumentProperty source, PropertyResultType type) { if (source == null) throw new ArgumentNullException("source"); @@ -16,7 +16,7 @@ namespace Umbraco.Core.Dynamics Version = source.Version; PropertyType = type; } - public PropertyResult(string alias, object value, Guid version, PropertyResultType type) + internal PropertyResult(string alias, object value, Guid version, PropertyResultType type) { if (alias == null) throw new ArgumentNullException("alias"); if (value == null) throw new ArgumentNullException("value"); @@ -32,10 +32,16 @@ namespace Umbraco.Core.Dynamics public string Alias { get; private set; } public object Value { get; private set; } - - public string ValueAsString + + /// + /// Returns the value as a string output, this is used in the final rendering process of a property + /// + internal string ValueAsString { - get { return Value == null ? "" : Convert.ToString(Value); } + get + { + return Value == null ? "" : Convert.ToString(Value); + } } public Guid Version { get; private set; } diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index 1defb0562e..d5a5e2e452 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -9,12 +9,14 @@ using System.Configuration; using System.Web; using System.Text.RegularExpressions; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Core.IO { internal static class IOHelper { private static string _rootDir = ""; + // static compiled regex for faster performance private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); @@ -49,46 +51,33 @@ namespace Umbraco.Core.IO return VirtualPathUtility.ToAbsolute(virtualPath, SystemDirectories.Root); } - + [Obsolete("Use Umbraco.Web.Templates.TemplateUtilities.ResolveUrlsFromTextString instead, this method on this class will be removed in future versions")] public static string ResolveUrlsFromTextString(string text) { if (UmbracoSettings.ResolveUrlsFromTextString) - { - var sw = new Stopwatch(); - sw.Start(); - Debug.WriteLine("Start: " + sw.ElapsedMilliseconds); - - // find all relative urls (ie. urls that contain ~) - var tags = - ResolveUrlPattern.Matches(text); - Debug.WriteLine("After regex: " + sw.ElapsedMilliseconds); - foreach (Match tag in tags) - { - Debug.WriteLine("-- inside regex: " + sw.ElapsedMilliseconds); - string url = ""; - if (tag.Groups[1].Success) - url = tag.Groups[1].Value; - - // The richtext editor inserts a slash in front of the url. That's why we need this little fix - // if (url.StartsWith("/")) - // text = text.Replace(url, ResolveUrl(url.Substring(1))); - // else - if (!String.IsNullOrEmpty(url)) - { - Debug.WriteLine("---- before resolve: " + sw.ElapsedMilliseconds); - string resolvedUrl = (url.Substring(0, 1) == "/") ? ResolveUrl(url.Substring(1)) : ResolveUrl(url); - Debug.WriteLine("---- after resolve: " + sw.ElapsedMilliseconds); - Debug.WriteLine("---- before replace: " + sw.ElapsedMilliseconds); - text = text.Replace(url, resolvedUrl); - Debug.WriteLine("---- after replace: " + sw.ElapsedMilliseconds); - } - - } - - Debug.WriteLine("total: " + sw.ElapsedMilliseconds); - sw.Stop(); - Debug.WriteLine("Resolve Urls", sw.ElapsedMilliseconds.ToString()); + { + using (var timer = DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete")) + { + // find all relative urls (ie. urls that contain ~) + var tags = ResolveUrlPattern.Matches(text); + LogHelper.Debug(typeof(IOHelper), "After regex: " + timer.Stopwatch.ElapsedMilliseconds + " matched: " + tags.Count); + foreach (Match tag in tags) + { + string url = ""; + if (tag.Groups[1].Success) + url = tag.Groups[1].Value; + // The richtext editor inserts a slash in front of the url. That's why we need this little fix + // if (url.StartsWith("/")) + // text = text.Replace(url, ResolveUrl(url.Substring(1))); + // else + if (!String.IsNullOrEmpty(url)) + { + string resolvedUrl = (url.Substring(0, 1) == "/") ? ResolveUrl(url.Substring(1)) : ResolveUrl(url); + text = text.Replace(url, resolvedUrl); + } + } + } } return text; } diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index 1fc9a98c40..521407898a 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -10,7 +10,7 @@ using System.IO; namespace Umbraco.Core.IO { //all paths has a starting but no trailing / - internal class SystemDirectories + public class SystemDirectories { public static string Bin { diff --git a/src/Umbraco.Core/IO/SystemFiles.cs b/src/Umbraco.Core/IO/SystemFiles.cs index 59b2debf0a..f8a7a368e5 100644 --- a/src/Umbraco.Core/IO/SystemFiles.cs +++ b/src/Umbraco.Core/IO/SystemFiles.cs @@ -8,7 +8,7 @@ using System.Web; namespace Umbraco.Core.IO { - internal class SystemFiles + public class SystemFiles { public static string AccessXml @@ -96,7 +96,7 @@ namespace Umbraco.Core.IO { get { - if (ContentCacheXmlIsEphemeral) + if (ContentCacheXmlIsEphemeral && SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted) { return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config"); } @@ -104,7 +104,7 @@ namespace Umbraco.Core.IO } } - public static bool ContentCacheXmlIsEphemeral + internal static bool ContentCacheXmlIsEphemeral { get { diff --git a/src/Umbraco.Web/Models/XmlDocumentProperty.cs b/src/Umbraco.Web/Models/XmlDocumentProperty.cs index 110e01d723..7affc17852 100644 --- a/src/Umbraco.Web/Models/XmlDocumentProperty.cs +++ b/src/Umbraco.Web/Models/XmlDocumentProperty.cs @@ -5,6 +5,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models; +using Umbraco.Web.Templates; namespace Umbraco.Web.Models { @@ -25,9 +26,27 @@ namespace Umbraco.Web.Models get { return _alias; } } + private string _parsedValue; + + /// + /// Returns the value of a property from the XML cache + /// + /// + /// This ensures that the result has any {localLink} syntax parsed and that urls are resolved correctly. + /// This also ensures that the parsing is only done once as the result is cached in a private field of this object. + /// public object Value { - get { return IOHelper.ResolveUrlsFromTextString(_value); } + get + { + if (_parsedValue == null) + { + _parsedValue = TemplateUtilities.ResolveUrlsFromTextString( + TemplateUtilities.ParseInternalLinks( + _value)); + } + return _parsedValue; + } } public Guid Version diff --git a/src/Umbraco.Web/Mvc/RenderViewPage.cs b/src/Umbraco.Web/Mvc/RenderViewPage.cs index 61568e8ecf..8dcf775672 100644 --- a/src/Umbraco.Web/Mvc/RenderViewPage.cs +++ b/src/Umbraco.Web/Mvc/RenderViewPage.cs @@ -71,10 +71,5 @@ namespace Umbraco.Web.Mvc get { return _helper ?? (_helper = new UmbracoHelper(UmbracoContext)); } } - public override void Write(object value) - { - base.Write(value); - } - } } \ No newline at end of file diff --git a/src/Umbraco.Web/Templates/TemplateUtilities.cs b/src/Umbraco.Web/Templates/TemplateUtilities.cs index a46e1673b6..6e55c42c2c 100644 --- a/src/Umbraco.Web/Templates/TemplateUtilities.cs +++ b/src/Umbraco.Web/Templates/TemplateUtilities.cs @@ -1,5 +1,10 @@ -using System.Text.RegularExpressions; +using System; +using System.Text.RegularExpressions; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using umbraco; +using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Templates { @@ -32,6 +37,47 @@ namespace Umbraco.Web.Templates return text; } + // static compiled regex for faster performance + private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + /// + /// The RegEx matches any HTML attribute values that start with a tilde (~), those that match are passed to ResolveUrl to replace the tilde with the application path. + /// + /// + /// + /// + /// When used with a Virtual-Directory set-up, this would resolve all URLs correctly. + /// The recommendation is that the "ResolveUrlsFromTextString" option (in umbracoSettings.config) is set to false for non-Virtual-Directory installs. + /// + public static string ResolveUrlsFromTextString(string text) + { + if (UmbracoSettings.ResolveUrlsFromTextString) + { + using (var timer = DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete")) + { + // find all relative urls (ie. urls that contain ~) + var tags = ResolveUrlPattern.Matches(text); + LogHelper.Debug(typeof(IOHelper), "After regex: " + timer.Stopwatch.ElapsedMilliseconds + " matched: " + tags.Count); + foreach (Match tag in tags) + { + string url = ""; + if (tag.Groups[1].Success) + url = tag.Groups[1].Value; + + // The richtext editor inserts a slash in front of the url. That's why we need this little fix + // if (url.StartsWith("/")) + // text = text.Replace(url, ResolveUrl(url.Substring(1))); + // else + if (!String.IsNullOrEmpty(url)) + { + string resolvedUrl = (url.Substring(0, 1) == "/") ? IOHelper.ResolveUrl(url.Substring(1)) : ResolveUrl(url); + text = text.Replace(url, resolvedUrl); + } + } + } + } + return text; + } } } diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index 75bdf4e7f2..2de4c1d2b8 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -17,6 +17,7 @@ using System.Web.UI.WebControls; using System.Xml; using System.Xml.Xsl; using Umbraco.Core; +using Umbraco.Web.Templates; using umbraco.BusinessLogic; using umbraco.BusinessLogic.Utils; using umbraco.cms.businesslogic.macro; @@ -757,7 +758,7 @@ namespace umbraco // Do transformation UmbracoContext.Current.Trace.Write("umbracoMacro", "Before performing transformation"); xslt.Transform(macroXML.CreateNavigator(), xslArgs, tw); - return IOHelper.ResolveUrlsFromTextString(tw.ToString()); + return TemplateUtilities.ResolveUrlsFromTextString(tw.ToString()); } public static XsltArgumentList AddXsltExtensions() diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Page_Legacy.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Page_Legacy.cs index c758cb9373..af162f6681 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Page_Legacy.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Page_Legacy.cs @@ -4,6 +4,7 @@ using System.Data; using System.Xml; using System.Xml.Serialization; using System.Xml.XPath; +using Umbraco.Web.Templates; using umbraco.cms.businesslogic; using umbraco.cms.businesslogic.propertytype; @@ -543,9 +544,11 @@ namespace umbraco.presentation.nodeFactory get { return _alias; } } + private string _parsedValue; + public string Value { - get { return IO.IOHelper.ResolveUrlsFromTextString(_value); } + get { return _parsedValue ?? (_parsedValue = TemplateUtilities.ResolveUrlsFromTextString(_value)); } } public Guid Version diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Property.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Property.cs index 7e06cac940..caee1f6689 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Property.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Property.cs @@ -1,6 +1,7 @@ using System; using System.Xml; using System.Xml.Serialization; +using Umbraco.Web.Templates; using umbraco.interfaces; namespace umbraco.NodeFactory @@ -18,9 +19,10 @@ namespace umbraco.NodeFactory get { return _alias; } } + private string _parsedValue; public string Value { - get { return IO.IOHelper.ResolveUrlsFromTextString(_value); } + get { return _parsedValue ?? (_parsedValue = TemplateUtilities.ResolveUrlsFromTextString(_value)); } } public Guid Version diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs index bedcc3a4cc..7a0b7a50f9 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs @@ -8,6 +8,7 @@ using System.Web; using System.Web.UI; using System.Xml; using Umbraco.Core.Macros; +using Umbraco.Web.Templates; using umbraco.cms.businesslogic; using umbraco.cms.businesslogic.property; using umbraco.cms.businesslogic.web; @@ -65,7 +66,7 @@ namespace umbraco.presentation.templateControls // handle text before/after xsltTransformedOutput = AddBeforeAfterText(xsltTransformedOutput, helper.FindAttribute(item.LegacyAttributes, "insertTextBefore"), helper.FindAttribute(item.LegacyAttributes, "insertTextAfter")); string finalResult = xsltTransformedOutput.Trim().Length > 0 ? xsltTransformedOutput : GetEmptyText(item); - writer.Write(IOHelper.ResolveUrlsFromTextString(finalResult)); + writer.Write(TemplateUtilities.ResolveUrlsFromTextString(finalResult)); } catch (Exception renderException) { diff --git a/src/umbraco.businesslogic/IO/IOHelper.cs b/src/umbraco.businesslogic/IO/IOHelper.cs index 8bc3f886b2..3679e1cdfa 100644 --- a/src/umbraco.businesslogic/IO/IOHelper.cs +++ b/src/umbraco.businesslogic/IO/IOHelper.cs @@ -36,7 +36,7 @@ namespace umbraco.IO return Umbraco.Core.IO.IOHelper.ResolveUrl(virtualPath); } - + [Obsolete("Use Umbraco.Web.Templates.TemplateUtilities.ResolveUrlsFromTextString instead, this method on this class will be removed in future versions")] public static string ResolveUrlsFromTextString(string text) { return Umbraco.Core.IO.IOHelper.ResolveUrlsFromTextString(text);