Merge branch 'dev-v7' into temp-U4-7716

Conflicts:
	src/Umbraco.Web/Editors/ContentTypeControllerBase.cs
This commit is contained in:
Shannon
2016-01-25 15:54:50 +01:00
82 changed files with 2209 additions and 649 deletions

View File

@@ -10,32 +10,26 @@ using Umbraco.Core.Models.Validation;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentType", Namespace = "")]
public class ContentTypeCompositionDisplay : ContentTypeBasic, INotificationModel
{
public ContentTypeCompositionDisplay()
public abstract class ContentTypeCompositionDisplay : ContentTypeBasic, INotificationModel
{
protected ContentTypeCompositionDisplay()
{
//initialize collections so at least their never null
Groups = new List<PropertyGroupDisplay>();
AllowedContentTypes = new List<int>();
CompositeContentTypes = new List<string>();
Notifications = new List<Notification>();
}
//name, alias, icon, thumb, desc, inherited from basic
}
//name, alias, icon, thumb, desc, inherited from basic
//List view
[DataMember(Name = "isContainer")]
public bool IsContainer { get; set; }
[DataMember(Name = "listViewEditorName")]
[ReadOnly(true)]
public string ListViewEditorName { get; set; }
public string ListViewEditorName { get; set; }
//Tabs
[DataMember(Name = "groups")]
public IEnumerable<PropertyGroupDisplay> Groups { get; set; }
//Allowed child types
[DataMember(Name = "allowedContentTypes")]
public IEnumerable<int> AllowedContentTypes { get; set; }
@@ -43,7 +37,7 @@ namespace Umbraco.Web.Models.ContentEditing
//Compositions
[DataMember(Name = "compositeContentTypes")]
public IEnumerable<string> CompositeContentTypes { get; set; }
//Locked compositions
[DataMember(Name = "lockedCompositeContentTypes")]
public IEnumerable<string> LockedCompositeContentTypes { get; set; }
@@ -72,4 +66,20 @@ namespace Umbraco.Web.Models.ContentEditing
[ReadOnly(true)]
public IDictionary<string, object> Errors { get; set; }
}
[DataContract(Name = "contentType", Namespace = "")]
public abstract class ContentTypeCompositionDisplay<TPropertyTypeDisplay> : ContentTypeCompositionDisplay
where TPropertyTypeDisplay : PropertyTypeDisplay
{
protected ContentTypeCompositionDisplay()
{
//initialize collections so at least their never null
Groups = new List<PropertyGroupDisplay<TPropertyTypeDisplay>>();
}
//Tabs
[DataMember(Name = "groups")]
public IEnumerable<PropertyGroupDisplay<TPropertyTypeDisplay>> Groups { get; set; }
}
}

View File

