Merge with 6.0.0

This commit is contained in:
Morten Christensen
2012-12-14 11:51:03 -01:00
7 changed files with 188 additions and 126 deletions

View File

@@ -75,6 +75,36 @@ namespace Umbraco.Core
}
#endregion
/// <summary>
/// Returns the recursive value of a field by iterating up the parent chain but starting at the publishedContent passed in
/// </summary>
/// <param name="publishedContent"></param>
/// <param name="fieldname"></param>
/// <returns></returns>
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");

View File

@@ -35,13 +35,16 @@ namespace Umbraco.Tests.PublishedContent
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
<umbracoNaviHide>1</umbracoNaviHide>
<testRecursive><![CDATA[This is the recursive val]]></testRecursive>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<testRecursive><![CDATA[]]></testRecursive>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
<testRecursive><![CDATA[]]></testRecursive>
</Home>
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
<content><![CDATA[]]></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()
{

View File

@@ -300,8 +300,7 @@ namespace Umbraco.Web
var item = new Item()
{
//NodeId = currentPage.Id.ToString();
{
Field = fieldAlias,
TextIfEmpty = altText,
LegacyAttributes = attributesForItem
@@ -470,17 +469,17 @@ namespace Umbraco.Web
public dynamic Content(object id)
{
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore);
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore, new DynamicNull());
}
public dynamic Content(int id)
{
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore);
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore, new DynamicNull());
}
public dynamic Content(string id)
{
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore);
return DocumentById(id, PublishedContentStoreResolver.Current.PublishedContentStore, new DynamicNull());
}
public dynamic Content(params object[] ids)
@@ -574,17 +573,17 @@ namespace Umbraco.Web
public dynamic Media(object id)
{
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore);
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore, new DynamicNull());
}
public dynamic Media(int id)
{
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore);
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore, new DynamicNull());
}
public dynamic Media(string id)
{
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore);
return DocumentById(id, PublishedMediaStoreResolver.Current.PublishedMediaStore, new DynamicNull());
}
public dynamic Media(params object[] ids)
@@ -651,7 +650,7 @@ namespace Umbraco.Web
{
int docId;
return int.TryParse(id, out docId)
? DocumentById(docId, store)
? DocumentById(docId, store, null)
: null;
}
@@ -686,35 +685,36 @@ namespace Umbraco.Web
/// </summary>
/// <param name="id"></param>
/// <param name="store"> </param>
/// <param name="ifNotFound"> </param>
/// <returns></returns>
/// <remarks>
/// We accept an object type because GetPropertyValue now returns an 'object', we still want to allow people to pass
/// this result in to this method.
/// This method will throw an exception if the value is not of type int or string.
/// </remarks>
private dynamic DocumentById(object id, IPublishedStore store)
private dynamic DocumentById(object id, IPublishedStore store, object ifNotFound)
{
if (id is string)
return DocumentById((string)id, store);
return DocumentById((string)id, store, ifNotFound);
if (id is int)
return DocumentById((int)id, store);
return DocumentById((int)id, store, ifNotFound);
throw new InvalidOperationException("The value of parameter 'id' must be either a string or an integer");
}
private dynamic DocumentById(int id, IPublishedStore store)
private dynamic DocumentById(int id, IPublishedStore store, object ifNotFound)
{
var doc = store.GetDocumentById(UmbracoContext.Current, id);
return doc == null
? new DynamicNull()
? ifNotFound
: new DynamicPublishedContent(doc).AsDynamic();
}
private dynamic DocumentById(string id, IPublishedStore store)
private dynamic DocumentById(string id, IPublishedStore store, object ifNotFound)
{
int docId;
return int.TryParse(id, out docId)
? DocumentById(docId, store)
: new DynamicNull();
? DocumentById(docId, store, ifNotFound)
: ifNotFound;
}
/// <summary>
@@ -730,7 +730,8 @@ namespace Umbraco.Web
/// </remarks>
private dynamic DocumentByIds(IPublishedStore store, params object[] ids)
{
var nodes = ids.Select(eachId => DocumentById(eachId, store))
var dNull = new DynamicNull();
var nodes = ids.Select(eachId => DocumentById(eachId, store, dNull))
.Where(x => !TypeHelper.IsTypeAssignableFrom<DynamicNull>(x))
.Cast<DynamicPublishedContent>();
return new DynamicPublishedContentList(nodes);
@@ -738,7 +739,8 @@ namespace Umbraco.Web
private dynamic DocumentByIds(IPublishedStore store, params int[] ids)
{
var nodes = ids.Select(eachId => DocumentById(eachId, store))
var dNull = new DynamicNull();
var nodes = ids.Select(eachId => DocumentById(eachId, store, dNull))
.Where(x => !TypeHelper.IsTypeAssignableFrom<DynamicNull>(x))
.Cast<DynamicPublishedContent>();
return new DynamicPublishedContentList(nodes);
@@ -746,7 +748,8 @@ namespace Umbraco.Web
private dynamic DocumentByIds(IPublishedStore store, params string[] ids)
{
var nodes = ids.Select(eachId => DocumentById(eachId, store))
var dNull = new DynamicNull();
var nodes = ids.Select(eachId => DocumentById(eachId, store, dNull))
.Where(x => !TypeHelper.IsTypeAssignableFrom<DynamicNull>(x))
.Cast<DynamicPublishedContent>();
return new DynamicPublishedContentList(nodes);

View File

@@ -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);
}
/// <summary>
///
/// Creates a new Legacy item
/// </summary>
/// <param name="umbPage"></param>
/// <param name="elements"></param>
/// <param name="attributes"></param>
///
public item(IDictionary elements, IDictionary attributes)
: this(null, elements, attributes)
{
}
/// <summary>
/// Creates an Item with a publishedContent item in order to properly recurse and return the value.
/// </summary>
/// <param name="publishedContent"></param>
/// <param name="elements"></param>
/// <param name="attributes"></param>
/// <remarks>
/// THIS ENTIRE CLASS WILL BECOME LEGACY, THE FIELD RENDERING NEEDS TO BE REPLACES SO THAT IS WHY THIS
/// CTOR IS INTERNAL.
/// </remarks>
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);
}
/// <summary>
/// Returns the recursive value using a legacy strategy of looking at the xml cache and the splitPath in the elements collection
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
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 == "")

