diff --git a/src/Our.Umbraco.Ditto/Attributes/UmbracoPropertyPrefixAttribute.cs b/src/Our.Umbraco.Ditto/Attributes/UmbracoPropertiesAttribute.cs similarity index 52% rename from src/Our.Umbraco.Ditto/Attributes/UmbracoPropertyPrefixAttribute.cs rename to src/Our.Umbraco.Ditto/Attributes/UmbracoPropertiesAttribute.cs index 1785656..f03b8f6 100644 --- a/src/Our.Umbraco.Ditto/Attributes/UmbracoPropertyPrefixAttribute.cs +++ b/src/Our.Umbraco.Ditto/Attributes/UmbracoPropertiesAttribute.cs @@ -3,26 +3,25 @@ using System; /// - /// The Umbraco property prefix attribute. + /// The Umbraco properties attribute. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class UmbracoPropertyPrefixAttribute : Attribute + public class UmbracoPropertiesAttribute : Attribute { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// - /// The property name. - /// - public UmbracoPropertyPrefixAttribute( - string prefix) - { - this.Prefix = prefix; - } + public UmbracoPropertiesAttribute() + { } /// /// Gets or sets the prefix. /// public string Prefix { get; set; } + + /// + /// Gets or sets whether the properties should be retrieved recursively up the tree. + /// + public bool Recursive { get; set; } } } \ No newline at end of file diff --git a/src/Our.Umbraco.Ditto/ComponentModel/ValueResolvers/UmbracoPropertyValueResolver.cs b/src/Our.Umbraco.Ditto/ComponentModel/ValueResolvers/UmbracoPropertyValueResolver.cs index 701e2fb..7e4de52 100644 --- a/src/Our.Umbraco.Ditto/ComponentModel/ValueResolvers/UmbracoPropertyValueResolver.cs +++ b/src/Our.Umbraco.Ditto/ComponentModel/ValueResolvers/UmbracoPropertyValueResolver.cs @@ -32,23 +32,31 @@ public override object ResolveValue(ITypeDescriptorContext context, UmbracoPrope { var defaultValue = attribute.DefaultValue; + var recursive = attribute.Recursive; var propName = context.PropertyDescriptor != null ? context.PropertyDescriptor.Name : string.Empty; var altPropName = ""; + // Check for umbraco properties attribute on class if (context.PropertyDescriptor != null) { - var prefixAttr = context.PropertyDescriptor.ComponentType - .GetCustomAttribute(); - if (prefixAttr != null) + var classAttr = context.PropertyDescriptor.ComponentType + .GetCustomAttribute(); + if (classAttr != null) { - altPropName = propName; - propName = prefixAttr.Prefix + propName; + // Apply the prefix + if (!string.IsNullOrWhiteSpace(classAttr.Prefix)) + { + altPropName = propName; + propName = classAttr.Prefix + propName; + } + + // Apply global recursive setting + recursive |= classAttr.Recursive; } } var umbracoPropertyName = attribute.PropertyName ?? propName; var altUmbracoPropertyName = attribute.AltPropertyName ?? altPropName; - var recursive = attribute.Recursive; var content = context.Instance as IPublishedContent; if (content == null) diff --git a/src/Our.Umbraco.Ditto/Our.Umbraco.Ditto.csproj b/src/Our.Umbraco.Ditto/Our.Umbraco.Ditto.csproj index d69ac28..a17bf15 100644 --- a/src/Our.Umbraco.Ditto/Our.Umbraco.Ditto.csproj +++ b/src/Our.Umbraco.Ditto/Our.Umbraco.Ditto.csproj @@ -83,7 +83,7 @@ - + diff --git a/tests/Our.Umbraco.Ditto.Tests/Mocks/ContentBuilder.cs b/tests/Our.Umbraco.Ditto.Tests/Mocks/ContentBuilder.cs index 3b39c3f..5bc3ec3 100644 --- a/tests/Our.Umbraco.Ditto.Tests/Mocks/ContentBuilder.cs +++ b/tests/Our.Umbraco.Ditto.Tests/Mocks/ContentBuilder.cs @@ -11,6 +11,7 @@ public class ContentBuilder { private int _id = 1234; private string _name = "Name"; + private IPublishedContent _parent; private List _children = new List(); private List _properties = new List(); @@ -49,9 +50,15 @@ public ContentBuilder AddChild(IPublishedContent child) return this; } + public ContentBuilder AddParent(IPublishedContent parent) + { + _parent = parent; + return this; + } + public IPublishedContent Build() { - return new PublishedContentMock(_id, _name, _children, _properties); + return new PublishedContentMock(_id, _name, _parent, _children, _properties); } } } \ No newline at end of file diff --git a/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentMock.cs b/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentMock.cs index 4edc9c5..7c3019a 100644 --- a/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentMock.cs +++ b/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentMock.cs @@ -1,4 +1,7 @@ -namespace Our.Umbraco.Ditto.Tests.Mocks +using System.Collections.ObjectModel; +using NUnit.Framework; + +namespace Our.Umbraco.Ditto.Tests.Mocks { using System; using System.Collections.Generic; @@ -15,15 +18,23 @@ /// public class PublishedContentMock : IPublishedContent { + public PublishedContentMock() + { + Properties = new Collection(); + Children = new List(); + } + public PublishedContentMock( int id, string name, + IPublishedContent _parent, IEnumerable children, ICollection properties) { Properties = properties; Id = id; Name = name; + Parent = Parent; Children = children; } @@ -39,56 +50,61 @@ public IPublishedContentProperty GetProperty(string alias) public IPublishedContentProperty GetProperty(string alias, bool recurse) { - return Properties.SingleOrDefault(p => p.Alias.InvariantEquals(alias)); + var prop = Properties.SingleOrDefault(p => p.Alias.InvariantEquals(alias)); + if (prop == null && recurse && Parent != null) + { + return Parent.GetProperty(alias, recurse); + } + return prop; } - public IEnumerable ContentSet { get; private set; } + public IEnumerable ContentSet { get; set; } - public PublishedContentType ContentType { get; private set; } + public PublishedContentType ContentType { get; set; } - public int Id { get; private set; } + public int Id { get; set; } - public int TemplateId { get; private set; } + public int TemplateId { get; set; } - public int SortOrder { get; private set; } + public int SortOrder { get; set; } - public string Name { get; private set; } + public string Name { get; set; } - public string UrlName { get; private set; } + public string UrlName { get; set; } - public string DocumentTypeAlias { get; private set; } + public string DocumentTypeAlias { get; set; } - public int DocumentTypeId { get; private set; } + public int DocumentTypeId { get; set; } - public string WriterName { get; private set; } + public string WriterName { get; set; } - public string CreatorName { get; private set; } + public string CreatorName { get; set; } - public int WriterId { get; private set; } + public int WriterId { get; set; } - public int CreatorId { get; private set; } + public int CreatorId { get; set; } - public string Path { get; private set; } + public string Path { get; set; } - public DateTime CreateDate { get; private set; } + public DateTime CreateDate { get; set; } - public DateTime UpdateDate { get; private set; } + public DateTime UpdateDate { get; set; } - public Guid Version { get; private set; } + public Guid Version { get; set; } - public int Level { get; private set; } + public int Level { get; set; } - public string Url { get; private set; } + public string Url { get; set; } - public PublishedItemType ItemType { get; private set; } + public PublishedItemType ItemType { get; set; } - public bool IsDraft { get; private set; } + public bool IsDraft { get; set; } - public IPublishedContent Parent { get; private set; } + public IPublishedContent Parent { get; set; } - public IEnumerable Children { get; private set; } + public IEnumerable Children { get; set; } - public ICollection Properties { get; private set; } + public ICollection Properties { get; set; } public object this[string alias] { diff --git a/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentPropertyMock.cs b/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentPropertyMock.cs index f1cd4c0..0046092 100644 --- a/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentPropertyMock.cs +++ b/tests/Our.Umbraco.Ditto.Tests/Mocks/PublishedContentPropertyMock.cs @@ -5,6 +5,9 @@ public class PublishedContentPropertyMock : IPublishedContentProperty { + public PublishedContentPropertyMock() + { } + public PublishedContentPropertyMock(string alias, object value, bool hasValue) { HasValue = hasValue; @@ -12,18 +15,18 @@ public PublishedContentPropertyMock(string alias, object value, bool hasValue) Value = value; } - public string PropertyTypeAlias { get; private set; } + public string PropertyTypeAlias { get; set; } - public bool HasValue { get; private set; } + public bool HasValue { get; set; } - public object DataValue { get; private set; } + public object DataValue { get; set; } - public object Value { get; private set; } + public object Value { get; set; } - public object XPathValue { get; private set; } + public object XPathValue { get; set; } - public string Alias { get; private set; } + public string Alias { get; set; } - public Guid Version { get; private set; } + public Guid Version { get; set; } } } \ No newline at end of file diff --git a/tests/Our.Umbraco.Ditto.Tests/Models/PrefixedModel.cs b/tests/Our.Umbraco.Ditto.Tests/Models/PrefixedModel.cs index 7b5ae55..4a1b41b 100644 --- a/tests/Our.Umbraco.Ditto.Tests/Models/PrefixedModel.cs +++ b/tests/Our.Umbraco.Ditto.Tests/Models/PrefixedModel.cs @@ -6,7 +6,7 @@ namespace Our.Umbraco.Ditto.Tests.Models { - [UmbracoPropertyPrefix("Site")] + [UmbracoProperties(Prefix = "Site", Recursive = true)] public class PrefixedModel { public string Name { get; set; } diff --git a/tests/Our.Umbraco.Ditto.Tests/PublishedContentTests.cs b/tests/Our.Umbraco.Ditto.Tests/PublishedContentTests.cs index 24f1f76..8c6815f 100644 --- a/tests/Our.Umbraco.Ditto.Tests/PublishedContentTests.cs +++ b/tests/Our.Umbraco.Ditto.Tests/PublishedContentTests.cs @@ -109,7 +109,7 @@ public void Content_To_String() } [Test] - public void Prefix_Attribute_Resolves_Prefixed_Properties() + public void Can_Resolve_Prefixed_Properties() { var prop1 = PropertyBuilder.Default("siteName", "Name").Build(); var prop2 = PropertyBuilder.Default("siteDescription", "Description").Build(); @@ -129,7 +129,7 @@ public void Prefix_Attribute_Resolves_Prefixed_Properties() } [Test] - public void Umbraco_Property_Attribute_Overrides_Prefix_Attribute() + public void Umbraco_Property_Attribute_Overrides_Prefix() { var prop1 = PropertyBuilder.Default("siteUnprefixedProp", "Site Unprefixed").Build(); var prop2 = PropertyBuilder.Default("unprefixedProp", "Unprefixed").Build(); @@ -143,5 +143,32 @@ public void Umbraco_Property_Attribute_Overrides_Prefix_Attribute() Assert.That(converted.UnprefixedProp, Is.EqualTo("Unprefixed")); } + + [Test] + public void Can_Resolve_Recursive_Properties_Via_Umbraco_Properties_Attribute() + { + var childContent = new PublishedContentMock(); + var parentContent = new PublishedContentMock + { + Properties = new[] + { + new PublishedContentPropertyMock + { + Alias = "description", + Value = "Description" + } + }, + Children = new[] + { + childContent + } + }; + + childContent.Parent = parentContent; + + var converted = childContent.As(); + + Assert.That(converted.Description, Is.EqualTo("Description")); + } } } \ No newline at end of file