@@ -6,13 +6,14 @@ using Umbraco.Core;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Abstract model used to save content types
/// </summary>
[DataContract(Name = "contentType", Namespace = "")]
public class ContentTypeSave : ContentTypeBasic, IValidatableObject
public abstract class ContentTypeSave : ContentTypeBasic, IValidatableObject
{
public ContentTypeSave()
protected ContentTypeSave()
{
//initialize collections so at least their never null
Groups = new List<PropertyGroupBasic<PropertyTypeBasic>>();
AllowedContentTypes = new List<int>();
CompositeContentTypes = new List<string>();
}
@@ -27,38 +28,50 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "allowAsRoot")]
public bool AllowAsRoot { get; set; }
/// <summary>
/// The list of allowed templates to assign (template alias)
/// </summary>
[DataMember(Name = "allowedTemplates")]
public IEnumerable<string> AllowedTemplates { get; set; }
//Allowed child types
[DataMember(Name = "allowedContentTypes")]
public IEnumerable<int> AllowedContentTypes { get; set; }
/// <summary>
/// The default template to assign (template alias)
/// </summary>
[DataMember(Name = "defaultTemplate")]
public string DefaultTemplate { get; set; }
//Tabs
[DataMember(Name = "groups")]
public IEnumerable<PropertyGroupBasic<PropertyTypeBasic>> Groups { get; set; }
/// <summary>
/// Custom validation
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (AllowedTemplates.Any(x => x.IsNullOrWhiteSpace()))
yield return new ValidationResult("Template value cannot be null", new[] {"AllowedTemplates"});
if (CompositeContentTypes.Any(x => x.IsNullOrWhiteSpace()))
yield return new ValidationResult("Composite Content Type value cannot be null", new[] { "CompositeContentTypes" });
yield return new ValidationResult("Composite Content Type value cannot be null", new[] {"CompositeContentTypes"});
}
}
/// <summary>
/// Abstract model used to save content types
/// </summary>
/// <typeparam name="TPropertyType"></typeparam>
[DataContract(Name = "contentType", Namespace = "")]
public abstract class ContentTypeSave<TPropertyType> : ContentTypeSave
where TPropertyType : PropertyTypeBasic
{
protected ContentTypeSave()
{
Groups = new List<PropertyGroupBasic<TPropertyType>>();
}
//Tabs
[DataMember(Name = "groups")]
public IEnumerable<PropertyGroupBasic<TPropertyType>> Groups { get; set; }
/// <summary>
/// Custom validation
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
foreach (var validationResult in base.Validate(validationContext))
{
yield return validationResult;
}
var duplicateGroups = Groups.GroupBy(x => x.Name).Where(x => x.Count() > 1).ToArray();
if (duplicateGroups.Any())
@@ -70,7 +83,7 @@ namespace Umbraco.Web.Models.ContentEditing
string.Format("Groups[{0}].Name", lastIndex)
});
}
var duplicateProperties = Groups.SelectMany(x => x.Properties).Where(x => x.Inherited == false).GroupBy(x => x.Alias).Where(x => x.Count() > 1).ToArray();
if (duplicateProperties.Any())
{
@@ -83,7 +96,7 @@ namespace Umbraco.Web.Models.ContentEditing
string.Format("Groups[{0}].Properties[{1}].Alias", propertyGroup.SortOrder, lastProperty.SortOrder)
});
}
}
}
}

View File

@@ -1,26 +1,25 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentType", Namespace = "")]
public class ContentTypeDisplay : ContentTypeCompositionDisplay
{
public ContentTypeDisplay()
{
//initialize collections so at least their never null
AllowedTemplates = new List<EntityBasic>();
}
//name, alias, icon, thumb, desc, inherited from the content type
// Templates
[DataMember(Name = "allowedTemplates")]
public IEnumerable<EntityBasic> AllowedTemplates { get; set; }
[DataMember(Name = "defaultTemplate")]
public EntityBasic DefaultTemplate { get; set; }
}
}
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentType", Namespace = "")]
public class DocumentTypeDisplay : ContentTypeCompositionDisplay<PropertyTypeDisplay>
{
public DocumentTypeDisplay()
{
//initialize collections so at least their never null
AllowedTemplates = new List<EntityBasic>();
}
//name, alias, icon, thumb, desc, inherited from the content type
// Templates
[DataMember(Name = "allowedTemplates")]
public IEnumerable<EntityBasic> AllowedTemplates { get; set; }
[DataMember(Name = "defaultTemplate")]
public EntityBasic DefaultTemplate { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Model used to save a document type
/// </summary>
[DataContract(Name = "contentType", Namespace = "")]
public class DocumentTypeSave : ContentTypeSave<PropertyTypeBasic>
{
/// <summary>
/// The list of allowed templates to assign (template alias)
/// </summary>
[DataMember(Name = "allowedTemplates")]
public IEnumerable<string> AllowedTemplates { get; set; }
/// <summary>
/// The default template to assign (template alias)
/// </summary>
[DataMember(Name = "defaultTemplate")]
public string DefaultTemplate { get; set; }
/// <summary>
/// Custom validation
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (AllowedTemplates.Any(x => StringExtensions.IsNullOrWhiteSpace(x)))
yield return new ValidationResult("Template value cannot be null", new[] { "AllowedTemplates" });
foreach (var v in base.Validate(validationContext))
{
yield return v;
}
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentType", Namespace = "")]
public class MediaTypeDisplay : ContentTypeCompositionDisplay<PropertyTypeDisplay>
{
}
}

View File

@@ -0,0 +1,12 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Model used to save a media type
/// </summary>
[DataContract(Name = "contentType", Namespace = "")]
public class MediaTypeSave : ContentTypeSave<PropertyTypeBasic>
{
}
}

View File

@@ -0,0 +1,17 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Basic member property type
/// </summary>
[DataContract(Name = "contentType", Namespace = "")]
public class MemberPropertyTypeBasic : PropertyTypeBasic
{
[DataMember(Name = "showOnMemberProfile")]
public bool MemberCanViewProperty { get; set; }
[DataMember(Name = "memberCanEdit")]
public bool MemberCanEditProperty { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "propertyType")]
public class MemberPropertyTypeDisplay : PropertyTypeDisplay
{
[DataMember(Name = "showOnMemberProfile")]
public bool MemberCanViewProperty { get; set; }
[DataMember(Name = "memberCanEdit")]
public bool MemberCanEditProperty { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentType", Namespace = "")]
public class MemberTypeDisplay : ContentTypeCompositionDisplay<MemberPropertyTypeDisplay>
{
}
}

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Model used to save a member type
/// </summary>
public class MemberTypeSave : ContentTypeSave<MemberPropertyTypeBasic>
{
}
}

View File

@@ -5,14 +5,8 @@ using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "propertyGroup", Namespace = "")]
public class PropertyGroupBasic<TPropertyType>
where TPropertyType: PropertyTypeBasic
public abstract class PropertyGroupBasic
{
public PropertyGroupBasic()
{
Properties = new List<TPropertyType>();
}
/// <summary>
/// Gets the special generic properties tab identifier.
/// </summary>
@@ -38,9 +32,6 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "id")]
public int Id { get; set; }
[DataMember(Name = "properties")]
public IEnumerable<TPropertyType> Properties { get; set; }
[DataMember(Name = "sortOrder")]
public int SortOrder { get; set; }
@@ -48,4 +39,21 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "name")]
public string Name { get; set; }
}
[DataContract(Name = "propertyGroup", Namespace = "")]
public class PropertyGroupBasic<TPropertyType> : PropertyGroupBasic
where TPropertyType: PropertyTypeBasic
{
public PropertyGroupBasic()
{
Properties = new List<TPropertyType>();
}
[DataMember(Name = "properties")]
public IEnumerable<TPropertyType> Properties { get; set; }
}
}