View File

@@ -87,9 +87,14 @@ namespace umbraco
}
/// <summary>
/// Initializes a new instance of the <see cref="page"/> class for a published document.
/// Initializes a new instance of the <see cref="page"/> class for a published document request.
/// </summary>
/// <param name="docreq">The <see cref="PublishedContentRequest"/> pointing to the document.</param>
/// <remarks>
/// 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.
/// </remarks>
internal page(PublishedContentRequest docreq)
{
@@ -112,6 +117,29 @@ namespace umbraco
}
/// <summary>
/// Initializes a new instance of the page for a published document
/// </summary>
/// <param name="doc"></param>
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);
}
/// <summary>
/// Initializes a new instance of the <see cref="page"/> class for a published document.
/// </summary>

View File

@@ -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 */

View File

@@ -406,44 +406,6 @@ namespace umbraco.MacroEngines
}
return result;
}
private List<string> GetAncestorOrSelfNodeTypeAlias(DynamicBackingItem node)
{
List<string> list = new List<string>();
if (node != null)
{
if (node.Type == DynamicBackingItemType.Content)
{
//find the doctype node, so we can walk it's parent's tree- not the working.parent content tree
CMSNode working = ContentType.GetByAlias(node.NodeTypeAlias);
while (working != null)
{
//NOTE: I'm not sure if anyone has ever tested this but if you get working.Parent it will return a CMSNode and
// it will never be castable to a 'ContentType' object
// pretty sure the only reason why this method works for the one place that it is used is that it returns
// the current node's alias which is all that is actually requried, this is just added overhead for no
// reason
if ((working as ContentType) != null)
{
list.Add((working as ContentType).Alias);
}
try
{
working = working.Parent;
}
catch (ArgumentException)
{
break;
}
}
}
else
{
return null;
}
}
return list;
}
private static Dictionary<System.Tuple<Guid, int>, Type> _razorDataTypeModelTypes = null;
private static readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
@@ -485,14 +447,6 @@ namespace umbraco.MacroEngines
}
});
//NOTE: We really dont need to log this?
//var i = 1;
//foreach (var item in foundTypes)
//{
// HttpContext.Current.Trace.Write(string.Format("{0}/{1}: {2}@{4} => {3}", i, foundTypes.Count, item.Key.Item1, item.Value.FullName, item.Key.Item2));
// i++;
//}
//there is no error, so set the collection
_razorDataTypeModelTypes = foundTypes;
@@ -605,21 +559,8 @@ namespace umbraco.MacroEngines
LogHelper.Warn<DynamicNode>(string.Format("Could not get the dataTypeType for the RazorDataTypeModel"));
}
}
else
{
//NOTE: Do we really want to log this? I'm not sure.
//if (RazorDataTypeModelTypes == null)
//{
// HttpContext.Current.Trace.Write(string.Format("RazorDataTypeModelTypes is null, probably an exception while building the cache, falling back to ConvertPropertyValueByDataType", dataType));
//}
//else
//{
// HttpContext.Current.Trace.Write(string.Format("GUID {0} does not have a DataTypeModel, falling back to ConvertPropertyValueByDataType", dataType));
//}
}
//convert the string value to a known type
//convert the string value to a known type
return ConvertPropertyValueByDataType(ref result, name, dataType);
}
@@ -629,15 +570,10 @@ namespace umbraco.MacroEngines
var typeChildren = n.ChildrenAsList;
if (typeChildren != null)
{
var filteredTypeChildren = typeChildren.Where(x =>
{
List<string> ancestorAliases = GetAncestorOrSelfNodeTypeAlias(x);
if (ancestorAliases == null)
{
return false;
}
return ancestorAliases.Any(alias => alias == name || MakePluralName(alias) == name);
});
var filteredTypeChildren = typeChildren
.Where(x => x.NodeTypeAlias.InvariantEquals(name) || x.NodeTypeAlias.MakePluralName().InvariantEquals(binder.Name))
.ToArray();
if (filteredTypeChildren.Any())
{
result = new DynamicNodeList(filteredTypeChildren);