diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js index c151aeba13..93e7fefa2b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js @@ -3,7 +3,7 @@ * @name umbraco.resources.mediaTypeResource * @description Loads in data for media types **/ -function mediaTypeResource($q, $http, umbRequestHelper) { +function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { return { @@ -81,12 +81,10 @@ function mediaTypeResource($q, $http, umbRequestHelper) { save: function (contentType) { + var saveModel = umbDataFormatter.formatContentTypePostData(contentType); + return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "mediaTypeApiBaseUrl", - "PostSave" - ), contentType), + $http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostSave"), saveModel), 'Failed to save data for content type id ' + contentType.id); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 75b5c41527..21d41cffb3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -154,33 +154,12 @@ vm.contentType = contentTypeHelper.updateTemplatePlaceholder(vm.contentType); } - //contentTypeResource.save(vm.contentType).then(function(dt){ - - // formHelper.resetForm({ scope: $scope, notifications: dt.notifications }); - // contentEditingHelper.handleSuccessfulSave({ - // scope: $scope, - // savedContent: dt, - // rebindCallback: function() { - - // } - // }); - - // notificationsService.success("Document type save"); - // //post save logic here -the saved doctype returns as a new object - // init(dt); - - // syncTreeNode(vm.contentType, dt.path); - - // vm.page.saveButtonState = "success"; - - //}); - contentEditingHelper.contentEditorPerformSave({ statusMessage: "Saving...", saveMethod: contentTypeResource.save, scope: $scope, content: vm.contentType, - //no-op for rebind callback... we don't really need to rebind for content types + //no-op for rebind callback... we don't really need to rebind for content types rebindCallback: angular.noop }).then(function (data) { //success diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index c872c593d9..d7f3f4ee83 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -9,7 +9,7 @@ (function() { "use strict"; - function MediaTypesEditController($scope, $routeParams, mediaTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter) { + function MediaTypesEditController($scope, $routeParams, mediaTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter, $q) { var vm = this; @@ -125,49 +125,47 @@ function save() { - // validate form - if (formHelper.submitForm({ scope: $scope })) { + var deferred = $q.defer(); - formHelper.resetForm({ scope: $scope }); + vm.page.saveButtonState = "busy"; - // if form validates - perform save - performSave(); + // reformat allowed content types to array if id's + vm.contentType.allowedContentTypes = contentTypeHelper.createIdArray(vm.contentType.allowedContentTypes); - } + // update placeholder template information on new doc types + if (!$routeParams.notemplate && vm.contentType.id === 0) { + vm.contentType = contentTypeHelper.updateTemplatePlaceholder(vm.contentType); + } + + contentEditingHelper.contentEditorPerformSave({ + statusMessage: "Saving...", + saveMethod: mediaTypeResource.save, + scope: $scope, + content: vm.contentType, + //no-op for rebind callback... we don't really need to rebind for content types + rebindCallback: angular.noop + }).then(function (data) { + //success + syncTreeNode(vm.contentType, data.path); + + vm.page.saveButtonState = "success"; + + deferred.resolve(data); + }, function (err) { + //error + if (err) { + editorState.set($scope.content); + } + + vm.page.saveButtonState = "error"; + + deferred.reject(err); + }); + + return deferred.promise; } - function performSave() { - - vm.page.saveButtonState = "busy"; - - // reformat allowed content types to array if id's - vm.contentType.allowedContentTypes = contentTypeHelper.createIdArray(vm.contentType.allowedContentTypes); - - mediaTypeResource.save(vm.contentType).then(function(dt){ - - formHelper.resetForm({ scope: $scope, notifications: dt.notifications }); - contentEditingHelper.handleSuccessfulSave({ - scope: $scope, - savedContent: dt, - rebindCallback: function() { - - } - }); - - notificationsService.success("Media type saved"); - //post save logic here -the saved doctype returns as a new object - init(dt); - - syncTreeNode(vm.contentType, dt.path); - - vm.page.saveButtonState = "success"; - - }); - - } - - function init(contentType){ // set all tab to inactive diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 561f929706..038b2b19ba 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -90,134 +90,33 @@ namespace Umbraco.Web.Editors : Request.CreateValidationErrorResponse(result.Exception.Message); } - /// - /// Validates the composition and adds errors to the model state if any are found then throws an error response if there are errors - /// - /// - /// - /// - private void ValidateComposition(ContentTypeSave contentTypeSave, IContentTypeComposition composition) - { - var validateAttempt = Services.ContentTypeService.ValidateComposition(composition); - if (validateAttempt == false) - { - //if it's not successful then we need to return some model state for the property aliases that - // are duplicated - var propertyAliases = validateAttempt.Result.Distinct(); - foreach (var propertyAlias in propertyAliases) - { - //find the property relating to these - var prop = contentTypeSave.Groups.SelectMany(x => x.Properties).Single(x => x.Alias == propertyAlias); - var group = contentTypeSave.Groups.Single(x => x.Properties.Contains(prop)); - var propIndex = group.Properties.IndexOf(prop); - var groupIndex = contentTypeSave.Groups.IndexOf(group); - - var key = string.Format("Groups[{0}].Properties[{1}].Alias", groupIndex, propIndex); - ModelState.AddModelError(key, "Duplicate property aliases not allowed between compositions"); - } - - var display = Mapper.Map(composition); - //map the 'save' data on top - display = Mapper.Map(contentTypeSave, display); - display.Errors = ModelState.ToErrorDictionary(); - throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); - } - - } + public ContentTypeDisplay PostSave(ContentTypeSave contentTypeSave) { - var ctId = Convert.ToInt32(contentTypeSave.Id); - - var ctService = Services.ContentTypeService; - - if (ModelState.IsValid == false) - { - var ct = ctService.GetContentType(ctId); - //Required data is invalid so we cannot continue - var forDisplay = Mapper.Map(ct); - //map the 'save' data on top - forDisplay = Mapper.Map(contentTypeSave, forDisplay); - forDisplay.Errors = ModelState.ToErrorDictionary(); - throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); - } - - //filter out empty properties - contentTypeSave.Groups = contentTypeSave.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList(); - foreach (var group in contentTypeSave.Groups) - { - group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList(); - } - - //TODO: This all needs to be done in a transaction!! - // Which means that all of this logic needs to take place inside the service - - ContentTypeDisplay display; - - if (ctId > 0) - { - //its an update to an existing - var found = ctService.GetContentType(ctId); - if (found == null) - throw new HttpResponseException(HttpStatusCode.NotFound); - - Mapper.Map(contentTypeSave, found); - - //NOTE: this throws an error response if it is not valid - ValidateComposition(contentTypeSave, found); - - ctService.Save(found); - display = Mapper.Map(found); - } - else - { - //set id to null to ensure its handled as a new type - contentTypeSave.Id = null; - contentTypeSave.CreateDate = DateTime.Now; - contentTypeSave.UpdateDate = DateTime.Now; - - //create a default template if it doesnt exist -but only if default template is == to the content type - //TODO: Is this really what we want? What if we don't want any template assigned at all ? - if (contentTypeSave.DefaultTemplate.IsNullOrWhiteSpace() == false && contentTypeSave.DefaultTemplate == contentTypeSave.Alias) + var savedCt = PerformPostSave( + contentTypeSave: contentTypeSave, + getContentType: i => Services.ContentTypeService.GetContentType(i), + saveContentType: type => Services.ContentTypeService.Save(type), + beforeCreateNew: ctSave => { - var template = Services.FileService.GetTemplate(contentTypeSave.Alias); - if (template == null) + //create a default template if it doesnt exist -but only if default template is == to the content type + //TODO: Is this really what we want? What if we don't want any template assigned at all ? + if (ctSave.DefaultTemplate.IsNullOrWhiteSpace() == false && ctSave.DefaultTemplate == ctSave.Alias) { - template = new Template(contentTypeSave.Name, contentTypeSave.Alias); - Services.FileService.SaveTemplate(template); + var template = Services.FileService.GetTemplate(ctSave.Alias); + if (template == null) + { + template = new Template(ctSave.Name, ctSave.Alias); + Services.FileService.SaveTemplate(template); + } + + //make sure the template alias is set on the default and allowed template so we can map it back + ctSave.DefaultTemplate = template.Alias; } + }); - //make sure the template alias is set on the default and allowed template so we can map it back - contentTypeSave.DefaultTemplate = template.Alias; - } - - //check if the type is trying to allow type 0 below itself - id zero refers to the currently unsaved type - //always filter these 0 types out - var allowItselfAsChild = false; - if (contentTypeSave.AllowedContentTypes != null) - { - allowItselfAsChild = contentTypeSave.AllowedContentTypes.Any(x => x == 0); - contentTypeSave.AllowedContentTypes = contentTypeSave.AllowedContentTypes.Where(x => x > 0).ToList(); - } - - //save as new - var newCt = Mapper.Map(contentTypeSave); - - //NOTE: this throws an error response if it is not valid - ValidateComposition(contentTypeSave, newCt); - - ctService.Save(newCt); - - //we need to save it twice to allow itself under itself. - if (allowItselfAsChild) - { - //NOTE: This will throw if the composition isn't right... but it shouldn't be at this stage - newCt.AddContentType(newCt); - ctService.Save(newCt); - } - - display = Mapper.Map(newCt); - } + var display = Mapper.Map(savedCt); display.AddSuccessNotification( Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"), diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index ea652dbe50..2926bd5983 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.Editors { } - public DataTypeBasic GetAssignedListViewDataType(int contentTypeId) + protected internal DataTypeBasic GetAssignedListViewDataType(int contentTypeId) { var objectType = Services.EntityService.GetObjectType(contentTypeId); @@ -81,12 +81,12 @@ namespace Umbraco.Web.Editors /// Gets all user defined properties. /// /// - public IEnumerable GetAllPropertyTypeAliases() + protected IEnumerable GetAllPropertyTypeAliases() { return ApplicationContext.Services.ContentTypeService.GetAllPropertyTypeAliases(); } - public ContentPropertyDisplay GetPropertyTypeScaffold(int id) + protected ContentPropertyDisplay GetPropertyTypeScaffold(int id) { var dataTypeDiff = Services.DataTypeService.GetDataTypeDefinitionById(id); @@ -107,7 +107,7 @@ namespace Umbraco.Web.Editors }; } - public dynamic GetSafeAlias(string value, bool camelCase = true) + protected dynamic GetSafeAlias(string value, bool camelCase = true) { var returnValue = (string.IsNullOrWhiteSpace(value)) ? string.Empty : value.ToSafeAlias(camelCase); dynamic returnObj = new System.Dynamic.ExpandoObject(); @@ -118,9 +118,42 @@ namespace Umbraco.Web.Editors return returnObj; } + /// + /// Validates the composition and adds errors to the model state if any are found then throws an error response if there are errors + /// + /// + /// + /// + protected void ValidateComposition(ContentTypeSave contentTypeSave, IContentTypeComposition composition) + { + var validateAttempt = Services.ContentTypeService.ValidateComposition(composition); + if (validateAttempt == false) + { + //if it's not successful then we need to return some model state for the property aliases that + // are duplicated + var propertyAliases = validateAttempt.Result.Distinct(); + foreach (var propertyAlias in propertyAliases) + { + //find the property relating to these + var prop = contentTypeSave.Groups.SelectMany(x => x.Properties).Single(x => x.Alias == propertyAlias); + var group = contentTypeSave.Groups.Single(x => x.Properties.Contains(prop)); + var propIndex = group.Properties.IndexOf(prop); + var groupIndex = contentTypeSave.Groups.IndexOf(group); + var key = string.Format("Groups[{0}].Properties[{1}].Alias", groupIndex, propIndex); + ModelState.AddModelError(key, "Duplicate property aliases not allowed between compositions"); + } - public string TranslateItem(string text) + var display = Mapper.Map(composition); + //map the 'save' data on top + display = Mapper.Map(contentTypeSave, display); + display.Errors = ModelState.ToErrorDictionary(); + throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); + } + + } + + protected string TranslateItem(string text) { if (text == null) { @@ -134,6 +167,89 @@ namespace Umbraco.Web.Editors return CultureDictionary[text].IfNullOrWhiteSpace(text); } + protected TContentType PerformPostSave( + ContentTypeSave contentTypeSave, + Func getContentType, + Action saveContentType, + Action beforeCreateNew = null) + where TContentType : IContentTypeComposition + { + var ctId = Convert.ToInt32(contentTypeSave.Id); + + if (ModelState.IsValid == false) + { + var ct = getContentType(ctId); + //Required data is invalid so we cannot continue + var forDisplay = Mapper.Map(ct); + //map the 'save' data on top + forDisplay = Mapper.Map(contentTypeSave, forDisplay); + forDisplay.Errors = ModelState.ToErrorDictionary(); + throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); + } + + //filter out empty properties + contentTypeSave.Groups = contentTypeSave.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList(); + foreach (var group in contentTypeSave.Groups) + { + group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList(); + } + + if (ctId > 0) + { + //its an update to an existing + var found = getContentType(ctId); + if (found == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + Mapper.Map(contentTypeSave, found); + + //NOTE: this throws an error response if it is not valid + ValidateComposition(contentTypeSave, found); + + saveContentType(found); + + return found; + } + else + { + if (beforeCreateNew != null) + { + beforeCreateNew(contentTypeSave); + } + + //set id to null to ensure its handled as a new type + contentTypeSave.Id = null; + contentTypeSave.CreateDate = DateTime.Now; + contentTypeSave.UpdateDate = DateTime.Now; + + //check if the type is trying to allow type 0 below itself - id zero refers to the currently unsaved type + //always filter these 0 types out + var allowItselfAsChild = false; + if (contentTypeSave.AllowedContentTypes != null) + { + allowItselfAsChild = contentTypeSave.AllowedContentTypes.Any(x => x == 0); + contentTypeSave.AllowedContentTypes = contentTypeSave.AllowedContentTypes.Where(x => x > 0).ToList(); + } + + //save as new + var newCt = Mapper.Map(contentTypeSave); + + //NOTE: this throws an error response if it is not valid + ValidateComposition(contentTypeSave, newCt); + + saveContentType(newCt); + + //we need to save it twice to allow itself under itself. + if (allowItselfAsChild) + { + //NOTE: This will throw if the composition isn't right... but it shouldn't be at this stage + newCt.AddContentType(newCt); + saveContentType(newCt); + } + return newCt; + } + } + private ICultureDictionary CultureDictionary { get diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index 91607f0df7..9cdc3e6b95 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -14,7 +14,9 @@ using System.Net; using Umbraco.Core.PropertyEditors; using System; using System.Net.Http; +using Umbraco.Web.WebApi; using ContentType = System.Net.Mime.ContentType; +using Umbraco.Core.Services; namespace Umbraco.Web.Editors { @@ -100,58 +102,20 @@ namespace Umbraco.Web.Editors .Select(Mapper.Map); } - public ContentTypeCompositionDisplay PostSave(ContentTypeCompositionDisplay contentType) + public ContentTypeCompositionDisplay PostSave(ContentTypeSave contentTypeSave) { + var savedCt = PerformPostSave( + contentTypeSave: contentTypeSave, + getContentType: i => Services.ContentTypeService.GetMediaType(i), + saveContentType: type => Services.ContentTypeService.Save(type)); - var ctService = ApplicationContext.Services.ContentTypeService; + var display = Mapper.Map(savedCt); - //TODO: warn on content type alias conflicts - //TODO: warn on property alias conflicts - - //TODO: Validate the submitted model - - //filter out empty properties - contentType.Groups = contentType.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList(); - foreach (var group in contentType.Groups) - { - group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList(); - } - - var ctId = Convert.ToInt32(contentType.Id); - - if (ctId > 0) - { - //its an update to an existing - IMediaType found = ctService.GetMediaType(ctId); - if (found == null) - throw new HttpResponseException(HttpStatusCode.NotFound); - - Mapper.Map(contentType, found); - ctService.Save(found); - - //map the saved item back to the content type (it should now get id etc set) - Mapper.Map(found, contentType); - return contentType; - } - else - { - //ensure alias is set - if (string.IsNullOrEmpty(contentType.Alias)) - contentType.Alias = contentType.Name.ToSafeAlias(); - - contentType.Id = null; - - //save as new - IMediaType newCt = new MediaType(-1); - Mapper.Map(contentType, newCt); - - ctService.Save(newCt); - - //map the saved item back to the content type (it should now get id etc set) - Mapper.Map(newCt, contentType); - return contentType; - } + display.AddSuccessNotification( + Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"), + string.Empty); + return display; } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 39bfcb77f0..2846c9a1ea 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -4,6 +4,7 @@ using System.Web.Security; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Core.Security; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -105,58 +106,20 @@ namespace Umbraco.Web.Editors return Enumerable.Empty(); } - public ContentTypeCompositionDisplay PostSave(ContentTypeCompositionDisplay contentType) + public ContentTypeCompositionDisplay PostSave(ContentTypeSave contentTypeSave) { + var savedCt = PerformPostSave( + contentTypeSave: contentTypeSave, + getContentType: i => Services.MemberTypeService.Get(i), + saveContentType: type => Services.MemberTypeService.Save(type)); - var ctService = ApplicationContext.Services.MemberTypeService; + var display = Mapper.Map(savedCt); - //TODO: warn on content type alias conflicts - //TODO: warn on property alias conflicts - - //TODO: Validate the submitted model - - //filter out empty properties - contentType.Groups = contentType.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList(); - foreach (var group in contentType.Groups) - { - group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList(); - } - - var ctId = Convert.ToInt32(contentType.Id); - - if (ctId > 0) - { - //its an update to an existing - IMemberType found = ctService.Get(ctId); - if (found == null) - throw new HttpResponseException(HttpStatusCode.NotFound); - - Mapper.Map(contentType, found); - ctService.Save(found); - - //map the saved item back to the content type (it should now get id etc set) - Mapper.Map(found, contentType); - return contentType; - } - else - { - //ensure alias is set - if (string.IsNullOrEmpty(contentType.Alias)) - contentType.Alias = contentType.Name.ToSafeAlias(); - - contentType.Id = null; - - //save as new - IMemberType newCt = new MemberType(-1); - Mapper.Map(contentType, newCt); - - ctService.Save(newCt); - - //map the saved item back to the content type (it should now get id etc set) - Mapper.Map(newCt, contentType); - return contentType; - } + display.AddSuccessNotification( + Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"), + string.Empty); + return display; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs index 75bd6bbaae..27aaf17599 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs @@ -49,7 +49,6 @@ namespace Umbraco.Web.Models.Mapping .ForMember(type => type.UpdateDate, expression => expression.Ignore()) .ForMember(type => type.HasIdentity, expression => expression.Ignore()); - config.CreateMap() //do the base mapping .MapBaseContentTypeSaveToEntity(applicationContext) @@ -64,84 +63,29 @@ namespace Umbraco.Web.Models.Mapping if (source.DefaultTemplate != null) dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate)); - //sync compositions - var current = dest.CompositionAliases().ToArray(); - var proposed = source.CompositeContentTypes; - - var remove = current.Where(x => proposed.Contains(x) == false); - var add = proposed.Where(x => current.Contains(x) == false); - - foreach (var rem in remove) - { - dest.RemoveContentType(rem); - } - - foreach (var a in add) - { - - //TODO: Remove N+1 lookup - var addCt = applicationContext.Services.ContentTypeService.GetContentType(a); - if (addCt != null) - dest.AddContentType(addCt); - } + ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext); }); - - - //config.CreateMap() - // //do the base mapping - // .MapBaseContentTypeSaveToEntity(applicationContext) - // .AfterMap((source, dest) => - // { - - // //sync compositions - // var current = dest.CompositionAliases().ToArray(); - // var proposed = source.CompositeContentTypes; - - // var remove = current.Where(x => proposed.Contains(x) == false); - // var add = proposed.Where(x => current.Contains(x) == false); - - // foreach (var rem in remove) - // dest.RemoveContentType(rem); - - // foreach (var a in add) - // { - // //TODO: Remove N+1 lookup - // var addCt = applicationContext.Services.MemberTypeService.Get(a); - // if (addCt != null) - // dest.AddContentType(addCt); - // } - // }); - - - //config.CreateMap() - // //do the base mapping - // .MapBaseContentTypeSaveToEntity(applicationContext) - // .AfterMap((source, dest) => - // { - // //sync compositions - // var current = dest.CompositionAliases().ToArray(); - // var proposed = source.CompositeContentTypes; - - // var remove = current.Where(x => proposed.Contains(x) == false); - // var add = proposed.Where(x => current.Contains(x) == false); - - // foreach (var rem in remove) - // dest.RemoveContentType(rem); - - // foreach (var a in add) - // { - // //TODO: Remove N+1 lookup - // var addCt = applicationContext.Services.ContentTypeService.GetMediaType(a); - // if (addCt != null) - // dest.AddContentType(addCt); - // } - // }); + config.CreateMap() + //do the base mapping + .MapBaseContentTypeSaveToEntity(applicationContext) + .ConstructUsing((source) => new MediaType(source.ParentId)) + .AfterMap((source, dest) => + { + ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext); + }); + config.CreateMap() + //do the base mapping + .MapBaseContentTypeSaveToEntity(applicationContext) + .ConstructUsing((source) => new MemberType(source.ParentId)) + .AfterMap((source, dest) => + { + ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext); + }); config.CreateMap().ConvertUsing(x => x.Alias); - config.CreateMap() //map base logic .MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver); @@ -151,7 +95,6 @@ namespace Umbraco.Web.Models.Mapping .MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver) .AfterMap((source, dest) => { - //default listview dest.ListViewEditorName = Constants.Conventions.DataTypes.ListViewPrefix + "Media"; @@ -224,15 +167,13 @@ namespace Umbraco.Web.Models.Mapping #region *** Used for mapping on top of an existing display object from a save object *** + config.CreateMap() + .MapBaseContentTypeSaveToDisplay(); + config.CreateMap() - .ForMember(dto => dto.CreateDate, expression => expression.Ignore()) - .ForMember(dto => dto.UpdateDate, expression => expression.Ignore()) + .MapBaseContentTypeSaveToDisplay() .ForMember(dto => dto.AllowedTemplates, expression => expression.Ignore()) .ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore()) - .ForMember(dto => dto.ListViewEditorName, expression => expression.Ignore()) - .ForMember(dto => dto.AvailableCompositeContentTypes, expression => expression.Ignore()) - .ForMember(dto => dto.Notifications, expression => expression.Ignore()) - .ForMember(dto => dto.Errors, expression => expression.Ignore()) .AfterMap((source, dest) => { //sync templates diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs index 9d9457eb50..cfa12e214f 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs @@ -19,6 +19,48 @@ namespace Umbraco.Web.Models.Mapping /// internal static class ContentTypeModelMapperExtensions { + + public static void AfterMapContentTypeSaveToEntity( + TSource source, TDestination dest, + ApplicationContext applicationContext) + where TSource : ContentTypeSave + where TDestination : IContentTypeComposition + { + //sync compositions + var current = dest.CompositionAliases().ToArray(); + var proposed = source.CompositeContentTypes; + + var remove = current.Where(x => proposed.Contains(x) == false); + var add = proposed.Where(x => current.Contains(x) == false); + + foreach (var rem in remove) + { + dest.RemoveContentType(rem); + } + + foreach (var a in add) + { + //TODO: Remove N+1 lookup + var addCt = applicationContext.Services.ContentTypeService.GetContentType(a); + if (addCt != null) + dest.AddContentType(addCt); + } + } + + public static IMappingExpression MapBaseContentTypeSaveToDisplay( + this IMappingExpression mapping) + where TSource : ContentTypeSave + where TDestination : ContentTypeCompositionDisplay + { + return mapping + .ForMember(dto => dto.CreateDate, expression => expression.Ignore()) + .ForMember(dto => dto.UpdateDate, expression => expression.Ignore()) + .ForMember(dto => dto.ListViewEditorName, expression => expression.Ignore()) + .ForMember(dto => dto.AvailableCompositeContentTypes, expression => expression.Ignore()) + .ForMember(dto => dto.Notifications, expression => expression.Ignore()) + .ForMember(dto => dto.Errors, expression => expression.Ignore()); + } + public static IMappingExpression MapBaseContentTypeEntityToDisplay( this IMappingExpression mapping, ApplicationContext applicationContext, Lazy propertyEditorResolver) where TSource : IContentTypeComposition