View File

@@ -5,11 +5,12 @@ using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "propertyGroup", Namespace = "")]
public class PropertyGroupDisplay : PropertyGroupBasic<PropertyTypeDisplay>
public class PropertyGroupDisplay<TPropertyTypeDisplay> : PropertyGroupBasic<TPropertyTypeDisplay>
where TPropertyTypeDisplay : PropertyTypeDisplay
{
public PropertyGroupDisplay()
{
Properties = new List<PropertyTypeDisplay>();
Properties = new List<TPropertyTypeDisplay>();
ParentTabContentTypeNames = new List<string>();
ParentTabContentTypes = new List<int>();
}

View File

@@ -27,15 +27,5 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "locked")]
[ReadOnly(true)]
public bool Locked { get; set; }
//SD: Seems strange that this is needed
[DataMember(Name = "contentTypeId")]
[ReadOnly(true)]
public int ContentTypeId { get; set; }
//SD: Seems strange that this is needed
[DataMember(Name = "contentTypeName")]
[ReadOnly(true)]
public string ContentTypeName { get; set; }
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core.Models;

View File

@@ -50,9 +50,9 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(type => type.UpdateDate, expression => expression.Ignore())
.ForMember(type => type.HasIdentity, expression => expression.Ignore());
config.CreateMap<ContentTypeSave, IContentType>()
config.CreateMap<DocumentTypeSave, IContentType>()
//do the base mapping
.MapBaseContentTypeSaveToEntity(applicationContext)
.MapBaseContentTypeSaveToEntity<DocumentTypeSave, PropertyTypeBasic, IContentType>(applicationContext)
.ConstructUsing((source) => new ContentType(source.ParentId))
.ForMember(source => source.AllowedTemplates, expression => expression.Ignore())
.ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore())
@@ -69,33 +69,59 @@ namespace Umbraco.Web.Models.Mapping
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
});
config.CreateMap<ContentTypeSave, IMediaType>()
config.CreateMap<MediaTypeSave, IMediaType>()
//do the base mapping
.MapBaseContentTypeSaveToEntity(applicationContext)
.MapBaseContentTypeSaveToEntity<MediaTypeSave, PropertyTypeBasic, IMediaType>(applicationContext)
.ConstructUsing((source) => new MediaType(source.ParentId))
.AfterMap((source, dest) =>
{
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
});
config.CreateMap<ContentTypeSave, IMemberType>()
config.CreateMap<MemberTypeSave, IMemberType>()
//do the base mapping
.MapBaseContentTypeSaveToEntity(applicationContext)
.MapBaseContentTypeSaveToEntity<MemberTypeSave, MemberPropertyTypeBasic, IMemberType>(applicationContext)
.ConstructUsing((source) => new MemberType(source.ParentId))
.AfterMap((source, dest) =>
{
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
//map the MemberCanEditProperty,MemberCanViewProperty
foreach (var propertyType in source.Groups.SelectMany(x => x.Properties))
{
var localCopy = propertyType;
var destProp = dest.PropertyTypes.SingleOrDefault(x => x.Alias.InvariantEquals(localCopy.Alias));
if (destProp != null)
{
dest.SetMemberCanEditProperty(localCopy.Alias, localCopy.MemberCanEditProperty);
dest.SetMemberCanViewProperty(localCopy.Alias, localCopy.MemberCanViewProperty);
}
}
});
config.CreateMap<IContentTypeComposition, string>().ConvertUsing(x => x.Alias);
config.CreateMap<IMemberType, ContentTypeCompositionDisplay>()
config.CreateMap<IMemberType, MemberTypeDisplay>()
//map base logic
.MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver);
.MapBaseContentTypeEntityToDisplay<IMemberType, MemberTypeDisplay, MemberPropertyTypeDisplay>(applicationContext, _propertyEditorResolver)
.AfterMap((memberType, display) =>
{
//map the MemberCanEditProperty,MemberCanViewProperty
foreach (var propertyType in memberType.PropertyTypes)
{
var localCopy = propertyType;
var displayProp = display.Groups.SelectMany(x => x.Properties).SingleOrDefault(x => x.Alias.InvariantEquals(localCopy.Alias));
if (displayProp != null)
{
displayProp.MemberCanEditProperty = memberType.MemberCanEditProperty(localCopy.Alias);
displayProp.MemberCanViewProperty = memberType.MemberCanViewProperty(localCopy.Alias);
}
}
});
config.CreateMap<IMediaType, ContentTypeCompositionDisplay>()
config.CreateMap<IMediaType, MediaTypeDisplay>()
//map base logic
.MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver)
.MapBaseContentTypeEntityToDisplay<IMediaType, MediaTypeDisplay, PropertyTypeDisplay>(applicationContext, _propertyEditorResolver)
.AfterMap((source, dest) =>
{
//default listview
@@ -109,9 +135,9 @@ namespace Umbraco.Web.Models.Mapping
}
});
config.CreateMap<IContentType, ContentTypeDisplay>()
config.CreateMap<IContentType, DocumentTypeDisplay>()
//map base logic
.MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver)
.MapBaseContentTypeEntityToDisplay<IContentType, DocumentTypeDisplay, PropertyTypeDisplay>(applicationContext, _propertyEditorResolver)
.ForMember(dto => dto.AllowedTemplates, expression => expression.Ignore())
.ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore())
.ForMember(display => display.Notifications, expression => expression.Ignore())
@@ -141,7 +167,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap<PropertyTypeBasic, PropertyType>()
.ConstructUsing((PropertyTypeBasic propertyTypeBasic) =>
.ConstructUsing(propertyTypeBasic =>
{
var dataType = applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(propertyTypeBasic.DataTypeId);
if (dataType == null) throw new NullReferenceException("No data type found with id " + propertyTypeBasic.DataTypeId);
@@ -170,11 +196,14 @@ namespace Umbraco.Web.Models.Mapping
#region *** Used for mapping on top of an existing display object from a save object ***
config.CreateMap<ContentTypeSave, ContentTypeCompositionDisplay>()
.MapBaseContentTypeSaveToDisplay();
config.CreateMap<MemberTypeSave, MemberTypeDisplay>()
.MapBaseContentTypeSaveToDisplay<MemberTypeSave, MemberPropertyTypeBasic, MemberTypeDisplay, MemberPropertyTypeDisplay>();
config.CreateMap<MediaTypeSave, MediaTypeDisplay>()
.MapBaseContentTypeSaveToDisplay<MediaTypeSave, PropertyTypeBasic, MediaTypeDisplay, PropertyTypeDisplay>();
config.CreateMap<ContentTypeSave, ContentTypeDisplay>()
.MapBaseContentTypeSaveToDisplay()
config.CreateMap<DocumentTypeSave, DocumentTypeDisplay>()
.MapBaseContentTypeSaveToDisplay<DocumentTypeSave, PropertyTypeBasic, DocumentTypeDisplay, PropertyTypeDisplay>()
.ForMember(dto => dto.AllowedTemplates, expression => expression.Ignore())
.ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore())
.AfterMap((source, dest) =>
@@ -206,41 +235,39 @@ namespace Umbraco.Web.Models.Mapping
}
});
//for doc types, media types
config.CreateMap<PropertyGroupBasic<PropertyTypeBasic>, PropertyGroup>()
.ForMember(dest => dest.Id, map => map.Condition(source => source.Id > 0))
.ForMember(dest => dest.Key, map => map.Ignore())
.ForMember(dest => dest.HasIdentity, map => map.Ignore())
.ForMember(dest => dest.CreateDate, map => map.Ignore())
.ForMember(dest => dest.UpdateDate, map => map.Ignore())
// fixme
// this is basically *replacing* dest properties by a mapped version of
// *every* source properties (including, I guess, inherited properties?)
// also, ContentTypeModelMapperExtensions will map properties *again* so
// this makes little sense - ignore for now
.ForMember(dest => dest.PropertyTypes, map => map.Ignore());
//.ForMember(dest => dest.PropertyTypes, map => map.MapFrom(source =>
// source.Properties.Select(Mapper.Map<PropertyType>)));
.MapPropertyGroupBasicToPropertyGroupPersistence<PropertyGroupBasic<PropertyTypeBasic>, PropertyTypeBasic>();
config.CreateMap<PropertyGroupBasic<PropertyTypeBasic>, PropertyGroupDisplay>()
.ForMember(dest => dest.Id, expression => expression.Condition(source => source.Id > 0))
.ForMember(g => g.ContentTypeId, expression => expression.Ignore())
.ForMember(g => g.ParentTabContentTypes, expression => expression.Ignore())
.ForMember(g => g.ParentTabContentTypeNames, expression => expression.Ignore())
.ForMember(g => g.Properties, expression => expression.MapFrom(display => display.Properties.Select(Mapper.Map<PropertyTypeDisplay>)));
//for members
config.CreateMap<PropertyGroupBasic<MemberPropertyTypeBasic>, PropertyGroup>()
.MapPropertyGroupBasicToPropertyGroupPersistence<PropertyGroupBasic<MemberPropertyTypeBasic>, MemberPropertyTypeBasic>();
//for doc types, media types
config.CreateMap<PropertyGroupBasic<PropertyTypeBasic>, PropertyGroupDisplay<PropertyTypeDisplay>>()
.MapPropertyGroupBasicToPropertyGroupDisplay<PropertyGroupBasic<PropertyTypeBasic>, PropertyTypeBasic, PropertyTypeDisplay>();
//for members
config.CreateMap<PropertyGroupBasic<MemberPropertyTypeBasic>, PropertyGroupDisplay<MemberPropertyTypeDisplay>>()
.MapPropertyGroupBasicToPropertyGroupDisplay<PropertyGroupBasic<MemberPropertyTypeBasic>, MemberPropertyTypeBasic, MemberPropertyTypeDisplay>();
config.CreateMap<PropertyTypeBasic, PropertyTypeDisplay>()
.ForMember(g => g.Editor, expression => expression.Ignore())
.ForMember(g => g.View, expression => expression.Ignore())
.ForMember(g => g.Config, expression => expression.Ignore())
.ForMember(g => g.ContentTypeId, expression => expression.Ignore())
.ForMember(g => g.ContentTypeName, expression => expression.Ignore())
.ForMember(g => g.Locked, exp => exp.Ignore());
config.CreateMap<MemberPropertyTypeBasic, MemberPropertyTypeDisplay>()
.ForMember(g => g.Editor, expression => expression.Ignore())
.ForMember(g => g.View, expression => expression.Ignore())
.ForMember(g => g.Config, expression => expression.Ignore())
.ForMember(g => g.Locked, exp => exp.Ignore());
#endregion
}

