diff --git a/src/Umbraco.Core/Models/IPublishedContent.cs b/src/Umbraco.Core/Models/IPublishedContent.cs index 869a6ae696..213a0e5ed3 100644 --- a/src/Umbraco.Core/Models/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/IPublishedContent.cs @@ -5,7 +5,7 @@ using System.Collections.ObjectModel; namespace Umbraco.Core.Models { /// - /// Defines a PublishedContent in Umbraco + /// Defines a published item in Umbraco /// /// /// A replacement for INode which needs to occur since INode doesn't contain the document type alias @@ -13,7 +13,6 @@ namespace Umbraco.Core.Models /// public interface IPublishedContent { - IPublishedContent Parent { get; } int Id { get; } int TemplateId { get; } int SortOrder { get; } @@ -30,9 +29,20 @@ namespace Umbraco.Core.Models DateTime UpdateDate { get; } Guid Version { get; } int Level { get; } - Collection Properties { get; } + string Url { get; } + PublishedItemType ItemType { get; } + IPublishedContent Parent { get; } IEnumerable Children { get; } + ICollection Properties { get; } + + /// + /// Returns the property value for the property alias specified + /// + /// + /// + object this[string propertyAlias] { get; } + /// /// Returns a property on the object based on an alias /// diff --git a/src/Umbraco.Core/Models/PublishedItemType.cs b/src/Umbraco.Core/Models/PublishedItemType.cs new file mode 100644 index 0000000000..b9fb603735 --- /dev/null +++ b/src/Umbraco.Core/Models/PublishedItemType.cs @@ -0,0 +1,11 @@ +namespace Umbraco.Core.Models +{ + /// + /// The type of published item + /// + public enum PublishedItemType + { + Content, + Media + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/PublishedContentExtensions.cs b/src/Umbraco.Core/PublishedContentExtensions.cs index bda88f115e..9d54198982 100644 --- a/src/Umbraco.Core/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/PublishedContentExtensions.cs @@ -14,8 +14,6 @@ namespace Umbraco.Core public static class PublishedContentExtensions { - - #region GetProperty public static IPublishedContentProperty GetProperty(this IPublishedContent content, string alias, bool recursive) { @@ -40,37 +38,6 @@ namespace Umbraco.Core } #endregion - #region GetPropertyValue - public static object GetPropertyValue(this IPublishedContent doc, string alias) - { - return doc.GetPropertyValue(alias, false); - } - public static object GetPropertyValue(this IPublishedContent doc, string alias, string fallback) - { - var prop = doc.GetPropertyValue(alias); - return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback; - } - public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive) - { - var p = doc.GetProperty(alias, recursive); - if (p == null) return null; - - //Here we need to put the value through the IPropertyEditorValueConverter's - //get the data type id for the current property - var dataType = PublishedContentHelper.GetDataType(doc.DocumentTypeAlias, alias); - //convert the string value to a known type - var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, doc.DocumentTypeAlias, alias); - return converted.Success - ? converted.Result - : p.Value; - } - public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback) - { - var prop = doc.GetPropertyValue(alias, recursive); - return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback; - } - #endregion - #region HasValue public static bool HasValue(this IPublishedContentProperty prop) @@ -129,57 +96,7 @@ namespace Umbraco.Core return false; } - /// - /// Returns the property as the specified type, if the property is not found or does not convert - /// then the default value of type T is returned. - /// - /// - /// - /// - /// - public static T GetPropertyValue(this IPublishedContent doc, string alias) - { - return doc.GetPropertyValue(alias, default(T)); - } - public static T GetPropertyValue(this IPublishedContent prop, string alias, bool recursive, T ifCannotConvert) - { - var p = prop.GetProperty(alias, recursive); - if (p == null) - return ifCannotConvert; - - //before we try to convert it manually, lets see if the PropertyEditorValueConverter does this for us - //Here we need to put the value through the IPropertyEditorValueConverter's - //get the data type id for the current property - var dataType = PublishedContentHelper.GetDataType(prop.DocumentTypeAlias, alias); - //convert the value to a known type - var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, prop.DocumentTypeAlias, alias); - if (converted.Success) - { - //if its successful, check if its the correct type and return it - if (converted.Result is T) - { - return (T)converted.Result; - } - //if that's not correct, try converting the converted type - var reConverted = converted.Result.TryConvertTo(); - if (reConverted.Success) - { - return reConverted.Result; - } - } - - //last, if all the above has failed, we'll just try converting the raw value straight to 'T' - var manualConverted = p.Value.TryConvertTo(); - if (manualConverted.Success) - return manualConverted.Result; - return ifCannotConvert; - } - - public static T GetPropertyValue(this IPublishedContent prop, string alias, T ifCannotConvert) - { - return prop.GetPropertyValue(alias, false, ifCannotConvert); - } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 71d95811a2..3717354a71 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -159,6 +159,7 @@ + diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 6d8b00e5eb..c6ce668a40 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -169,6 +169,17 @@ namespace Umbraco.Tests.PublishedContent private class TestPublishedContent : IPublishedContent { + public string Url { get; set; } + public PublishedItemType ItemType { get; set; } + + IPublishedContent IPublishedContent.Parent + { + get { return Parent; } + } + IEnumerable IPublishedContent.Children + { + get { return Children; } + } public IPublishedContent Parent { get; set; } public int Id { get; set; } public int TemplateId { get; set; } @@ -186,7 +197,13 @@ namespace Umbraco.Tests.PublishedContent public DateTime UpdateDate { get; set; } public Guid Version { get; set; } public int Level { get; set; } - public Collection Properties { get; set; } + public ICollection Properties { get; set; } + + public object this[string propertyAlias] + { + get { return GetProperty(propertyAlias).Value; } + } + public IEnumerable Children { get; set; } public IPublishedContentProperty GetProperty(string alias) { diff --git a/src/Umbraco.Tests/PublishedContent/StronglyTypedQueryTests.cs b/src/Umbraco.Tests/PublishedContent/StronglyTypedQueryTests.cs index 39695065ac..5053279617 100644 --- a/src/Umbraco.Tests/PublishedContent/StronglyTypedQueryTests.cs +++ b/src/Umbraco.Tests/PublishedContent/StronglyTypedQueryTests.cs @@ -5,19 +5,37 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Web; +using Umbraco.Web.Routing; namespace Umbraco.Tests.PublishedContent { [TestFixture] - public class StronglyTypedQueryTests : BaseWebTest + public class StronglyTypedQueryTests : BaseRoutingTest { protected override bool RequiresDbSetup { get { return false; } } + public override void Initialize() + { + base.Initialize(); + + var routingCtx = GetRoutingContext("/test", 1234); + UmbracoContext.Current = routingCtx.UmbracoContext; + PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(Enumerable.Empty()); + } + + public override void TearDown() + { + base.TearDown(); + UmbracoContext.Current = null; + PropertyEditorValueConvertersResolver.Reset(); + } + protected override string GetXmlContent(int templateId) { return @" @@ -62,7 +80,7 @@ namespace Umbraco.Tests.PublishedContent internal IPublishedContent GetNode(int id) { - var ctx = GetUmbracoContext("/test", 1234); + var ctx = UmbracoContext.Current; var contentStore = new DefaultPublishedContentStore(); var doc = contentStore.GetDocumentById(ctx, id); Assert.IsNotNull(doc); @@ -160,7 +178,7 @@ namespace Umbraco.Tests.PublishedContent if (content.DocumentTypeAlias == alias) return creator(content); throw new InvalidOperationException("The content type cannot be cast to " + typeof(T).FullName + " since it is type: " + content.DocumentTypeAlias); } - + public static HomeContentItem AsHome(this IPublishedContent content) { return content.AsDocumentType("Home", x => new HomeContentItem(x)); @@ -211,6 +229,16 @@ namespace Umbraco.Tests.PublishedContent WrappedContent = content; } + public string Url + { + get { return WrappedContent.Url; } + } + + public PublishedItemType ItemType + { + get { return WrappedContent.ItemType; } + } + public IPublishedContent Parent { get { return WrappedContent.Parent; } @@ -280,10 +308,16 @@ namespace Umbraco.Tests.PublishedContent { get { return WrappedContent.Level; } } - public Collection Properties + public ICollection Properties { get { return WrappedContent.Properties; } } + + public object this[string propertyAlias] + { + get { return GetProperty(propertyAlias).Value; } + } + public IEnumerable Children { get { return WrappedContent.Children; } @@ -295,8 +329,9 @@ namespace Umbraco.Tests.PublishedContent } public partial class HomeContentItem : ContentPageContentItem - { - public HomeContentItem(IPublishedContent content) : base(content) + { + public HomeContentItem(IPublishedContent content) + : base(content) { } diff --git a/src/Umbraco.Web/DefaultPublishedMediaStore.cs b/src/Umbraco.Web/DefaultPublishedMediaStore.cs index 0ea46a5efd..1834e1252f 100644 --- a/src/Umbraco.Web/DefaultPublishedMediaStore.cs +++ b/src/Umbraco.Web/DefaultPublishedMediaStore.cs @@ -10,6 +10,7 @@ using Lucene.Net.Documents; using Umbraco.Core; using Umbraco.Core.Dynamics; using Umbraco.Core.Models; +using Umbraco.Web.Models; using umbraco; using umbraco.cms.businesslogic; using ContentType = umbraco.cms.businesslogic.ContentType; @@ -366,7 +367,7 @@ namespace Umbraco.Web /// This is a helper class and definitely not intended for public use, it expects that all of the values required /// to create an IPublishedContent exist in the dictionary by specific aliases. /// - internal class DictionaryPublishedContent : IPublishedContent + internal class DictionaryPublishedContent : PublishedContentBase { public DictionaryPublishedContent( @@ -386,21 +387,21 @@ namespace Umbraco.Web LoadedFromExamine = fromExamine; - ValidateAndSetProperty(valueDictionary, val => Id = int.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int! - ValidateAndSetProperty(valueDictionary, val => TemplateId = int.Parse(val), "template", "templateId"); - ValidateAndSetProperty(valueDictionary, val => SortOrder = int.Parse(val), "sortOrder"); - ValidateAndSetProperty(valueDictionary, val => Name = val, "nodeName", "__nodeName"); - ValidateAndSetProperty(valueDictionary, val => UrlName = val, "urlName"); - ValidateAndSetProperty(valueDictionary, val => DocumentTypeAlias = val, "nodeTypeAlias", "__NodeTypeAlias"); - ValidateAndSetProperty(valueDictionary, val => DocumentTypeId = int.Parse(val), "nodeType"); - ValidateAndSetProperty(valueDictionary, val => WriterName = val, "writerName"); - ValidateAndSetProperty(valueDictionary, val => CreatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132 - ValidateAndSetProperty(valueDictionary, val => WriterId = int.Parse(val), "writerID"); - ValidateAndSetProperty(valueDictionary, val => CreatorId = int.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132 - ValidateAndSetProperty(valueDictionary, val => Path = val, "path", "__Path"); - ValidateAndSetProperty(valueDictionary, val => CreateDate = ParseDateTimeValue(val), "createDate"); - ValidateAndSetProperty(valueDictionary, val => UpdateDate = ParseDateTimeValue(val), "updateDate"); - ValidateAndSetProperty(valueDictionary, val => Level = int.Parse(val), "level"); + ValidateAndSetProperty(valueDictionary, val => _id = int.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int! + ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId"); + ValidateAndSetProperty(valueDictionary, val => _sortOrder = int.Parse(val), "sortOrder"); + ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName"); + ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName"); + ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", "__NodeTypeAlias"); + ValidateAndSetProperty(valueDictionary, val => _documentTypeId = int.Parse(val), "nodeType"); + ValidateAndSetProperty(valueDictionary, val => _writerName = val, "writerName"); + ValidateAndSetProperty(valueDictionary, val => _creatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132 + ValidateAndSetProperty(valueDictionary, val => _writerId = int.Parse(val), "writerID"); + ValidateAndSetProperty(valueDictionary, val => _creatorId = int.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132 + ValidateAndSetProperty(valueDictionary, val => _path = val, "path", "__Path"); + ValidateAndSetProperty(valueDictionary, val => _createDate = ParseDateTimeValue(val), "createDate"); + ValidateAndSetProperty(valueDictionary, val => _updateDate = ParseDateTimeValue(val), "updateDate"); + ValidateAndSetProperty(valueDictionary, val => _level = int.Parse(val), "level"); ValidateAndSetProperty(valueDictionary, val => { int pId; @@ -411,13 +412,13 @@ namespace Umbraco.Web } }, "parentID"); - Properties = new Collection(); + _properties = new Collection(); //loop through remaining values that haven't been applied foreach (var i in valueDictionary.Where(x => !_keysAdded.Contains(x.Key))) { //this is taken from examine - Properties.Add(i.Key.InvariantStartsWith("__") + _properties.Add(i.Key.InvariantStartsWith("__") ? new PropertyResult(i.Key, i.Value, Guid.Empty, PropertyResultType.CustomProperty) : new PropertyResult(i.Key, i.Value, Guid.Empty, PropertyResultType.UserProperty)); } @@ -450,40 +451,134 @@ namespace Umbraco.Web private readonly Func> _getChildren; private readonly Func _getProperty; - public IPublishedContent Parent + /// + /// Returns 'Media' as the item type + /// + public override PublishedItemType ItemType + { + get { return PublishedItemType.Media; } + } + + public override IPublishedContent Parent { get { return _getParent(this); } } public int ParentId { get; private set; } - public int Id { get; private set; } - public int TemplateId { get; private set; } - public int SortOrder { get; private set; } - public string Name { get; private set; } - public string UrlName { get; private set; } - public string DocumentTypeAlias { get; private set; } - public int DocumentTypeId { get; private set; } - public string WriterName { get; private set; } - public string CreatorName { get; private set; } - public int WriterId { get; private set; } - public int CreatorId { get; private set; } - public string Path { get; private set; } - public DateTime CreateDate { get; private set; } - public DateTime UpdateDate { get; private set; } - public Guid Version { get; private set; } - public int Level { get; private set; } - public Collection Properties { get; private set; } - public IEnumerable Children + public override int Id + { + get { return _id; } + } + + public override int TemplateId + { + get { return _templateId; } + } + + public override int SortOrder + { + get { return _sortOrder; } + } + + public override string Name + { + get { return _name; } + } + + public override string UrlName + { + get { return _urlName; } + } + + public override string DocumentTypeAlias + { + get { return _documentTypeAlias; } + } + + public override int DocumentTypeId + { + get { return _documentTypeId; } + } + + public override string WriterName + { + get { return _writerName; } + } + + public override string CreatorName + { + get { return _creatorName; } + } + + public override int WriterId + { + get { return _writerId; } + } + + public override int CreatorId + { + get { return _creatorId; } + } + + public override string Path + { + get { return _path; } + } + + public override DateTime CreateDate + { + get { return _createDate; } + } + + public override DateTime UpdateDate + { + get { return _updateDate; } + } + + public override Guid Version + { + get { return _version; } + } + + public override int Level + { + get { return _level; } + } + + public override ICollection Properties + { + get { return _properties; } + } + + public override IEnumerable Children { get { return _getChildren(this); } } - public IPublishedContentProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return _getProperty(this, alias); } private readonly List _keysAdded = new List(); + private int _id; + private int _templateId; + private int _sortOrder; + private string _name; + private string _urlName; + private string _documentTypeAlias; + private int _documentTypeId; + private string _writerName; + private string _creatorName; + private int _writerId; + private int _creatorId; + private string _path; + private DateTime _createDate; + private DateTime _updateDate; + private Guid _version; + private int _level; + private readonly ICollection _properties; + private void ValidateAndSetProperty(IDictionary valueDictionary, Action setProperty, params string[] potentialKeys) { var key = potentialKeys.FirstOrDefault(x => valueDictionary.ContainsKey(x) && valueDictionary[x] != null); diff --git a/src/Umbraco.Web/Models/DynamicPublishedContent.cs b/src/Umbraco.Web/Models/DynamicPublishedContent.cs index a4c4a29d81..f03d06f607 100644 --- a/src/Umbraco.Web/Models/DynamicPublishedContent.cs +++ b/src/Umbraco.Web/Models/DynamicPublishedContent.cs @@ -529,11 +529,26 @@ namespace Umbraco.Web.Models get { return PublishedContent.Level; } } + public string Url + { + get { return PublishedContent.Url; } + } + + public PublishedItemType ItemType + { + get { return PublishedContent.ItemType; } + } + public IEnumerable Properties { get { return PublishedContent.Properties; } } + public object this[string propertyAlias] + { + get { return PublishedContent[propertyAlias]; } + } + public DynamicPublishedContentList Children { get @@ -739,7 +754,7 @@ namespace Umbraco.Web.Models get { return PublishedContent.Level; } } - System.Collections.ObjectModel.Collection IPublishedContent.Properties + ICollection IPublishedContent.Properties { get { return PublishedContent.Properties; } } diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs new file mode 100644 index 0000000000..186e0b5bd0 --- /dev/null +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Web.Templates; + +namespace Umbraco.Web.Models +{ + + /// + /// An abstract base class to use for IPublishedContent which ensures that the Url and Indexed property return values + /// are consistently returned. + /// + public abstract class PublishedContentBase : IPublishedContent + { + /// + /// Returns the Url for this content item + /// + public virtual string Url + { + get + { + if (UmbracoContext.Current == null) + throw new InvalidOperationException("Cannot resolve a Url for a content item with a null UmbracoContext.Current reference"); + if (UmbracoContext.Current.NiceUrlProvider == null) + throw new InvalidOperationException("Cannot resolve a Url for a content item with a null UmbracoContext.Current.NiceUrlProvider reference"); + return UmbracoContext.Current.NiceUrlProvider.GetNiceUrl(this.Id); + } + } + + public abstract PublishedItemType ItemType { get; } + public abstract int Id { get; } + public abstract int TemplateId { get; } + public abstract int SortOrder { get; } + public abstract string Name { get; } + public abstract string UrlName { get; } + public abstract string DocumentTypeAlias { get; } + public abstract int DocumentTypeId { get; } + public abstract string WriterName { get; } + public abstract string CreatorName { get; } + public abstract int WriterId { get; } + public abstract int CreatorId { get; } + public abstract string Path { get; } + public abstract DateTime CreateDate { get; } + public abstract DateTime UpdateDate { get; } + public abstract Guid Version { get; } + public abstract int Level { get; } + public abstract ICollection Properties { get; } + + /// + /// Returns the property value for the property alias specified + /// + /// + /// + /// + /// Ensures that the value is executed through the IPropertyEditorValueConverters and that all internal links are are to date + /// + public virtual object this[string propertyAlias] + { + get { return this.GetPropertyValue(propertyAlias); } + } + + public abstract IPublishedContentProperty GetProperty(string alias); + public abstract IPublishedContent Parent { get; } + public abstract IEnumerable Children { get; } + } +} diff --git a/src/Umbraco.Web/Models/XmlPublishedContent.cs b/src/Umbraco.Web/Models/XmlPublishedContent.cs index 41e134bee2..18bfbe8115 100644 --- a/src/Umbraco.Web/Models/XmlPublishedContent.cs +++ b/src/Umbraco.Web/Models/XmlPublishedContent.cs @@ -8,6 +8,7 @@ using System.Xml.XPath; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Models; +using Umbraco.Web.Routing; namespace Umbraco.Web.Models { @@ -17,7 +18,7 @@ namespace Umbraco.Web.Models /// [Serializable] [XmlType(Namespace = "http://umbraco.org/webservices/")] - internal class XmlPublishedContent : IPublishedContent + internal class XmlPublishedContent : PublishedContentBase { /// /// Constructor @@ -65,7 +66,7 @@ namespace Umbraco.Web.Models private int _sortOrder; private int _level; - public IEnumerable Children + public override IEnumerable Children { get { @@ -75,12 +76,20 @@ namespace Umbraco.Web.Models } } - public IPublishedContentProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); } - public IPublishedContent Parent + /// + /// returns 'Content' as the ItemType + /// + public override PublishedItemType ItemType + { + get { return PublishedItemType.Content; } + } + + public override IPublishedContent Parent { get { @@ -90,7 +99,7 @@ namespace Umbraco.Web.Models } } - public int Id + public override int Id { get { @@ -100,7 +109,7 @@ namespace Umbraco.Web.Models } } - public int TemplateId + public override int TemplateId { get { @@ -110,7 +119,7 @@ namespace Umbraco.Web.Models } } - public int SortOrder + public override int SortOrder { get { @@ -120,7 +129,7 @@ namespace Umbraco.Web.Models } } - public string Name + public override string Name { get { @@ -129,8 +138,8 @@ namespace Umbraco.Web.Models return _name; } } - - public string DocumentTypeAlias + + public override string DocumentTypeAlias { get { @@ -140,7 +149,7 @@ namespace Umbraco.Web.Models } } - public int DocumentTypeId + public override int DocumentTypeId { get { @@ -150,7 +159,7 @@ namespace Umbraco.Web.Models } } - public string WriterName + public override string WriterName { get { @@ -160,7 +169,7 @@ namespace Umbraco.Web.Models } } - public string CreatorName + public override string CreatorName { get { @@ -170,7 +179,7 @@ namespace Umbraco.Web.Models } } - public int WriterId + public override int WriterId { get { @@ -180,7 +189,7 @@ namespace Umbraco.Web.Models } } - public int CreatorId + public override int CreatorId { get { @@ -191,7 +200,7 @@ namespace Umbraco.Web.Models } - public string Path + public override string Path { get { @@ -201,7 +210,7 @@ namespace Umbraco.Web.Models } } - public DateTime CreateDate + public override DateTime CreateDate { get { @@ -211,7 +220,7 @@ namespace Umbraco.Web.Models } } - public DateTime UpdateDate + public override DateTime UpdateDate { get { @@ -221,7 +230,7 @@ namespace Umbraco.Web.Models } } - public Guid Version + public override Guid Version { get { @@ -231,7 +240,7 @@ namespace Umbraco.Web.Models } } - public string UrlName + public override string UrlName { get { @@ -241,7 +250,7 @@ namespace Umbraco.Web.Models } } - public int Level + public override int Level { get { @@ -251,7 +260,7 @@ namespace Umbraco.Web.Models } } - public Collection Properties + public override ICollection Properties { get { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 93e6d9be72..c5e892780c 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Dynamics; using Umbraco.Core.Models; using Umbraco.Web.Models; using Umbraco.Web.Routing; +using Umbraco.Web.Templates; using umbraco; using umbraco.cms.businesslogic; using Umbraco.Core; @@ -73,6 +74,114 @@ namespace Umbraco.Web return template.Alias; } + #region GetPropertyValue + + /// + /// if the val is a string, ensures all internal local links are parsed + /// + /// + /// + internal static object GetValueWithParsedLinks(object val) + { + //if it is a string send it through the url parser + var text = val as string; + if (text != null) + { + return TemplateUtilities.ResolveUrlsFromTextString( + TemplateUtilities.ParseInternalLinks(text)); + } + //its not a string + return val; + } + + public static object GetPropertyValue(this IPublishedContent doc, string alias) + { + return doc.GetPropertyValue(alias, false); + } + public static object GetPropertyValue(this IPublishedContent doc, string alias, string fallback) + { + var prop = doc.GetPropertyValue(alias); + return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback; + } + public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive) + { + var p = doc.GetProperty(alias, recursive); + if (p == null) return null; + + //Here we need to put the value through the IPropertyEditorValueConverter's + //get the data type id for the current property + var dataType = PublishedContentHelper.GetDataType(doc.DocumentTypeAlias, alias); + //convert the string value to a known type + var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, doc.DocumentTypeAlias, alias); + return converted.Success + ? GetValueWithParsedLinks(converted.Result) + : GetValueWithParsedLinks(p.Value); + } + public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback) + { + var prop = doc.GetPropertyValue(alias, recursive); + return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback; + } + + /// + /// Returns the property as the specified type, if the property is not found or does not convert + /// then the default value of type T is returned. + /// + /// + /// + /// + /// + public static T GetPropertyValue(this IPublishedContent doc, string alias) + { + return doc.GetPropertyValue(alias, default(T)); + } + + public static T GetPropertyValue(this IPublishedContent prop, string alias, bool recursive, T ifCannotConvert) + { + var p = prop.GetProperty(alias, recursive); + if (p == null) + return ifCannotConvert; + + //before we try to convert it manually, lets see if the PropertyEditorValueConverter does this for us + //Here we need to put the value through the IPropertyEditorValueConverter's + //get the data type id for the current property + var dataType = PublishedContentHelper.GetDataType(prop.DocumentTypeAlias, alias); + //convert the value to a known type + var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, prop.DocumentTypeAlias, alias); + object parsedLinksVal; + if (converted.Success) + { + parsedLinksVal = GetValueWithParsedLinks(converted.Result); + + //if its successful, check if its the correct type and return it + if (parsedLinksVal is T) + { + return (T)parsedLinksVal; + } + //if that's not correct, try converting the converted type + var reConverted = converted.Result.TryConvertTo(); + if (reConverted.Success) + { + return reConverted.Result; + } + } + + //first, parse links if possible + parsedLinksVal = GetValueWithParsedLinks(p.Value); + //last, if all the above has failed, we'll just try converting the raw value straight to 'T' + var manualConverted = parsedLinksVal.TryConvertTo(); + if (manualConverted.Success) + return manualConverted.Result; + return ifCannotConvert; + } + + public static T GetPropertyValue(this IPublishedContent prop, string alias, T ifCannotConvert) + { + return prop.GetPropertyValue(alias, false, ifCannotConvert); + } + + #endregion + #region Search public static IEnumerable Search(this IPublishedContent d, string term, bool useWildCards = true, string searchProvider = null) { diff --git a/src/Umbraco.Web/Templates/TemplateUtilities.cs b/src/Umbraco.Web/Templates/TemplateUtilities.cs index c730461f70..94b36323f0 100644 --- a/src/Umbraco.Web/Templates/TemplateUtilities.cs +++ b/src/Umbraco.Web/Templates/TemplateUtilities.cs @@ -3,7 +3,6 @@ using System.Text.RegularExpressions; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Logging; -using umbraco; using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Templates diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 2e8a5068c7..97b7a43e98 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -264,6 +264,7 @@ +