Cleanup and fix mappers

This commit is contained in:
Stephan
2019-03-26 18:47:35 +01:00
parent 70c2090a56
commit 72bdf56ddf
23 changed files with 451 additions and 647 deletions

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.ContentEditing;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Trees;
using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile;
namespace Umbraco.Web.Models.Mapping
{
internal class CommonMapper
{
private readonly IUserService _userService;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ContentAppFactoryCollection _contentAppDefinitions;
private readonly ILocalizedTextService _localizedTextService;
public CommonMapper(IUserService userService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor,
ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService)
{
_userService = userService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_contentAppDefinitions = contentAppDefinitions;
_localizedTextService = localizedTextService;
}
public UserProfile GetOwner(IContentBase source, Mapper mapper)
{
var profile = source.GetCreatorProfile(_userService);
return profile == null ? null : mapper.Map<IProfile, UserProfile>(profile);
}
public UserProfile GetCreator(IContent source, Mapper mapper)
{
var profile = source.GetWriterProfile(_userService);
return profile == null ? null : mapper.Map<IProfile, UserProfile>(profile);
}
public ContentTypeBasic GetContentType(IContentBase source, Mapper mapper)
{
// TODO: We can resolve the UmbracoContext from the IValueResolver options!
// OMG
if (HttpContext.Current != null && Composing.Current.UmbracoContext != null && Composing.Current.UmbracoContext.Security.CurrentUser != null
&& Composing.Current.UmbracoContext.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source);
var contentTypeBasic = mapper.Map<IContentTypeComposition, ContentTypeBasic>(contentType);
return contentTypeBasic;
}
//no access
return null;
}
public string GetTreeNodeUrl<TController>(IContentBase source)
where TController : ContentTreeControllerBase
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext == null) return null;
var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext);
return urlHelper.GetUmbracoApiService<TController>(controller => controller.GetTreeNode(source.Key.ToString("N"), null));
}
public string GetMemberTreeNodeUrl(IContentBase source)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext == null) return null;
var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext);
return urlHelper.GetUmbracoApiService<MemberTreeController>(controller => controller.GetTreeNode(source.Key.ToString("N"), null));
}
public IEnumerable<ContentApp> GetContentApps(IContentBase source)
{
var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray();
// localize content app names
foreach (var app in apps)
{
var localizedAppName = _localizedTextService.Localize($"apps/{app.Alias}");
if (localizedAppName.Equals($"[{app.Alias}]", StringComparison.OrdinalIgnoreCase) == false)
{
app.Name = localizedAppName;
}
}
return apps;
}
}
}

View File

