bca0886ed6
[TFS Changeset #73429]
844 lines
31 KiB
C#
844 lines
31 KiB
C#
using System;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Collections;
|
|
using System.Xml;
|
|
using umbraco.DataLayer;
|
|
using System.Text.RegularExpressions;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using umbraco.cms.businesslogic.cache;
|
|
using umbraco.BusinessLogic;
|
|
using umbraco.IO;
|
|
using System.Web;
|
|
using umbraco.cms.businesslogic.web;
|
|
|
|
namespace umbraco.cms.businesslogic.template
|
|
{
|
|
/// <summary>
|
|
/// Summary description for Template.
|
|
/// </summary>
|
|
public class Template : CMSNode
|
|
{
|
|
|
|
|
|
#region Private members
|
|
|
|
private string _OutputContentType;
|
|
private string _design;
|
|
private string _alias;
|
|
private string _oldAlias;
|
|
private int _mastertemplate;
|
|
private bool _hasChildrenInitialized = false;
|
|
private bool _hasChildren;
|
|
|
|
#endregion
|
|
|
|
#region Static members
|
|
|
|
public static readonly string UmbracoMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master";
|
|
private static Hashtable _templateAliases = new Hashtable();
|
|
private static volatile bool _templateAliasesInitialized = false;
|
|
private static object templateCacheSyncLock = new object();
|
|
private static readonly string UmbracoTemplateCacheKey = "UmbracoTemplateCache";
|
|
private static object _templateLoaderLocker = new object();
|
|
private static Guid _objectType = new Guid("6fbde604-4178-42ce-a10b-8a2600a2f07d");
|
|
|
|
#endregion
|
|
|
|
public string MasterPageFile
|
|
{
|
|
get { return IOHelper.MapPath(SystemDirectories.Masterpages + "/" + Alias.Replace(" ", "") + ".master"); }
|
|
}
|
|
|
|
public static Hashtable TemplateAliases
|
|
{
|
|
get { return _templateAliases; }
|
|
set { _templateAliases = value; }
|
|
}
|
|
|
|
#region Constructors
|
|
public Template(int id) : base(id) { }
|
|
|
|
public Template(Guid id) : base(id) { }
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility
|
|
/// </summary>
|
|
public override void Save()
|
|
{
|
|
SaveEventArgs e = new SaveEventArgs();
|
|
FireBeforeSave(e);
|
|
|
|
if (!e.Cancel)
|
|
{
|
|
FlushCache();
|
|
base.Save();
|
|
FireAfterSave(e);
|
|
}
|
|
}
|
|
|
|
public string GetRawText()
|
|
{
|
|
return base.Text;
|
|
}
|
|
|
|
public override string Text
|
|
{
|
|
get
|
|
{
|
|
string tempText = base.Text;
|
|
if (!tempText.StartsWith("#"))
|
|
return tempText;
|
|
else
|
|
{
|
|
language.Language lang = language.Language.GetByCultureCode(System.Threading.Thread.CurrentThread.CurrentCulture.Name);
|
|
if (lang != null)
|
|
{
|
|
if (Dictionary.DictionaryItem.hasKey(tempText.Substring(1, tempText.Length - 1)))
|
|
{
|
|
Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(tempText.Substring(1, tempText.Length - 1));
|
|
if (di != null)
|
|
return di.Value(lang.id);
|
|
}
|
|
}
|
|
|
|
return "[" + tempText + "]";
|
|
}
|
|
}
|
|
set
|
|
{
|
|
FlushCache();
|
|
base.Text = value;
|
|
}
|
|
}
|
|
|
|
public string OutputContentType
|
|
{
|
|
get { return _OutputContentType; }
|
|
set { _OutputContentType = value; }
|
|
}
|
|
|
|
protected override void setupNode()
|
|
{
|
|
base.setupNode();
|
|
|
|
IRecordsReader dr = SqlHelper.ExecuteReader("Select alias,design,master from cmsTemplate where nodeId = " + this.Id);
|
|
if (dr.HasRecords)
|
|
{
|
|
dr.Read();
|
|
_alias = dr.GetString("alias");
|
|
_design = dr.GetString("design");
|
|
//set the master template to zero if it's null
|
|
_mastertemplate = dr.IsNull("master") ? 0 : dr.GetInt("master");
|
|
}
|
|
dr.Close();
|
|
|
|
// test for masterpages
|
|
if (UmbracoSettings.UseAspNetMasterPages)
|
|
{
|
|
_design = getMasterPageContent();
|
|
}
|
|
}
|
|
|
|
private bool isMasterPageSyntax(string code)
|
|
{
|
|
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 string Alias
|
|
{
|
|
get { return _alias; }
|
|
set
|
|
{
|
|
FlushCache();
|
|
_oldAlias = _alias;
|
|
_alias = value;
|
|
|
|
SqlHelper.ExecuteNonQuery("Update cmsTemplate set alias = @alias where NodeId = " + this.Id, SqlHelper.CreateParameter("@alias", _alias));
|
|
_templateAliasesInitialized = false;
|
|
|
|
initTemplateAliases();
|
|
}
|
|
|
|
}
|
|
|
|
public bool HasMasterTemplate
|
|
{
|
|
get { return (_mastertemplate > 0); }
|
|
}
|
|
|
|
|
|
public override bool HasChildren
|
|
{
|
|
get
|
|
{
|
|
if (!_hasChildrenInitialized)
|
|
{
|
|
_hasChildren = SqlHelper.ExecuteScalar<int>("select count(NodeId) as tmp from cmsTemplate where master = " + Id) > 0;
|
|
}
|
|
return _hasChildren;
|
|
}
|
|
set
|
|
{
|
|
_hasChildrenInitialized = true;
|
|
_hasChildren = value;
|
|
}
|
|
}
|
|
|
|
public int MasterTemplate
|
|
{
|
|
get { return _mastertemplate; }
|
|
set
|
|
{
|
|
FlushCache();
|
|
_mastertemplate = value;
|
|
|
|
//set to null if it's zero
|
|
object masterVal = value;
|
|
if (value == 0) masterVal = DBNull.Value;
|
|
|
|
SqlHelper.ExecuteNonQuery("Update cmsTemplate set master = @master where NodeId = @nodeId",
|
|
SqlHelper.CreateParameter("@master", masterVal),
|
|
SqlHelper.CreateParameter("@nodeId", this.Id));
|
|
}
|
|
}
|
|
|
|
public string Design
|
|
{
|
|
get { return _design; }
|
|
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));
|
|
|
|
}
|
|
else
|
|
SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id",
|
|
SqlHelper.CreateParameter("@design", value),
|
|
SqlHelper.CreateParameter("@id", Id));
|
|
}
|
|
}
|
|
|
|
public XmlNode ToXml(XmlDocument doc)
|
|
{
|
|
XmlNode template = doc.CreateElement("Template");
|
|
template.AppendChild(xmlHelper.addTextNode(doc, "Name", this.Text));
|
|
template.AppendChild(xmlHelper.addTextNode(doc, "Alias", this.Alias));
|
|
|
|
if (this.MasterTemplate != 0)
|
|
{
|
|
template.AppendChild(xmlHelper.addTextNode(doc, "Master", new Template(this.MasterTemplate).Alias));
|
|
}
|
|
|
|
template.AppendChild(xmlHelper.addCDataNode(doc, "Design", this.Design));
|
|
|
|
return template;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes any references to this templates from child templates, documenttypes and documents
|
|
/// </summary>
|
|
public void RemoveAllReferences()
|
|
{
|
|
if (HasChildren)
|
|
{
|
|
foreach (Template t in Template.GetAllAsList().FindAll(delegate(Template t) { return t.MasterTemplate == this.Id; }))
|
|
{
|
|
t.MasterTemplate = 0;
|
|
}
|
|
}
|
|
|
|
RemoveFromDocumentTypes();
|
|
|
|
// remove from documents
|
|
Document.RemoveTemplateFromDocument(this.Id);
|
|
|
|
|
|
}
|
|
|
|
public void RemoveFromDocumentTypes()
|
|
{
|
|
foreach (DocumentType dt in DocumentType.GetAllAsList().Where(x => x.allowedTemplates.Select(t => t.Id).Contains(this.Id)))
|
|
{
|
|
dt.RemoveTemplate(this.Id);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static Template MakeNew(string Name, BusinessLogic.User u, Template master)
|
|
{
|
|
Template t = MakeNew(Name, u);
|
|
t.MasterTemplate = master.Id;
|
|
t.Design = "";
|
|
|
|
if (UmbracoSettings.UseAspNetMasterPages)
|
|
{
|
|
string design = t.getMasterPageHeader() + "\n";
|
|
|
|
foreach (string cpId in master.contentPlaceholderIds())
|
|
{
|
|
design += "<asp:content ContentPlaceHolderId=\"" + cpId + "\" runat=\"server\">\n\t\n</asp:content>\n\n";
|
|
}
|
|
|
|
t.Design = design;
|
|
}
|
|
|
|
t.Save();
|
|
return t;
|
|
}
|
|
|
|
public static Template MakeNew(string Name, BusinessLogic.User u)
|
|
{
|
|
// CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID)
|
|
CMSNode n = CMSNode.MakeNew(-1, _objectType, u.Id, 1, Name, Guid.NewGuid());
|
|
Name = Name.Replace("/", ".").Replace("\\", "");
|
|
|
|
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),
|
|
SqlHelper.CreateParameter("@alias", Name),
|
|
SqlHelper.CreateParameter("@design", ' '),
|
|
SqlHelper.CreateParameter("@master", DBNull.Value));
|
|
|
|
Template t = new Template(n.Id);
|
|
NewEventArgs e = new NewEventArgs();
|
|
t.OnNew(e);
|
|
|
|
return t;
|
|
}
|
|
|
|
public static Template GetByAlias(string Alias)
|
|
{
|
|
try
|
|
{
|
|
return new Template(SqlHelper.ExecuteScalar<int>("select nodeId from cmsTemplate where alias = @alias", SqlHelper.CreateParameter("@alias", Alias)));
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
[Obsolete("Obsolete, please use GetAllAsList() method instead", true)]
|
|
public static Template[] getAll()
|
|
{
|
|
return GetAllAsList().ToArray();
|
|
}
|
|
|
|
public static List<Template> GetAllAsList()
|
|
{
|
|
Guid[] ids = CMSNode.TopMostNodeIds(_objectType);
|
|
List<Template> retVal = new List<Template>();
|
|
foreach (Guid id in ids)
|
|
{
|
|
retVal.Add(new Template(id));
|
|
}
|
|
retVal.Sort(delegate(Template t1, Template t2) { return t1.Text.CompareTo(t2.Text); });
|
|
return retVal;
|
|
}
|
|
|
|
public static int GetTemplateIdFromAlias(string alias)
|
|
{
|
|
initTemplateAliases();
|
|
if (TemplateAliases.ContainsKey(alias))
|
|
return (int)TemplateAliases[alias];
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
private static void initTemplateAliases()
|
|
{
|
|
if (!_templateAliasesInitialized)
|
|
{
|
|
lock (_templateLoaderLocker)
|
|
{
|
|
//double check
|
|
if (!_templateAliasesInitialized)
|
|
{
|
|
_templateAliases.Clear();
|
|
foreach (Template t in GetAllAsList())
|
|
TemplateAliases.Add(t.Alias.ToLower(), t.Id);
|
|
|
|
_templateAliasesInitialized = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void delete()
|
|
{
|
|
// don't allow template deletion if it has child templates
|
|
if (this.HasChildren)
|
|
{
|
|
Log.Add(LogTypes.Error, this.Id, "Can't delete a master template. Remove any bindings from child templates first.");
|
|
throw new InvalidOperationException("Can't delete a master template. Remove any bindings from child templates first.");
|
|
}
|
|
|
|
// NH: Changed this; if you delete a template we'll remove all references instead of
|
|
// throwing an exception
|
|
if (DocumentType.GetAllAsList().Where(x => x.allowedTemplates.Select(t => t.Id).Contains(this.Id)).Count() > 0)
|
|
{
|
|
// the uncommented code below have been refactored into removeAllReferences method that clears template
|
|
// from documenttypes, subtemplates and documents.
|
|
RemoveAllReferences();
|
|
/*
|
|
|
|
// Added to remove template doctype relationship
|
|
SqlHelper.ExecuteNonQuery("delete from cmsDocumentType where templateNodeId =" + this.Id);
|
|
|
|
// Need to update any other template that references this one as it's master to NULL
|
|
SqlHelper.ExecuteNonQuery("update cmsTemplate set [master] = NULL where [master] = " + this.Id);
|
|
*/
|
|
|
|
// don't allow template deletion if it is in use
|
|
// (get all doc types and filter based on any that have the template id of this one)
|
|
/*
|
|
Log.Add(LogTypes.Error, this.Id, "Can't delete a template that is assigned to existing content");
|
|
throw new InvalidOperationException("Can't delete a template that is assigned to existing content");
|
|
*/
|
|
}
|
|
|
|
DeleteEventArgs e = new DeleteEventArgs();
|
|
FireBeforeDelete(e);
|
|
|
|
if (!e.Cancel)
|
|
{
|
|
//re-set the template aliases
|
|
_templateAliasesInitialized = false;
|
|
initTemplateAliases();
|
|
|
|
//delete the template
|
|
SqlHelper.ExecuteNonQuery("delete from cmsTemplate where NodeId =" + this.Id);
|
|
|
|
base.delete();
|
|
|
|
// remove masterpages
|
|
if (System.IO.File.Exists(MasterPageFile))
|
|
System.IO.File.Delete(MasterPageFile);
|
|
|
|
FireAfterDelete(e);
|
|
}
|
|
}
|
|
|
|
public void SaveAsMasterPage()
|
|
{
|
|
SaveMasterPageFile(ConvertToMasterPageSyntax(Design));
|
|
}
|
|
|
|
public string GetMasterContentElement(int masterTemplateId)
|
|
{
|
|
if (masterTemplateId != 0)
|
|
{
|
|
string masterAlias = new Template(masterTemplateId).Alias.Replace(" ", "");
|
|
return
|
|
String.Format("<asp:Content ContentPlaceHolderID=\"{1}ContentPlaceHolder\" runat=\"server\">",
|
|
Alias.Replace(" ", ""), masterAlias);
|
|
}
|
|
else
|
|
return
|
|
String.Format("<asp:Content ContentPlaceHolderID=\"ContentPlaceHolderDefault\" runat=\"server\">",
|
|
Alias.Replace(" ", ""));
|
|
|
|
}
|
|
|
|
public List<string> contentPlaceholderIds()
|
|
{
|
|
List<string> retVal = new List<string>();
|
|
|
|
string masterPageFile = this.MasterPageFile;
|
|
string mp = System.IO.File.ReadAllText(masterPageFile);
|
|
string pat = "<asp:ContentPlaceHolder+(\\s+[a-zA-Z]+\\s*=\\s*(\"([^\"]*)\"|'([^']*)'))*\\s*/?>";
|
|
Regex r = new Regex(pat, RegexOptions.IgnoreCase);
|
|
Match m = r.Match(mp);
|
|
|
|
while (m.Success)
|
|
{
|
|
CaptureCollection cc = m.Groups[3].Captures;
|
|
foreach (Capture c in cc)
|
|
{
|
|
if (c.Value != "server")
|
|
retVal.Add(c.Value);
|
|
}
|
|
|
|
m = m.NextMatch();
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
public string ConvertToMasterPageSyntax(string templateDesign)
|
|
{
|
|
string masterPageContent = GetMasterContentElement(MasterTemplate) + "\n";
|
|
|
|
masterPageContent += templateDesign;
|
|
|
|
// Parse the design for getitems
|
|
masterPageContent = EnsureMasterPageSyntax(masterPageContent);
|
|
|
|
// append ending asp:content element
|
|
masterPageContent += "\n</asp:Content>" + Environment.NewLine;
|
|
|
|
return masterPageContent;
|
|
}
|
|
|
|
public string EnsureMasterPageSyntax(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/>", getAspNetMasterPageContentContainer()).Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD />", getAspNetMasterPageContentContainer());
|
|
// Parse the design for aspnet forms
|
|
getAspNetMasterPageForm(ref masterPageContent);
|
|
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\">", Alias.Replace(" ", "")));
|
|
masterPageContent = masterPageContent.Replace("</?ASPNET_HEAD>", "</head>");
|
|
return masterPageContent;
|
|
}
|
|
|
|
public void ImportDesign(string design)
|
|
{
|
|
if (!isMasterPageSyntax(design))
|
|
{
|
|
Design = ConvertToMasterPageSyntax(design);
|
|
}
|
|
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)
|
|
{
|
|
// Add header to master page if it doesn't exist
|
|
if (!masterPageContent.StartsWith("<%@"))
|
|
{
|
|
masterPageContent = getMasterPageHeader() + "\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 = currentMasterTemplateFileName();
|
|
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(_oldAlias) && _oldAlias != _alias)
|
|
{
|
|
|
|
//Ensure that child templates have the right master masterpage file name
|
|
if (HasChildren)
|
|
{
|
|
//store children array here because iterating over an Array property object is very inneficient.
|
|
var c = Children;
|
|
foreach (CMSNode cmn in c)
|
|
{
|
|
Template t = new Template(cmn.Id);
|
|
t.SaveAsMasterPage();
|
|
t.Save();
|
|
}
|
|
}
|
|
|
|
//then kill the old file..
|
|
string _oldFile = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + _oldAlias.Replace(" ", "") + ".master");
|
|
|
|
if (System.IO.File.Exists(_oldFile))
|
|
System.IO.File.Delete(_oldFile);
|
|
}
|
|
|
|
// save the file in UTF-8
|
|
|
|
File.WriteAllText(MasterPageFile, masterPageContent, System.Text.Encoding.UTF8);
|
|
}
|
|
|
|
private void getAspNetMasterPageForm(ref string design)
|
|
{
|
|
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\">", Alias.Replace(" ", ""));
|
|
if (formElement.Groups.Count == 0)
|
|
{
|
|
formReplace += "<asp:scriptmanager runat=\"server\"></asp:scriptmanager>";
|
|
}
|
|
design = design.Replace(formElement.Value, formReplace);
|
|
}
|
|
}
|
|
|
|
private string getAspNetMasterPageContentContainer()
|
|
{
|
|
return String.Format(
|
|
"<asp:ContentPlaceHolder ID=\"{0}ContentPlaceHolder\" runat=\"server\"></asp:ContentPlaceHolder>",
|
|
Alias.Replace(" ", ""));
|
|
}
|
|
|
|
private 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 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);
|
|
|
|
}
|
|
|
|
|
|
protected virtual void FlushCache()
|
|
{
|
|
// clear local cache
|
|
cache.Cache.ClearCacheItem(GetCacheKey(Id));
|
|
}
|
|
|
|
public static Template GetTemplate(int id)
|
|
{
|
|
return Cache.GetCacheItem<Template>(GetCacheKey(id), templateCacheSyncLock,
|
|
TimeSpan.FromMinutes(30),
|
|
delegate
|
|
{
|
|
try
|
|
{
|
|
return new Template(id);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void InvalidateCache()
|
|
{
|
|
Cache.ClearCacheItem(GetCacheKey(this.Id));
|
|
}
|
|
|
|
private static string GetCacheKey(int id)
|
|
{
|
|
return UmbracoTemplateCacheKey + id;
|
|
}
|
|
|
|
|
|
public static Template Import(XmlNode n, User u)
|
|
{
|
|
string alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Alias"));
|
|
|
|
Template t = Template.GetByAlias(alias);
|
|
|
|
if (t == null)
|
|
{
|
|
t = MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), u);
|
|
}
|
|
|
|
t.Alias = alias;
|
|
|
|
t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
|
|
|
|
return t;
|
|
}
|
|
|
|
#region Events
|
|
//EVENTS
|
|
/// <summary>
|
|
/// The save event handler
|
|
/// </summary>
|
|
public delegate void SaveEventHandler(Template sender, SaveEventArgs e);
|
|
/// <summary>
|
|
/// The new event handler
|
|
/// </summary>
|
|
public delegate void NewEventHandler(Template sender, NewEventArgs e);
|
|
/// <summary>
|
|
/// The delete event handler
|
|
/// </summary>
|
|
public delegate void DeleteEventHandler(Template sender, DeleteEventArgs e);
|
|
|
|
|
|
/// <summary>
|
|
/// Occurs when [before save].
|
|
/// </summary>
|
|
public static event SaveEventHandler BeforeSave;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeSave"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeSave(SaveEventArgs e)
|
|
{
|
|
if (BeforeSave != null)
|
|
BeforeSave(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after save].
|
|
/// </summary>
|
|
public static event SaveEventHandler AfterSave;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterSave"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterSave(SaveEventArgs e)
|
|
{
|
|
if (AfterSave != null)
|
|
AfterSave(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [new].
|
|
/// </summary>
|
|
public static event NewEventHandler New;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:New"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void OnNew(NewEventArgs e)
|
|
{
|
|
if (New != null)
|
|
New(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before delete].
|
|
/// </summary>
|
|
public static event DeleteEventHandler BeforeDelete;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeDelete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeDelete(DeleteEventArgs e)
|
|
{
|
|
if (BeforeDelete != null)
|
|
BeforeDelete(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after delete].
|
|
/// </summary>
|
|
public static event DeleteEventHandler AfterDelete;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterDelete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterDelete(DeleteEventArgs e)
|
|
{
|
|
if (AfterDelete != null)
|
|
AfterDelete(this, e);
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
}
|