View File

@@ -20,6 +20,34 @@ namespace Umbraco.Web.Models.Mapping
internal static class ContentTypeModelMapperExtensions
{
public static IMappingExpression<TSource, PropertyGroup> MapPropertyGroupBasicToPropertyGroupPersistence<TSource, TPropertyTypeBasic>(
this IMappingExpression<TSource, PropertyGroup> mapping)
where TSource : PropertyGroupBasic<TPropertyTypeBasic>
where TPropertyTypeBasic : PropertyTypeBasic
{
return mapping
.ForMember(dest => dest.Id, map => map.Condition(source => source.Id > 0))
.ForMember(dest => dest.Key, map => map.Ignore())
.ForMember(dest => dest.HasIdentity, map => map.Ignore())
.ForMember(dest => dest.CreateDate, map => map.Ignore())
.ForMember(dest => dest.UpdateDate, map => map.Ignore())
.ForMember(dest => dest.PropertyTypes, map => map.Ignore());
}
public static IMappingExpression<TSource, PropertyGroupDisplay<TPropertyTypeDisplay>> MapPropertyGroupBasicToPropertyGroupDisplay<TSource, TPropertyTypeBasic, TPropertyTypeDisplay>(
this IMappingExpression<TSource, PropertyGroupDisplay<TPropertyTypeDisplay>> mapping)
where TSource : PropertyGroupBasic<TPropertyTypeBasic>
where TPropertyTypeBasic : PropertyTypeBasic
where TPropertyTypeDisplay : PropertyTypeDisplay
{
return mapping
.ForMember(dest => dest.Id, expression => expression.Condition(source => source.Id > 0))
.ForMember(g => g.ContentTypeId, expression => expression.Ignore())
.ForMember(g => g.ParentTabContentTypes, expression => expression.Ignore())
.ForMember(g => g.ParentTabContentTypeNames, expression => expression.Ignore())
.ForMember(g => g.Properties, expression => expression.MapFrom(display => display.Properties.Select(Mapper.Map<TPropertyTypeDisplay>)));
}
public static void AfterMapContentTypeSaveToEntity<TSource, TDestination>(
TSource source, TDestination dest,
ApplicationContext applicationContext)
@@ -47,10 +75,12 @@ namespace Umbraco.Web.Models.Mapping
}
}
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeSaveToDisplay<TSource, TDestination>(
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeSaveToDisplay<TSource, TPropertyTypeSource, TDestination, TPropertyTypeDestination>(
this IMappingExpression<TSource, TDestination> mapping)
where TSource : ContentTypeSave
where TDestination : ContentTypeCompositionDisplay
where TSource : ContentTypeSave<TPropertyTypeSource>
where TDestination : ContentTypeCompositionDisplay<TPropertyTypeDestination>
where TPropertyTypeDestination : PropertyTypeDisplay
where TPropertyTypeSource : PropertyTypeBasic
{
return mapping
.ForMember(dto => dto.CreateDate, expression => expression.Ignore())
@@ -58,13 +88,15 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dto => dto.ListViewEditorName, expression => expression.Ignore())
.ForMember(dto => dto.Notifications, expression => expression.Ignore())
.ForMember(dto => dto.Errors, expression => expression.Ignore())
.ForMember(dto => dto.LockedCompositeContentTypes, exp => exp.Ignore());
.ForMember(dto => dto.LockedCompositeContentTypes, exp => exp.Ignore())
.ForMember(dto => dto.Groups, expression => expression.ResolveUsing(new PropertyGroupDisplayResolver<TSource, TPropertyTypeSource, TPropertyTypeDestination>()));
}
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeEntityToDisplay<TSource, TDestination>(
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeEntityToDisplay<TSource, TDestination, TPropertyTypeDisplay>(
this IMappingExpression<TSource, TDestination> mapping, ApplicationContext applicationContext, Lazy<PropertyEditorResolver> propertyEditorResolver)
where TSource : IContentTypeComposition
where TDestination : ContentTypeCompositionDisplay
where TDestination : ContentTypeCompositionDisplay<TPropertyTypeDisplay>
where TPropertyTypeDisplay : PropertyTypeDisplay, new()
{
return mapping
.ForMember(display => display.Notifications, expression => expression.Ignore())
@@ -88,7 +120,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(
dto => dto.Groups,
expression => expression.ResolveUsing(new PropertyTypeGroupResolver(applicationContext, propertyEditorResolver)));
expression => expression.ResolveUsing(new PropertyTypeGroupResolver<TPropertyTypeDisplay>(applicationContext, propertyEditorResolver)));
}
/// <summary>
@@ -96,14 +128,16 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TDestination"></typeparam>
/// <typeparam name="TSourcePropertyType"></typeparam>
/// <param name="mapping"></param>
/// <param name="applicationContext"></param>
/// <returns></returns>
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeSaveToEntity<TSource, TDestination>(
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeSaveToEntity<TSource, TSourcePropertyType, TDestination>(
this IMappingExpression<TSource, TDestination> mapping, ApplicationContext applicationContext)
//where TSource : ContentTypeCompositionDisplay
where TSource : ContentTypeSave
where TDestination : IContentTypeComposition
where TSource : ContentTypeSave<TSourcePropertyType>
where TDestination : IContentTypeComposition
where TSourcePropertyType : PropertyTypeBasic
{
return mapping
//only map id if set to something higher then zero
@@ -200,7 +234,8 @@ namespace Umbraco.Web.Models.Mapping
});
}
private static PropertyGroup MapSaveGroup(PropertyGroupBasic<PropertyTypeBasic> sourceGroup, IEnumerable<PropertyGroup> destOrigGroups)
private static PropertyGroup MapSaveGroup<TPropertyType>(PropertyGroupBasic<TPropertyType> sourceGroup, IEnumerable<PropertyGroup> destOrigGroups)
where TPropertyType: PropertyTypeBasic
{
PropertyGroup destGroup;
if (sourceGroup.Id > 0)

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class PropertyGroupDisplayResolver<TSource, TPropertyTypeSource, TPropertyTypeDestination> : ValueResolver<TSource, IEnumerable<PropertyGroupDisplay<TPropertyTypeDestination>>>
where TSource : ContentTypeSave<TPropertyTypeSource>
where TPropertyTypeDestination : PropertyTypeDisplay
where TPropertyTypeSource : PropertyTypeBasic
{
protected override IEnumerable<PropertyGroupDisplay<TPropertyTypeDestination>> ResolveCore(TSource source)
{
return source.Groups.Select(Mapper.Map<PropertyGroupDisplay<TPropertyTypeDestination>>);
}
}
}

