diff --git a/src/Umbraco.Core/Models/MemberType.cs b/src/Umbraco.Core/Models/MemberType.cs
index ed7d5cd3ab..2b32681392 100644
--- a/src/Umbraco.Core/Models/MemberType.cs
+++ b/src/Umbraco.Core/Models/MemberType.cs
@@ -114,5 +114,26 @@ namespace Umbraco.Core.Models
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
+
+ ///
+ /// Method to call when Entity is being saved
+ ///
+ /// Created date is set and a Unique key is assigned
+ internal override void AddingEntity()
+ {
+ base.AddingEntity();
+
+ if (Key == Guid.Empty)
+ Key = Guid.NewGuid();
+ }
+
+ ///
+ /// Method to call when Entity is being updated
+ ///
+ /// Modified Date is set and a new Version guid is set
+ internal override void UpdatingEntity()
+ {
+ base.UpdatingEntity();
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs
index 78e250a8b5..2f48035ba5 100644
--- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs
+++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("contentTypeId")]
public int ContentTypeId { get; set; }
- [Column("propertyTypeGroupId")]
+ [Column("PropertyTypesGroupId")]
public int? PropertyTypeGroupId { get; set; }
[Column("Alias")]
diff --git a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
index eb6e2c787d..09d4765eb3 100644
--- a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Persistence.Factories
? propertyType.CreatePropertyFromValue(null)
: propertyType.CreatePropertyFromRawValue(propertyDataDto.GetValue,
propertyDataDto.VersionId,
- propertyDataDto.Id);
+ propertyDataDto.PropertyDataId.Value);
//on initial construction we don't want to have dirty properties tracked
property.CreateDate = createDate;
property.UpdateDate = createDate;
diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
index e9e7fe19c4..925e0edccd 100644
--- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
@@ -55,51 +55,72 @@ namespace Umbraco.Core.Persistence.Factories
private PropertyGroupCollection GetPropertyTypeGroupCollection(MemberTypeReadOnlyDto dto, MemberType memberType)
{
- var propertyTypeGroupCollection = new PropertyGroupCollection();
- foreach (var propertyTypeGroup in dto.PropertyTypeGroups.Where(x => x.Id.HasValue))
+ var propertyGroups = new PropertyGroupCollection();
+ foreach (var groupDto in dto.PropertyTypeGroups.Where(x => x.Id.HasValue))
{
- //Find PropertyTypes that belong to the current PropertyTypeGroup
- var groupId = propertyTypeGroup.Id.Value;
- var propertyTypesByGroup =
- dto.PropertyTypes.Where(
- x => x.Id.HasValue && x.PropertyTypeGroupId.HasValue && x.PropertyTypeGroupId.Value.Equals(groupId));
- //Create PropertyTypeCollection for passing into the PropertyTypeGroup, and loop through the above result to create PropertyTypes
- var propertyTypeCollection = new PropertyTypeCollection();
- foreach (var propTypeDto in propertyTypesByGroup)
+ var group = new PropertyGroup();
+ //Only assign an Id if the PropertyGroup belongs to this ContentType
+ if (groupDto.Id.HasValue && groupDto.Id == memberType.Id)
{
- //Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
- memberType.MemberTypePropertyTypes.Add(propTypeDto.Alias,
- new Tuple(propTypeDto.CanEdit, propTypeDto.ViewOnProfile, propTypeDto.Id.Value));
- //PropertyType Collection
- propertyTypeCollection.Add(new PropertyType(propTypeDto.ControlId,
- propTypeDto.DbType.EnumParse(true))
- {
- Alias = propTypeDto.Alias,
- DataTypeDefinitionId = propTypeDto.DataTypeId,
- Description = propTypeDto.Description,
- HelpText = propTypeDto.HelpText,
- Id = propTypeDto.Id.Value,
- Mandatory = propTypeDto.Mandatory,
- Name = propTypeDto.Name,
- SortOrder = propTypeDto.SortOrder,
- ValidationRegExp = propTypeDto.ValidationRegExp,
- PropertyGroupId = new Lazy(() => propTypeDto.PropertyTypeGroupId.Value),
- CreateDate = dto.CreateDate,
- UpdateDate = dto.CreateDate
- });
+ group.Id = groupDto.Id.Value;
+
+ if (groupDto.ParentGroupId.HasValue)
+ group.ParentId = groupDto.ParentGroupId.Value;
+ }
+ else
+ {
+ //If the PropertyGroup is inherited, we add a reference to the group as a Parent.
+ group.ParentId = groupDto.Id;
}
- var group = new PropertyGroup(propertyTypeCollection) {Id = groupId};
- propertyTypeGroupCollection.Add(@group);
+ group.Name = groupDto.Text;
+ group.SortOrder = groupDto.SortOrder;
+ group.PropertyTypes = new PropertyTypeCollection();
+
+ //Because we are likely to have a group with no PropertyTypes we need to ensure that these are excluded
+ var typeDtos = dto.PropertyTypes.Where(x => x.Id.HasValue && x.Id > 0 && x.PropertyTypeGroupId.HasValue && x.PropertyTypeGroupId.Value == groupDto.Id.Value);
+ foreach (var typeDto in typeDtos)
+ {
+ //Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
+ memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
+ new Tuple(typeDto.CanEdit, typeDto.ViewOnProfile, typeDto.Id.Value));
+
+ var tempGroupDto = groupDto;
+ var propertyType = new PropertyType(typeDto.ControlId,
+ typeDto.DbType.EnumParse(true))
+ {
+ Alias = typeDto.Alias,
+ DataTypeDefinitionId = typeDto.DataTypeId,
+ Description = typeDto.Description,
+ Id = typeDto.Id.Value,
+ Name = typeDto.Name,
+ HelpText = typeDto.HelpText,
+ Mandatory = typeDto.Mandatory,
+ SortOrder = typeDto.SortOrder,
+ ValidationRegExp = typeDto.ValidationRegExp,
+ PropertyGroupId = new Lazy(() => tempGroupDto.Id.Value),
+ CreateDate = memberType.CreateDate,
+ UpdateDate = memberType.UpdateDate
+ };
+ //on initial construction we don't want to have dirty properties tracked
+ // http://issues.umbraco.org/issue/U4-1946
+ propertyType.ResetDirtyProperties(false);
+ group.PropertyTypes.Add(propertyType);
+ }
+ //on initial construction we don't want to have dirty properties tracked
+ // http://issues.umbraco.org/issue/U4-1946
+ group.ResetDirtyProperties(false);
+ propertyGroups.Add(group);
}
- return propertyTypeGroupCollection;
+
+ return propertyGroups;
}
private List GetPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType)
{
//Find PropertyTypes that does not belong to a PropertyTypeGroup
var propertyTypes = new List();
- foreach (var propertyType in dto.PropertyTypes.Where(x => x.PropertyTypeGroupId.HasValue == false && x.Id.HasValue))
+ foreach (var propertyType in dto.PropertyTypes.Where(x => (x.PropertyTypeGroupId.HasValue == false || x.PropertyTypeGroupId.Value == 0) && x.Id.HasValue))
{
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(propertyType.Alias,
diff --git a/src/Umbraco.Core/Persistence/Relators/PropertyDataRelator.cs b/src/Umbraco.Core/Persistence/Relators/PropertyDataRelator.cs
index 49c5e671e6..4eabe8c669 100644
--- a/src/Umbraco.Core/Persistence/Relators/PropertyDataRelator.cs
+++ b/src/Umbraco.Core/Persistence/Relators/PropertyDataRelator.cs
@@ -15,6 +15,8 @@ namespace Umbraco.Core.Persistence.Relators
if (a == null)
return Current;
+ p.VersionId = a.VersionId;
+
// Is this the same MemberReadOnlyDto as the current one we're processing
if (Current != null && Current.UniqueId == a.UniqueId)
{
diff --git a/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs b/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs
index e16a61db6f..a9129498c5 100644
--- a/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs
+++ b/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Relators
@@ -21,7 +22,7 @@ namespace Umbraco.Core.Persistence.Relators
// Yes, just add this PropertyTypeReadOnlyDto to the current MemberTypeReadOnlyDto's collection
Current.PropertyTypes.Add(p);
- if(g.Id.HasValue)
+ if (g.Id.HasValue && Current.PropertyTypeGroups != null && Current.PropertyTypeGroups.Any(x => x.Id == g.Id.Value) == false)
Current.PropertyTypeGroups.Add(g);
// Return null to indicate we're not done with this MemberTypeReadOnlyDto yet
diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
index 856ede87d1..caa92f94ef 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
@@ -229,10 +229,8 @@ namespace Umbraco.Core.Persistence.Repositories
dto.NodeId = nodeDto.NodeId;
Database.Insert(dto);
- //TODO ContentType for the Member entity
-
//Create the PropertyData for this version - cmsPropertyData
- /*var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
+ var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
var propertyDataDtos = propertyFactory.BuildDto(((Member)entity).Properties);
var keyDictionary = new Dictionary();
@@ -247,7 +245,7 @@ namespace Umbraco.Core.Persistence.Repositories
foreach (var property in ((Member)entity).Properties)
{
property.Id = keyDictionary[property.PropertyTypeId];
- }*/
+ }
((Member)entity).ResetDirtyProperties();
}
@@ -300,7 +298,7 @@ namespace Umbraco.Core.Persistence.Repositories
//TODO ContentType for the Member entity
//Create the PropertyData for this version - cmsPropertyData
- /*var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
+ var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
var propertyDataDtos = propertyFactory.BuildDto(((Member)entity).Properties);
var keyDictionary = new Dictionary();
@@ -325,7 +323,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
property.Id = keyDictionary[property.PropertyTypeId];
}
- }*/
+ }
((ICanBeDirty)entity).ResetDirtyProperties();
}
diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
index 305f828c2d..be3a9eb752 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
@@ -101,7 +101,7 @@ namespace Umbraco.Core.Persistence.Repositories
sql.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias",
"cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.helpText", "cmsPropertyType.mandatory",
"cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder",
- "cmsPropertyType.propertyTypeGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile",
+ "cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile",
"cmsDataType.controlId", "cmsDataType.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId",
"cmsPropertyTypeGroup.text AS PropertyGroupName", "cmsPropertyTypeGroup.parentGroupId",
"cmsPropertyTypeGroup.sortorder AS PropertyGroupSortOrder")
diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
index 6aa9609807..6795f2c608 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
@@ -15,6 +15,7 @@ using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
+using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Persistence.Repositories
{
@@ -174,6 +175,31 @@ namespace Umbraco.Tests.Persistence.Repositories
}
}
+ [Test]
+ public void MemberRepository_Can_Persist_Member()
+ {
+ IMember sut;
+ var unitOfWork = UnitOfWorkProvider.GetUnitOfWork();
+ MemberTypeRepository memberTypeRepository;
+ using (var repository = CreateRepository(unitOfWork, out memberTypeRepository))
+ {
+ var memberType = MockedContentTypes.CreateSimpleMemberType();
+ memberTypeRepository.AddOrUpdate(memberType);
+ unitOfWork.Commit();
+
+ var member = MockedMember.CreateSimpleContent(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty", -1);
+ repository.AddOrUpdate(member);
+ unitOfWork.Commit();
+
+ sut = repository.Get(member.Id);
+
+ Assert.That(sut, Is.Not.Null);
+ Assert.That(sut.ContentType.PropertyGroups.Count(), Is.EqualTo(1));
+ Assert.That(sut.ContentType.PropertyTypes.Count(), Is.EqualTo(12));
+ Assert.That(sut.Properties.Count(), Is.EqualTo(12));
+ }
+ }
+
[Test]
public void Can_Create_Correct_Subquery()
{
diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs
index f3f09e5fae..cc22ce913b 100644
--- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs
+++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs
@@ -265,5 +265,32 @@ namespace Umbraco.Tests.TestHelpers.Entities
return mediaType;
}
+
+ public static MemberType CreateSimpleMemberType()
+ {
+ var contentType = new MemberType(-1)
+ {
+ Alias = "simple",
+ Name = "Simple Page",
+ Description = "ContentType used for simple text pages",
+ Icon = ".sprTreeDoc3",
+ Thumbnail = "doc.png",
+ SortOrder = 1,
+ CreatorId = 0,
+ Trashed = false
+ };
+
+ var contentCollection = new PropertyTypeCollection();
+ contentCollection.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
+ contentCollection.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
+ contentCollection.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
+
+ contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
+
+ //ensure that nothing is marked as dirty
+ contentType.ResetDirtyProperties(false);
+
+ return contentType;
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs
new file mode 100644
index 0000000000..4aeb406811
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs
@@ -0,0 +1,26 @@
+using Umbraco.Core.Models;
+
+namespace Umbraco.Tests.TestHelpers.Entities
+{
+ public class MockedMember
+ {
+ public static Member CreateSimpleContent(IMemberType contentType, string name, string email, string password, string username, int parentId)
+ {
+ var member = new Member(name, parentId, contentType, new PropertyCollection())
+ {
+ CreatorId = 0,
+ Email = email,
+ Password = password,
+ Username = username
+ };
+
+ member.SetValue("title", name + " member");
+ member.SetValue("bodyText", "This is a subpage");
+ member.SetValue("author", "John Doe");
+
+ member.ResetDirtyProperties(false);
+
+ return member;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index a37a253e9b..469caa926c 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -301,6 +301,7 @@
+