No these aren't changes to make the demos work at CG09. Move along [TFS Changeset #55237]
494 lines
24 KiB
C#
494 lines
24 KiB
C#
using System;
|
|
using System.Xml;
|
|
using System.Web.Caching;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using System.Data;
|
|
using System.Web.UI;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
using umbraco.DataLayer;
|
|
using umbraco.BusinessLogic;
|
|
|
|
namespace umbraco {
|
|
/// <summary>
|
|
/// Holds methods for parsing and building umbraco templates
|
|
/// </summary>
|
|
///
|
|
public class template {
|
|
#region private variables
|
|
StringBuilder templateOutput = new StringBuilder();
|
|
|
|
// Cache
|
|
static System.Web.Caching.Cache templateCache = System.Web.HttpRuntime.Cache;
|
|
|
|
private string _templateDesign = "";
|
|
int _masterTemplate = -1;
|
|
private string _templateName = "";
|
|
private string _templateAlias = "";
|
|
#endregion
|
|
|
|
#region public properties
|
|
public String TemplateContent {
|
|
set {
|
|
templateOutput.Append(value);
|
|
}
|
|
get {
|
|
return templateOutput.ToString();
|
|
}
|
|
}
|
|
|
|
public int MasterTemplate {
|
|
get { return _masterTemplate; }
|
|
}
|
|
|
|
//added fallback to the default template to avoid nasty .net errors.
|
|
//This is referenced in /default.aspx.cs during page rendering.
|
|
public string MasterPageFile {
|
|
get {
|
|
|
|
string file = TemplateAlias.Replace(" ", "") + ".master";
|
|
|
|
if (System.IO.File.Exists(GlobalSettings.FullpathToRoot + "masterPages" + System.IO.Path.DirectorySeparatorChar + file))
|
|
return "~/masterPages/" + file;
|
|
else
|
|
return "~/" + GlobalSettings.Path.Trim('~','/') + "/masterPages/default.master";
|
|
}
|
|
}
|
|
|
|
public string TemplateAlias {
|
|
get { return _templateAlias; }
|
|
}
|
|
#endregion
|
|
|
|
#region public methods
|
|
|
|
public override string ToString() {
|
|
return this._templateName;
|
|
}
|
|
|
|
public Control ParseWithControls(page umbPage) {
|
|
System.Web.HttpContext.Current.Trace.Write("umbracoTemplate", "Start parsing");
|
|
|
|
if (System.Web.HttpContext.Current.Items["macrosAdded"] == null)
|
|
System.Web.HttpContext.Current.Items.Add("macrosAdded", 0);
|
|
|
|
StringBuilder tempOutput = templateOutput;
|
|
|
|
Control pageLayout = new Control();
|
|
Control pageHeader = new Control();
|
|
Control pageFooter = new Control();
|
|
Control pageContent = new Control();
|
|
System.Web.UI.HtmlControls.HtmlForm pageForm = new System.Web.UI.HtmlControls.HtmlForm();
|
|
System.Web.UI.HtmlControls.HtmlHead pageAspNetHead = new System.Web.UI.HtmlControls.HtmlHead();
|
|
|
|
// Find header and footer of page if there is an aspnet-form on page
|
|
if (templateOutput.ToString().ToLower().IndexOf("<?aspnet_form>") > 0 ||
|
|
templateOutput.ToString().ToLower().IndexOf("<?aspnet_form disablescriptmanager=\"true\">") > 0) {
|
|
pageForm.Attributes.Add("method", "post");
|
|
pageForm.Attributes.Add("action", Convert.ToString(System.Web.HttpContext.Current.Items["VirtualUrl"]));
|
|
|
|
// Find header and footer from tempOutput
|
|
int aspnetFormTagBegin = tempOutput.ToString().ToLower().IndexOf("<?aspnet_form>");
|
|
int aspnetFormTagLength = 14;
|
|
int aspnetFormTagEnd = tempOutput.ToString().ToLower().IndexOf("</?aspnet_form>") + 15;
|
|
|
|
// check if we should disable the script manager
|
|
if (aspnetFormTagBegin == -1) {
|
|
aspnetFormTagBegin =
|
|
templateOutput.ToString().ToLower().IndexOf("<?aspnet_form disablescriptmanager=\"true\">");
|
|
aspnetFormTagLength = 42;
|
|
} else {
|
|
ScriptManager sm = new ScriptManager();
|
|
sm.ID = "umbracoScriptManager";
|
|
pageForm.Controls.Add(sm);
|
|
}
|
|
|
|
|
|
StringBuilder header = new StringBuilder(tempOutput.ToString().Substring(0, aspnetFormTagBegin));
|
|
|
|
// Check if there's an asp.net head element in the header
|
|
if (header.ToString().ToLower().Contains("<?aspnet_head>")) {
|
|
StringBuilder beforeHeader = new StringBuilder(header.ToString().Substring(0, header.ToString().ToLower().IndexOf("<?aspnet_head>")));
|
|
header.Remove(0, header.ToString().ToLower().IndexOf("<?aspnet_head>") + 14);
|
|
StringBuilder afterHeader = new StringBuilder(header.ToString().Substring(header.ToString().ToLower().IndexOf("</?aspnet_head>") + 15, header.Length - header.ToString().ToLower().IndexOf("</?aspnet_head>") - 15));
|
|
header.Remove(header.ToString().ToLower().IndexOf("</?aspnet_head>"), header.Length - header.ToString().ToLower().IndexOf("</?aspnet_head>"));
|
|
|
|
// Find the title from head
|
|
MatchCollection matches = Regex.Matches(header.ToString(), @"<title>(.*?)</title>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
|
if (matches.Count > 0) {
|
|
StringBuilder titleText = new StringBuilder();
|
|
HtmlTextWriter titleTextTw = new HtmlTextWriter(new System.IO.StringWriter(titleText));
|
|
parseStringBuilder(new StringBuilder(matches[0].Groups[1].Value), umbPage).RenderControl(titleTextTw);
|
|
pageAspNetHead.Title = titleText.ToString();
|
|
header = new StringBuilder(header.ToString().Replace(matches[0].Value, ""));
|
|
}
|
|
|
|
pageAspNetHead.Controls.Add(parseStringBuilder(header, umbPage));
|
|
pageAspNetHead.ID = "head1";
|
|
|
|
// build the whole header part
|
|
pageHeader.Controls.Add(parseStringBuilder(beforeHeader, umbPage));
|
|
pageHeader.Controls.Add(pageAspNetHead);
|
|
pageHeader.Controls.Add(parseStringBuilder(afterHeader, umbPage));
|
|
|
|
} else
|
|
pageHeader.Controls.Add(parseStringBuilder(header, umbPage));
|
|
|
|
|
|
pageFooter.Controls.Add(parseStringBuilder(new StringBuilder(tempOutput.ToString().Substring(aspnetFormTagEnd, tempOutput.Length - aspnetFormTagEnd)), umbPage));
|
|
tempOutput.Remove(0, aspnetFormTagBegin + aspnetFormTagLength);
|
|
aspnetFormTagEnd = tempOutput.ToString().ToLower().IndexOf("</?aspnet_form>");
|
|
tempOutput.Remove(aspnetFormTagEnd, tempOutput.Length - aspnetFormTagEnd);
|
|
|
|
|
|
//throw new ArgumentException(tempOutput.ToString());
|
|
pageForm.Controls.Add(parseStringBuilder(tempOutput, umbPage));
|
|
|
|
pageContent.Controls.Add(pageHeader);
|
|
pageContent.Controls.Add(pageForm);
|
|
pageContent.Controls.Add(pageFooter);
|
|
return pageContent;
|
|
|
|
} else
|
|
return parseStringBuilder(tempOutput, umbPage);
|
|
|
|
}
|
|
|
|
public Control parseStringBuilder(StringBuilder tempOutput, page umbPage) {
|
|
|
|
Control pageContent = new Control();
|
|
|
|
bool stop = false;
|
|
bool debugMode = umbraco.presentation.UmbracoContext.Current.Request.IsDebug;
|
|
|
|
while (!stop) {
|
|
System.Web.HttpContext.Current.Trace.Write("template", "Begining of parsing rutine...");
|
|
int tagIndex = tempOutput.ToString().ToLower().IndexOf("<?umbraco");
|
|
if (tagIndex > -1) {
|
|
String tempElementContent = "";
|
|
pageContent.Controls.Add(new LiteralControl(tempOutput.ToString().Substring(0, tagIndex)));
|
|
|
|
tempOutput.Remove(0, tagIndex);
|
|
|
|
String tag = tempOutput.ToString().Substring(0, tempOutput.ToString().IndexOf(">") + 1);
|
|
Hashtable attributes = helper.ReturnAttributes(tag);
|
|
|
|
// Check whether it's a single tag (<?.../>) or a tag with children (<?..>...</?...>)
|
|
if (tag.Substring(tag.Length - 2, 1) != "/" && tag.IndexOf(" ") > -1) {
|
|
String closingTag = "</" + (tag.Substring(1, tag.IndexOf(" ") - 1)) + ">";
|
|
// Tag with children are only used when a macro is inserted by the umbraco-editor, in the
|
|
// following format: "<?UMBRACO_MACRO ...><IMG SRC="..."..></?UMBRACO_MACRO>", so we
|
|
// need to delete extra information inserted which is the image-tag and the closing
|
|
// umbraco_macro tag
|
|
if (tempOutput.ToString().IndexOf(closingTag) > -1) {
|
|
tempOutput.Remove(0, tempOutput.ToString().IndexOf(closingTag));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
System.Web.HttpContext.Current.Trace.Write("umbTemplate", "Outputting item: " + tag);
|
|
|
|
// Handle umbraco macro tags
|
|
if (tag.ToString().ToLower().IndexOf("umbraco_macro") > -1) {
|
|
if (debugMode)
|
|
pageContent.Controls.Add(new LiteralControl("<div title=\"Macro Tag: '" + System.Web.HttpContext.Current.Server.HtmlEncode(tag) + "'\" style=\"border: 1px solid #009;\">"));
|
|
|
|
// NH: Switching to custom controls for macros
|
|
if (UmbracoSettings.UseAspNetMasterPages) {
|
|
umbraco.presentation.templateControls.Macro macroControl = new umbraco.presentation.templateControls.Macro();
|
|
macroControl.Alias = helper.FindAttribute(attributes, "macroalias");
|
|
IDictionaryEnumerator ide = attributes.GetEnumerator();
|
|
while (ide.MoveNext())
|
|
if (macroControl.Attributes[ide.Key.ToString()] == null)
|
|
macroControl.Attributes.Add(ide.Key.ToString(), ide.Value.ToString());
|
|
pageContent.Controls.Add(macroControl);
|
|
} else {
|
|
macro tempMacro;
|
|
String macroID = helper.FindAttribute(attributes, "macroid");
|
|
if (macroID != String.Empty)
|
|
tempMacro = getMacro(macroID);
|
|
else
|
|
tempMacro = macro.ReturnFromAlias(helper.FindAttribute(attributes, "macroalias"));
|
|
|
|
if (tempMacro != null) {
|
|
|
|
try {
|
|
Control c = tempMacro.renderMacro(attributes, umbPage.Elements, umbPage.PageID);
|
|
if (c != null)
|
|
pageContent.Controls.Add(c);
|
|
else
|
|
System.Web.HttpContext.Current.Trace.Warn("Template", "Result of macro " + tempMacro.Name + " is null");
|
|
|
|
} catch (Exception e) {
|
|
System.Web.HttpContext.Current.Trace.Warn("Template", "Error adding macro " + tempMacro.Name, e);
|
|
}
|
|
}
|
|
}
|
|
if (debugMode)
|
|
pageContent.Controls.Add(new LiteralControl("</div>"));
|
|
} else {
|
|
if (tag.ToLower().IndexOf("umbraco_getitem") > -1) {
|
|
|
|
// NH: Switching to custom controls for items
|
|
if (UmbracoSettings.UseAspNetMasterPages) {
|
|
umbraco.presentation.templateControls.Item itemControl = new umbraco.presentation.templateControls.Item();
|
|
itemControl.Field = helper.FindAttribute(attributes, "field");
|
|
IDictionaryEnumerator ide = attributes.GetEnumerator();
|
|
while (ide.MoveNext())
|
|
if (itemControl.Attributes[ide.Key.ToString()] == null)
|
|
itemControl.Attributes.Add(ide.Key.ToString(), ide.Value.ToString());
|
|
pageContent.Controls.Add(itemControl);
|
|
} else {
|
|
try {
|
|
if (helper.FindAttribute(attributes, "nodeId") != "" && int.Parse(helper.FindAttribute(attributes, "nodeId")) != 0) {
|
|
cms.businesslogic.Content c = new umbraco.cms.businesslogic.Content(int.Parse(helper.FindAttribute(attributes, "nodeId")));
|
|
item umbItem = new item(c.getProperty(helper.FindAttribute(attributes, "field")).Value.ToString(), attributes);
|
|
tempElementContent = umbItem.FieldContent;
|
|
|
|
// Check if the content is published
|
|
if (c.nodeObjectType == cms.businesslogic.web.Document._objectType) {
|
|
try {
|
|
cms.businesslogic.web.Document d = (cms.businesslogic.web.Document)c;
|
|
if (!d.Published)
|
|
tempElementContent = "";
|
|
} catch { }
|
|
}
|
|
|
|
} else {
|
|
// NH adds Live Editing test stuff
|
|
item umbItem = new item(umbPage.Elements, attributes);
|
|
// item umbItem = new item(umbPage.PageElements[helper.FindAttribute(attributes, "field")].ToString(), attributes);
|
|
tempElementContent = umbItem.FieldContent;
|
|
}
|
|
|
|
if (debugMode)
|
|
tempElementContent =
|
|
"<div title=\"Field Tag: '" + System.Web.HttpContext.Current.Server.HtmlEncode(tag) + "'\" style=\"border: 1px solid #fc6;\">" + tempElementContent + "</div>";
|
|
} catch (Exception e) {
|
|
System.Web.HttpContext.Current.Trace.Warn("umbracoTemplate", "Error reading element (" + helper.FindAttribute(attributes, "field") + ")", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tempOutput.Remove(0, tempOutput.ToString().IndexOf(">") + 1);
|
|
tempOutput.Insert(0, tempElementContent);
|
|
} else {
|
|
pageContent.Controls.Add(new LiteralControl(tempOutput.ToString()));
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return pageContent;
|
|
|
|
}
|
|
|
|
public static string ParseInternalLinks(string pageContents)
|
|
{
|
|
// Parse internal links
|
|
MatchCollection tags = Regex.Matches(pageContents, @"href=""[/]?(?:\{|\%7B)localLink:([0-9]+)(?:\}|\%7D)", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
|
foreach (Match tag in tags)
|
|
if (tag.Groups.Count > 0)
|
|
{
|
|
string id = tag.Groups[1].Value; //.Remove(tag.Groups[1].Value.Length - 1, 1);
|
|
string newLink = library.NiceUrl(int.Parse(id));
|
|
pageContents = pageContents.Replace(tag.Value.ToString(), "href=\"" + newLink);
|
|
}
|
|
return pageContents;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses the content of the templateOutput stringbuilder, and matches any tags given in the
|
|
/// XML-file /umbraco/config/umbracoTemplateTags.xml.
|
|
/// Replaces the found tags in the StringBuilder object, with "real content"
|
|
/// </summary>
|
|
/// <param name="umbPage"></param>
|
|
public void Parse(page umbPage) {
|
|
System.Web.HttpContext.Current.Trace.Write("umbracoTemplate", "Start parsing");
|
|
|
|
// First parse for known umbraco tags
|
|
// <?UMBRACO_MACRO/> - macros
|
|
// <?UMBRACO_GETITEM/> - print item from page, level, or recursive
|
|
MatchCollection tags = Regex.Matches(templateOutput.ToString(), "<\\?UMBRACO_MACRO[^>]*/>|<\\?UMBRACO_GETITEM[^>]*/>|<\\?(?<tagName>[\\S]*)[^>]*/>", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
|
|
|
foreach (Match tag in tags) {
|
|
Hashtable attributes = helper.ReturnAttributes(tag.Value.ToString());
|
|
|
|
|
|
if (tag.ToString().ToLower().IndexOf("umbraco_macro") > -1) {
|
|
String macroID = helper.FindAttribute(attributes, "macroid");
|
|
if (macroID != "") {
|
|
macro tempMacro = getMacro(macroID);
|
|
templateOutput.Replace(tag.Value.ToString(), tempMacro.MacroContent.ToString());
|
|
}
|
|
} else {
|
|
if (tag.ToString().ToLower().IndexOf("umbraco_getitem") > -1) {
|
|
try {
|
|
String tempElementContent = umbPage.Elements[helper.FindAttribute(attributes, "field")].ToString();
|
|
MatchCollection tempMacros = Regex.Matches(tempElementContent, "<\\?UMBRACO_MACRO(?<attributes>[^>]*)><img[^>]*><\\/\\?UMBRACO_MACRO>", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
|
foreach (Match tempMacro in tempMacros) {
|
|
Hashtable tempAttributes = helper.ReturnAttributes(tempMacro.Groups["attributes"].Value.ToString());
|
|
String macroID = helper.FindAttribute(tempAttributes, "macroid");
|
|
if (Convert.ToInt32(macroID) > 0) {
|
|
macro tempContentMacro = getMacro(macroID);
|
|
templateOutput.Replace(tag.Value.ToString(), tempContentMacro.MacroContent.ToString());
|
|
}
|
|
|
|
}
|
|
|
|
templateOutput.Replace(tag.Value.ToString(), tempElementContent);
|
|
} catch (Exception e) {
|
|
System.Web.HttpContext.Current.Trace.Warn("umbracoTemplate", "Error reading element (" + helper.FindAttribute(attributes, "field") + ")", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
System.Web.HttpContext.Current.Trace.Write("umbracoTemplate", "Done parsing");
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region private methods
|
|
|
|
private macro getMacro(String macroID) {
|
|
System.Web.HttpContext.Current.Trace.Write("umbracoTemplate", "Starting macro (" + macroID.ToString() + ")");
|
|
return new macro(Convert.ToInt16(macroID));
|
|
}
|
|
|
|
private String FindAttribute(Hashtable attributes, String key) {
|
|
if (attributes[key] != null)
|
|
return attributes[key].ToString();
|
|
else
|
|
return "";
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
protected static ISqlHelper SqlHelper {
|
|
get { return Application.SqlHelper; }
|
|
}
|
|
|
|
#region constructors
|
|
|
|
public static string GetMasterPageName(int templateID) {
|
|
template t = (template)templateCache["template" + templateID];
|
|
if (t == null)
|
|
t = new template(templateID);
|
|
|
|
if (t != null)
|
|
return t.MasterPageFile;
|
|
else
|
|
throw new ArgumentException(String.Format("Template with id '{0}' not found", templateID));
|
|
}
|
|
|
|
public template(int templateID) {
|
|
if (templateCache["template" + templateID.ToString()] != null) {
|
|
template t = (template)templateCache["template" + templateID];
|
|
this._masterTemplate = t._masterTemplate;
|
|
this._templateAlias = t._templateAlias;
|
|
this._templateDesign = t._templateDesign;
|
|
this._masterTemplate = t._masterTemplate;
|
|
this._templateName = t._templateName;
|
|
} else {
|
|
using (IRecordsReader templateData = SqlHelper.ExecuteReader("select nodeId, alias, master, text, design from cmsTemplate inner join umbracoNode node on node.id = cmsTemplate.nodeId where nodeId = @templateID", SqlHelper.CreateParameter("@templateID", templateID))) {
|
|
if (templateData.Read()) {
|
|
// Get template master and replace content where the template
|
|
if (!templateData.IsNull("master"))
|
|
_masterTemplate = templateData.GetInt("master");
|
|
if (!templateData.IsNull("alias"))
|
|
_templateAlias = templateData.GetString("alias");
|
|
if (!templateData.IsNull("text"))
|
|
_templateName = templateData.GetString("text");
|
|
if (!templateData.IsNull("design"))
|
|
_templateDesign = templateData.GetString("design");
|
|
templateData.Close();
|
|
templateCache.Insert("template" + templateID.ToString(), this);
|
|
}
|
|
}
|
|
}
|
|
checkForMaster(templateID);
|
|
}
|
|
|
|
private void checkForMaster(int templateID) {
|
|
// Get template design
|
|
if (_masterTemplate != 0 && _masterTemplate != templateID) {
|
|
template masterTemplateDesign = new template(_masterTemplate);
|
|
if (masterTemplateDesign.TemplateContent.IndexOf("<?UMBRACO_TEMPLATE_LOAD_CHILD/>") > -1
|
|
|| masterTemplateDesign.TemplateContent.IndexOf("<?UMBRACO_TEMPLATE_LOAD_CHILD />") > -1) {
|
|
templateOutput.Append(
|
|
masterTemplateDesign.TemplateContent.Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD/>",
|
|
_templateDesign).Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD />", _templateDesign)
|
|
);
|
|
} else
|
|
templateOutput.Append(_templateDesign);
|
|
} else {
|
|
if (_masterTemplate == templateID)
|
|
System.Web.HttpContext.Current.Trace.Warn("template", "Master template is the same as the current template. It would course an endless loop!");
|
|
templateOutput.Append(_templateDesign);
|
|
}
|
|
}
|
|
|
|
public static void ClearCachedTemplate(int templateID) {
|
|
if (templateCache["template" + templateID.ToString()] != null)
|
|
templateCache.Remove("template" + templateID.ToString());
|
|
}
|
|
|
|
public template(String templateContent) {
|
|
templateOutput.Append(templateContent);
|
|
_masterTemplate = 0;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class templateCacheRefresh : interfaces.ICacheRefresher {
|
|
#region ICacheRefresher Members
|
|
|
|
public string Name {
|
|
get {
|
|
// TODO: Add templateCacheRefresh.Name getter implementation
|
|
return "Template cache refresher";
|
|
}
|
|
}
|
|
|
|
public Guid UniqueIdentifier {
|
|
get {
|
|
// TODO: Add templateCacheRefresh.UniqueIdentifier getter implementation
|
|
return new Guid("DD12B6A0-14B9-46e8-8800-C154F74047C8");
|
|
}
|
|
}
|
|
|
|
public void RefreshAll() {
|
|
// Doesn't do anything
|
|
}
|
|
|
|
public void Refresh(Guid Id) {
|
|
// Doesn't do anything
|
|
}
|
|
|
|
void umbraco.interfaces.ICacheRefresher.Refresh(int Id) {
|
|
template.ClearCachedTemplate(Id);
|
|
}
|
|
|
|
//PPH remove tamplete from cache
|
|
public void Remove(int Id) {
|
|
|
|
template.ClearCachedTemplate(Id);
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|