Moves masterpage and view creation away from the template

class and into seperate helpers.
This commit is contained in:
PerPloug
2012-09-27 06:23:09 -02:00
parent 7e5db90b3b
commit 2c995f7fa7
4 changed files with 418 additions and 49 deletions

View File

@@ -0,0 +1,261 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Umbraco.Core.IO;
namespace umbraco.cms.businesslogic.template
{
internal class MasterpageHelper
{
internal static readonly string DefaultMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master";
internal static string CreateMasterpageFile(Template t, bool overWrite = false)
{
string masterpageContent = "";
if (!File.Exists(t.MasterPageFile) || overWrite)
masterpageContent = saveTemplateToFile(t, t.Alias);
else
{
System.IO.TextReader tr = new StreamReader(t.MasterPageFile);
masterpageContent = tr.ReadToEnd();
tr.Close();
}
return masterpageContent;
}
internal static string GetMasterpageFile(Template t)
{
string masterpageContent = "";
if (File.Exists(t.MasterPageFile)){
System.IO.TextReader tr = new StreamReader(t.MasterPageFile);
masterpageContent = tr.ReadToEnd();
tr.Close();
}
return masterpageContent;
}
internal static string UpdateMasterpageFile(Template t, string currentAlias)
{
return saveTemplateToFile(t, currentAlias);
}
internal static string saveTemplateToFile(Template template, string currentAlias)
{
var masterPageContent = template.Design;
if (!isMasterPageSyntax(masterPageContent))
masterPageContent = ConvertToMasterPageSyntax(template);
// Add header to master page if it doesn't exist
if (!masterPageContent.TrimStart().StartsWith("<%@"))
{
masterPageContent = getMasterPageHeader(template) + "\n" + masterPageContent;
}
else
{
// verify that the masterpage attribute is the same as the masterpage
string masterHeader =
masterPageContent.Substring(0, masterPageContent.IndexOf("%>") + 2).Trim(
Environment.NewLine.ToCharArray());
// find the masterpagefile attribute
MatchCollection m = Regex.Matches(masterHeader, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match attributeSet in m)
{
if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile")
{
// validate the masterpagefile
string currentMasterPageFile = attributeSet.Groups["attributeValue"].Value;
string currentMasterTemplateFile = parentTemplatePath(template);
if (currentMasterPageFile != currentMasterTemplateFile)
{
masterPageContent =
masterPageContent.Replace(
attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"",
attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile +
"\"");
}
}
}
}
//we have a Old Alias if the alias and therefor the masterpage file name has changed...
//so before we save the new masterfile, we'll clear the old one, so we don't up with
//Unused masterpage files
if (!string.IsNullOrEmpty(currentAlias) && currentAlias != template.Alias)
{
//Ensure that child templates have the right master masterpage file name
if (template.HasChildren)
{
//store children array here because iterating over an Array property object is very inneficient.
var c = template.Children;
foreach (CMSNode cmn in c)
UpdateMasterpageFile(new Template(cmn.Id), null);
}
//then kill the old file..
string _oldFile = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + currentAlias.Replace(" ", "") + ".master");
if (System.IO.File.Exists(_oldFile))
System.IO.File.Delete(_oldFile);
}
// save the file in UTF-8
System.IO.File.WriteAllText(template.MasterPageFile, masterPageContent, System.Text.Encoding.UTF8);
return masterPageContent;
}
internal static string ConvertToMasterPageSyntax(Template template)
{
string masterPageContent = GetMasterContentElement(template) + "\n";
masterPageContent += template.Design;
// Parse the design for getitems
masterPageContent = EnsureMasterPageSyntax(template.Alias, masterPageContent);
// append ending asp:content element
masterPageContent += "\n</asp:Content>" + Environment.NewLine;
return masterPageContent;
}
private static bool isMasterPageSyntax(string code)
{
return code.Contains("<%@ Master") || code.Contains("<umbraco:Item") || code.Contains("<asp:") || code.Contains("<umbraco:Macro");
}
private static string getMasterPageHeader(Template template)
{
return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>", parentTemplatePath(template)) + Environment.NewLine;
}
private static string parentTemplatePath(Template template)
{
var masterTemplate = DefaultMasterTemplate;
if (template.MasterTemplate != 0)
masterTemplate = SystemDirectories.Masterpages + "/" + new Template(template.MasterTemplate).Alias.Replace(" ", "") + ".master";
return masterTemplate;
}
private static string GetMasterContentElement(Template template)
{
if (template.MasterTemplate != 0)
{
string masterAlias = new Template(template.MasterTemplate).Alias.Replace(" ", "");
return
String.Format("<asp:Content ContentPlaceHolderID=\"{1}ContentPlaceHolder\" runat=\"server\">",
template.Alias.Replace(" ", ""), masterAlias);
}
else
return
String.Format("<asp:Content ContentPlaceHolderID=\"ContentPlaceHolderDefault\" runat=\"server\">",
template.Alias.Replace(" ", ""));
}
internal static string EnsureMasterPageSyntax(string templateAlias, string masterPageContent)
{
replaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", true);
replaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", false);
// Parse the design for macros
replaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", true);
replaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", false);
// Parse the design for load childs
masterPageContent = masterPageContent.Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD/>", createDefaultPlaceHolder(templateAlias))
.Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD />", createDefaultPlaceHolder(templateAlias));
// Parse the design for aspnet forms
getAspNetMasterPageForm(ref masterPageContent, templateAlias);
masterPageContent = masterPageContent.Replace("</?ASPNET_FORM>", "</form>");
// Parse the design for aspnet heads
masterPageContent = masterPageContent.Replace("</ASPNET_HEAD>", String.Format("<head id=\"{0}Head\" runat=\"server\">", templateAlias.Replace(" ", "")));
masterPageContent = masterPageContent.Replace("</?ASPNET_HEAD>", "</head>");
return masterPageContent;
}
private static void getAspNetMasterPageForm(ref string design, string templateAlias)
{
Match formElement = Regex.Match(design, getElementRegExp("?ASPNET_FORM", false), RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
if (formElement != null && formElement.Value != "")
{
string formReplace = String.Format("<form id=\"{0}Form\" runat=\"server\">", templateAlias.Replace(" ", ""));
if (formElement.Groups.Count == 0)
{
formReplace += "<asp:scriptmanager runat=\"server\"></asp:scriptmanager>";
}
design = design.Replace(formElement.Value, formReplace);
}
}
private static string createDefaultPlaceHolder(string templateAlias)
{
return String.Format("<asp:ContentPlaceHolder ID=\"{0}ContentPlaceHolder\" runat=\"server\"></asp:ContentPlaceHolder>", templateAlias.Replace(" ", ""));
}
private static void replaceElement(ref string design, string elementName, string newElementName, bool checkForQuotes)
{
MatchCollection m =
Regex.Matches(design, getElementRegExp(elementName, checkForQuotes),
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match match in m)
{
GroupCollection groups = match.Groups;
// generate new element (compensate for a closing trail on single elements ("/"))
string elementAttributes = groups[1].Value;
// test for macro alias
if (elementName == "?UMBRACO_MACRO")
{
Hashtable tags = helpers.xhtml.ReturnAttributes(match.Value);
if (tags["macroAlias"] != null)
elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroAlias"].ToString()) + elementAttributes;
else if (tags["macroalias"] != null)
elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroalias"].ToString()) + elementAttributes;
}
string newElement = "<" + newElementName + " runat=\"server\" " + elementAttributes.Trim() + ">";
if (elementAttributes.EndsWith("/"))
{
elementAttributes = elementAttributes.Substring(0, elementAttributes.Length - 1);
}
else if (groups[0].Value.StartsWith("</"))
// It's a closing element, so generate that instead of a starting element
newElement = "</" + newElementName + ">";
if (checkForQuotes)
{
// if it's inside quotes, we'll change element attribute quotes to single quotes
newElement = newElement.Replace("\"", "'");
newElement = String.Format("\"{0}\"", newElement);
}
design = design.Replace(match.Value, newElement);
}
}
private static string getElementRegExp(string elementName, bool checkForQuotes)
{
if (checkForQuotes)
return String.Format("\"<[^>\\s]*\\b{0}(\\b[^>]*)>\"", elementName);
else
return String.Format("<[^>\\s]*\\b{0}(\\b[^>]*)>", elementName);
}
}
}