@@ -55,11 +55,18 @@ namespace Umbraco.Web.Models.Mapping
public void SetMaps(Mapper mapper)
{
mapper.Define<IContent, ContentPropertyCollectionDto>((source, context) => new ContentPropertyCollectionDto(), Map);
mapper.Define<IContent, ContentItemDisplay>((source, context) => new ContentItemDisplay(), Map);
mapper.Define<IContent, ContentVariantDisplay>((source, context) => new ContentVariantDisplay(), Map);
mapper.Define<IContent, ContentItemBasic<ContentPropertyBasic>>((source, context) => new ContentItemBasic<ContentPropertyBasic>(), Map);
}
// Umbraco.Code.MapAll
private static void Map(IContent source, ContentPropertyCollectionDto target, MapperContext context)
{
target.Properties = source.Properties.Select(context.Mapper.Map<ContentPropertyDto>);
}
// Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent
private void Map(IContent source, ContentItemDisplay target, MapperContext context)
{
@@ -120,7 +127,7 @@ namespace Umbraco.Web.Models.Mapping
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.Properties = context.Mapper.Map<IEnumerable<ContentPropertyBasic>>(source.Properties);
target.Properties = source.Properties.Select(context.Mapper.Map<ContentPropertyBasic>);
target.SortOrder = source.SortOrder;
target.State = _basicStateMapper.Map(source, context);
target.Trashed = source.Trashed;

View File

@@ -31,7 +31,7 @@ namespace Umbraco.Web.Models.Mapping
/// Assigns the PropertyEditor, Id, Alias and Value to the property
/// </summary>
/// <returns></returns>
public virtual TDestination Map(Property property, TDestination dest, MapperContext context)
public virtual void Map(Property property, TDestination dest, MapperContext context)
{
var editor = _propertyEditors[property.PropertyType.PropertyEditorAlias];
if (editor == null)
@@ -44,19 +44,16 @@ namespace Umbraco.Web.Models.Mapping
editor = _propertyEditors[Constants.PropertyEditors.Aliases.Label];
}
var result = new TDestination
{
Id = property.Id,
Alias = property.Alias,
PropertyEditor = editor,
Editor = editor.Alias
};
dest.Id = property.Id;
dest.Alias = property.Alias;
dest.PropertyEditor = editor;
dest.Editor = editor.Alias;
// if there's a set of property aliases specified, we will check if the current property's value should be mapped.
// if it isn't one of the ones specified in 'includeProperties', we will just return the result without mapping the Value.
var includedProperties = context.GetIncludedProperties();
if (includedProperties != null && !includedProperties.Contains(property.Alias))
return result;
return;
//Get the culture from the context which will be set during the mapping operation for each property
var culture = context.GetCulture();
@@ -68,11 +65,10 @@ namespace Umbraco.Web.Models.Mapping
//set the culture to null if it's an invariant property type
culture = !property.PropertyType.VariesByCulture() ? null : culture;
result.Culture = culture;
dest.Culture = culture;
// if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return.
result.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, culture);
return result;
dest.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, culture);
}
}
}

View File

@@ -19,9 +19,9 @@ namespace Umbraco.Web.Models.Mapping
{
_textService = textService;
}
public override ContentPropertyDisplay Map(Property originalProp, ContentPropertyDisplay dest, MapperContext context)
public override void Map(Property originalProp, ContentPropertyDisplay dest, MapperContext context)
{
var display = base.Map(originalProp, dest, context);
base.Map(originalProp, dest, context);
var config = DataTypeService.GetDataType(originalProp.PropertyType.DataTypeId).Configuration;
@@ -32,37 +32,35 @@ namespace Umbraco.Web.Models.Mapping
// - does it make any sense to use a IDataValueEditor without configuring it?
// configure the editor for display with configuration
var valEditor = display.PropertyEditor.GetValueEditor(config);
var valEditor = dest.PropertyEditor.GetValueEditor(config);
//set the display properties after mapping
display.Alias = originalProp.Alias;
display.Description = originalProp.PropertyType.Description;
display.Label = originalProp.PropertyType.Name;
display.HideLabel = valEditor.HideLabel;
dest.Alias = originalProp.Alias;
dest.Description = originalProp.PropertyType.Description;
dest.Label = originalProp.PropertyType.Name;
dest.HideLabel = valEditor.HideLabel;
//add the validation information
display.Validation.Mandatory = originalProp.PropertyType.Mandatory;
display.Validation.Pattern = originalProp.PropertyType.ValidationRegExp;
dest.Validation.Mandatory = originalProp.PropertyType.Mandatory;
dest.Validation.Pattern = originalProp.PropertyType.ValidationRegExp;
if (display.PropertyEditor == null)
if (dest.PropertyEditor == null)
{
//display.Config = PreValueCollection.AsDictionary(preVals);
//if there is no property editor it means that it is a legacy data type
// we cannot support editing with that so we'll just render the readonly value view.
display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html";
dest.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html";
}
else
{
//let the property editor format the pre-values
display.Config = display.PropertyEditor.GetConfigurationEditor().ToValueEditor(config);
display.View = valEditor.View;
dest.Config = dest.PropertyEditor.GetConfigurationEditor().ToValueEditor(config);
dest.View = valEditor.View;
}
//Translate
display.Label = _textService.UmbracoDictionaryTranslate(display.Label);
display.Description = _textService.UmbracoDictionaryTranslate(display.Description);
return display;
dest.Label = _textService.UmbracoDictionaryTranslate(dest.Label);
dest.Description = _textService.UmbracoDictionaryTranslate(dest.Description);
}
}
}

