From 2a90e93a6f6cb42376c836570a219f9578e2fc5d Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 7 Dec 2012 07:04:11 +0500 Subject: [PATCH] Updated partial view macro engine to support storing the files in the App_Plugins/[packagename]/Views/MacroPartials so they can be stored with a package and not pollute the main file system. --- src/Umbraco.Core/IO/SystemDirectories.cs | 9 ++++ .../developer/Macros/EditMacro.aspx.cs | 43 +++++++++++++++---- .../Macros/PartialViewMacroEngine.cs | 4 +- src/Umbraco.Web/Mvc/Constants.cs | 1 - src/Umbraco.Web/Mvc/PluginViewEngine.cs | 24 +++++------ src/umbraco.cms/businesslogic/macro/Macro.cs | 9 ++-- 6 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index 6828b0e353..e70046c90e 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -69,6 +69,15 @@ namespace Umbraco.Core.IO } } + public static string AppPlugins + { + get + { + //NOTE: this is not configurable and shouldn't need to be + return "~/App_Plugins"; + } + } + public static string MvcViews { get diff --git a/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs b/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs index 3f2a0ec4ef..faa356e177 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Web; using System.Web.UI.WebControls; using Umbraco.Core.IO; @@ -32,10 +33,11 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros { base.PopulateFieldsOnLoad(macro, macroAssemblyValue, macroTypeValue); //check if the ScriptingFile property contains the MacroPartials path - if (macro.ScriptingFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")) + if (macro.ScriptingFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/") + || (Regex.IsMatch(macro.ScriptingFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled))) { macroPython.Text = ""; - SelectedPartialView.Text = Path.GetFileName(macro.ScriptingFile); + SelectedPartialView.Text = macro.ScriptingFile; } } @@ -52,7 +54,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros base.SetMacroValuesFromPostBack(macro, macroCachePeriod, macroAssemblyValue, macroTypeValue); if (!SelectedPartialView.Text.IsNullOrWhiteSpace()) { - macro.ScriptingFile = SystemDirectories.MvcViews + "/MacroPartials/" + SelectedPartialView.Text; + macro.ScriptingFile = SelectedPartialView.Text; } } @@ -62,19 +64,40 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros private void PopulatePartialViewFiles() { var partialsDir = IOHelper.MapPath(SystemDirectories.MvcViews + "/MacroPartials"); - var views = GetPartialViewFiles(partialsDir, partialsDir); - PartialViewList.DataSource = views; + //get all the partials in the normal /MacroPartials folder + var foundMacroPartials = GetPartialViewFiles(partialsDir, partialsDir, SystemDirectories.MvcViews + "/MacroPartials"); + //now try to find all of them int he App_Plugins/[PackageName]/Views/MacroPartials folder + var partialPluginsDir = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + foreach(var d in partialPluginsDir.GetDirectories()) + { + var viewsFolder = d.GetDirectories("Views"); + if (viewsFolder.Any()) + { + var macroPartials = viewsFolder.First().GetDirectories("MacroPartials"); + if (macroPartials.Any()) + { + foundMacroPartials = foundMacroPartials.Concat( + GetPartialViewFiles(macroPartials.First().FullName, macroPartials.First().FullName, SystemDirectories.AppPlugins + "/" + d.Name + "/Views/MacroPartials")); + } + } + } + + + + PartialViewList.DataSource = foundMacroPartials; PartialViewList.DataBind(); PartialViewList.Items.Insert(0, new ListItem("Browse partial view files on server...", string.Empty)); } /// - /// Get the list of partial view files in the ~/Views/MacroPartials folder + /// Get the list of partial view files in the ~/Views/MacroPartials folder and in all + /// folders of ~/App_Plugins/[PackageName]/Views/MacroPartials /// /// /// + /// /// - private IEnumerable GetPartialViewFiles(string orgPath, string path) + private IEnumerable GetPartialViewFiles(string orgPath, string path, string prefixVirtualPath) { var files = new List(); var dirInfo = new DirectoryInfo(path); @@ -83,12 +106,14 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros var dirInfos = dirInfo.GetDirectories(); foreach (var dir in dirInfos) { - files.AddRange(GetPartialViewFiles(orgPath, path + "/" + dir.Name)); + files.AddRange(GetPartialViewFiles(orgPath, path + "/" + dir.Name, prefixVirtualPath)); } var fileInfo = dirInfo.GetFiles("*.*"); - files.AddRange(fileInfo.Select(file => (path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/'))); + files.AddRange( + fileInfo.Select(file => + prefixVirtualPath.TrimEnd('/') + "/" + (path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/'))); return files; } diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs index 600d2d1fd6..28e558e358 100644 --- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Web; using System.Web.Mvc; using System.Web.Routing; @@ -90,7 +91,8 @@ namespace Umbraco.Web.Macros if (macro == null) throw new ArgumentNullException("macro"); if (currentPage == null) throw new ArgumentNullException("currentPage"); - if (!macro.ScriptName.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")) + if (!macro.ScriptName.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/") + && (!Regex.IsMatch(macro.ScriptName, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled))) { throw new InvalidOperationException("Cannot render the Partial View Macro with file: " + macro.ScriptName + ". All Partial View Macros must exist in the " + SystemDirectories.MvcViews + "/MacroPartials/ folder"); } diff --git a/src/Umbraco.Web/Mvc/Constants.cs b/src/Umbraco.Web/Mvc/Constants.cs index 63ddf5fa05..1ec35e4928 100644 --- a/src/Umbraco.Web/Mvc/Constants.cs +++ b/src/Umbraco.Web/Mvc/Constants.cs @@ -3,6 +3,5 @@ namespace Umbraco.Web.Mvc internal static class Constants { public const string ViewLocation = "~/Views"; - public const string PluginsLocation = "~/App_Plugins"; } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/PluginViewEngine.cs b/src/Umbraco.Web/Mvc/PluginViewEngine.cs index bca14c2058..2ffc98afa2 100644 --- a/src/Umbraco.Web/Mvc/PluginViewEngine.cs +++ b/src/Umbraco.Web/Mvc/PluginViewEngine.cs @@ -33,16 +33,16 @@ namespace Umbraco.Web.Mvc var viewLocationsArray = new[] { - string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.vbhtml") + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.vbhtml") }; //set all of the area view locations to the plugin folder AreaViewLocationFormats = viewLocationsArray .Concat(new[] { - string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.vbhtml") + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.vbhtml") }) .ToArray(); @@ -51,15 +51,15 @@ namespace Umbraco.Web.Mvc AreaPartialViewLocationFormats = new[] { //will be used when we have partial view and child action macros - string.Concat(Constants.PluginsLocation, "/{2}/Views/Partials/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/Partials/{0}.vbhtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/MacroPartials/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/MacroPartials/{0}.vbhtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.vbhtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.vbhtml"), //for partials - string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.vbhtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.cshtml"), - string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.vbhtml") + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.vbhtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), + string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.vbhtml") }; } diff --git a/src/umbraco.cms/businesslogic/macro/Macro.cs b/src/umbraco.cms/businesslogic/macro/Macro.cs index 5c61562108..6fc80ec556 100644 --- a/src/umbraco.cms/businesslogic/macro/Macro.cs +++ b/src/umbraco.cms/businesslogic/macro/Macro.cs @@ -2,6 +2,7 @@ using System; using System.Data; using System.Security.Cryptography; using System.Text; +using System.Text.RegularExpressions; using System.Xml; using System.Runtime.CompilerServices; using Umbraco.Core.IO; @@ -536,9 +537,11 @@ namespace umbraco.cms.businesslogic.macro { //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 - return scriptFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/") - ? MacroTypes.PartialView - : MacroTypes.Script; + //we also check if the file exists in ~/App_Plugins/[Packagename]/Views/MacroPartials, if so then it is also a partial view. + return (scriptFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/") + || (Regex.IsMatch(scriptFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled))) + ? MacroTypes.PartialView + : MacroTypes.Script; } if (!string.IsNullOrEmpty(scriptType) && scriptType.ToLower().IndexOf(".ascx") > -1)