View File

@@ -9,7 +9,8 @@ using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class PropertyTypeGroupResolver : ValueResolver<IContentTypeComposition, IEnumerable<PropertyGroupDisplay>>
internal class PropertyTypeGroupResolver<TPropertyType> : ValueResolver<IContentTypeComposition, IEnumerable<PropertyGroupDisplay<TPropertyType>>>
where TPropertyType : PropertyTypeDisplay, new()
{
private readonly ApplicationContext _applicationContext;
private readonly Lazy<PropertyEditorResolver> _propertyEditorResolver;
@@ -40,15 +41,15 @@ namespace Umbraco.Web.Models.Mapping
.FirstOrDefault(x => x != null);
}
protected override IEnumerable<PropertyGroupDisplay> ResolveCore(IContentTypeComposition source)
protected override IEnumerable<PropertyGroupDisplay<TPropertyType>> ResolveCore(IContentTypeComposition source)
{
// deal with groups
var groups = new List<PropertyGroupDisplay>();
var groups = new List<PropertyGroupDisplay<TPropertyType>>();
// add groups local to this content type
foreach (var tab in source.PropertyGroups)
{
var group = new PropertyGroupDisplay
var group = new PropertyGroupDisplay<TPropertyType>
{
Id = tab.Id,
Inherited = false,
@@ -57,7 +58,7 @@ namespace Umbraco.Web.Models.Mapping
ContentTypeId = source.Id
};
group.Properties = MapProperties(tab.PropertyTypes, source, tab.Id, false);
group.Properties = MapProperties(tab.PropertyTypes, tab.Id, false);
groups.Add(group);
}
@@ -73,7 +74,7 @@ namespace Umbraco.Web.Models.Mapping
if (definingContentType == null)
throw new Exception("PropertyGroup with id=" + tab.Id + " was not found on any of the content type's compositions.");
var group = new PropertyGroupDisplay
var group = new PropertyGroupDisplay<TPropertyType>
{
Id = tab.Id,
Inherited = true,
@@ -84,30 +85,30 @@ namespace Umbraco.Web.Models.Mapping
ParentTabContentTypeNames = new[] { definingContentType.Name }
};
group.Properties = MapProperties(tab.PropertyTypes, definingContentType, tab.Id, true);
group.Properties = MapProperties(tab.PropertyTypes, tab.Id, true);
groups.Add(group);
}
// deal with generic properties
var genericProperties = new List<PropertyTypeDisplay>();
var genericProperties = new List<TPropertyType>();
// add generic properties local to this content type
var entityGenericProperties = source.PropertyTypes.Where(x => x.PropertyGroupId == null);
genericProperties.AddRange(MapProperties(entityGenericProperties, source, PropertyGroupDisplay.GenericPropertiesGroupId, false));
genericProperties.AddRange(MapProperties(entityGenericProperties, PropertyGroupBasic.GenericPropertiesGroupId, false));
// add generic properties inherited through compositions
var localGenericPropertyIds = genericProperties.Select(x => x.Id).ToArray();
var compositionGenericProperties = source.CompositionPropertyTypes
.Where(x => x.PropertyGroupId == null // generic
&& localGenericPropertyIds.Contains(x.Id) == false); // skip those that are local
genericProperties.AddRange(MapProperties(compositionGenericProperties, source, PropertyGroupDisplay.GenericPropertiesGroupId, true));
genericProperties.AddRange(MapProperties(compositionGenericProperties, PropertyGroupBasic.GenericPropertiesGroupId, true));
// if there are any generic properties, add the corresponding tab
if (genericProperties.Any())
{
var genericTab = new PropertyGroupDisplay
var genericTab = new PropertyGroupDisplay<TPropertyType>
{
Id = PropertyGroupDisplay.GenericPropertiesGroupId,
Id = PropertyGroupBasic.GenericPropertiesGroupId,
Name = "Generic properties",
ContentTypeId = source.Id,
SortOrder = 999,
@@ -133,7 +134,7 @@ namespace Umbraco.Web.Models.Mapping
// now merge tabs based on names
// as for one name, we might have one local tab, plus some inherited tabs
var groupsGroupsByName = groups.GroupBy(x => x.Name).ToArray();
groups = new List<PropertyGroupDisplay>(); // start with a fresh list
groups = new List<PropertyGroupDisplay<TPropertyType>>(); // start with a fresh list
foreach (var groupsByName in groupsGroupsByName)
{
// single group, just use it
@@ -164,17 +165,20 @@ namespace Umbraco.Web.Models.Mapping
return groups.OrderBy(x => x.SortOrder);
}
private IEnumerable<PropertyTypeDisplay> MapProperties(IEnumerable<PropertyType> properties, IContentTypeBase contentType, int groupId, bool inherited)
private IEnumerable<TPropertyType> MapProperties(IEnumerable<PropertyType> properties, int groupId, bool inherited)
{
var mappedProperties = new List<PropertyTypeDisplay>();
var mappedProperties = new List<TPropertyType>();
foreach (var p in properties.Where(x => x.DataTypeDefinitionId != 0).OrderBy(x => x.SortOrder))
{
var propertyEditor = _propertyEditorResolver.Value.GetByAlias(p.PropertyEditorAlias);
var preValues = _applicationContext.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(p.DataTypeDefinitionId);
mappedProperties.Add(new PropertyTypeDisplay
{
if (propertyEditor == null)
throw new InvalidOperationException("No property editor could be resolved with the alias: " + p.PropertyEditorAlias + ", ensure all packages are installed correctly.");
mappedProperties.Add(new TPropertyType
{
Id = p.Id,
Alias = p.Alias,
Description = p.Description,
@@ -184,8 +188,6 @@ namespace Umbraco.Web.Models.Mapping
View = propertyEditor.ValueEditor.View,
Config = propertyEditor.PreValueEditor.ConvertDbToEditor(propertyEditor.DefaultPreValues, preValues) ,
//Value = "",
ContentTypeId = contentType.Id,
ContentTypeName = contentType.Name,
GroupId = groupId,
Inherited = inherited,
DataTypeId = p.DataTypeDefinitionId,