diff --git a/src/Umbraco.Core/PublishedContentExtensions.cs b/src/Umbraco.Core/PublishedContentExtensions.cs
index 9d54198982..c039cf881c 100644
--- a/src/Umbraco.Core/PublishedContentExtensions.cs
+++ b/src/Umbraco.Core/PublishedContentExtensions.cs
@@ -75,6 +75,36 @@ namespace Umbraco.Core
}
#endregion
+ ///
+ /// Returns the recursive value of a field by iterating up the parent chain but starting at the publishedContent passed in
+ ///
+ ///
+ ///
+ ///
+ public static string GetRecursiveValue(this IPublishedContent publishedContent, string fieldname)
+ {
+ var contentValue = "";
+ var currentContent = publishedContent;
+
+ while (contentValue.IsNullOrWhiteSpace())
+ {
+ var val = currentContent[fieldname];
+ if (val == null || val.ToString().IsNullOrWhiteSpace())
+ {
+ if (currentContent.Parent == null)
+ {
+ break; //we've reached the top
+ }
+ currentContent = currentContent.Parent;
+ }
+ else
+ {
+ contentValue = val.ToString(); //we've found a recursive val
+ }
+ }
+ return contentValue;
+ }
+
public static bool IsVisible(this IPublishedContent doc)
{
var umbracoNaviHide = doc.GetProperty("umbracoNaviHide");
diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs
index bf3a410e51..d2570dacfd 100644
--- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs
@@ -35,13 +35,16 @@ namespace Umbraco.Tests.PublishedContent
1
+
This is some content]]>
+
+
@@ -105,6 +108,16 @@ namespace Umbraco.Tests.PublishedContent
return doc;
}
+ [Test]
+ public void Test_Get_Recursive_Val()
+ {
+ var doc = GetNode(1174);
+ var rVal = doc.GetRecursiveValue("testRecursive");
+ var nullVal = doc.GetRecursiveValue("DoNotFindThis");
+ Assert.AreEqual("This is the recursive val", rVal);
+ Assert.AreEqual("", nullVal);
+ }
+
[Test]
public void Get_Property_Value_Uses_Converter()
{
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index ebd3e74a7d..7a9ba39cf3 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -300,8 +300,7 @@ namespace Umbraco.Web
var item = new Item()
- {
- //NodeId = currentPage.Id.ToString();
+ {
Field = fieldAlias,
TextIfEmpty = altText,
LegacyAttributes = attributesForItem
diff --git a/src/Umbraco.Web/umbraco.presentation/item.cs b/src/Umbraco.Web/umbraco.presentation/item.cs
index 30c5a2c217..fe6c8faea7 100644
--- a/src/Umbraco.Web/umbraco.presentation/item.cs
+++ b/src/Umbraco.Web/umbraco.presentation/item.cs
@@ -3,6 +3,7 @@ using System.Collections;
using System.Web;
using System.Xml;
using Umbraco.Core;
+using Umbraco.Core.Models;
namespace umbraco
{
@@ -12,7 +13,7 @@ namespace umbraco
public class item
{
private String _fieldContent = "";
- private String _fieldName;
+ private readonly String _fieldName;
public String FieldContent
{
@@ -22,64 +23,108 @@ namespace umbraco
public item(string itemValue, IDictionary attributes)
{
_fieldContent = itemValue;
- parseItem(attributes);
+ ParseItem(attributes);
}
///
- ///
+ /// Creates a new Legacy item
///
- ///
+ ///
///
- ///
public item(IDictionary elements, IDictionary attributes)
+ : this(null, elements, attributes)
+ {
+ }
+
+ ///
+ /// Creates an Item with a publishedContent item in order to properly recurse and return the value.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// THIS ENTIRE CLASS WILL BECOME LEGACY, THE FIELD RENDERING NEEDS TO BE REPLACES SO THAT IS WHY THIS
+ /// CTOR IS INTERNAL.
+ ///
+ internal item(IPublishedContent publishedContent, IDictionary elements, IDictionary attributes)
{
_fieldName = helper.FindAttribute(attributes, "field");
- if(_fieldName.StartsWith("#"))
+ if (_fieldName.StartsWith("#"))
{
_fieldContent = library.GetDictionaryItem(_fieldName.Substring(1, _fieldName.Length - 1));
}
else
{
// Loop through XML children we need to find the fields recursive
- if(helper.FindAttribute(attributes, "recursive") == "true")
+ if (helper.FindAttribute(attributes, "recursive") == "true")
{
-
- XmlDocument umbracoXML = presentation.UmbracoContext.Current.GetXml();
-
- String[] splitpath = (String[]) elements["splitpath"];
- for(int i = 0; i < splitpath.Length - 1; i++)
+ if (publishedContent == null)
{
- XmlNode element = umbracoXML.GetElementById(splitpath[splitpath.Length - i - 1].ToString());
- if (element == null)
- continue;
- string xpath = UmbracoSettings.UseLegacyXmlSchema ? "./data [@alias = '{0}']" : "./{0}";
- XmlNode currentNode = element.SelectSingleNode(string.Format(xpath,
- _fieldName));
- if(currentNode != null && currentNode.FirstChild != null &&
- !string.IsNullOrEmpty(currentNode.FirstChild.Value) &&
- !string.IsNullOrEmpty(currentNode.FirstChild.Value.Trim()))
- {
- HttpContext.Current.Trace.Write("item.recursive", "Item loaded from " + splitpath[splitpath.Length - i - 1]);
- _fieldContent = currentNode.FirstChild.Value;
- break;
- }
+ var recursiveVal = GetRecursiveValueLegacy(elements);
+ _fieldContent = recursiveVal.IsNullOrWhiteSpace() ? _fieldContent : recursiveVal;
+ }
+ else
+ {
+ var recursiveVal = publishedContent.GetRecursiveValue(_fieldName);
+ _fieldContent = recursiveVal.IsNullOrWhiteSpace() ? _fieldContent : recursiveVal;
}
}
else
{
- if (elements[_fieldName] != null && !string.IsNullOrEmpty(elements[_fieldName].ToString()))
- _fieldContent = elements[_fieldName].ToString().Trim();
- else if(!string.IsNullOrEmpty(helper.FindAttribute(attributes, "useIfEmpty")))
- if (elements[helper.FindAttribute(attributes, "useIfEmpty")] != null && !string.IsNullOrEmpty(elements[helper.FindAttribute(attributes, "useIfEmpty")].ToString()))
- _fieldContent = elements[helper.FindAttribute(attributes, "useIfEmpty")].ToString().Trim();
+ if (elements[_fieldName] != null && !string.IsNullOrEmpty(elements[_fieldName].ToString()))
+ {
+ _fieldContent = elements[_fieldName].ToString().Trim();
+ }
+ else if (!string.IsNullOrEmpty(helper.FindAttribute(attributes, "useIfEmpty")))
+ {
+ if (elements[helper.FindAttribute(attributes, "useIfEmpty")] != null && !string.IsNullOrEmpty(elements[helper.FindAttribute(attributes, "useIfEmpty")].ToString()))
+ {
+ _fieldContent = elements[helper.FindAttribute(attributes, "useIfEmpty")].ToString().Trim();
+ }
+ }
+
}
}
- parseItem(attributes);
+ ParseItem(attributes);
+ }
+
+ ///
+ /// Returns the recursive value using a legacy strategy of looking at the xml cache and the splitPath in the elements collection
+ ///
+ ///
+ ///
+ private string GetRecursiveValueLegacy(IDictionary elements)
+ {
+ var content = "";
+
+ var umbracoXml = presentation.UmbracoContext.Current.GetXml();
+
+ var splitpath = (String[])elements["splitpath"];
+ for (int i = 0; i < splitpath.Length - 1; i++)
+ {
+ XmlNode element = umbracoXml.GetElementById(splitpath[splitpath.Length - i - 1]);
+
+ if (element == null)
+ continue;
+
+ var xpath = UmbracoSettings.UseLegacyXmlSchema ? "./data [@alias = '{0}']" : "./{0}";
+ var currentNode = element.SelectSingleNode(string.Format(xpath, _fieldName));
+
+ //continue if all is null
+ if (currentNode == null || currentNode.FirstChild == null || string.IsNullOrEmpty(currentNode.FirstChild.Value) || string.IsNullOrEmpty(currentNode.FirstChild.Value.Trim()))
+ continue;
+
+ HttpContext.Current.Trace.Write("item.recursive", "Item loaded from " + splitpath[splitpath.Length - i - 1]);
+ content = currentNode.FirstChild.Value;
+ break;
+ }
+
+ return content;
}
- private void parseItem(IDictionary attributes)
+ private void ParseItem(IDictionary attributes)
{
HttpContext.Current.Trace.Write("item", "Start parsing '" + _fieldName + "'");
if(helper.FindAttribute(attributes, "textIfEmpty") != "" && _fieldContent == "")
diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs
index efba296b44..e98efd8e5e 100644
--- a/src/Umbraco.Web/umbraco.presentation/page.cs
+++ b/src/Umbraco.Web/umbraco.presentation/page.cs
@@ -87,9 +87,14 @@ namespace umbraco
}
///
- /// Initializes a new instance of the class for a published document.
+ /// Initializes a new instance of the class for a published document request.
///
/// The pointing to the document.
+ ///
+ /// The difference between creating the page with PublishedContentRequest vs an IPublishedContent item is
+ /// that the PublishedContentRequest takes into account how a template is assigned during the routing process whereas
+ /// with an IPublishedContent item, the template id is asssigned purely based on the default.
+ ///
internal page(PublishedContentRequest docreq)
{
@@ -112,6 +117,29 @@ namespace umbraco
}
+ ///
+ /// Initializes a new instance of the page for a published document
+ ///
+ ///
+ internal page(IPublishedContent doc)
+ {
+ if (doc == null) throw new ArgumentNullException("doc");
+
+ populatePageData(doc.Id,
+ doc.Name, doc.DocumentTypeId, doc.DocumentTypeAlias,
+ doc.WriterName, doc.CreatorName, doc.CreateDate, doc.UpdateDate,
+ doc.Path, doc.Version, doc.Parent == null ? -1 : doc.Parent.Id);
+
+ if (doc.TemplateId > 0)
+ {
+ //set the template to whatever is assigned to the doc
+ _template = doc.TemplateId;
+ _elements["template"] = _template.ToString();
+ }
+
+ PopulateElementData(doc);
+ }
+
///
/// Initializes a new instance of the class for a published document.
///
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs
index de2149b1c4..a1d423bfa3 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/ItemRenderer.cs
@@ -8,6 +8,8 @@ using System.Web;
using System.Web.UI;
using System.Xml;
using Umbraco.Core.Macros;
+using Umbraco.Web;
+using Umbraco.Web.Routing;
using Umbraco.Web.Templates;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.property;
@@ -99,8 +101,13 @@ namespace umbraco.presentation.templateControls
//moved the following from the catch block up as this will allow fallback options alt text etc to work
- page itemPage = new page(content.Instance.XmlContent.GetElementById(tempNodeId.ToString()));
- tempElementContent = new item(itemPage.Elements, item.LegacyAttributes).FieldContent;
+ //get the publishedcontent item
+ var publishedContent = PublishedContentStoreResolver.Current.PublishedContentStore.GetDocumentById(
+ Umbraco.Web.UmbracoContext.Current,
+ tempNodeId.Value);
+
+ var itemPage = new page(publishedContent);
+ tempElementContent = new item(publishedContent, itemPage.Elements, item.LegacyAttributes).FieldContent;
/*removed as would fail as there is a incorrect cast in the method called.
Also the following code does not respect any of Umbraco Items fallback and formatting options */