Created MacroTagParser and updated ItemRenderer to use it. Have DynamicDocument rendering RTE content
with macro content without having to use any special methods, we just use a new custom Property Editor value converter. Now just need to port this over to DynamicNode too. Obsoleted a method on the 'helper' class to something much more meaningful... hopefully we can do that with the rest of that class too.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
//public interface IRazorDataTypeModel
|
||||
//{
|
||||
// bool Init(int currentNodeId, string propertyData, out object instance);
|
||||
//}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
//[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
|
||||
//public sealed class RazorDataTypeModel : Attribute
|
||||
//{
|
||||
// public readonly Guid DataTypeEditorId;
|
||||
// public readonly int Priority;
|
||||
|
||||
// public RazorDataTypeModel(string DataTypeEditorId)
|
||||
// {
|
||||
// this.DataTypeEditorId = new Guid(DataTypeEditorId);
|
||||
// Priority = 100;
|
||||
// }
|
||||
|
||||
// public RazorDataTypeModel(string DataTypeEditorId, int Priority)
|
||||
// {
|
||||
// this.DataTypeEditorId = new Guid(DataTypeEditorId);
|
||||
// this.Priority = Priority;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
@@ -1,583 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco.interfaces;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using System.Web;
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
//internal class RazorLibraryCore
|
||||
//{
|
||||
// private readonly IDocument _node;
|
||||
// public IDocument Node
|
||||
// {
|
||||
// get { return _node; }
|
||||
// }
|
||||
// public RazorLibraryCore(IDocument node)
|
||||
// {
|
||||
// this._node = node;
|
||||
// }
|
||||
|
||||
// public dynamic NodeById(int id)
|
||||
// {
|
||||
// var node = new DynamicNode(id);
|
||||
// if (node != null && node.Id == 0) return new DynamicNull();
|
||||
// return node;
|
||||
// }
|
||||
// public dynamic NodeById(string id)
|
||||
// {
|
||||
// var node = new DynamicNode(id);
|
||||
// if (node != null && node.Id == 0) return new DynamicNull();
|
||||
// return node;
|
||||
// }
|
||||
// public dynamic NodeById(DynamicNull Id)
|
||||
// {
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// public dynamic NodeById(object Id)
|
||||
// {
|
||||
// if (Id.GetType() == typeof(DynamicNull))
|
||||
// {
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// var node = new DynamicNode(Id);
|
||||
// if (node != null && node.Id == 0) return new DynamicNull();
|
||||
// return node;
|
||||
// }
|
||||
// public dynamic NodesById(List<object> Ids)
|
||||
// {
|
||||
// List<DynamicNode> nodes = new List<DynamicNode>();
|
||||
// foreach (object eachId in Ids)
|
||||
// nodes.Add(new DynamicNode(eachId));
|
||||
// return new DynamicNodeList(nodes);
|
||||
// }
|
||||
// public dynamic NodesById(List<int> Ids)
|
||||
// {
|
||||
// List<DynamicNode> nodes = new List<DynamicNode>();
|
||||
// foreach (int eachId in Ids)
|
||||
// nodes.Add(new DynamicNode(eachId));
|
||||
// return new DynamicNodeList(nodes);
|
||||
// }
|
||||
// public dynamic NodesById(List<int> Ids, DynamicBackingItemType ItemType)
|
||||
// {
|
||||
// List<DynamicNode> nodes = new List<DynamicNode>();
|
||||
// foreach (int eachId in Ids)
|
||||
// nodes.Add(new DynamicNode(eachId, ItemType));
|
||||
// return new DynamicNodeList(nodes);
|
||||
// }
|
||||
// public dynamic NodesById(params object[] Ids)
|
||||
// {
|
||||
// return NodesById(Ids.ToList());
|
||||
// }
|
||||
// public dynamic MediaById(DynamicNull Id)
|
||||
// {
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// public dynamic MediaById(int Id)
|
||||
// {
|
||||
// var ebm = ExamineBackedMedia.GetUmbracoMedia(Id);
|
||||
// if (ebm != null && ebm.Id == 0)
|
||||
// {
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// return new DynamicNode(new DynamicBackingItem(ebm));
|
||||
// }
|
||||
// public dynamic MediaById(string Id)
|
||||
// {
|
||||
// int mediaId = 0;
|
||||
// if (int.TryParse(Id, out mediaId))
|
||||
// {
|
||||
// return MediaById(mediaId);
|
||||
// }
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// public dynamic MediaById(object Id)
|
||||
// {
|
||||
// if (Id.GetType() == typeof(DynamicNull))
|
||||
// {
|
||||
// return new DynamicNull();
|
||||
// }
|
||||
// int mediaId = 0;
|
||||
// if (int.TryParse(string.Format("{0}", Id), out mediaId))
|
||||
// {
|
||||
// return MediaById(mediaId);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// public dynamic MediaById(List<object> Ids)
|
||||
// {
|
||||
// List<DynamicNode> nodes = new List<DynamicNode>();
|
||||
// foreach (object eachId in Ids)
|
||||
// nodes.Add(MediaById(eachId));
|
||||
// return new DynamicNodeList(nodes);
|
||||
// }
|
||||
// public dynamic MediaById(List<int> Ids)
|
||||
// {
|
||||
// List<DynamicNode> nodes = new List<DynamicNode>();
|
||||
// foreach (int eachId in Ids)
|
||||
// nodes.Add(MediaById(eachId));
|
||||
// return new DynamicNodeList(nodes);
|
||||
// }
|
||||
// public dynamic MediaById(params object[] Ids)
|
||||
// {
|
||||
// return MediaById(Ids.ToList());
|
||||
// }
|
||||
|
||||
|
||||
// //public dynamic Search(string term, bool useWildCards = true, string searchProvider = null)
|
||||
// //{
|
||||
// // var searcher = Examine.ExamineManager.Instance.DefaultSearchProvider;
|
||||
// // if (!string.IsNullOrEmpty(searchProvider))
|
||||
// // searcher = Examine.ExamineManager.Instance.SearchProviderCollection[searchProvider];
|
||||
|
||||
// // var results = searcher.Search(term, useWildCards);
|
||||
// // return ExamineSearchUtill.convertSearchResultToDynamicNode(results);
|
||||
// //}
|
||||
|
||||
// //public dynamic Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null)
|
||||
// //{
|
||||
// // var s = Examine.ExamineManager.Instance.DefaultSearchProvider;
|
||||
// // if (searchProvider != null)
|
||||
// // s = searchProvider;
|
||||
|
||||
// // var results = s.Search(criteria);
|
||||
// // return ExamineSearchUtill.convertSearchResultToDynamicNode(results);
|
||||
// //}
|
||||
|
||||
|
||||
// public T As<T>() where T : class
|
||||
// {
|
||||
// return (this as T);
|
||||
// }
|
||||
|
||||
// public dynamic ToDynamicXml(string xml)
|
||||
// {
|
||||
// if (string.IsNullOrWhiteSpace(xml)) return null;
|
||||
// var xElement = XElement.Parse(xml);
|
||||
// return new DynamicXml(xElement);
|
||||
// }
|
||||
// public dynamic ToDynamicXml(XElement xElement)
|
||||
// {
|
||||
// return new DynamicXml(xElement);
|
||||
// }
|
||||
// public dynamic ToDynamicXml(XPathNodeIterator xpni)
|
||||
// {
|
||||
// return new DynamicXml(xpni);
|
||||
// }
|
||||
// public string Coalesce(params object[] args)
|
||||
// {
|
||||
// foreach (var arg in args)
|
||||
// {
|
||||
// if (arg != null && arg.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// var sArg = string.Format("{0}", arg);
|
||||
// if (!string.IsNullOrWhiteSpace(sArg))
|
||||
// {
|
||||
// return sArg;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return string.Empty;
|
||||
// }
|
||||
|
||||
// public string Concatenate(params object[] args)
|
||||
// {
|
||||
// StringBuilder result = new StringBuilder();
|
||||
// foreach (var arg in args)
|
||||
// {
|
||||
// if (arg != null && arg.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// var sArg = string.Format("{0}", arg);
|
||||
// if (!string.IsNullOrWhiteSpace(sArg))
|
||||
// {
|
||||
// result.Append(sArg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result.ToString();
|
||||
// }
|
||||
// public string Join(string seperator, params object[] args)
|
||||
// {
|
||||
// List<string> results = new List<string>();
|
||||
// foreach (var arg in args)
|
||||
// {
|
||||
// if (arg != null && arg.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// var sArg = string.Format("{0}", arg);
|
||||
// if (!string.IsNullOrWhiteSpace(sArg))
|
||||
// {
|
||||
// results.Add(sArg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return string.Join(seperator, results);
|
||||
// }
|
||||
|
||||
// public HtmlString If(bool test, string valueIfTrue, string valueIfFalse)
|
||||
// {
|
||||
// return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse);
|
||||
// }
|
||||
// public HtmlString If(bool test, string valueIfTrue)
|
||||
// {
|
||||
// return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty);
|
||||
// }
|
||||
|
||||
// public HtmlTagWrapper Wrap(string tag, string innerText, params IHtmlTagWrapper[] Children)
|
||||
// {
|
||||
// var item = Wrap(tag, innerText, (object)null);
|
||||
// foreach (var child in Children)
|
||||
// {
|
||||
// item.AddChild(child);
|
||||
// }
|
||||
// return item;
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(string tag, string innerText)
|
||||
// {
|
||||
// return Wrap(tag, innerText, (object)null);
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(string tag, object inner, object anonymousAttributes)
|
||||
// {
|
||||
// string innerText = null;
|
||||
// if (inner != null && inner.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// innerText = string.Format("{0}", inner);
|
||||
// }
|
||||
// return Wrap(tag, innerText, anonymousAttributes);
|
||||
// }
|
||||
|
||||
// public HtmlTagWrapper Wrap(string tag, object inner, object anonymousAttributes, params IHtmlTagWrapper[] Children)
|
||||
// {
|
||||
// string innerText = null;
|
||||
// if (inner != null && inner.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// innerText = string.Format("{0}", inner);
|
||||
// }
|
||||
// var item = Wrap(tag, innerText, anonymousAttributes);
|
||||
// foreach (var child in Children)
|
||||
// {
|
||||
// item.AddChild(child);
|
||||
// }
|
||||
// return item;
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(string tag, object inner)
|
||||
// {
|
||||
// string innerText = null;
|
||||
// if (inner != null && inner.GetType() != typeof(DynamicNull))
|
||||
// {
|
||||
// innerText = string.Format("{0}", inner);
|
||||
// }
|
||||
// return Wrap(tag, innerText, null);
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(string tag, string innerText, object anonymousAttributes)
|
||||
// {
|
||||
// HtmlTagWrapper wrap = new HtmlTagWrapper(tag);
|
||||
// if (anonymousAttributes != null)
|
||||
// {
|
||||
// wrap.ReflectAttributesFromAnonymousType(anonymousAttributes);
|
||||
// }
|
||||
// if (!string.IsNullOrWhiteSpace(innerText))
|
||||
// {
|
||||
// wrap.Children.Add(new HtmlTagWrapperTextNode(innerText));
|
||||
// }
|
||||
// return wrap;
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(string tag, string innerText, object anonymousAttributes, params IHtmlTagWrapper[] Children)
|
||||
// {
|
||||
// HtmlTagWrapper wrap = new HtmlTagWrapper(tag);
|
||||
// if (anonymousAttributes != null)
|
||||
// {
|
||||
// wrap.ReflectAttributesFromAnonymousType(anonymousAttributes);
|
||||
// }
|
||||
// if (!string.IsNullOrWhiteSpace(innerText))
|
||||
// {
|
||||
// wrap.Children.Add(new HtmlTagWrapperTextNode(innerText));
|
||||
// }
|
||||
// foreach (var child in Children)
|
||||
// {
|
||||
// wrap.AddChild(child);
|
||||
// }
|
||||
// return wrap;
|
||||
// }
|
||||
|
||||
// public HtmlTagWrapper Wrap(bool visible, string tag, string innerText, object anonymousAttributes)
|
||||
// {
|
||||
// var item = Wrap(tag, innerText, anonymousAttributes);
|
||||
// item.Visible = visible;
|
||||
// return item;
|
||||
// }
|
||||
// public HtmlTagWrapper Wrap(bool visible, string tag, string innerText, object anonymousAttributes, params IHtmlTagWrapper[] Children)
|
||||
// {
|
||||
// var item = Wrap(tag, innerText, anonymousAttributes, Children);
|
||||
// item.Visible = visible;
|
||||
// foreach (var child in Children)
|
||||
// {
|
||||
// item.AddChild(child);
|
||||
// }
|
||||
// return item;
|
||||
// }
|
||||
// public IHtmlString Truncate(IHtmlString html, int length)
|
||||
// {
|
||||
// return Truncate(html.ToHtmlString(), length, true, false);
|
||||
// }
|
||||
// public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis)
|
||||
// {
|
||||
// return Truncate(html.ToHtmlString(), length, addElipsis, false);
|
||||
// }
|
||||
// public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent)
|
||||
// {
|
||||
// return Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent);
|
||||
// }
|
||||
// public IHtmlString Truncate(DynamicNull html, int length)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public IHtmlString Truncate(DynamicNull html, int length, bool addElipsis)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public IHtmlString Truncate(DynamicNull html, int length, bool addElipsis, bool treatTagsAsContent)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public IHtmlString Truncate(string html, int length)
|
||||
// {
|
||||
// return Truncate(html, length, true, false);
|
||||
// }
|
||||
// public IHtmlString Truncate(string html, int length, bool addElipsis)
|
||||
// {
|
||||
// return Truncate(html, length, addElipsis, false);
|
||||
// }
|
||||
// public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent)
|
||||
// {
|
||||
// using (MemoryStream outputms = new MemoryStream())
|
||||
// {
|
||||
// using (TextWriter outputtw = new StreamWriter(outputms))
|
||||
// {
|
||||
// using (MemoryStream ms = new MemoryStream())
|
||||
// {
|
||||
// using (TextWriter tw = new StreamWriter(ms))
|
||||
// {
|
||||
// tw.Write(html);
|
||||
// tw.Flush();
|
||||
// ms.Position = 0;
|
||||
// Stack<string> tagStack = new Stack<string>();
|
||||
// using (TextReader tr = new StreamReader(ms))
|
||||
// {
|
||||
// bool IsInsideElement = false;
|
||||
// bool lengthReached = false;
|
||||
// int ic = 0;
|
||||
// int currentLength = 0, currentTextLength = 0;
|
||||
// string currentTag = string.Empty;
|
||||
// string tagContents = string.Empty;
|
||||
// bool insideTagSpaceEncountered = false;
|
||||
// bool isTagClose = false;
|
||||
// while ((ic = tr.Read()) != -1)
|
||||
// {
|
||||
// bool write = true;
|
||||
|
||||
// if (ic == (int)'<')
|
||||
// {
|
||||
// if (!lengthReached)
|
||||
// {
|
||||
// IsInsideElement = true;
|
||||
// }
|
||||
// insideTagSpaceEncountered = false;
|
||||
// currentTag = string.Empty;
|
||||
// tagContents = string.Empty;
|
||||
// isTagClose = false;
|
||||
// if (tr.Peek() == (int)'/')
|
||||
// {
|
||||
// isTagClose = true;
|
||||
// }
|
||||
// }
|
||||
// else if (ic == (int)'>')
|
||||
// {
|
||||
// //if (IsInsideElement)
|
||||
// //{
|
||||
// IsInsideElement = false;
|
||||
// //if (write)
|
||||
// //{
|
||||
// // outputtw.Write('>');
|
||||
// //}
|
||||
// currentTextLength++;
|
||||
// if (isTagClose && tagStack.Count > 0)
|
||||
// {
|
||||
// string thisTag = tagStack.Pop();
|
||||
// outputtw.Write("</" + thisTag + ">");
|
||||
// }
|
||||
// if (!isTagClose && currentTag.Length > 0)
|
||||
// {
|
||||
// if (!lengthReached)
|
||||
// {
|
||||
// tagStack.Push(currentTag);
|
||||
// outputtw.Write("<" + currentTag);
|
||||
// if (tr.Peek() != (int)' ')
|
||||
// {
|
||||
// if (!string.IsNullOrEmpty(tagContents))
|
||||
// {
|
||||
// if (tagContents.EndsWith("/"))
|
||||
// {
|
||||
// //short close
|
||||
// tagStack.Pop();
|
||||
// }
|
||||
// outputtw.Write(tagContents);
|
||||
// }
|
||||
// outputtw.Write(">");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //}
|
||||
// continue;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (IsInsideElement)
|
||||
// {
|
||||
// if (ic == (int)' ')
|
||||
// {
|
||||
// if (!insideTagSpaceEncountered)
|
||||
// {
|
||||
// insideTagSpaceEncountered = true;
|
||||
// //if (!isTagClose)
|
||||
// //{
|
||||
// // tagStack.Push(currentTag);
|
||||
// //}
|
||||
// }
|
||||
// }
|
||||
// if (!insideTagSpaceEncountered)
|
||||
// {
|
||||
// currentTag += (char)ic;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (IsInsideElement || insideTagSpaceEncountered)
|
||||
// {
|
||||
// write = false;
|
||||
// if (insideTagSpaceEncountered)
|
||||
// {
|
||||
// tagContents += (char)ic;
|
||||
// }
|
||||
// }
|
||||
// if (!IsInsideElement || treatTagsAsContent)
|
||||
// {
|
||||
// currentTextLength++;
|
||||
// }
|
||||
// currentLength++;
|
||||
// if (currentTextLength <= length || (lengthReached && IsInsideElement))
|
||||
// {
|
||||
// if (write)
|
||||
// {
|
||||
// outputtw.Write((char)ic);
|
||||
// }
|
||||
// }
|
||||
// if (!lengthReached && currentTextLength >= length)
|
||||
// {
|
||||
// //reached truncate point
|
||||
// if (addElipsis)
|
||||
// {
|
||||
// outputtw.Write("…");
|
||||
// }
|
||||
// lengthReached = true;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// outputtw.Flush();
|
||||
// outputms.Position = 0;
|
||||
// using (TextReader outputtr = new StreamReader(outputms))
|
||||
// {
|
||||
// return new HtmlString(outputtr.ReadToEnd().Replace(" ", " ").Trim());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// public HtmlString StripHtml(IHtmlString html)
|
||||
// {
|
||||
// return StripHtml(html.ToHtmlString(), (List<string>)null);
|
||||
// }
|
||||
// public HtmlString StripHtml(DynamicNull html)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public HtmlString StripHtml(string html)
|
||||
// {
|
||||
// return StripHtmlTags(html, (List<string>)null);
|
||||
// }
|
||||
|
||||
// public HtmlString StripHtml(IHtmlString html, List<string> tags)
|
||||
// {
|
||||
// return StripHtml(html.ToHtmlString(), tags);
|
||||
// }
|
||||
// public HtmlString StripHtml(DynamicNull html, List<string> tags)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public HtmlString StripHtml(string html, List<string> tags)
|
||||
// {
|
||||
// return StripHtmlTags(html, tags);
|
||||
// }
|
||||
|
||||
// public HtmlString StripHtml(IHtmlString html, params string[] tags)
|
||||
// {
|
||||
// return StripHtml(html.ToHtmlString(), tags.ToList());
|
||||
// }
|
||||
// public HtmlString StripHtml(DynamicNull html, params string[] tags)
|
||||
// {
|
||||
// return new HtmlString(string.Empty);
|
||||
// }
|
||||
// public HtmlString StripHtml(string html, params string[] tags)
|
||||
// {
|
||||
// return StripHtmlTags(html, tags.ToList());
|
||||
// }
|
||||
|
||||
// private HtmlString StripHtmlTags(string html, List<string> tags)
|
||||
// {
|
||||
// HtmlDocument doc = new HtmlDocument();
|
||||
// doc.LoadHtml("<p>" + html + "</p>");
|
||||
// using (MemoryStream ms = new MemoryStream())
|
||||
// {
|
||||
// List<HtmlNode> targets = new List<HtmlNode>();
|
||||
|
||||
// var nodes = doc.DocumentNode.FirstChild.SelectNodes(".//*");
|
||||
// if (nodes != null)
|
||||
// {
|
||||
// foreach (var node in nodes)
|
||||
// {
|
||||
// //is element
|
||||
// if (node.NodeType == HtmlNodeType.Element)
|
||||
// {
|
||||
// bool filterAllTags = (tags == null || tags.Count == 0);
|
||||
// if (filterAllTags || tags.Any(tag => string.Equals(tag, node.Name, StringComparison.CurrentCultureIgnoreCase)))
|
||||
// {
|
||||
// targets.Add(node);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// foreach (var target in targets)
|
||||
// {
|
||||
// HtmlNode content = doc.CreateTextNode(target.InnerText);
|
||||
// target.ParentNode.ReplaceChild(content, target);
|
||||
// }
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return new HtmlString(html);
|
||||
// }
|
||||
// return new HtmlString(doc.DocumentNode.FirstChild.InnerHtml);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
88
src/Umbraco.Core/Macros/MacroTagParser.cs
Normal file
88
src/Umbraco.Core/Macros/MacroTagParser.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Macros
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses the macro syntax in a string and renders out it's contents
|
||||
/// </summary>
|
||||
internal class MacroTagParser
|
||||
{
|
||||
/// <summary>
|
||||
/// This will accept a text block and seach/parse it for macro markup.
|
||||
/// When either a text block or a a macro is found, it will call the callback method.
|
||||
/// </summary>
|
||||
/// <param name="text"> </param>
|
||||
/// <param name="textFoundCallback"></param>
|
||||
/// <param name="macroFoundCallback"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This method simply parses the macro contents, it does not create a string or result,
|
||||
/// this is up to the developer calling this method to implement this with the callbacks.
|
||||
/// </remarks>
|
||||
internal static void ParseMacros(
|
||||
string text,
|
||||
Action<string> textFoundCallback,
|
||||
Action<string, Dictionary<string, string>> macroFoundCallback )
|
||||
{
|
||||
if (textFoundCallback == null) throw new ArgumentNullException("textFoundCallback");
|
||||
if (macroFoundCallback == null) throw new ArgumentNullException("macroFoundCallback");
|
||||
|
||||
string elementText = text;
|
||||
|
||||
var fieldResult = new StringBuilder(elementText);
|
||||
|
||||
//NOTE: This is legacy code, this is definitely not the correct way to do a while loop! :)
|
||||
var stop = false;
|
||||
while (!stop)
|
||||
{
|
||||
var tagIndex = fieldResult.ToString().ToLower().IndexOf("<?umbraco");
|
||||
if (tagIndex < 0)
|
||||
tagIndex = fieldResult.ToString().ToLower().IndexOf("<umbraco:macro");
|
||||
if (tagIndex > -1)
|
||||
{
|
||||
var tempElementContent = "";
|
||||
|
||||
//text block found, call the call back method
|
||||
textFoundCallback(fieldResult.ToString().Substring(0, tagIndex));
|
||||
|
||||
fieldResult.Remove(0, tagIndex);
|
||||
|
||||
var tag = fieldResult.ToString().Substring(0, fieldResult.ToString().IndexOf(">") + 1);
|
||||
var attributes = XmlHelper.GetAttributesFromElement(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 (fieldResult.ToString().IndexOf(closingTag) > -1)
|
||||
{
|
||||
fieldResult.Remove(0, fieldResult.ToString().IndexOf(closingTag));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var macroAlias = attributes["macroalias"] ?? attributes["alias"];
|
||||
|
||||
//call the callback now that we have the macro parsed
|
||||
macroFoundCallback(macroAlias, attributes);
|
||||
|
||||
fieldResult.Remove(0, fieldResult.ToString().IndexOf(">") + 1);
|
||||
fieldResult.Insert(0, tempElementContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
//text block found, call the call back method
|
||||
textFoundCallback(fieldResult.ToString());
|
||||
|
||||
stop = true; //break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Umbraco.Core.Macros
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// NOTE: This is legacy code, might require a cleanup
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,9 @@ using System.Web;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used.
|
||||
/// </summary>
|
||||
internal class TinyMcePropertyEditorValueConverter : IPropertyEditorValueConverter
|
||||
{
|
||||
public bool IsConverterFor(Guid propertyEditorId, string docTypeAlias, string propertyTypeAlias)
|
||||
@@ -15,7 +18,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public Attempt<object> ConvertPropertyValue(object value)
|
||||
public virtual Attempt<object> ConvertPropertyValue(object value)
|
||||
{
|
||||
return new Attempt<object>(true, new HtmlString(value.ToString()));
|
||||
}
|
||||
|
||||
@@ -88,17 +88,15 @@
|
||||
<Compile Include="IO\FileSystemProviderAttribute.cs" />
|
||||
<Compile Include="IO\IFileSystemExtensions.cs" />
|
||||
<Compile Include="IO\IMediaFileSystem.cs" />
|
||||
<Compile Include="Macros\MacroTagParser.cs" />
|
||||
<Compile Include="PropertyEditors\DatePickerPropertyEditorValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\IPropertyEditorValueConverter.cs" />
|
||||
<Compile Include="HtmlTagWrapper.cs" />
|
||||
<Compile Include="HtmlTagWrapperBase.cs" />
|
||||
<Compile Include="HtmlTagWrapperTextNode.cs" />
|
||||
<Compile Include="Dynamics\IDynamicDocumentDataSource.cs" />
|
||||
<Compile Include="Dynamics\IRazorDataTypeModel.cs" />
|
||||
<Compile Include="Dynamics\ParseException.cs" />
|
||||
<Compile Include="Dynamics\PropertyResult.cs" />
|
||||
<Compile Include="Dynamics\RazorDataTypeModel.cs" />
|
||||
<Compile Include="Dynamics\RazorLibraryCore.cs" />
|
||||
<Compile Include="Dynamics\Res.cs" />
|
||||
<Compile Include="Dynamics\Signature.cs" />
|
||||
<Compile Include="ExpressionExtensions.cs" />
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
@@ -164,5 +168,20 @@ namespace Umbraco.Core
|
||||
// return the XML node.
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a dictionary of attributes found for a string based tag
|
||||
/// </summary>
|
||||
/// <param name="tag"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<string, string> GetAttributesFromElement(string tag)
|
||||
{
|
||||
var m =
|
||||
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
// fix for issue 14862: return lowercase attributes for case insensitive matching
|
||||
var d = m.Cast<Match>().ToDictionary(attributeSet => attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet => attributeSet.Groups["attributeValue"].Value.ToString());
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Macros;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// A value converter for TinyMCE that will ensure any macro content is rendered properly even when
|
||||
/// used dynamically.
|
||||
/// </summary>
|
||||
internal class RteMacroRenderingPropertyEditorValueConverter : TinyMcePropertyEditorValueConverter
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Return IHtmlString so devs doesn't need to decode html
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public override Attempt<object> ConvertPropertyValue(object value)
|
||||
{
|
||||
//TODO: we need to make a few new classes, like a new MacroParser, etc... and move a bunch of the logic
|
||||
// out of 'Item' that does all of this but it will be tricky because of the way that it creates a 'Macro' class
|
||||
// we may have to do some server Execute trickyness.
|
||||
// Then, we need to add this to the resolver and remove the base class and make it abstract.
|
||||
|
||||
var sb = new StringBuilder();
|
||||
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
|
||||
MacroTagParser.ParseMacros(
|
||||
value.ToString(),
|
||||
//callback for when text block is found
|
||||
textBlock => sb.Append(textBlock),
|
||||
//callback for when macro syntax is found
|
||||
(macroAlias, macroAttributes) => sb.Append(umbracoHelper.RenderMacro(
|
||||
macroAlias,
|
||||
//needs to be explicitly casted to Dictionary<string, object>
|
||||
macroAttributes.ConvertTo(x => (string)x, x => (object)x)).ToString()));
|
||||
|
||||
return new Attempt<object>(true, new HtmlString(sb.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,6 +257,7 @@
|
||||
<Compile Include="Media\EmbedProviders\Settings\String.cs" />
|
||||
<Compile Include="Media\EmbedProviders\Twitgoo.cs" />
|
||||
<Compile Include="ModelStateExtensions.cs" />
|
||||
<Compile Include="PropertyEditors\RteMacroRenderingPropertyEditorValueConverter.cs" />
|
||||
<Compile Include="RenderFieldCaseType.cs" />
|
||||
<Compile Include="RenderFieldEncodingType.cs" />
|
||||
<Compile Include="Routing\LookupByPageIdQuery.cs" />
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Umbraco.Web
|
||||
|
||||
internal UmbracoHelper(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
_umbracoContext = umbracoContext;
|
||||
_currentPage = _umbracoContext.DocumentRequest.Document;
|
||||
}
|
||||
@@ -46,6 +47,17 @@ namespace Umbraco.Web
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, object parameters)
|
||||
{
|
||||
return RenderMacro(alias, parameters.ToDictionary<object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters)
|
||||
{
|
||||
if (alias == null) throw new ArgumentNullException("alias");
|
||||
var containerPage = new FormlessPage();
|
||||
@@ -59,20 +71,20 @@ namespace Umbraco.Web
|
||||
throw new InvalidOperationException("Cannot render a macro when there is no current DocumentRequest.");
|
||||
}
|
||||
var macroProps = new Hashtable();
|
||||
foreach(var i in parameters.ToDictionary<object>())
|
||||
foreach (var i in parameters)
|
||||
{
|
||||
//TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method of macro.cs
|
||||
// looks for a lower case match. WTF. the whole macro concept needs to be rewritten.
|
||||
macroProps.Add(i.Key.ToLower(), i.Value);
|
||||
}
|
||||
var macroControl = m.renderMacro(macroProps,
|
||||
UmbracoContext.Current.DocumentRequest.UmbracoPage.Elements,
|
||||
}
|
||||
var macroControl = m.renderMacro(macroProps,
|
||||
UmbracoContext.Current.DocumentRequest.UmbracoPage.Elements,
|
||||
_umbracoContext.PageId.Value);
|
||||
containerPage.Controls.Add(macroControl);
|
||||
using (var output = new StringWriter())
|
||||
{
|
||||
_umbracoContext.HttpContext.Server.Execute(containerPage, output, false);
|
||||
return new HtmlString(output.ToString());
|
||||
return new HtmlString(output.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@ using System.Web.Routing;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.Dictionary;
|
||||
using Umbraco.Web.Media.ThumbnailProviders;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.businesslogic;
|
||||
|
||||
@@ -126,6 +128,11 @@ namespace Umbraco.Web
|
||||
{
|
||||
base.InitializeResolvers();
|
||||
|
||||
//the base creates the PropertyEditorValueConvertersResolver but we want to modify it in the web app and replace
|
||||
//the TinyMcePropertyEditorValueConverter with the RteMacroRenderingPropertyEditorValueConverter
|
||||
PropertyEditorValueConvertersResolver.Current.RemoveType<TinyMcePropertyEditorValueConverter>();
|
||||
PropertyEditorValueConvertersResolver.Current.AddType<RteMacroRenderingPropertyEditorValueConverter>();
|
||||
|
||||
ContentStoreResolver.Current = new ContentStoreResolver(new XmlPublishedContentStore());
|
||||
|
||||
FilteredControllerFactoriesResolver.Current = new FilteredControllerFactoriesResolver(
|
||||
|
||||
@@ -36,18 +36,16 @@ namespace umbraco
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
[Obsolete("Has been superceded by Umbraco.Core.XmlHelper.GetAttributesFromElement")]
|
||||
public static Hashtable ReturnAttributes(String tag)
|
||||
{
|
||||
Hashtable ht = new Hashtable();
|
||||
MatchCollection m =
|
||||
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
// fix for issue 14862: return lowercase attributes for case insensitive matching
|
||||
foreach (Match attributeSet in m)
|
||||
ht.Add(attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet.Groups["attributeValue"].Value.ToString());
|
||||
|
||||
return ht;
|
||||
}
|
||||
{
|
||||
var h = new Hashtable();
|
||||
foreach(var i in Umbraco.Core.XmlHelper.GetAttributesFromElement(tag))
|
||||
{
|
||||
h.Add(i.Key, i.Value);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static String FindAttribute(IDictionary attributes, String key)
|
||||
{
|
||||
|
||||
@@ -2,10 +2,12 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Macros;
|
||||
using Umbraco.Web.umbraco.templateControls;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.cms.businesslogic.property;
|
||||
@@ -14,309 +16,277 @@ using umbraco.IO;
|
||||
|
||||
namespace umbraco.presentation.templateControls
|
||||
{
|
||||
public class ItemRenderer
|
||||
{
|
||||
public readonly static ItemRenderer Instance = new ItemRenderer();
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemRenderer"/> class.
|
||||
/// </summary>
|
||||
protected ItemRenderer()
|
||||
{ }
|
||||
public class ItemRenderer
|
||||
{
|
||||
public readonly static ItemRenderer Instance = new ItemRenderer();
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemRenderer"/> class.
|
||||
/// </summary>
|
||||
protected ItemRenderer()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Renders the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="writer">The writer.</param>
|
||||
public virtual void Render(Item item, HtmlTextWriter writer)
|
||||
{
|
||||
if (item.DebugMode)
|
||||
{
|
||||
writer.AddAttribute(HtmlTextWriterAttribute.Title, string.Format("Field Tag: '{0}'", item.Field));
|
||||
writer.AddAttribute("style", "border: 1px solid #fc6;");
|
||||
writer.RenderBeginTag(HtmlTextWriterTag.Div);
|
||||
}
|
||||
/// <summary>
|
||||
/// Renders the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="writer">The writer.</param>
|
||||
public virtual void Render(Item item, HtmlTextWriter writer)
|
||||
{
|
||||
if (item.DebugMode)
|
||||
{
|
||||
writer.AddAttribute(HtmlTextWriterAttribute.Title, string.Format("Field Tag: '{0}'", item.Field));
|
||||
writer.AddAttribute("style", "border: 1px solid #fc6;");
|
||||
writer.RenderBeginTag(HtmlTextWriterTag.Div);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
StringWriter renderOutputWriter = new StringWriter();
|
||||
HtmlTextWriter htmlWriter = new HtmlTextWriter(renderOutputWriter);
|
||||
foreach (Control control in item.Controls)
|
||||
{
|
||||
try
|
||||
{
|
||||
control.RenderControl(htmlWriter);
|
||||
}
|
||||
catch (Exception renderException)
|
||||
{
|
||||
// TODO: Validate that the current control is within the scope of a form control
|
||||
// Even controls that are inside this scope, can produce this error in async postback.
|
||||
HttpContext.Current.Trace.Warn("ItemRenderer",
|
||||
String.Format("Error rendering control {0} of {1}.", control.ClientID, item), renderException);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
StringWriter renderOutputWriter = new StringWriter();
|
||||
HtmlTextWriter htmlWriter = new HtmlTextWriter(renderOutputWriter);
|
||||
foreach (Control control in item.Controls)
|
||||
{
|
||||
try
|
||||
{
|
||||
control.RenderControl(htmlWriter);
|
||||
}
|
||||
catch (Exception renderException)
|
||||
{
|
||||
// TODO: Validate that the current control is within the scope of a form control
|
||||
// Even controls that are inside this scope, can produce this error in async postback.
|
||||
HttpContext.Current.Trace.Warn("ItemRenderer",
|
||||
String.Format("Error rendering control {0} of {1}.", control.ClientID, item), renderException);
|
||||
}
|
||||
}
|
||||
|
||||
// parse macros and execute the XSLT transformation on the result if not empty
|
||||
string renderOutput = renderOutputWriter.ToString();
|
||||
string xsltTransformedOutput = renderOutput.Trim().Length == 0
|
||||
? String.Empty
|
||||
: XsltTransform(item.Xslt, renderOutput, item.XsltDisableEscaping);
|
||||
// handle text before/after
|
||||
xsltTransformedOutput = AddBeforeAfterText(xsltTransformedOutput, helper.FindAttribute(item.LegacyAttributes, "insertTextBefore"), helper.FindAttribute(item.LegacyAttributes, "insertTextAfter"));
|
||||
string finalResult = xsltTransformedOutput.Trim().Length > 0 ? xsltTransformedOutput : GetEmptyText(item);
|
||||
writer.Write(IOHelper.ResolveUrlsFromTextString(finalResult));
|
||||
}
|
||||
catch (Exception renderException)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn("ItemRenderer", String.Format("Error rendering {0}.", item), renderException);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (item.DebugMode)
|
||||
{
|
||||
writer.RenderEndTag();
|
||||
}
|
||||
}
|
||||
}
|
||||
// parse macros and execute the XSLT transformation on the result if not empty
|
||||
string renderOutput = renderOutputWriter.ToString();
|
||||
string xsltTransformedOutput = renderOutput.Trim().Length == 0
|
||||
? String.Empty
|
||||
: XsltTransform(item.Xslt, renderOutput, item.XsltDisableEscaping);
|
||||
// handle text before/after
|
||||
xsltTransformedOutput = AddBeforeAfterText(xsltTransformedOutput, helper.FindAttribute(item.LegacyAttributes, "insertTextBefore"), helper.FindAttribute(item.LegacyAttributes, "insertTextAfter"));
|
||||
string finalResult = xsltTransformedOutput.Trim().Length > 0 ? xsltTransformedOutput : GetEmptyText(item);
|
||||
writer.Write(IOHelper.ResolveUrlsFromTextString(finalResult));
|
||||
}
|
||||
catch (Exception renderException)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn("ItemRenderer", String.Format("Error rendering {0}.", item), renderException);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (item.DebugMode)
|
||||
{
|
||||
writer.RenderEndTag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the field contents.
|
||||
/// Checks via the NodeId attribute whether to fetch data from another page than the current one.
|
||||
/// </summary>
|
||||
/// <returns>A string of field contents (macros not parsed)</returns>
|
||||
protected virtual string GetFieldContents(Item item)
|
||||
{
|
||||
string tempElementContent = String.Empty;
|
||||
/// <summary>
|
||||
/// Renders the field contents.
|
||||
/// Checks via the NodeId attribute whether to fetch data from another page than the current one.
|
||||
/// </summary>
|
||||
/// <returns>A string of field contents (macros not parsed)</returns>
|
||||
protected virtual string GetFieldContents(Item item)
|
||||
{
|
||||
string tempElementContent = String.Empty;
|
||||
|
||||
// if a nodeId is specified we should get the data from another page than the current one
|
||||
if (!String.IsNullOrEmpty(item.NodeId))
|
||||
{
|
||||
int? tempNodeId = item.GetParsedNodeId();
|
||||
if (tempNodeId != null && tempNodeId.Value != 0)
|
||||
{
|
||||
string currentField = helper.FindAttribute(item.LegacyAttributes, "field");
|
||||
// check for a cached instance of the content
|
||||
object contents = GetContentFromCache(tempNodeId.Value, currentField);
|
||||
if (contents != null)
|
||||
tempElementContent = (string)contents;
|
||||
else
|
||||
{
|
||||
// as the field can be used for both documents, media and even members we'll use the
|
||||
// content class to lookup field items
|
||||
try
|
||||
{
|
||||
tempElementContent = GetContentFromDatabase(item.Attributes, tempNodeId.Value, currentField);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// content was not found in property fields,
|
||||
// so the last place to look for is page fields
|
||||
page itemPage = new page(content.Instance.XmlContent.GetElementById(tempNodeId.ToString()));
|
||||
tempElementContent = new item(itemPage.Elements, item.LegacyAttributes).FieldContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if a nodeId is specified we should get the data from another page than the current one
|
||||
if (!String.IsNullOrEmpty(item.NodeId))
|
||||
{
|
||||
int? tempNodeId = item.GetParsedNodeId();
|
||||
if (tempNodeId != null && tempNodeId.Value != 0)
|
||||
{
|
||||
string currentField = helper.FindAttribute(item.LegacyAttributes, "field");
|
||||
// check for a cached instance of the content
|
||||
object contents = GetContentFromCache(tempNodeId.Value, currentField);
|
||||
if (contents != null)
|
||||
tempElementContent = (string)contents;
|
||||
else
|
||||
{
|
||||
// as the field can be used for both documents, media and even members we'll use the
|
||||
// content class to lookup field items
|
||||
try
|
||||
{
|
||||
tempElementContent = GetContentFromDatabase(item.Attributes, tempNodeId.Value, currentField);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// content was not found in property fields,
|
||||
// so the last place to look for is page fields
|
||||
page itemPage = new page(content.Instance.XmlContent.GetElementById(tempNodeId.ToString()));
|
||||
tempElementContent = new item(itemPage.Elements, item.LegacyAttributes).FieldContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// gets the field content from the current page (via the PageElements collection)
|
||||
tempElementContent = new item(item.PageElements, item.LegacyAttributes).FieldContent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// gets the field content from the current page (via the PageElements collection)
|
||||
tempElementContent = new item(item.PageElements, item.LegacyAttributes).FieldContent;
|
||||
}
|
||||
|
||||
return tempElementContent;
|
||||
}
|
||||
return tempElementContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inits the specified item. To be called from the OnInit method of Item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public virtual void Init(Item item)
|
||||
{
|
||||
ParseMacros(item);
|
||||
}
|
||||
/// <summary>
|
||||
/// Inits the specified item. To be called from the OnInit method of Item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public virtual void Init(Item item)
|
||||
{
|
||||
ParseMacros(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified item. To be called from the OnLoad method of Item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public virtual void Load(Item item)
|
||||
{ }
|
||||
/// <summary>
|
||||
/// Loads the specified item. To be called from the OnLoad method of Item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public virtual void Load(Item item)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Parses the macros inside the text, by creating child elements for each item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual void ParseMacros(Item item)
|
||||
{
|
||||
// do nothing if the macros have already been rendered
|
||||
if (item.Controls.Count > 0)
|
||||
return;
|
||||
/// <summary>
|
||||
/// Parses the macros inside the text, by creating child elements for each item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual void ParseMacros(Item item)
|
||||
{
|
||||
// do nothing if the macros have already been rendered
|
||||
if (item.Controls.Count > 0)
|
||||
return;
|
||||
|
||||
string elementText = GetFieldContents(item);
|
||||
string elementText = GetFieldContents(item);
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
StringBuilder fieldResult = new StringBuilder(elementText);
|
||||
MacroTagParser.ParseMacros(
|
||||
elementText,
|
||||
|
||||
bool stop = false;
|
||||
while (!stop)
|
||||
{
|
||||
int tagIndex = fieldResult.ToString().ToLower().IndexOf("<?umbraco");
|
||||
if (tagIndex < 0)
|
||||
tagIndex = fieldResult.ToString().ToLower().IndexOf("<umbraco:macro");
|
||||
if (tagIndex > -1)
|
||||
{
|
||||
String tempElementContent = "";
|
||||
item.Controls.Add(new LiteralControl(fieldResult.ToString().Substring(0, tagIndex)));
|
||||
//callback for when a text block is parsed
|
||||
textBlock => item.Controls.Add(new LiteralControl(textBlock)),
|
||||
|
||||
fieldResult.Remove(0, tagIndex);
|
||||
//callback for when a macro is parsed:
|
||||
(macroAlias, attributes) =>
|
||||
{
|
||||
var macroControl = new Macro
|
||||
{
|
||||
Alias = macroAlias
|
||||
};
|
||||
foreach (var i in attributes.Where(i => macroControl.Attributes[i.Key] == null))
|
||||
{
|
||||
macroControl.Attributes.Add(i.Key, i.Value);
|
||||
}
|
||||
item.Controls.Add(macroControl);
|
||||
});
|
||||
}
|
||||
|
||||
String tag = fieldResult.ToString().Substring(0, fieldResult.ToString().IndexOf(">") + 1);
|
||||
Hashtable attributes = helper.ReturnAttributes(tag);
|
||||
/// <summary>
|
||||
/// Transforms the content using the XSLT attribute, if provided.
|
||||
/// </summary>
|
||||
/// <param name="xpath">The xpath expression.</param>
|
||||
/// <param name="itemData">The item's rendered content.</param>
|
||||
/// <param name="disableEscaping">if set to <c>true</c>, escaping is disabled.</param>
|
||||
/// <returns>The transformed content if the XSLT attribute is present, otherwise the original content.</returns>
|
||||
protected virtual string XsltTransform(string xpath, string itemData, bool disableEscaping)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(xpath))
|
||||
{
|
||||
// XML-encode the expression and add the itemData parameter to it
|
||||
string xpathEscaped = xpath.Replace("<", "<").Replace(">", ">").Replace("\"", """);
|
||||
string xpathExpression = string.Format(xpathEscaped, "$itemData");
|
||||
|
||||
// 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 (fieldResult.ToString().IndexOf(closingTag) > -1)
|
||||
{
|
||||
fieldResult.Remove(0, fieldResult.ToString().IndexOf(closingTag));
|
||||
}
|
||||
}
|
||||
// prepare support for XSLT extensions
|
||||
StringBuilder namespaceList = new StringBuilder();
|
||||
StringBuilder namespaceDeclaractions = new StringBuilder();
|
||||
foreach (KeyValuePair<string, object> extension in macro.GetXsltExtensions())
|
||||
{
|
||||
namespaceList.Append(extension.Key).Append(' ');
|
||||
namespaceDeclaractions.AppendFormat("xmlns:{0}=\"urn:{0}\" ", extension.Key);
|
||||
}
|
||||
|
||||
Macro macroControl = new Macro();
|
||||
macroControl.Alias = helper.FindAttribute(attributes, "macroalias");
|
||||
if (macroControl.Alias.Length == 0)
|
||||
macroControl.Alias = helper.FindAttribute(attributes, "alias");
|
||||
IDictionaryEnumerator ide = attributes.GetEnumerator();
|
||||
while (ide.MoveNext())
|
||||
if (macroControl.Attributes[ide.Key.ToString()] == null)
|
||||
macroControl.Attributes.Add(ide.Key.ToString(), ide.Value.ToString());
|
||||
item.Controls.Add(macroControl);
|
||||
fieldResult.Remove(0, fieldResult.ToString().IndexOf(">") + 1);
|
||||
fieldResult.Insert(0, tempElementContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Controls.Add(new LiteralControl(fieldResult.ToString()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add the XSLT expression into the full XSLT document, together with the needed parameters
|
||||
string xslt = string.Format(Resources.InlineXslt, xpathExpression, disableEscaping ? "yes" : "no",
|
||||
namespaceList, namespaceDeclaractions);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the content using the XSLT attribute, if provided.
|
||||
/// </summary>
|
||||
/// <param name="xpath">The xpath expression.</param>
|
||||
/// <param name="itemData">The item's rendered content.</param>
|
||||
/// <param name="disableEscaping">if set to <c>true</c>, escaping is disabled.</param>
|
||||
/// <returns>The transformed content if the XSLT attribute is present, otherwise the original content.</returns>
|
||||
protected virtual string XsltTransform(string xpath, string itemData, bool disableEscaping)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(xpath))
|
||||
{
|
||||
// XML-encode the expression and add the itemData parameter to it
|
||||
string xpathEscaped = xpath.Replace("<", "<").Replace(">", ">").Replace("\"", """);
|
||||
string xpathExpression = string.Format(xpathEscaped, "$itemData");
|
||||
// create the parameter
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>(1);
|
||||
parameters.Add("itemData", itemData);
|
||||
|
||||
// prepare support for XSLT extensions
|
||||
StringBuilder namespaceList = new StringBuilder();
|
||||
StringBuilder namespaceDeclaractions = new StringBuilder();
|
||||
foreach (KeyValuePair<string, object> extension in macro.GetXsltExtensions())
|
||||
{
|
||||
namespaceList.Append(extension.Key).Append(' ');
|
||||
namespaceDeclaractions.AppendFormat("xmlns:{0}=\"urn:{0}\" ", extension.Key);
|
||||
}
|
||||
// apply the XSLT transformation
|
||||
XmlTextReader xslReader = new XmlTextReader(new StringReader(xslt));
|
||||
System.Xml.Xsl.XslCompiledTransform xsl = macro.CreateXsltTransform(xslReader, false);
|
||||
itemData = macro.GetXsltTransformResult(new XmlDocument(), xsl, parameters);
|
||||
xslReader.Close();
|
||||
}
|
||||
return itemData;
|
||||
}
|
||||
|
||||
// add the XSLT expression into the full XSLT document, together with the needed parameters
|
||||
string xslt = string.Format(Resources.InlineXslt, xpathExpression, disableEscaping ? "yes" : "no",
|
||||
namespaceList, namespaceDeclaractions);
|
||||
protected string AddBeforeAfterText(string text, string before, string after)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(text))
|
||||
{
|
||||
if (!String.IsNullOrEmpty(before))
|
||||
text = String.Format("{0}{1}", HttpContext.Current.Server.HtmlDecode(before), text);
|
||||
if (!String.IsNullOrEmpty(after))
|
||||
text = String.Format("{0}{1}", text, HttpContext.Current.Server.HtmlDecode(after));
|
||||
}
|
||||
|
||||
// create the parameter
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>(1);
|
||||
parameters.Add("itemData", itemData);
|
||||
return text;
|
||||
}
|
||||
|
||||
// apply the XSLT transformation
|
||||
XmlTextReader xslReader = new XmlTextReader(new StringReader(xslt));
|
||||
System.Xml.Xsl.XslCompiledTransform xsl = macro.CreateXsltTransform(xslReader, false);
|
||||
itemData = macro.GetXsltTransformResult(new XmlDocument(), xsl, parameters);
|
||||
xslReader.Close();
|
||||
}
|
||||
return itemData;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the text to display if the field contents are empty.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>The text to display.</returns>
|
||||
protected virtual string GetEmptyText(Item item)
|
||||
{
|
||||
return item.TextIfEmpty;
|
||||
}
|
||||
|
||||
protected string AddBeforeAfterText(string text, string before, string after)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(text))
|
||||
{
|
||||
if (!String.IsNullOrEmpty(before))
|
||||
text = String.Format("{0}{1}", HttpContext.Current.Server.HtmlDecode(before), text);
|
||||
if (!String.IsNullOrEmpty(after))
|
||||
text = String.Format("{0}{1}", text, HttpContext.Current.Server.HtmlDecode(after));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the field content from database instead of the published XML via the APIs.
|
||||
/// </summary>
|
||||
/// <param name="nodeIdInt">The node id.</param>
|
||||
/// <param name="currentField">The field that should be fetched.</param>
|
||||
/// <returns>The contents of the <paramref name="currentField"/> from the <paramref name="nodeIdInt"/> content object</returns>
|
||||
protected virtual string GetContentFromDatabase(AttributeCollection itemAttributes, int nodeIdInt, string currentField)
|
||||
{
|
||||
Content c = new Content(nodeIdInt);
|
||||
|
||||
return text;
|
||||
}
|
||||
Property property = c.getProperty(currentField);
|
||||
if (property == null)
|
||||
throw new ArgumentException(String.Format("Could not find property {0} of node {1}.", currentField, nodeIdInt));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text to display if the field contents are empty.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>The text to display.</returns>
|
||||
protected virtual string GetEmptyText(Item item)
|
||||
{
|
||||
return item.TextIfEmpty;
|
||||
}
|
||||
item umbItem = new item(property.Value.ToString(), new AttributeCollectionAdapter(itemAttributes));
|
||||
string tempElementContent = umbItem.FieldContent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the field content from database instead of the published XML via the APIs.
|
||||
/// </summary>
|
||||
/// <param name="nodeIdInt">The node id.</param>
|
||||
/// <param name="currentField">The field that should be fetched.</param>
|
||||
/// <returns>The contents of the <paramref name="currentField"/> from the <paramref name="nodeIdInt"/> content object</returns>
|
||||
protected virtual string GetContentFromDatabase(AttributeCollection itemAttributes, int nodeIdInt, string currentField)
|
||||
{
|
||||
Content c = new Content(nodeIdInt);
|
||||
// If the current content object is a document object, we'll only output it if it's published
|
||||
if (c.nodeObjectType == cms.businesslogic.web.Document._objectType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Document d = (Document)c;
|
||||
if (!d.Published)
|
||||
tempElementContent = "";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
Property property = c.getProperty(currentField);
|
||||
if (property == null)
|
||||
throw new ArgumentException(String.Format("Could not find property {0} of node {1}.", currentField, nodeIdInt));
|
||||
// Add the content to the cache
|
||||
if (!String.IsNullOrEmpty(tempElementContent))
|
||||
HttpContext.Current.Cache.Insert(String.Format("contentItem{0}_{1}", nodeIdInt.ToString(), currentField), tempElementContent);
|
||||
return tempElementContent;
|
||||
}
|
||||
|
||||
item umbItem = new item(property.Value.ToString(), new AttributeCollectionAdapter(itemAttributes));
|
||||
string tempElementContent = umbItem.FieldContent;
|
||||
|
||||
// If the current content object is a document object, we'll only output it if it's published
|
||||
if (c.nodeObjectType == cms.businesslogic.web.Document._objectType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Document d = (Document)c;
|
||||
if (!d.Published)
|
||||
tempElementContent = "";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Add the content to the cache
|
||||
if (!String.IsNullOrEmpty(tempElementContent))
|
||||
HttpContext.Current.Cache.Insert(String.Format("contentItem{0}_{1}", nodeIdInt.ToString(), currentField), tempElementContent);
|
||||
return tempElementContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content from cache.
|
||||
/// </summary>
|
||||
/// <param name="nodeIdInt">The node id.</param>
|
||||
/// <param name="field">The field.</param>
|
||||
/// <returns>The cached contents of the <paramref name="currentField"/> from the <paramref name="nodeIdInt"/> content object</returns>
|
||||
protected virtual object GetContentFromCache(int nodeIdInt, string field)
|
||||
{
|
||||
object content = HttpContext.Current.Cache[String.Format("contentItem{0}_{1}", nodeIdInt.ToString(), field.ToString())];
|
||||
return content;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the content from cache.
|
||||
/// </summary>
|
||||
/// <param name="nodeIdInt">The node id.</param>
|
||||
/// <param name="field">The field.</param>
|
||||
/// <returns>The cached contents of the <paramref name="currentField"/> from the <paramref name="nodeIdInt"/> content object</returns>
|
||||
protected virtual object GetContentFromCache(int nodeIdInt, string field)
|
||||
{
|
||||
object content = HttpContext.Current.Cache[String.Format("contentItem{0}_{1}", nodeIdInt.ToString(), field.ToString())];
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,17 +127,16 @@ namespace umbraco.cms.helpers
|
||||
return closeBracket+tag;
|
||||
}
|
||||
|
||||
public static Hashtable ReturnAttributes(String tag) {
|
||||
Hashtable ht = new Hashtable();
|
||||
MatchCollection m =
|
||||
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
// fix for issue 14862: return lowercase attributes for case insensitive matching
|
||||
foreach (Match attributeSet in m)
|
||||
ht.Add(attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet.Groups["attributeValue"].Value.ToString());
|
||||
|
||||
return ht;
|
||||
}
|
||||
[Obsolete("Has been superceded by Umbraco.Core.XmlHelper.GetAttributesFromElement")]
|
||||
public static Hashtable ReturnAttributes(String tag)
|
||||
{
|
||||
var h = new Hashtable();
|
||||
foreach (var i in Umbraco.Core.XmlHelper.GetAttributesFromElement(tag))
|
||||
{
|
||||
h.Add(i.Key, i.Value);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private static string returnLowerCaseAttributes(String tag)
|
||||
{
|
||||
|
||||
@@ -534,18 +534,16 @@ namespace umbraco.editorControls.tinyMCE3
|
||||
return macroTag;
|
||||
}
|
||||
|
||||
public static Hashtable ReturnAttributes(String tag)
|
||||
{
|
||||
var ht = new Hashtable();
|
||||
MatchCollection m =
|
||||
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
foreach (Match attributeSet in m)
|
||||
ht.Add(attributeSet.Groups["attributeName"].Value,
|
||||
attributeSet.Groups["attributeValue"].Value);
|
||||
|
||||
return ht;
|
||||
}
|
||||
[Obsolete("Has been superceded by Umbraco.Core.XmlHelper.GetAttributesFromElement")]
|
||||
public static Hashtable ReturnAttributes(String tag)
|
||||
{
|
||||
var h = new Hashtable();
|
||||
foreach (var i in Umbraco.Core.XmlHelper.GetAttributesFromElement(tag))
|
||||
{
|
||||
h.Add(i.Key, i.Value);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private int findStartTag(string text)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user