View File

@@ -16,17 +16,15 @@ namespace Umbraco.Web.Models.Mapping
: base(dataTypeService, logger, propertyEditors)
{ }
public override ContentPropertyDto Map(Property property, ContentPropertyDto dest, MapperContext context)
public override void Map(Property property, ContentPropertyDto dest, MapperContext context)
{
var propertyDto = base.Map(property, dest, context);
base.Map(property, dest, context);
propertyDto.IsRequired = property.PropertyType.Mandatory;
propertyDto.ValidationRegExp = property.PropertyType.ValidationRegExp;
propertyDto.Description = property.PropertyType.Description;
propertyDto.Label = property.PropertyType.Name;
propertyDto.DataType = DataTypeService.GetDataType(property.PropertyType.DataTypeId);
return propertyDto;
dest.IsRequired = property.PropertyType.Mandatory;
dest.ValidationRegExp = property.PropertyType.ValidationRegExp;
dest.Description = property.PropertyType.Description;
dest.Label = property.PropertyType.Name;
dest.DataType = DataTypeService.GetDataType(property.PropertyType.DataTypeId);
}
}
}

View File

@@ -383,9 +383,12 @@ namespace Umbraco.Web.Models.Mapping
target.AllowedAsRoot = source.AllowAsRoot;
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
target.Variations = ContentVariation.Nothing;
if (!(target is IMemberType) && source.AllowCultureVariant)
target.Variations |= ContentVariation.Culture;
if (!(target is IMemberType))
{
target.Variations = ContentVariation.Nothing;
if (source.AllowCultureVariant)
target.Variations |= ContentVariation.Culture;
}
// handle property groups and property types
// note that ContentTypeSave has

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.ContentEditing;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Trees;
using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile;
namespace Umbraco.Web.Models.Mapping
{
@@ -42,10 +34,17 @@ namespace Umbraco.Web.Models.Mapping
public void SetMaps(Mapper mapper)
{
mapper.Define<IMedia, ContentPropertyCollectionDto>((source, context) => new ContentPropertyCollectionDto(), Map);
mapper.Define<IMedia, MediaItemDisplay>((source, context) => new MediaItemDisplay(), Map);
mapper.Define<IMedia, ContentItemBasic<ContentPropertyBasic>>((source, context) => new ContentItemBasic<ContentPropertyBasic>(), Map);
}
// Umbraco.Code.MapAll
private static void Map(IMedia source, ContentPropertyCollectionDto target, MapperContext context)
{
target.Properties = source.Properties.Select(context.Mapper.Map<ContentPropertyDto>);
}
// Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer
private void Map(IMedia source, MediaItemDisplay target, MapperContext context)
{
@@ -85,7 +84,7 @@ namespace Umbraco.Web.Models.Mapping
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.Properties = context.Mapper.Map<IEnumerable<ContentPropertyBasic>>(source.Properties);
target.Properties = source.Properties.Select(context.Mapper.Map<ContentPropertyBasic>);
target.SortOrder = source.SortOrder;
target.State = null;
target.Trashed = source.Trashed;
@@ -101,88 +100,4 @@ namespace Umbraco.Web.Models.Mapping
return parent != null && (parent.ContentType.IsContainer || _mediaTypeService.HasContainerInPath(parent.Path));
}
}
// fixme temp + rename
internal class CommonMapper
{
private readonly IUserService _userService;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ContentAppFactoryCollection _contentAppDefinitions;
private readonly ILocalizedTextService _localizedTextService;
public CommonMapper(IUserService userService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor,
ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService)
{
_userService = userService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_contentAppDefinitions = contentAppDefinitions;
_localizedTextService = localizedTextService;
}
public UserProfile GetOwner(IContentBase source, Mapper mapper)
{
var profile = source.GetCreatorProfile(_userService);
return profile == null ? null : mapper.Map<IProfile, UserProfile>(profile);
}
public UserProfile GetCreator(IContent source, Mapper mapper)
{
var profile = source.GetWriterProfile(_userService);
return profile == null ? null : mapper.Map<IProfile, UserProfile>(profile);
}
public ContentTypeBasic GetContentType(IContentBase source, Mapper mapper)
{
// TODO: We can resolve the UmbracoContext from the IValueResolver options!
// OMG
if (HttpContext.Current != null && Composing.Current.UmbracoContext != null && Composing.Current.UmbracoContext.Security.CurrentUser != null
&& Composing.Current.UmbracoContext.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source);
var contentTypeBasic = mapper.Map<IContentTypeComposition, ContentTypeBasic>(contentType);
return contentTypeBasic;
}
//no access
return null;
}
public string GetTreeNodeUrl<TController>(IContentBase source)
where TController : ContentTreeControllerBase
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext == null) return null;
var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext);
return urlHelper.GetUmbracoApiService<TController>(controller => controller.GetTreeNode(source.Key.ToString("N"), null));
}
public string GetMemberTreeNodeUrl(IContentBase source)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext == null) return null;
var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext);
return urlHelper.GetUmbracoApiService<MemberTreeController>(controller => controller.GetTreeNode(source.Key.ToString("N"), null));
}
public IEnumerable<ContentApp> GetContentApps(IContentBase source)
{
var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray();
// localize content app names
foreach (var app in apps)
{
var localizedAppName = _localizedTextService.Localize($"apps/{app.Alias}");
if (localizedAppName.Equals($"[{app.Alias}]", StringComparison.OrdinalIgnoreCase) == false)
{
app.Name = localizedAppName;
}
}
return apps;
}
}
}

