Cleanup - macros

This commit is contained in:
Stephan
2016-06-08 15:32:21 +02:00
parent f8d6c90193
commit 2345d0c543
9 changed files with 92 additions and 249 deletions

View File

@@ -84,38 +84,6 @@ namespace Umbraco.Tests.Macros
Assert.AreEqual(converted.Result, prop.GetValue(ctrl));
}
[TestCase("text.xslt", "", "", "Xslt")]
[TestCase("", "~/Views/MacroPartials/test.cshtml", "", "PartialView")]
[TestCase("", "~/App_Plugins/MyPackage/Views/MacroPartials/test.cshtml", "", "PartialView")]
[TestCase("", "", "~/usercontrols/menu.ascx", "UserControl")]
[TestCase("", "", "~/usercontrols/Header.ASCX", "UserControl")]
[TestCase("", "", "", "Unknown")]
public void Determine_Macro_Type(string xslt, string scriptFile, string scriptType, string expectedType)
{
var expected = Enum<MacroTypes>.Parse(expectedType);
Assert.AreEqual(expected, Macro.FindMacroType(xslt, scriptFile, scriptType));
}
[TestCase("text.xslt", "", "", "~/xslt/text.xslt")]
//[TestCase("", "razor-script.cshtml", "", "~/macroScripts/razor-script.cshtml")] // gone in v8
[TestCase("", "~/Views/MacroPartials/test.cshtml", "", "~/Views/MacroPartials/test.cshtml")]
[TestCase("", "~/App_Plugins/MyPackage/Views/MacroPartials/test.cshtml", "", "~/App_Plugins/MyPackage/Views/MacroPartials/test.cshtml")]
[TestCase("", "", "~/usercontrols/menu.ascx", "~/usercontrols/menu.ascx")]
public void Get_Macro_File(string xslt, string scriptFile, string scriptType, string expectedResult)
{
var model = new MacroModel
{
Name = "Test",
Alias = "test",
TypeName = scriptType,
Xslt = xslt,
ScriptName = scriptFile,
MacroType = MacroModel.FindMacroType(xslt, scriptFile, scriptType)
};
var file = MacroRenderer.GetMacroFileName(model);
Assert.AreEqual(expectedResult, file);
}
[TestCase("Xslt", true)]
[TestCase("PartialView", true)]
[TestCase("UserControl", true)]

View File

@@ -87,9 +87,10 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var macro = MacroRenderer.GetMacroModel(macroAlias);
if (macro == null)
var m = Services.MacroService.GetByAlias(macroAlias);
if (m == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
var macro = new MacroModel(m);
//if it isn't supposed to be rendered in the editor then return an empty string
if (macro.RenderInEditor == false)

View File

@@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using umbraco.cms.businesslogic.macro;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Macro = Umbraco.Core.Models.Macro;
namespace Umbraco.Web.Macros
{
@@ -74,32 +68,5 @@ namespace Umbraco.Web.Macros
// can convert enums
MacroType = Core.Services.MacroService.GetMacroType(macro);
}
// fixme what's the point? used only in tests!
internal static MacroTypes FindMacroType(string xslt, string scriptFile, string scriptType /*, string scriptAssembly*/)
{
if (string.IsNullOrEmpty(xslt) == false)
return MacroTypes.Xslt;
if (string.IsNullOrEmpty(scriptFile) == false)
{
//we need to check if the file path saved is a virtual path starting with ~/Views/MacroPartials, if so then this is
//a partial view macro, not a script macro
//we also check if the file exists in ~/App_Plugins/[Packagename]/Views/MacroPartials, if so then it is also a partial view.
return (scriptFile.InvariantStartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
|| (Regex.IsMatch(scriptFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled | RegexOptions.IgnoreCase)))
? MacroTypes.PartialView
: MacroTypes.Script;
}
if (string.IsNullOrEmpty(scriptType) == false && scriptType.InvariantContains(".ascx"))
return MacroTypes.UserControl;
//if (string.IsNullOrEmpty(scriptType) == false && !string.IsNullOrEmpty(scriptAssembly))
// return MacroTypes.CustomControl;
return MacroTypes.Unknown;
}
}
}

