diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 95f3f55308..f59a167e07 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -227,17 +227,7 @@ namespace Umbraco.Tests.Models.Mapping .Returns(new[] { new TextboxPropertyEditor() }); var contentType = MockedContentTypes.CreateTextpageContentType(); - //ensure everything has ids - contentType.Id = 1234; - var itemid = 8888; - foreach (var propertyGroup in contentType.CompositionPropertyGroups) - { - propertyGroup.Id = itemid++; - } - foreach (var propertyType in contentType.CompositionPropertyTypes) - { - propertyType.Id = itemid++; - } + MockedContentTypes.EnsureAllIds(contentType, 8888); //Act @@ -289,6 +279,94 @@ namespace Umbraco.Tests.Models.Mapping } + [Test] + public void IContentTypeComposition_To_ContentTypeDisplay() + { + //Arrange + + // setup the mocks to return the data we want to test against... + + // for any call to GetPreValuesCollectionByDataTypeId just return an empty dictionary for now + // TODO: but we'll need to change this to return some pre-values to test the mappings + _dataTypeService.Setup(x => x.GetPreValuesCollectionByDataTypeId(It.IsAny())) + .Returns(new PreValueCollection(new Dictionary())); + + //return a textbox property editor for any requested editor by alias + _propertyEditorResolver.Setup(resolver => resolver.GetByAlias(It.IsAny())) + .Returns(new TextboxPropertyEditor()); + //for testing, just return a list of whatever property editors we want + _propertyEditorResolver.Setup(resolver => resolver.PropertyEditors) + .Returns(new[] { new TextboxPropertyEditor() }); + + var ctMain = MockedContentTypes.CreateSimpleContentType(); + //not assigned to tab + ctMain.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + { + Alias = "umbracoUrlName", Name = "Slug", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + }); + MockedContentTypes.EnsureAllIds(ctMain, 8888); + var ctChild1 = MockedContentTypes.CreateSimpleContentType("child1", "Child 1", ctMain, true); + MockedContentTypes.EnsureAllIds(ctChild1, 7777); + var contentType = MockedContentTypes.CreateSimpleContentType("child2", "Child 2", ctChild1, true, "CustomGroup"); + //not assigned to tab + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + { + Alias = "umbracoUrlAlias", Name = "AltUrl", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + }); + MockedContentTypes.EnsureAllIds(contentType, 6666); + + + //Act + + var result = Mapper.Map(contentType); + + //Assert + + Assert.AreEqual(contentType.Alias, result.Alias); + Assert.AreEqual(contentType.Description, result.Description); + Assert.AreEqual(contentType.Icon, result.Icon); + Assert.AreEqual(contentType.Id, result.Id); + Assert.AreEqual(contentType.Name, result.Name); + Assert.AreEqual(contentType.ParentId, result.ParentId); + Assert.AreEqual(contentType.Path, result.Path); + Assert.AreEqual(contentType.Thumbnail, result.Thumbnail); + Assert.AreEqual(contentType.IsContainer, result.IsContainer); + Assert.AreEqual(contentType.CreateDate, result.CreateDate); + Assert.AreEqual(contentType.UpdateDate, result.UpdateDate); + Assert.AreEqual(contentType.DefaultTemplate.Alias, result.DefaultTemplate.Alias); + + //TODO: Now we need to assert all of the more complicated parts + + Assert.AreEqual(contentType.CompositionPropertyGroups.Select(x => x.Name).Distinct().Count(), result.Groups.Count(x => x.Id != -666)); + Assert.AreEqual(1, result.Groups.Count(x => x.Id == -666)); + Assert.AreEqual(contentType.PropertyGroups.Count(), result.Groups.Count(x => x.Inherited == false && x.Id != -666)); + + var allPropertiesMapped = result.Groups.SelectMany(x => x.Properties).ToArray(); + var allPropertyIdsMapped = allPropertiesMapped.Select(x => x.Id).ToArray(); + var allSourcePropertyIds = contentType.CompositionPropertyTypes.Select(x => x.Id).ToArray(); + + Assert.AreEqual(contentType.PropertyTypes.Count(), allPropertiesMapped.Count(x => x.Inherited == false)); + Assert.AreEqual(allPropertyIdsMapped.Count(), allSourcePropertyIds.Count()); + Assert.IsTrue(allPropertyIdsMapped.ContainsAll(allSourcePropertyIds)); + + Assert.AreEqual(1, result.Groups.Count(x => x.ParentTabContentTypes.Any())); + Assert.IsTrue(result.Groups.SelectMany(x => x.ParentTabContentTypes).ContainsAll(new[] {ctMain.Id, ctChild1.Id})); + + Assert.AreEqual(contentType.AllowedTemplates.Count(), result.AllowedTemplates.Count()); + for (var i = 0; i < contentType.AllowedTemplates.Count(); i++) + { + Assert.AreEqual(contentType.AllowedTemplates.ElementAt(i).Id, result.AllowedTemplates.ElementAt(i).Id); + } + + Assert.AreEqual(contentType.AllowedContentTypes.Count(), result.AllowedContentTypes.Count()); + for (var i = 0; i < contentType.AllowedContentTypes.Count(); i++) + { + Assert.AreEqual(contentType.AllowedContentTypes.ElementAt(i).Id.Value, result.AllowedContentTypes.ElementAt(i)); + } + + } + + private ContentTypeDisplay CreateSimpleContentTypeDisplay() { return new ContentTypeDisplay diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index 356abe65b2..0eeb79af4e 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; @@ -181,11 +182,24 @@ namespace Umbraco.Tests.TestHelpers.Entities contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("bodyText", randomizeAliases), Name = "Body Text", Description = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("author", randomizeAliases) , Name = "Author", Description = "Name of the author", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 }); - contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = propertyGroupName, SortOrder = 1 }); + var pg = new PropertyGroup(contentCollection) {Name = propertyGroupName, SortOrder = 1}; + contentType.PropertyGroups.Add(pg); + + if (parent != null) + { + var foundPg = parent.PropertyGroups.FirstOrDefault(x => x.Name == propertyGroupName); + if (foundPg != null) + { + //this exists on the parent, so set the parent id + pg.ParentId = foundPg.Id; + } + } //ensure that nothing is marked as dirty contentType.ResetDirtyProperties(false); + contentType.SetDefaultTemplate(new Template("Textpage", "textpage")); + return contentType; } @@ -399,6 +413,21 @@ namespace Umbraco.Tests.TestHelpers.Entities return contentType; } + public static void EnsureAllIds(ContentType contentType, int seedId) + { + //ensure everything has ids + contentType.Id = seedId; + var itemid = seedId + 1; + foreach (var propertyGroup in contentType.PropertyGroups) + { + propertyGroup.Id = itemid++; + } + foreach (var propertyType in contentType.PropertyTypes) + { + propertyType.Id = itemid++; + } + } + private static string RandomAlias(string alias, bool randomizeAliases) { if (randomizeAliases) diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs index 04fbd7f697..529327d694 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs @@ -126,6 +126,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() .ForMember(display => display.AllowAsRoot, expression => expression.MapFrom(type => type.AllowedAsRoot)) + .ForMember(display => display.ListViewEditorName, expression => expression.Ignore()) //Ignore because this is not actually used for content types .ForMember(display => display.Trashed, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs index 1530787d7e..97f08bc695 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs @@ -34,20 +34,28 @@ namespace Umbraco.Web.Models.Mapping Constants.System.DefaultMembersListViewDataTypeId }; - config.CreateMap(); + config.CreateMap() + .ForMember(x => x.IsSystemDataType, expression => expression.Ignore()) + .ForMember(x => x.Id, expression => expression.Ignore()) + .ForMember(x => x.Trashed, expression => expression.Ignore()) + .ForMember(x => x.Key, expression => expression.Ignore()) + .ForMember(x => x.ParentId, expression => expression.Ignore()) + .ForMember(x => x.Path, expression => expression.Ignore()) + .ForMember(x => x.AdditionalData, expression => expression.Ignore()); config.CreateMap() .ForMember(x => x.Icon, expression => expression.Ignore()) .ForMember(x => x.Alias, expression => expression.Ignore()) + .ForMember(x => x.Group, expression => expression.Ignore()) .ForMember(x => x.IsSystemDataType, expression => expression.MapFrom(definition => systemIds.Contains(definition.Id))) - .AfterMap( (def,basic) => + .AfterMap((def, basic) => { var editor = PropertyEditorResolver.Current.GetByAlias(def.PropertyEditorAlias); - if(editor != null){ + if (editor != null) + { basic.Group = editor.Group; basic.Icon = editor.Icon; } - }); config.CreateMap() @@ -59,7 +67,17 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.Notifications, expression => expression.Ignore()) .ForMember(x => x.Icon, expression => expression.Ignore()) .ForMember(x => x.Alias, expression => expression.Ignore()) - .ForMember(x => x.IsSystemDataType, expression => expression.MapFrom(definition => systemIds.Contains(definition.Id))); + .ForMember(x => x.Group, expression => expression.Ignore()) + .ForMember(x => x.IsSystemDataType, expression => expression.MapFrom(definition => systemIds.Contains(definition.Id))) + .AfterMap((def, basic) => + { + var editor = PropertyEditorResolver.Current.GetByAlias(def.PropertyEditorAlias); + if (editor != null) + { + basic.Group = editor.Group; + basic.Icon = editor.Icon; + } + }); //gets a list of PreValueFieldDisplay objects from the data type definition config.CreateMap>() diff --git a/src/Umbraco.Web/Models/Mapping/MemberTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberTypeModelMapper.cs index 54d726b8e5..b03b7a6ebd 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTypeModelMapper.cs @@ -46,6 +46,8 @@ namespace Umbraco.Web.Models.Mapping //only map id if set to something higher then zero .ForMember(dto => dto.Id, expression => expression.Condition(display => (Convert.ToInt32(display.Id) > 0))) .ForMember(dto => dto.Id, expression => expression.MapFrom(display => Convert.ToInt32(display.Id))) + .ForMember(dto => dto.AllowedAsRoot, expression => expression.Ignore()) + .ForMember(dto => dto.IsContainer, expression => expression.Ignore()) .ForMember(dto => dto.CreatorId, expression => expression.Ignore()) .ForMember(dto => dto.Level, expression => expression.Ignore()) .ForMember(dto => dto.SortOrder, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs index c34a1acc1f..ce3b9b082f 100644 --- a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs @@ -1,180 +1,190 @@ -using AutoMapper; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Models.Mapping -{ - - - internal class PropertyTypeGroupResolver : ValueResolver> - { - private readonly ApplicationContext _applicationContext; - private readonly Lazy _propertyEditorResolver; - - public PropertyTypeGroupResolver(ApplicationContext applicationContext, Lazy propertyEditorResolver) - { - _applicationContext = applicationContext; - _propertyEditorResolver = propertyEditorResolver; - } - - - protected override IEnumerable ResolveCore(IContentTypeComposition source) - { - var groups = new Dictionary(); - - //for storing generic properties - var genericProperties = new List(); - - - //iterate through all composite types - foreach (var ct in source.ContentTypeComposition) - { - //process each tab - foreach(var tab in ct.CompositionPropertyGroups){ - var group = new PropertyGroupDisplay() { Id = tab.Id, Inherited = true, Name = tab.Name, SortOrder = tab.SortOrder }; - group.ContentTypeId = ct.Id; - group.ParentTabContentTypes = new[] { ct.Id }; - group.ParentTabContentTypeNames = new[] { ct.Name }; - - if (tab.ParentId.HasValue) - group.ParentGroupId = tab.ParentId.Value; - - group.Properties = MapProperties(tab.PropertyTypes, ct, tab.Id, true); - groups.Add(tab.Id, group); - } - - //process inherited generic properties - var inheritedGenProperties = ct.CompositionPropertyTypes.Where(x => x.PropertyGroupId == null); - if (inheritedGenProperties.Any()) - genericProperties.AddRange(MapProperties(inheritedGenProperties, ct, 0, true)); - } - - - - //pull from own groups - foreach (var ownTab in source.CompositionPropertyGroups) - { - PropertyGroupDisplay group; - - //if already added - if (groups.ContainsKey(ownTab.Id)) - group = groups[ownTab.Id]; - - //if parent - else if (ownTab.ParentId.HasValue && groups.ContainsKey(ownTab.ParentId.Value)) - group = groups[ownTab.ParentId.Value]; - - else - { - //if own - group = new PropertyGroupDisplay() { Id = ownTab.Id, Inherited = false, Name = ownTab.Name, SortOrder = ownTab.SortOrder, ContentTypeId = source.Id }; - groups.Add(ownTab.Id, group); - } - - //merge the properties - var mergedProperties = new List(); - mergedProperties.AddRange(group.Properties); - - var newproperties = MapProperties( ownTab.PropertyTypes , source, ownTab.Id, false).Where(x => mergedProperties.Any( y => y.Id == x.Id ) == false); - mergedProperties.AddRange(newproperties); - - group.Properties = mergedProperties.OrderBy(x => x.SortOrder); - } - - - //get all generic properties not already mapped to the generic props collection - var ownGenericProperties = source.CompositionPropertyTypes.Where(x => x.PropertyGroupId == null && !genericProperties.Any(y => y.Id == x.Id)); - genericProperties.AddRange(MapProperties(ownGenericProperties, source, 0, false)); - - if (genericProperties.Any()) - { - var genericTab = new PropertyGroupDisplay() { Id = -666, Name = "Generic properties", ParentGroupId = 0, ContentTypeId = source.Id, SortOrder = 999, Inherited = false }; - genericTab.Properties = genericProperties; - groups.Add(0, genericTab); - } - - - //merge tabs based on names (magic and insanity) - var nameGroupedGroups = groups.Values.GroupBy(x => x.Name); - if (nameGroupedGroups.Any(x => x.Count() > 1)) - { - var sortedGroups = new List(); - - foreach (var groupOfGroups in nameGroupedGroups) - { - //single name groups - if(groupOfGroups.Count() == 1) - sortedGroups.Add(groupOfGroups.First()); - else{ - //multiple name groups - - //find the mother tab - if we have our own use it. otherwise pick a random inherited one - since it wont matter - var mainTab = groupOfGroups.FirstOrDefault(x => x.Inherited == false); - if (mainTab == null) - mainTab = groupOfGroups.First(); - - - //take all properties from all the other tabs and merge into one tab - var properties = new List(); +using AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Models.Mapping +{ + + + internal class PropertyTypeGroupResolver : ValueResolver> + { + private readonly ApplicationContext _applicationContext; + private readonly Lazy _propertyEditorResolver; + + public PropertyTypeGroupResolver(ApplicationContext applicationContext, Lazy propertyEditorResolver) + { + _applicationContext = applicationContext; + _propertyEditorResolver = propertyEditorResolver; + } + + /// + /// Will recursively check all compositions (of compositions) to find the content type that contains the + /// tabId being searched for. + /// + /// + /// + /// + private IContentTypeComposition GetContentTypeFromTabId(IContentTypeComposition ct, int tabId) + { + if (ct.PropertyGroups.Any(x => x.Id == tabId)) return ct; + + foreach (var composition in ct.ContentTypeComposition) + { + var found = GetContentTypeFromTabId(composition, tabId); + if (found != null) return found; + } + + return null; + } + + protected override IEnumerable ResolveCore(IContentTypeComposition source) + { + var groups = new Dictionary(); + + //for storing generic properties + var genericProperties = new List(); + + //add groups directly assigned to this content type + foreach (var tab in source.PropertyGroups) + { + var group = new PropertyGroupDisplay() + { + Id = tab.Id, Inherited = false, Name = tab.Name, SortOrder = tab.SortOrder, ContentTypeId = source.Id + }; + group.Properties = MapProperties(tab.PropertyTypes, source, tab.Id, false); + groups.Add(tab.Id, group); + } + + //add groups not assigned to this content type (via compositions) + foreach (var tab in source.CompositionPropertyGroups) + { + if (groups.ContainsKey(tab.Id)) continue; + + var composition = GetContentTypeFromTabId(source, tab.Id); + if (composition == null) + throw new InvalidOperationException("The tabId " + tab.Id + " was not found on any of the content type's compositions"); + + var group = new PropertyGroupDisplay() + { + Id = tab.Id, Inherited = false, Name = tab.Name, SortOrder = tab.SortOrder, ContentTypeId = composition.Id, + ParentTabContentTypes = new[] {composition.Id}, + ParentTabContentTypeNames = new[] {composition.Name} + }; + + if (tab.ParentId.HasValue) + group.ParentGroupId = tab.ParentId.Value; + + group.Properties = MapProperties(tab.PropertyTypes, composition, tab.Id, true); + groups.Add(tab.Id, group); + } + + //process generic properties assigned to this content item (without a group) + + //NOTE: -666 is just a thing that is checked for on the front-end... I'm not a fan of this for the mapping + // since this is just for front-end, this could probably be updated to be -666 in the controller which is associated + // with giving the front-end it's data + + var entityGenericProperties = source.PropertyTypes.Where(x => x.PropertyGroupId == null); + genericProperties.AddRange(MapProperties(entityGenericProperties, source, -666, false)); + + //process generic properties from compositions (ensures properties are flagged as inherited) + var currentGenericPropertyIds = genericProperties.Select(x => x.Id).ToArray(); + var compositionGenericProperties = source.CompositionPropertyTypes + .Where(x => x.PropertyGroupId == null && currentGenericPropertyIds.Contains(x.Id) == false); + genericProperties.AddRange(MapProperties(compositionGenericProperties, source, -666, true)); + + //now add the group if there are any generic props + if (genericProperties.Any()) + { + var genericTab = new PropertyGroupDisplay + { + Id = -666, Name = "Generic properties", ParentGroupId = 0, ContentTypeId = source.Id, SortOrder = 999, Inherited = false, Properties = genericProperties + }; + groups.Add(0, genericTab); + } + + + //merge tabs based on names (magic and insanity) + var nameGroupedGroups = groups.Values.GroupBy(x => x.Name).ToArray(); + if (nameGroupedGroups.Any(x => x.Count() > 1)) + { + var sortedGroups = new List(); + + foreach (var groupOfGroups in nameGroupedGroups) + { + //single name groups + if (groupOfGroups.Count() == 1) + { + sortedGroups.Add(groupOfGroups.First()); + } + else + { + //multiple name groups + + //find the mother tab - if we have our own use it. otherwise pick a random inherited one - since it wont matter + var mainTab = groupOfGroups.FirstOrDefault(x => x.Inherited == false) ?? groupOfGroups.First(); + + //take all properties from all the other tabs and merge into one tab + var properties = new List(); properties.AddRange(groupOfGroups.Where(x => x.Id != mainTab.Id).SelectMany(x => x.Properties)); - properties.AddRange(mainTab.Properties); - mainTab.Properties = properties; - - //lock the tab - mainTab.Inherited = true; - + properties.AddRange(mainTab.Properties); + mainTab.Properties = properties; + + //lock the tab + mainTab.Inherited = true; + //collect all the involved content types var parents = groupOfGroups.Where(x => x.ContentTypeId != source.Id).ToList(); - mainTab.ParentTabContentTypes = parents.Select(x => x.ContentTypeId); - mainTab.ParentTabContentTypeNames = parents.SelectMany(x => x.ParentTabContentTypeNames); - sortedGroups.Add(mainTab); - } - } - - return sortedGroups.OrderBy(x => x.SortOrder); - } - - - return groups.Values.OrderBy(x => x.SortOrder); - } - - private IEnumerable MapProperties(IEnumerable properties, IContentTypeBase contentType, int groupId, bool inherited) - { - var mappedProperties = new List(); - foreach (var p in properties.Where(x => x.DataTypeDefinitionId != 0) ) - { - var editor = _propertyEditorResolver.Value.GetByAlias(p.PropertyEditorAlias); - var preVals = _applicationContext.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(p.DataTypeDefinitionId); - - mappedProperties.Add( - new PropertyTypeDisplay() - { - Id = p.Id, - Alias = p.Alias, - Description = p.Description, - Editor = p.PropertyEditorAlias, - Validation = new PropertyTypeValidation() { Mandatory = p.Mandatory, Pattern = p.ValidationRegExp }, - Label = p.Name, - View = editor.ValueEditor.View, - Config = editor.PreValueEditor.ConvertDbToEditor(editor.DefaultPreValues, preVals) , - Value = "", - ContentTypeId = contentType.Id, - ContentTypeName = contentType.Name, - GroupId = groupId, - Inherited = inherited, - DataTypeId = p.DataTypeDefinitionId, - SortOrder = p.SortOrder - }); - } - - return mappedProperties; - } - } -} + mainTab.ParentTabContentTypes = parents.SelectMany(x => x.ParentTabContentTypes).ToArray(); + mainTab.ParentTabContentTypeNames = parents.SelectMany(x => x.ParentTabContentTypeNames).ToArray(); + sortedGroups.Add(mainTab); + } + } + + return sortedGroups.OrderBy(x => x.SortOrder); + } + + + return groups.Values.OrderBy(x => x.SortOrder); + } + + private IEnumerable MapProperties(IEnumerable properties, IContentTypeBase contentType, int groupId, bool inherited) + { + var mappedProperties = new List(); + foreach (var p in properties.Where(x => x.DataTypeDefinitionId != 0) ) + { + var editor = _propertyEditorResolver.Value.GetByAlias(p.PropertyEditorAlias); + var preVals = _applicationContext.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(p.DataTypeDefinitionId); + + mappedProperties.Add( + new PropertyTypeDisplay() + { + Id = p.Id, + Alias = p.Alias, + Description = p.Description, + Editor = p.PropertyEditorAlias, + Validation = new PropertyTypeValidation() { Mandatory = p.Mandatory, Pattern = p.ValidationRegExp }, + Label = p.Name, + View = editor.ValueEditor.View, + Config = editor.PreValueEditor.ConvertDbToEditor(editor.DefaultPreValues, preVals) , + Value = "", + ContentTypeId = contentType.Id, + ContentTypeName = contentType.Name, + GroupId = groupId, + Inherited = inherited, + DataTypeId = p.DataTypeDefinitionId, + SortOrder = p.SortOrder + }); + } + + return mappedProperties; + } + } +}