View File

@@ -105,14 +105,8 @@ namespace Umbraco.Web.Models.Mapping
/// <returns></returns>
protected virtual List<ContentPropertyDisplay> MapProperties(IContentBase content, List<Property> properties, MapperContext context)
{
//we need to map this way to pass the context through, I don't like it but we'll see what AutoMapper says: https://github.com/AutoMapper/AutoMapper/issues/2588
var result = context.Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyDisplay>>(
properties.OrderBy(prop => prop.PropertyType.SortOrder),
null,
context)
.ToList();
return result;
// must pass the context through
return properties.OrderBy(x => x.PropertyType.SortOrder).Select(x => context.Mapper.Map<ContentPropertyDisplay>(x, context)).ToList();
}
}

View File

@@ -42,7 +42,7 @@ namespace Umbraco.Web.Models.Mapping
{
mapper.Define<UserGroupSave, IUserGroup>((source, context) => new UserGroup { CreateDate = DateTime.UtcNow }, Map);
mapper.Define<UserInvite, IUser>(Map);
mapper.Define<IProfile, ContentEditing.UserProfile>(Map);
mapper.Define<IProfile, ContentEditing.UserProfile>((source, context) => new ContentEditing.UserProfile(), Map);
mapper.Define<IReadOnlyUserGroup, UserGroupBasic>((source, context) => new UserGroupBasic(), Map);
mapper.Define<IUserGroup, UserGroupBasic>((source, context) => new UserGroupBasic(), Map);
mapper.Define<IUserGroup, AssignedUserGroupPermissions>((source, context) => new AssignedUserGroupPermissions(), Map);
@@ -115,8 +115,8 @@ namespace Umbraco.Web.Models.Mapping
private void Map(UserSave source, IUser target, MapperContext context)
{
target.Name = source.Name;
target.StartContentIds = source.StartContentIds;
target.StartMediaIds = source.StartMediaIds;
target.StartContentIds = source.StartContentIds ?? Array.Empty<int>();
target.StartMediaIds = source.StartMediaIds ?? Array.Empty<int>();
target.Language = source.Culture;
target.Email = source.Email;
target.Key = source.Key;