View File

@@ -12,7 +12,6 @@ using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.UI;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
@@ -29,6 +28,8 @@ namespace Umbraco.Web.Macros
{
private readonly ProfilingLogger _plogger;
// todo: there are many more things that would need to be injected in here
public MacroRenderer(ProfilingLogger plogger)
{
_plogger = plogger;
@@ -37,22 +38,6 @@ namespace Umbraco.Web.Macros
// probably can do better - just porting from v7
public IList<Exception> Exceptions { get; } = new List<Exception>();
#region Static getters - MOVE!
public static MacroModel GetMacroModel(int id)
{
var macro = ApplicationContext.Current.Services.MacroService.GetById(id);
return macro == null ? null : new MacroModel(macro);
}
public static MacroModel GetMacroModel(string alias)
{
var macro = ApplicationContext.Current.Services.MacroService.GetByAlias(alias);
return macro == null ? null : new MacroModel(macro);
}
#endregion
#region MacroContent cache
// gets this macro content cache identifier
@@ -118,7 +103,7 @@ namespace Umbraco.Web.Macros
LogHelper.Debug<MacroRenderer>("Macro content loaded from cache \"{0}\".", () => model.CacheIdentifier);
// ensure that the source has not changed
// fixme - does not handle dependencies (never has)
// note: does not handle dependencies, and never has
var macroSource = GetMacroFile(model); // null if macro is not file-based
if (macroSource != null)
{
@@ -135,7 +120,7 @@ namespace Umbraco.Web.Macros
}
}
// fixme - legacy - what's the point? (let's keep it for now)
// this is legacy and I'm not sure what exactly it is supposed to do
if (macroContent.Control != null)
macroContent.Control.ID = macroContent.ControlId;
@@ -165,7 +150,7 @@ namespace Umbraco.Web.Macros
// controls is a bad idea, it can lead to plenty of issues ?!
// eg with IDs...
// fixme - legacy - what's the point? (let's keep it for now)
// this is legacy and I'm not sure what exactly it is supposed to do
if (macroContent.Control != null)
macroContent.ControlId = macroContent.Control.ID;
@@ -272,12 +257,7 @@ namespace Umbraco.Web.Macros
// trigger MacroRendering event so that the model can be manipulated before rendering
OnMacroRendering(new MacroRenderingEventArgs(pageElements, pageId));
// fixme - meaning INLINE macros are SCRIPTs - are we still supporting this?
var macroInfo = (macro.MacroType == MacroTypes.Script && macro.Name.IsNullOrWhiteSpace())
? $"Render Inline Macro, cache: {macro.CacheDuration}"
: $"Render Macro: {macro.Name}, type: {macro.MacroType}, cache: {macro.CacheDuration}";
var macroInfo = $"Render Macro: {macro.Name}, type: {macro.MacroType}, cache: {macro.CacheDuration}";
using (_plogger.DebugDuration<MacroRenderer>(macroInfo, "Rendered Macro."))
{
// parse macro parameters ie replace the special [#key], [$key], etc. syntaxes
@@ -304,7 +284,7 @@ namespace Umbraco.Web.Macros
// just check to avoid internal errors
macroContent = attempt.Result;
if (macroContent == null)
throw new Exception("Internal error, ExecuteMacroByType returned no content.");
throw new Exception("Internal error, ExecuteMacroOfType returned no content.");
// add to cache if render is successful
// content may be empty but that's not an issue
@@ -563,13 +543,10 @@ namespace Umbraco.Web.Macros
private static string ParseAttributeOnParents(IDictionary pageElements, string name)
{
// fixme - this was an ugly piece of nonsense
// getting better but we should inject the content cache
// and we should skip that "splitpath" thing entirely and use the
// recursive GetPropertyValue!
// this was, and still is, an ugly piece of nonsense
var value = string.Empty;
var cache = UmbracoContext.Current.ContentCache; // fixme inject?
var cache = UmbracoContext.Current.ContentCache; // should be injected
var splitpath = (string[])pageElements["splitpath"];
for (var i = splitpath.Length - 1; i > 0; i--) // at 0 we have root (-1)
@@ -625,15 +602,15 @@ namespace Umbraco.Web.Macros
private static readonly Regex HrefRegex = new Regex("href=\"([^\"]*)\"",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
// fixme - ONLY reference to an old DLL!
public static string GetRenderedMacro(int macroId, global::umbraco.page umbPage, Hashtable attributes, int pageId, ProfilingLogger plogger)
public static string GetRenderedMacro(int macroId, Hashtable elements, Hashtable attributes, int pageId, IMacroService macroService, ProfilingLogger plogger)
{
var macro = GetMacroModel(macroId);
if (macro == null) return string.Empty;
var m = macroService.GetById(macroId);
if (m == null) return string.Empty;
var model = new MacroModel(m);
// get as text, will render the control if any
var renderer = new MacroRenderer(plogger);
var macroContent = renderer.Render(macro, umbPage.Elements, pageId);
var macroContent = renderer.Render(model, elements, pageId);
var text = macroContent.GetAsText();
// remove hrefs
@@ -642,7 +619,7 @@ namespace Umbraco.Web.Macros
return text;
}
public static string MacroContentByHttp(int pageId, Guid pageVersion, Hashtable attributes)
public static string MacroContentByHttp(int pageId, Guid pageVersion, Hashtable attributes, IMacroService macroService)
{
// though... we only support FullTrust now?
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted)
@@ -650,7 +627,9 @@ namespace Umbraco.Web.Macros
var tempAlias = attributes["macroalias"]?.ToString() ?? attributes["macroAlias"].ToString();
var macro = GetMacroModel(tempAlias);
var m = macroService.GetByAlias(tempAlias);
if (m == null) return string.Empty;
var macro = new MacroModel(m);
if (macro.RenderInEditor == false)
return ShowNoMacroContent(macro);
@@ -733,8 +712,8 @@ namespace Umbraco.Web.Macros
private static string ShowNoMacroContent(MacroModel model)
{
// fixme should we html-escape the name?
return $"<span style=\"color: green\"><strong>{model.Name}</strong><br />No macro content available for WYSIWYG editing</span>";
var name = HttpUtility.HtmlEncode(model.Name); // safe
return $"<span style=\"color: green\"><strong>{name}</strong><br />No macro content available for WYSIWYG editing</span>";
}
private static bool ValidateRemoteCertificate(

View File

@@ -3,7 +3,6 @@ using System.IO;
using System.Web;
using System.Web.UI;
using umbraco;
using umbraco.cms.businesslogic.macro;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -28,35 +27,15 @@ namespace Umbraco.Web.Macros
: model.MacroControlIdentifier;
// initialize the control
// note: we are not setting the 'CurrentNode' property on the control anymore,
// as that was an INode which is gone in v8. Use UmbracoContext to access the
// current content.
LogHelper.Info<UserControlMacroEngine>($"Loaded control \"{filename}\" with ID \"{control.ID}\".");
//SetControlCurrentNode(control); // fixme what are the consequences?
UpdateControlProperties(control, model);
return new MacroContent { Control = control };
}
// no more INode in v8
/*
// sets the control CurrentNode|currentNode property
private static void SetControlCurrentNode(Control control)
{
var node = GetCurrentNode(); // get the current INode
SetControlCurrentNode(control, "CurrentNode", node);
SetControlCurrentNode(control, "currentNode", node);
}
// sets the control 'propertyName' property, of type INode
private static void SetControlCurrentNode(Control control, string propertyName, INode node)
{
var currentNodeProperty = control.GetType().GetProperty(propertyName);
if (currentNodeProperty != null && currentNodeProperty.CanWrite &&
currentNodeProperty.PropertyType.IsAssignableFrom(typeof(INode)))
{
currentNodeProperty.SetValue(control, node, null);
}
}
*/
private static string GetControlUniqueId(string filename)
{
const string key = "MacroControlUniqueId";

View File

@@ -2,29 +2,14 @@ using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Xml.Linq;
using System.Xml.XPath;
using HtmlAgilityPack;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Xml;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Templates;
using umbraco;
using System.Collections.Generic;
using umbraco.cms.businesslogic.web;
using umbraco.presentation.templateControls;
using Umbraco.Core.Cache;
using Umbraco.Web.Macros;
namespace Umbraco.Web
@@ -118,13 +103,11 @@ namespace Umbraco.Web
if (alias == null) throw new ArgumentNullException("alias");
if (umbracoPage == null) throw new ArgumentNullException("umbracoPage");
var m = MacroRenderer.GetMacroModel(alias);
var m = ApplicationContext.Current.Services.MacroService.GetByAlias(alias);
if (m == null)
{
throw new KeyNotFoundException("Could not find macro with alias " + alias);
}
return RenderMacro(m, parameters, umbracoPage);
return RenderMacro(new MacroModel(m), parameters, umbracoPage);
}
/// <summary>

View File

@@ -279,13 +279,9 @@ namespace umbraco
}
else
{
MacroModel tempMacro;
String macroID = helper.FindAttribute(attributes, "macroid");
if (macroID != String.Empty)
tempMacro = GetMacro(macroID);
else
tempMacro = MacroRenderer.GetMacroModel(helper.FindAttribute(attributes, "macroalias"));
var macroId = helper.FindAttribute(attributes, "macroid");
if (macroId == string.Empty) macroId = helper.FindAttribute(attributes, "macroalias");
var tempMacro = GetMacro(macroId);
if (tempMacro != null)
{
@@ -448,8 +444,9 @@ namespace umbraco
private static MacroModel GetMacro(string macroId)
{
HttpContext.Current.Trace.Write("umbracoTemplate", "Starting macro (" + macroId + ")");
var id = int.Parse(macroId);
return MacroRenderer.GetMacroModel(id);
// it's all obsolete anyways...
var macro = ApplicationContext.Current.Services.MacroService.GetByAlias(macroId);
return macro == null ? null : new MacroModel(macro);
}
#endregion

View File

@@ -4,7 +4,6 @@ using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using umbraco.cms.businesslogic.macro;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -21,23 +20,7 @@ namespace umbraco.presentation.templateControls
[ParseChildren(true, "Text")]
public class Macro : WebControl, ITextControl
{
private Hashtable m_Attributes = new Hashtable();
private string m_Code = String.Empty;
public Hashtable MacroAttributes
{
get
{
// Hashtable attributes = (Hashtable)ViewState["Attributes"];
return m_Attributes;
}
set
{
m_Attributes = value;
}
}
public Hashtable MacroAttributes { get; set; } = new Hashtable();
[Bindable(true)]
[Category("Umbraco")]
@@ -47,8 +30,8 @@ namespace umbraco.presentation.templateControls
{
get
{
String s = (String)ViewState["Alias"];
return ((s == null) ? String.Empty : s);
var s = (string)ViewState["Alias"];
return s ?? string.Empty;
}
set
@@ -63,8 +46,8 @@ namespace umbraco.presentation.templateControls
[Localizable(true)]
public string Language {
get {
var s = (String)ViewState["Language"];
return (s ?? String.Empty);
var s = (string)ViewState["Language"];
return s ?? string.Empty;
}
set {
ViewState["Language"] = value.ToLower();
@@ -77,8 +60,8 @@ namespace umbraco.presentation.templateControls
[Localizable(true)]
public string FileLocation {
get {
var s = (String)ViewState["FileLocation"];
return (s ?? String.Empty);
var s = (string)ViewState["FileLocation"];
return s ?? string.Empty;
}
set {
ViewState["FileLocation"] = value.ToLower();
@@ -92,7 +75,7 @@ namespace umbraco.presentation.templateControls
{
get
{
RenderEvents renderEvent = RenderEvents.Init;
var renderEvent = RenderEvents.Init;
if (ViewState["RenderEvent"] != null)
renderEvent = (RenderEvents)ViewState["RenderEvent"];
return renderEvent;
@@ -121,7 +104,7 @@ namespace umbraco.presentation.templateControls
base.OnInit(e);
// Create child controls when told to - this is the default
if (this.RenderEvent == RenderEvents.Init)
if (RenderEvent == RenderEvents.Init)
EnsureChildControls();
}
@@ -130,7 +113,7 @@ namespace umbraco.presentation.templateControls
{
base.OnPreRender(e);
if (this.RenderEvent == RenderEvents.PreRender)
if (RenderEvent == RenderEvents.PreRender)
EnsureChildControls();
}
@@ -143,32 +126,41 @@ namespace umbraco.presentation.templateControls
foreach (string key in keys)
MacroAttributes.Add(key.ToLower(), HttpUtility.HtmlDecode(Attributes[key]));
if (!MacroAttributes.ContainsKey("macroalias") && !MacroAttributes.ContainsKey("macroAlias"))
if (MacroAttributes.ContainsKey("macroalias") == false && MacroAttributes.ContainsKey("macroAlias") == false)
MacroAttributes.Add("macroalias", Alias);
// set pageId to int.MinValue if no pageID was found,
// e.g. if the macro was rendered on a custom (non-Umbraco) page
int pageId = Context.Items["pageID"] == null ? int.MinValue : int.Parse(Context.Items["pageID"].ToString());
var pageId = Context.Items["pageID"] == null ? int.MinValue : int.Parse(Context.Items["pageID"].ToString());
if ((!String.IsNullOrEmpty(Language) && Text != "") || !string.IsNullOrEmpty(FileLocation)) {
if ((string.IsNullOrEmpty(Language) == false && Text != "") || string.IsNullOrEmpty(FileLocation) == false) {
var tempMacro = new MacroModel();
MacroRenderer.GenerateMacroModelPropertiesFromAttributes(tempMacro, MacroAttributes);
if (string.IsNullOrEmpty(FileLocation)) {
tempMacro.ScriptCode = Text;
tempMacro.ScriptLanguage = Language;
} else {
tempMacro.ScriptName = FileLocation;
}
tempMacro.MacroType = MacroTypes.PartialView;
if (!String.IsNullOrEmpty(Attributes["Cache"])) {
var cacheDuration = 0;
// executing an inline macro?
// ie the code of the macro is in the control's text body
// ok, this is not supported in v8 anymore
if (string.IsNullOrEmpty(FileLocation))
throw new NotSupportedException("Inline macros are not supported anymore.");
// executing an on-disk macro
// it has to be a partial (cshtml or vbhtml) macro in v8
var extension = System.IO.Path.GetExtension(FileLocation);
if (extension.InvariantEndsWith(".cshtml") == false && extension.InvariantEndsWith(".vbhtml") == false)
throw new NotSupportedException("");
tempMacro.ScriptName = FileLocation;
tempMacro.MacroType = MacroTypes.PartialView;
if (string.IsNullOrEmpty(Attributes["Cache"]) == false)
{
int cacheDuration;
if (int.TryParse(Attributes["Cache"], out cacheDuration))
tempMacro.CacheDuration = cacheDuration;
else
Context.Trace.Warn("Template", "Cache attribute is in incorect format (should be an integer).");
}
var renderer = new MacroRenderer(ApplicationContext.Current.ProfilingLogger);
var c = renderer.Render(tempMacro, (Hashtable) Context.Items["pageElements"], pageId).GetAsControl();
if (c != null)
@@ -177,22 +169,29 @@ namespace umbraco.presentation.templateControls
Controls.Add(c);
}
else
{
Context.Trace.Warn("Template", "Result of inline macro scripting is null");
} else {
var tempMacro = MacroRenderer.GetMacroModel(Alias);
if (tempMacro != null) {
try {
var renderer = new MacroRenderer(ApplicationContext.Current.ProfilingLogger);
var c = renderer.Render(tempMacro, (Hashtable)Context.Items["pageElements"], pageId, MacroAttributes).GetAsControl();
if (c != null)
Controls.Add(c);
else
Context.Trace.Warn("Template", "Result of macro " + tempMacro.Name + " is null");
} catch (Exception ee) {
Context.Trace.Warn("Template", "Error adding macro " + tempMacro.Name, ee);
throw;
}
}
}
else
{
var m = ApplicationContext.Current.Services.MacroService.GetByAlias(Alias);
if (m == null) return;
var tempMacro = new MacroModel(m);
try
{
var renderer = new MacroRenderer(ApplicationContext.Current.ProfilingLogger);
var c = renderer.Render(tempMacro, (Hashtable)Context.Items["pageElements"], pageId, MacroAttributes).GetAsControl();
if (c != null)
Controls.Add(c);
else
Context.Trace.Warn("Template", "Result of macro " + tempMacro.Name + " is null");
}
catch (Exception ee)
{
Context.Trace.Warn("Template", "Error adding macro " + tempMacro.Name, ee);
throw;
}
}
}
@@ -206,23 +205,18 @@ namespace umbraco.presentation.templateControls
// Create child controls when told to - do it here anyway as it has to be done
EnsureChildControls();
bool isDebug = GlobalSettings.DebugMode && (Context.Request.GetItemAsString("umbdebugshowtrace") != "" || Context.Request.GetItemAsString("umbdebug") != "");
var isDebug = GlobalSettings.DebugMode && (Context.Request.GetItemAsString("umbdebugshowtrace") != "" || Context.Request.GetItemAsString("umbdebug") != "");
if (isDebug)
{
writer.Write("<div title=\"Macro Tag: '{0}'\" style=\"border: 1px solid #009;\">", Alias);
}
base.RenderChildren(writer);
RenderChildren(writer);
if (isDebug)
{
writer.Write("</div>");
}
}
public string Text
{
get { return m_Code; }
set { m_Code = value; }
}
public string Text { get; set; } = string.Empty;
}
}

View File

@@ -342,7 +342,6 @@ namespace umbraco.cms.businesslogic.macro
{
}
#region STATICS
/// <summary>
@@ -407,28 +406,6 @@ namespace umbraco.cms.businesslogic.macro
});
}
public static MacroTypes FindMacroType(string xslt, string scriptFile, string scriptType)
{
if (string.IsNullOrEmpty(xslt) == false)
return MacroTypes.Xslt;
if (string.IsNullOrEmpty(scriptFile) == false)
{
//we need to check if the file path saved is a virtual path starting with ~/Views/MacroPartials, if so then this is
//a partial view macro, not a script macro
//we also check if the file exists in ~/App_Plugins/[Packagename]/Views/MacroPartials, if so then it is also a partial view.
return (scriptFile.InvariantStartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
|| (Regex.IsMatch(scriptFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled | RegexOptions.IgnoreCase)))
? MacroTypes.PartialView
: MacroTypes.Script;
}
if (string.IsNullOrEmpty(scriptType) == false && scriptType.InvariantContains(".ascx"))
return MacroTypes.UserControl;
return MacroTypes.Unknown;
}
#region Macro Refactor
private static string GetCacheKey(string alias)
@@ -438,8 +415,6 @@ namespace umbraco.cms.businesslogic.macro
#endregion
#endregion
}
}