diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs new file mode 100644 index 0000000000..f08610350e --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs @@ -0,0 +1,69 @@ +using System; +using System.Text; +using System.Web; +using Umbraco.Core; +using Umbraco.Core.Macros; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Web.PropertyEditors.ValueConverters +{ + /// + /// Ensures macro syntax is parsed for the macro container which will work when getting the field + /// values in any way (i.e. dynamically, using Field(), or IPublishedContent) + /// + [PropertyValueType(typeof (IHtmlString))] + [PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Request)] + public class MacroContainerValueConverter : PropertyValueConverterBase + { + public override bool IsConverter(PublishedPropertyType propertyType) + { + return Guid.Parse(Constants.PropertyEditors.MacroContainer).Equals(propertyType.PropertyEditorGuid); + } + + // NOT thread-safe over a request because it modifies the + // global UmbracoContext.Current.InPreviewMode status. So it + // should never execute in // over the same UmbracoContext with + // different preview modes. + static string RenderMacros(string source, bool preview) + { + // save and set for macro rendering + var inPreviewMode = UmbracoContext.Current.InPreviewMode; + UmbracoContext.Current.InPreviewMode = preview; + + var sb = new StringBuilder(); + + try + { + var umbracoHelper = new UmbracoHelper(UmbracoContext.Current); + MacroTagParser.ParseMacros( + source, + //callback for when text block is found + textBlock => sb.Append(textBlock), + //callback for when macro syntax is found + (macroAlias, macroAttributes) => sb.Append(umbracoHelper.RenderMacro( + macroAlias, + //needs to be explicitly casted to Dictionary + macroAttributes.ConvertTo(x => (string)x, x => x)).ToString())); + } + finally + { + // restore + UmbracoContext.Current.InPreviewMode = inPreviewMode; + } + + return sb.ToString(); + } + + public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview) + { + if (source == null) return null; + var sourceString = source.ToString(); + + // ensure string is parsed for macros and macros are executed correctly + sourceString = RenderMacros(sourceString, preview); + + return sourceString; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index 2824f9a137..548d4357db 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -11,7 +11,7 @@ using Umbraco.Web.Templates; namespace Umbraco.Web.PropertyEditors.ValueConverters { - /// + /// /// A value converter for TinyMCE that will ensure any macro content is rendered properly even when /// used dynamically. /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 797b353009..aba7c4d109 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -355,6 +355,7 @@ +