View File

@@ -132,12 +132,12 @@ namespace umbraco.cms.businesslogic.template
_mastertemplate = dr.IsNull("master") ? 0 : dr.GetInt("master");
}
dr.Close();
if (UmbracoSettings.EnableMvcSupport && Template.HasView(this))
_design = ViewHelper.GetViewFile(this);
else
_design = MasterpageHelper.GetMasterpageFile(this);
// test for masterpages
if (UmbracoSettings.UseAspNetMasterPages)
{
_design = getMasterPageContent();
}
}
private bool isMasterPageSyntax(string code)
@@ -145,18 +145,6 @@ namespace umbraco.cms.businesslogic.template
return code.Contains("<%@ Master") || code.Contains("<umbraco:Item") || code.Contains("<asp:") || code.Contains("<umbraco:Macro");
}
private string getMasterPageContent()
{
string masterpageContent = "";
if (!File.Exists(MasterPageFile))
SaveAsMasterPage();
System.IO.TextReader tr = new StreamReader(MasterPageFile);
masterpageContent = tr.ReadToEnd();
tr.Close();
return masterpageContent;
}
public new string Path
{
get
@@ -257,24 +245,23 @@ namespace umbraco.cms.businesslogic.template
set
{
FlushCache();
_design = value.Trim(Environment.NewLine.ToCharArray());
// NH: Removing an generating the directive can mess up code behind
// We don't store the masterpage directive in the design value
// if (_design.StartsWith("<%@"))
// _design = _design.Substring(_design.IndexOf("%>") + 3).Trim(Environment.NewLine.ToCharArray());
if (UmbracoSettings.UseAspNetMasterPages && isMasterPageSyntax(_design))
{
SaveMasterPageFile(_design);
SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id",
SqlHelper.CreateParameter("@design", value),
SqlHelper.CreateParameter("@id", Id));
//we only switch to MVC View editing if the template has a view file, and MVC editing is enabled
if (UmbracoSettings.EnableMvcSupport && !isMasterPageSyntax(_design))
_design = ViewHelper.UpdateViewFile(this);
else if (UmbracoSettings.UseAspNetMasterPages)
_design = MasterpageHelper.UpdateMasterpageFile(this, _oldAlias);
}
else
SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id",
SqlHelper.CreateParameter("@design", value),
SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id",
SqlHelper.CreateParameter("@design", _design),
SqlHelper.CreateParameter("@id", Id));
}
}
@@ -331,11 +318,17 @@ namespace umbraco.cms.businesslogic.template
public static Template MakeNew(string Name, BusinessLogic.User u, Template master)
{
Template t = MakeNew(Name, u);
t.MasterTemplate = master.Id;
t.Design = "";
if (UmbracoSettings.EnableMvcSupport)
ViewHelper.CreateViewFile(t, true);
else
MasterpageHelper.CreateMasterpageFile(t, true);
/*
if (UmbracoSettings.UseAspNetMasterPages)
{
string design = t.getMasterPageHeader() + "\n";
@@ -346,7 +339,7 @@ namespace umbraco.cms.businesslogic.template
}
t.Design = design;
}
}*/
t.Save();
return t;
@@ -367,6 +360,8 @@ namespace umbraco.cms.businesslogic.template
if (name.Length > 100)
name = name.Substring(0, 95) + "...";
SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)",
SqlHelper.CreateParameter("@nodeId", n.Id),
@@ -378,6 +373,12 @@ namespace umbraco.cms.businesslogic.template
NewEventArgs e = new NewEventArgs();
t.OnNew(e);
if (UmbracoSettings.EnableMvcSupport)
t._design = ViewHelper.CreateViewFile(t);
else
t._design = MasterpageHelper.CreateMasterpageFile(t);
return t;
}
@@ -504,13 +505,17 @@ namespace umbraco.cms.businesslogic.template
if (System.IO.File.Exists(MasterPageFile))
System.IO.File.Delete(MasterPageFile);
if (System.IO.File.Exists(Umbraco.Core.IO.IOHelper.MapPath(ViewHelper.ViewPath(this))))
System.IO.File.Delete(Umbraco.Core.IO.IOHelper.MapPath(ViewHelper.ViewPath(this)));
FireAfterDelete(e);
}
}
public void SaveAsMasterPage()
[Obsolete("This method, doesnt actually do anything, as the file is created when the design is set", false)]
public void _SaveAsMasterPage()
{
SaveMasterPageFile(ConvertToMasterPageSyntax(Design));
//SaveMasterPageFile(ConvertToMasterPageSyntax(Design));
}
public string GetMasterContentElement(int masterTemplateId)
@@ -526,7 +531,6 @@ namespace umbraco.cms.businesslogic.template
return
String.Format("<asp:Content ContentPlaceHolderID=\"ContentPlaceHolderDefault\" runat=\"server\">",
Alias.Replace(" ", ""));
}
public List<string> contentPlaceholderIds()
@@ -591,8 +595,13 @@ namespace umbraco.cms.businesslogic.template
return masterPageContent;
}
public void ImportDesign(string design)
{
Design = design;
/*
if (!isMasterPageSyntax(design))
{
Design = ConvertToMasterPageSyntax(design);
@@ -600,26 +609,17 @@ namespace umbraco.cms.businesslogic.template
else
{
Design = design;
}
}*/
}
private string getMasterPageHeader()
{
return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>",
currentMasterTemplateFileName()) + Environment.NewLine;
}
private string currentMasterTemplateFileName()
{
if (MasterTemplate != 0)
return SystemDirectories.Masterpages + "/" + new Template(MasterTemplate).Alias.Replace(" ", "") + ".master";
else
return UmbracoMasterTemplate;
}
public void SaveMasterPageFile(string masterPageContent)
{
//this will trigger the helper and store everything
this.Design = masterPageContent;
/*
// Add header to master page if it doesn't exist
if (!masterPageContent.StartsWith("<%@"))
{
@@ -681,6 +681,21 @@ namespace umbraco.cms.businesslogic.template
// save the file in UTF-8
File.WriteAllText(MasterPageFile, masterPageContent, System.Text.Encoding.UTF8);
* */
}
private string getMasterPageHeader()
{
return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>",
currentMasterTemplateFileName()) + Environment.NewLine;
}
private string currentMasterTemplateFileName()
{
if (MasterTemplate != 0)
return SystemDirectories.Masterpages + "/" + new Template(MasterTemplate).Alias.Replace(" ", "") + ".master";
else
return UmbracoMasterTemplate;
}
private void getAspNetMasterPageForm(ref string design)
@@ -802,12 +817,18 @@ namespace umbraco.cms.businesslogic.template
}
t.Alias = alias;
t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
return t;
}
public static bool HasView(Template t)
{
var path = Umbraco.Core.IO.SystemDirectories.MvcViews + "/" + t.Alias.Replace(" ", "") + ".cshtml";
return System.IO.File.Exists(Umbraco.Core.IO.IOHelper.MapPath(path));
}
#region Events
//EVENTS
/// <summary>

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Umbraco.Core.IO;
namespace umbraco.cms.businesslogic.template
{
class ViewHelper
{
internal static string GetViewFile(Template t)
{
string viewContent = "";
string path = IOHelper.MapPath(ViewPath(t));
if (File.Exists(path))
{
System.IO.TextReader tr = new StreamReader(path);
viewContent = tr.ReadToEnd();
tr.Close();
}
return viewContent;
}
internal static string CreateViewFile(Template t, bool overWrite = false)
{
string viewContent = "";
string path = IOHelper.MapPath(ViewPath(t));
if (!File.Exists(path) || overWrite)
viewContent = saveTemplateToFile(t, t.Alias);
else
{
System.IO.TextReader tr = new StreamReader(path);
viewContent = tr.ReadToEnd();
tr.Close();
}
return viewContent;
}
internal static string saveTemplateToFile(Template template, string currentAlias)
{
var design = EnsureInheritedLayout(template);
System.IO.File.WriteAllText(IOHelper.MapPath(ViewPath(template)), design, Encoding.UTF8);
return template.Design;
}
internal static string UpdateViewFile(Template t)
{
var path = IOHelper.MapPath(ViewPath(t));
System.IO.File.WriteAllText(path, t.Design, Encoding.UTF8);
return t.Design;
}
public static string ViewPath(Template t)
{
return Umbraco.Core.IO.SystemDirectories.MvcViews + "/" + t.Alias.Replace(" ", "") + ".cshtml";
}
private static string EnsureInheritedLayout(Template template)
{
string design = template.Design;
if (string.IsNullOrEmpty(design))
{
design = @"@inherits Umbraco.Web.Mvc.RenderViewPage
@{
Layout = null;
}";
if (template.MasterTemplate > 0)
design = design.Replace("null", "\"" + new Template(template.MasterTemplate).Alias.Replace(" ", "") + "\"");
}
return design;
}
}
}

View File

@@ -261,6 +261,8 @@
<Compile Include="businesslogic\skinning\TaskType.cs" />
<Compile Include="businesslogic\Tags\Tag.cs" />
<Compile Include="businesslogic\task\Tasks.cs" />
<Compile Include="businesslogic\template\MasterpageHelper.cs" />
<Compile Include="businesslogic\template\ViewHelper.cs" />
<Compile Include="businesslogic\Tuple.cs" />
<Compile Include="businesslogic\web\DocumentVersionList.cs" />
<Compile Include="businesslogic\skinning\Skinning.cs" />