From 8371105c10927827b7ce39e31dfde9abc8f05868 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 2 Apr 2014 16:00:08 +0200 Subject: [PATCH 1/3] U4-4575 - property converters use wrong source value --- src/Umbraco.Web/Models/PublishedProperty.cs | 75 +++++++++++++++++++ .../PublishedCache/MemberPublishedContent.cs | 13 +--- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- 3 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Web/Models/PublishedProperty.cs diff --git a/src/Umbraco.Web/Models/PublishedProperty.cs b/src/Umbraco.Web/Models/PublishedProperty.cs new file mode 100644 index 0000000000..65430ba5f6 --- /dev/null +++ b/src/Umbraco.Web/Models/PublishedProperty.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Models +{ + public static class PublishedProperty + { + /// + /// Maps a collection of Property to a collection of IPublishedProperty for a specified collection of PublishedPropertyType. + /// + /// The published property types. + /// The properties. + /// A mapping function. + /// A collection of IPublishedProperty corresponding to the collection of PublishedPropertyType + /// and taking values from the collection of Property. + /// Ensures that all conversions took place correctly. + internal static IEnumerable MapProperties( + IEnumerable propertyTypes, IEnumerable properties, + Func map) + { + var peResolver = DataTypesResolver.Current; + var dtService = ApplicationContext.Current.Services.DataTypeService; + return MapProperties(propertyTypes, properties, peResolver, dtService, map); + } + + /// + /// Maps a collection of Property to a collection of IPublishedProperty for a specified collection of PublishedPropertyType. + /// + /// The published property types. + /// The properties. + /// A mapping function. + /// A DataTypesResolver instance. + /// An IDataTypeService instance. + /// A collection of IPublishedProperty corresponding to the collection of PublishedPropertyType + /// and taking values from the collection of Property. + /// Ensures that all conversions took place correctly. + internal static IEnumerable MapProperties( + IEnumerable propertyTypes, IEnumerable properties, + DataTypesResolver dataTypesResolver, IDataTypeService dataTypeService, + Func map) + { + return propertyTypes + .Select(x => + { + var p = properties.SingleOrDefault(xx => xx.Alias == x.PropertyTypeAlias); + var v = p == null || p.Value == null ? null : p.Value; + if (v != null) + { + var dataType = dataTypesResolver.DataTypes.SingleOrDefault(qq => qq.Id == x.PropertyEditorGuid); + if (dataType != null) + { + var data = dataType.Data; + data.Value = v; + var n = data.ToXMl(new XmlDocument()); + v = n.InnerXml; + } + } + // fixme - means that the IPropertyValueConverter will always get a string + // fixme and never an int or DateTime that's in the DB unless the value editor has + // fixme a way to say it's OK to use what's in the DB? + + return map(x, p, v); + }); + } + } +} diff --git a/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs index deafcaab40..e538d135d3 100644 --- a/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.PublishedCache private readonly IMember _member; private readonly MembershipUser _membershipUser; - private readonly List _properties; + private readonly IPublishedProperty[] _properties; private readonly PublishedContentType _publishedMemberType; public MemberPublishedContent(IMember member, MembershipUser membershipUser) @@ -28,19 +28,14 @@ namespace Umbraco.Web.PublishedCache _member = member; _membershipUser = membershipUser; - _properties = new List(); _publishedMemberType = PublishedContentType.Get(PublishedItemType.Member, _member.ContentTypeAlias); if (_publishedMemberType == null) { throw new InvalidOperationException("Could not get member type with alias " + _member.ContentTypeAlias); } - foreach (var propType in _publishedMemberType.PropertyTypes) - { - var val = _member.Properties.Any(x => x.Alias == propType.PropertyTypeAlias) == false - ? string.Empty - : _member.Properties[propType.PropertyTypeAlias].Value; - _properties.Add(new RawValueProperty(propType, val ?? string.Empty)); - } + _properties = PublishedProperty.MapProperties(_publishedMemberType.PropertyTypes, _member.Properties, + (t, p, v) => new RawValueProperty(t, v ?? string.Empty)) + .ToArray(); } #region Membership provider member properties diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 22fd963203..581893f2ea 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1,4 +1,4 @@ - + @@ -300,6 +300,7 @@ + From 9940b78a57268c0a08353911f111b143546c754c Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 2 Apr 2014 17:00:24 +0200 Subject: [PATCH 2/3] U4-4575 - fix 8371105 --- src/Umbraco.Web/Models/PublishedProperty.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Models/PublishedProperty.cs b/src/Umbraco.Web/Models/PublishedProperty.cs index 65430ba5f6..b24d1260a3 100644 --- a/src/Umbraco.Web/Models/PublishedProperty.cs +++ b/src/Umbraco.Web/Models/PublishedProperty.cs @@ -55,13 +55,20 @@ namespace Umbraco.Web.Models var v = p == null || p.Value == null ? null : p.Value; if (v != null) { - var dataType = dataTypesResolver.DataTypes.SingleOrDefault(qq => qq.Id == x.PropertyEditorGuid); + // note - not sure about the performance here + var dataTypeDefinition = global::umbraco.cms.businesslogic.datatype.DataTypeDefinition + .GetDataTypeDefinition(x.DataTypeId); + var dataType = dataTypeDefinition.DataType; if (dataType != null) { var data = dataType.Data; data.Value = v; var n = data.ToXMl(new XmlDocument()); - v = n.InnerXml; + if (n.NodeType == XmlNodeType.CDATA || n.NodeType == XmlNodeType.Text) + v = n.InnerText; + else if (n.NodeType == XmlNodeType.Element) + v = n.InnerXml; + // note - is there anything else we should take care of? } } // fixme - means that the IPropertyValueConverter will always get a string From bf8add4f8d75886043c202c4785c0c929217f489 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 3 Apr 2014 11:10:43 +0200 Subject: [PATCH 3/3] Manually picked up PR #343 --- src/Umbraco.Core/Services/IRelationService.cs | 47 +++++++++++++ src/Umbraco.Core/Services/RelationService.cs | 67 ++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/IRelationService.cs b/src/Umbraco.Core/Services/IRelationService.cs index a219cfc43b..73f8e7a88d 100644 --- a/src/Umbraco.Core/Services/IRelationService.cs +++ b/src/Umbraco.Core/Services/IRelationService.cs @@ -63,6 +63,21 @@ namespace Umbraco.Core.Services /// An enumerable list of objects IEnumerable GetByParentId(int id); + /// + /// Gets a list of objects by their parent entity + /// + /// Parent Entity to retrieve relations for + /// An enumerable list of objects + IEnumerable GetByParent(IUmbracoEntity parent); + + /// + /// Gets a list of objects by their parent entity + /// + /// Parent Entity to retrieve relations for + /// Alias of the type of relation to retrieve + /// An enumerable list of objects + IEnumerable GetByParent(IUmbracoEntity parent, string relationTypeAlias); + /// /// Gets a list of objects by their child Id /// @@ -70,6 +85,21 @@ namespace Umbraco.Core.Services /// An enumerable list of objects IEnumerable GetByChildId(int id); + /// + /// Gets a list of objects by their child Entity + /// + /// Child Entity to retrieve relations for + /// An enumerable list of objects + IEnumerable GetByChild(IUmbracoEntity child); + + /// + /// Gets a list of objects by their child Entity + /// + /// Child Entity to retrieve relations for + /// Alias of the type of relation to retrieve + /// An enumerable list of objects + IEnumerable GetByChild(IUmbracoEntity child, string relationTypeAlias); + /// /// Gets a list of objects by their child or parent Id. /// Using this method will get you all relations regards of it being a child or parent relation. @@ -190,6 +220,23 @@ namespace Umbraco.Core.Services /// Returns True if any relations exists with the given Ids, otherwise False bool AreRelated(int parentId, int childId); + /// + /// Checks whether two items are related + /// + /// Parent entity + /// Child entity + /// Returns True if any relations exist between the entities, otherwise False + bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child); + + /// + /// Checks whether two items are related + /// + /// Parent entity + /// Child entity + /// Alias of the type of relation to create + /// Returns True if any relations exist between the entities, otherwise False + bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias); + /// /// Saves a /// diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index 5102731902..bd4a46c75e 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -128,6 +128,27 @@ namespace Umbraco.Core.Services } } + /// + /// Gets a list of objects by their parent entity + /// + /// Parent Entity to retrieve relations for + /// An enumerable list of objects + public IEnumerable GetByParent(IUmbracoEntity parent) + { + return GetByParentId(parent.Id); + } + + /// + /// Gets a list of objects by their parent entity + /// + /// Parent Entity to retrieve relations for + /// Alias of the type of relation to retrieve + /// An enumerable list of objects + public IEnumerable GetByParent(IUmbracoEntity parent, string relationTypeAlias) + { + return GetByParent(parent).Where(relation => relation.RelationType.Alias == relationTypeAlias); + } + /// /// Gets a list of objects by their child Id /// @@ -142,6 +163,27 @@ namespace Umbraco.Core.Services } } + /// + /// Gets a list of objects by their child Entity + /// + /// Child Entity to retrieve relations for + /// An enumerable list of objects + public IEnumerable GetByChild(IUmbracoEntity child) + { + return GetByChildId(child.Id); + } + + /// + /// Gets a list of objects by their child Entity + /// + /// Child Entity to retrieve relations for + /// Alias of the type of relation to retrieve + /// An enumerable list of objects + public IEnumerable GetByChild(IUmbracoEntity child, string relationTypeAlias) + { + return GetByChild(child).Where(relation => relation.RelationType.Alias == relationTypeAlias); + } + /// /// Gets a list of objects by their child or parent Id. /// Using this method will get you all relations regards of it being a child or parent relation. @@ -422,7 +464,7 @@ namespace Umbraco.Core.Services public bool AreRelated(int parentId, int childId, string relationTypeAlias) { var relType = GetRelationTypeByAlias(relationTypeAlias); - if(relType == null) + if (relType == null) return false; return AreRelated(parentId, childId, relType); @@ -445,6 +487,29 @@ namespace Umbraco.Core.Services } } + /// + /// Checks whether two items are related + /// + /// Parent entity + /// Child entity + /// Returns True if any relations exist between the entities, otherwise False + public bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child) + { + return AreRelated(parent.Id, child.Id); + } + + /// + /// Checks whether two items are related + /// + /// Parent entity + /// Child entity + /// Alias of the type of relation to create + /// Returns True if any relations exist between the entities, otherwise False + public bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias) + { + return AreRelated(parent.Id, child.Id, relationTypeAlias); + } + /// /// Saves a