Refactor more mappers - AutoMapper gone now

This commit is contained in:
Stephan
2019-03-26 13:58:38 +01:00
parent d274737296
commit 70c2090a56
48 changed files with 502 additions and 1257 deletions
-1
View File
@@ -22,7 +22,6 @@
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="AutoMapper" version="[8.0.0,8.999999)" />
<dependency id="LightInject" version="[5.4.0,5.999999)" />
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
+3
View File
@@ -27,11 +27,14 @@ namespace Umbraco.Core
/// <returns></returns>
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// keep here for reference - we don't use AutoMapper
/*
//AutoMapper:
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
*/
return null;
+4 -70
View File
@@ -1,19 +1,11 @@
using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Mapping
{
// FIXME we should inject the mapper
// FIXME in order to transition, this should also handle AutoMapper?
// FIXME we might have to manage a 'context' for some contextual mappings?
// FIXME we have an infinite loop problem w/ logging in due to mapping issues
// FIXME refactor
// ctor: (source, context) =>
// map: (source, target, context) =>
// and context.Mapper is mapper
// FIXME needs documentation and cleanup!
public class Mapper
{
@@ -31,21 +23,12 @@ namespace Umbraco.Core.Mapping
#region Define
//public void Define<TSource, TTarget>()
// => Define<TSource, TTarget>((source, target) => { });
public void Define<TSource, TTarget>()
=> Define<TSource, TTarget>((source, target, context) => { });
//public void Define<TSource, TTarget>(Action<TSource, TTarget> map)
// => Define(source => throw new NotSupportedException($"Don't know how to create {typeof(TTarget)} instances."), map);
public void Define<TSource, TTarget>(Action<TSource, TTarget, MapperContext> map)
=> Define((source, context) => throw new NotSupportedException($"Don't know how to create {typeof(TTarget)} instances."), map);
//public void Define<TSource, TTarget>(Func<TSource, TTarget> ctor)
// => Define(ctor, (source, target) => { });
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor)
=> Define(ctor, (source, target, context) => { });
@@ -63,42 +46,6 @@ namespace Umbraco.Core.Mapping
return sourceMap;
}
//public void Define<TSource, TTarget>(Func<TSource, TTarget> ctor, Action<TSource, TTarget> map)
//{
// var sourceType = typeof(TSource);
// var targetType = typeof(TTarget);
// var sourceCtors = DefineCtors(sourceType);
// sourceCtors[targetType] = (source, context) => ctor((TSource) source);
// var sourceMaps = DefineMaps(sourceType);
// sourceMaps[targetType] = (source, target, context) => map((TSource) source, (TTarget) target);
//}
//public void Define<TSource, TTarget>(Func<TSource, TTarget> ctor, Action<TSource, TTarget, MapperContext> map)
//{
// var sourceType = typeof(TSource);
// var targetType = typeof(TTarget);
// var sourceCtors = DefineCtors(sourceType);
// sourceCtors[targetType] = (source, context) => ctor((TSource)source);
// var sourceMaps = DefineMaps(sourceType);
// sourceMaps[targetType] = (source, target, context) => map((TSource)source, (TTarget)target, context);
//}
//public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor, Action<TSource, TTarget> map)
//{
// var sourceType = typeof(TSource);
// var targetType = typeof(TTarget);
// var sourceCtors = DefineCtors(sourceType);
// sourceCtors[targetType] = (source, context) => ctor((TSource)source, context);
// var sourceMaps = DefineMaps(sourceType);
// sourceMaps[targetType] = (source, target, context) => map((TSource)source, (TTarget)target);
//}
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor, Action<TSource, TTarget, MapperContext> map)
{
var sourceType = typeof(TSource);
@@ -186,15 +133,10 @@ namespace Umbraco.Core.Mapping
return (TTarget)targetEnumerable;
}
// fixme - temp
return AutoMapper.Mapper.Map<TTarget>(source);
}
}
// fixme this is temp
//throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
return AutoMapper.Mapper.Map<TTarget>(source);
throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
}
// TODO: when AutoMapper is completely gone these two methods can merge
@@ -254,15 +196,10 @@ namespace Umbraco.Core.Mapping
return (TTarget)targetEnumerable;
}
// fixme - temp
return AutoMapper.Mapper.Map<TSource, TTarget>(source);
}
}
// fixme this is temp
//throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
return AutoMapper.Mapper.Map<TSource, TTarget>(source);
throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
}
public TTarget Map<TSource, TTarget>(TSource source, TTarget target)
@@ -275,7 +212,6 @@ namespace Umbraco.Core.Mapping
return Map(source, target, context);
}
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, MapperContext context)
{
// fixme should we deal with enumerables?
@@ -283,9 +219,7 @@ namespace Umbraco.Core.Mapping
var map = GetMap(source.GetType(), typeof(TTarget));
if (map == null)
{
// fixme this is temp
//throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
return AutoMapper.Mapper.Map(source, target);
throw new InvalidOperationException($"Don't know how to map {typeof(TSource).FullName} to {typeof(TTarget).FullName}.");
}
map(source, target, context);
@@ -1,28 +1,12 @@
using System.Collections.Generic;
using AutoMapper;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
namespace Umbraco.Core.Runtime
{
public class CoreInitialComponent : IComponent
{
private readonly IEnumerable<Profile> _mapperProfiles;
public CoreInitialComponent(IEnumerable<Profile> mapperProfiles) // fixme - this is what we want to kill: mapper
{
_mapperProfiles = mapperProfiles;
}
public void Initialize()
{
// mapper profiles have been registered & are created by the container
Mapper.Initialize(configuration =>
{
foreach (var profile in _mapperProfiles)
configuration.AddProfile(profile);
});
// ensure we have some essential directories
// every other component can then initialize safely
IOHelper.EnsurePathExists("~/App_Data");
+3
View File
@@ -217,10 +217,13 @@ namespace Umbraco.Core.Runtime
// This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// here for reference - we don't use automapper anymore + see BindingRedirects ??
/*
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stack overflow
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
*/
return null;
};
}
-1
View File
@@ -60,7 +60,6 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="LightInject" Version="5.4.0" />
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
<PackageReference Include="LightInject.Web" Version="2.0.0" />
+2 -3
View File
@@ -79,13 +79,12 @@ namespace Umbraco.Tests.Mapping
{
public void SetMaps(Mapper mapper)
{
mapper.Define<Thing1, Thing2>(source => new Thing2(), (source, target) => Map(source, target));
mapper.Define<Thing1, Thing2>((source, context) => new Thing2(), Map);
}
private Thing2 Map(Thing1 source, Thing2 target)
private void Map(Thing1 source, Thing2 target, MapperContext context)
{
target.Value = source.Value;
return target;
}
}
}
-1
View File
@@ -78,7 +78,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="Castle.Core" Version="4.3.1" />
<PackageReference Include="Examine" Version="1.0.0" />
<PackageReference Include="HtmlAgilityPack">
-1
View File
@@ -83,7 +83,6 @@
<Folder Include="Views\MacroPartials\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
<PackageReference Include="ClientDependency" Version="1.9.7" />
<PackageReference Include="ClientDependency-Mvc5" Version="1.8.0.0" />
@@ -1,10 +1,7 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Web.Models.Mapping;
using Umbraco.Web.Trees;
namespace Umbraco.Web.Composing.CompositionExtensions
{
@@ -12,10 +9,10 @@ namespace Umbraco.Web.Composing.CompositionExtensions
{
public static Composition ComposeWebMappingProfiles(this Composition composition)
{
// register the profiles
composition.WithCollectionBuilder<MapperProfileCollectionBuilder>()
.Append<AuditMapperProfile>()
.Append<CodeFileMapperProfile>()
.Append<ContentMapperProfile>()
.Append<ContentPropertyMapperProfile>()
.Append<ContentTypeMapperProfile>()
.Append<DataTypeMapperProfile>()
@@ -23,6 +20,7 @@ namespace Umbraco.Web.Composing.CompositionExtensions
.Append<DictionaryMapperProfile>()
.Append<MacroMapperProfile>()
.Append<MediaMapperProfile>()
.Append<MemberMapperProfile>()
.Append<RedirectUrlMapperProfile>()
.Append<RelationMapperProfile>()
.Append<SectionMapperProfile>()
@@ -31,37 +29,7 @@ namespace Umbraco.Web.Composing.CompositionExtensions
.Append<UserMapperProfile>()
.Append<LanguageMapperProfile>();
//register the profiles
//composition.Register<Profile, AuditMapperProfile>();
//composition.Register<Profile, CodeFileMapperProfile>();
composition.Register<Profile, ContentMapperProfile>();
//composition.Register<Profile, ContentPropertyMapperProfile>();
//composition.Register<Profile, ContentTypeMapperProfile>();
//composition.Register<Profile, DataTypeMapperProfile>();
//composition.Register<Profile, EntityMapperProfile>();
//composition.Register<Profile, DictionaryMapperProfile>();
//composition.Register<Profile, MacroMapperProfile>();
//composition.Register<Profile, MediaMapperProfile>();
composition.Register<Profile, MemberMapperProfile>();
//composition.Register<Profile, RedirectUrlMapperProfile>();
//composition.Register<Profile, RelationMapperProfile>();
//composition.Register<Profile, SectionMapperProfile>();
//composition.Register<Profile, TagMapperProfile>();
//composition.Register<Profile, TemplateMapperProfile>();
//composition.Register<Profile, UserMapperProfile>();
//composition.Register<Profile, LanguageMapperProfile>();
//register any resolvers, etc.. that the profiles use
composition.Register<ContentUrlResolver>();
composition.Register<ContentTreeNodeUrlResolver<IContent, ContentTreeController>>();
composition.Register<TabsAndPropertiesMapper<IContent>>();
composition.Register<TabsAndPropertiesMapper<IMedia>>();
composition.Register<ContentTreeNodeUrlResolver<IMedia, MediaTreeController>>();
composition.Register<MemberTabsAndPropertiesMapper>();
composition.Register<MemberTreeNodeUrlResolver>();
composition.Register<MemberBasicPropertiesResolver>();
composition.Register<MediaAppResolver>();
composition.Register<ContentAppResolver>();
composition.Register<CommonMapper>();
return composition;
}
@@ -2,7 +2,6 @@
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
@@ -1,14 +1,10 @@
using System;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.Editors.Binders
{
@@ -46,7 +42,7 @@ namespace Umbraco.Web.Editors.Binders
//create the dto from the persisted model
if (model.PersistedContent != null)
{
model.PropertyCollectionDto = Mapper.Map<IMedia, ContentPropertyCollectionDto>(model.PersistedContent);
model.PropertyCollectionDto = Current.Mapper.Map<IMedia, ContentPropertyCollectionDto>(model.PersistedContent);
//now map all of the saved values to the dto
_modelBinderHelper.MapPropertyValuesFromSaved(model, model.PropertyCollectionDto);
}
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Security;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
@@ -50,7 +49,7 @@ namespace Umbraco.Web.Editors.Binders
//create the dto from the persisted model
if (model.PersistedContent != null)
{
model.PropertyCollectionDto = Mapper.Map<IMember, ContentPropertyCollectionDto>(model.PersistedContent);
model.PropertyCollectionDto = Current.Mapper.Map<IMember, ContentPropertyCollectionDto>(model.PersistedContent);
//now map all of the saved values to the dto
_modelBinderHelper.MapPropertyValuesFromSaved(model, model.PropertyCollectionDto);
}
@@ -106,7 +105,7 @@ namespace Umbraco.Web.Editors.Binders
//}
//member.Key = convertResult.Result;
var member = Mapper.Map<MembershipUser, IMember>(membershipUser);
var member = Current.Mapper.Map<MembershipUser, IMember>(membershipUser);
return member;
}
@@ -5,7 +5,6 @@ using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
@@ -501,13 +500,13 @@ namespace Umbraco.Web.Editors
where TPropertyType : PropertyTypeBasic
{
InvalidCompositionException invalidCompositionException = null;
if (ex is AutoMapperMappingException && ex.InnerException is InvalidCompositionException)
if (ex is InvalidCompositionException)
{
invalidCompositionException = (InvalidCompositionException)ex.InnerException;
invalidCompositionException = (InvalidCompositionException)ex;
}
else if (ex.InnerException is InvalidCompositionException)
{
invalidCompositionException = (InvalidCompositionException)ex;
invalidCompositionException = (InvalidCompositionException)ex.InnerException;
}
if (invalidCompositionException != null)
{
@@ -4,7 +4,6 @@ using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
@@ -71,12 +70,12 @@ namespace Umbraco.Web.Editors
return;
}
// map the model to the persisted instance
Mapper.Map(dataType, persisted);
Current.Mapper.Map(dataType, persisted);
break;
case ContentSaveAction.SaveNew:
// create the persisted model from mapping the saved model
persisted = Mapper.Map<IDataType>(dataType);
persisted = Current.Mapper.Map<IDataType>(dataType);
((DataType) persisted).ResetIdentity();
break;
@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Creates the list of action buttons allowed for this user - Publish, Send to publish, save, unpublish returned as the button's 'letter'
/// </summary>
internal class ActionButtonsResolver
{
public ActionButtonsResolver(IUserService userService, IContentService contentService)
{
UserService = userService;
ContentService = contentService;
}
private IUserService UserService { get; }
private IContentService ContentService { get; }
public IEnumerable<string> Resolve(IContent source)
{
//cannot check permissions without a context
if (Current.UmbracoContext == null)
return Enumerable.Empty<string>();
string path;
if (source.HasIdentity)
path = source.Path;
else
{
var parent = ContentService.GetById(source.ParentId);
path = parent == null ? "-1" : parent.Path;
}
// TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is
// with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null
// reference exception :(
return UserService.GetPermissionsForPath(Current.UmbracoContext.Security.CurrentUser, path).GetAllPermissions();
}
}
}
@@ -8,11 +8,11 @@ namespace Umbraco.Web.Models.Mapping
{
public void SetMaps(Mapper mapper)
{
mapper.Define<IAuditItem, AuditLog>(source => new AuditLog(), Map);
mapper.Define<IAuditItem, AuditLog>((source, context) => new AuditLog(), Map);
}
// Umbraco.Code.MapAll -UserAvatars -UserName
private void Map(IAuditItem source, AuditLog target)
private void Map(IAuditItem source, AuditLog target, MapperContext context)
{
target.UserId = source.UserId;
target.NodeId = source.Id;
@@ -9,17 +9,17 @@ namespace Umbraco.Web.Models.Mapping
{
public void SetMaps(Mapper mapper)
{
mapper.Define<Stylesheet, EntityBasic>(source => new EntityBasic(), Map);
mapper.Define<IPartialView, CodeFileDisplay>(source => new CodeFileDisplay(), Map);
mapper.Define<Script, CodeFileDisplay>(source => new CodeFileDisplay(), Map);
mapper.Define<Stylesheet, CodeFileDisplay>(source => new CodeFileDisplay(), Map);
mapper.Define<Stylesheet, EntityBasic>((source, context) => new EntityBasic(), Map);
mapper.Define<IPartialView, CodeFileDisplay>((source, context) => new CodeFileDisplay(), Map);
mapper.Define<Script, CodeFileDisplay>((source, context) => new CodeFileDisplay(), Map);
mapper.Define<Stylesheet, CodeFileDisplay>((source, context) => new CodeFileDisplay(), Map);
mapper.Define<CodeFileDisplay, IPartialView>(Map);
mapper.Define<CodeFileDisplay, Script>(Map);
}
// Umbraco.Code.MapAll -Trashed -Udi -Icon
private static void Map(Stylesheet source, EntityBasic target)
private static void Map(Stylesheet source, EntityBasic target, MapperContext context)
{
target.Alias = source.Alias;
target.Id = source.Id;
@@ -30,7 +30,7 @@ namespace Umbraco.Web.Models.Mapping
}
// Umbraco.Code.MapAll -FileType -Notifications -Path -Snippet
private static void Map(IPartialView source, CodeFileDisplay target)
private static void Map(IPartialView source, CodeFileDisplay target, MapperContext context)
{
target.Content = source.Content;
target.Id = source.Id.ToString();
@@ -39,7 +39,7 @@ namespace Umbraco.Web.Models.Mapping
}
// Umbraco.Code.MapAll -FileType -Notifications -Path -Snippet
private static void Map(Script source, CodeFileDisplay target)
private static void Map(Script source, CodeFileDisplay target, MapperContext context)
{
target.Content = source.Content;
target.Id = source.Id.ToString();
@@ -48,7 +48,7 @@ namespace Umbraco.Web.Models.Mapping
}
// Umbraco.Code.MapAll -FileType -Notifications -Path -Snippet
private static void Map(Stylesheet source, CodeFileDisplay target)
private static void Map(Stylesheet source, CodeFileDisplay target, MapperContext context)
{
target.Content = source.Content;
target.Id = source.Id.ToString();
@@ -58,7 +58,7 @@ namespace Umbraco.Web.Models.Mapping
// Umbraco.Code.MapAll -CreateDate -DeleteDate -UpdateDate
// Umbraco.Code.MapAll -Id -Key -Alias -Name -OriginalPath -Path
private static void Map(CodeFileDisplay source, IPartialView target)
private static void Map(CodeFileDisplay source, IPartialView target, MapperContext context)
{
target.Content = source.Content;
target.VirtualPath = source.VirtualPath;
@@ -66,7 +66,7 @@ namespace Umbraco.Web.Models.Mapping
// Umbraco.Code.MapAll -CreateDate -DeleteDate -UpdateDate -GetFileContent
// Umbraco.Code.MapAll -Id -Key -Alias -Name -OriginalPath -Path
private static void Map(CodeFileDisplay source, Script target)
private static void Map(CodeFileDisplay source, Script target, MapperContext context)
{
target.Content = source.Content;
target.VirtualPath = source.VirtualPath;
@@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Models.ContentEditing;
using Umbraco.Core.Services;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
// injected into ContentMapperProfile,
// maps ContentApps when mapping IContent to ContentItemDisplay
internal class ContentAppResolver : IValueResolver<IContent, ContentItemDisplay, IEnumerable<ContentApp>>
{
private readonly ContentAppFactoryCollection _contentAppDefinitions;
private readonly ILocalizedTextService _localizedTextService;
public ContentAppResolver(ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService)
{
_contentAppDefinitions = contentAppDefinitions;
_localizedTextService = localizedTextService;
}
public IEnumerable<ContentApp> Resolve(IContent source, ContentItemDisplay destination, IEnumerable<ContentApp> destMember, ResolutionContext context)
{
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;
}
}
}
@@ -1,26 +0,0 @@
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class ContentChildOfListViewResolver : IValueResolver<IContent, ContentItemDisplay, bool>
{
private readonly IContentService _contentService;
private readonly IContentTypeService _contentTypeService;
public ContentChildOfListViewResolver(IContentService contentService, IContentTypeService contentTypeService)
{
_contentService = contentService;
_contentTypeService = contentTypeService;
}
public bool Resolve(IContent source, ContentItemDisplay destination, bool destMember, ResolutionContext context)
{
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
var parent = _contentService.GetParent(source);
return parent != null && (parent.ContentType.IsContainer || _contentTypeService.HasContainerInPath(parent.Path));
}
}
}
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Routing;
using Umbraco.Web.Trees;
namespace Umbraco.Web.Models.Mapping
@@ -13,157 +15,233 @@ namespace Umbraco.Web.Models.Mapping
/// <summary>
/// Declares how model mappings for content
/// </summary>
internal class ContentMapperProfile : Profile
internal class ContentMapperProfile : IMapperProfile
{
public ContentMapperProfile(
ContentUrlResolver contentUrlResolver,
ContentTreeNodeUrlResolver<IContent, ContentTreeController> contentTreeNodeUrlResolver,
TabsAndPropertiesMapper<IContent> tabsAndPropertiesMapper,
ContentAppResolver contentAppResolver,
IUserService userService,
IContentService contentService,
IContentTypeService contentTypeService,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService)
private readonly CommonMapper _commonMapper;
private readonly ILocalizedTextService _localizedTextService;
private readonly IContentService _contentService;
private readonly IContentTypeService _contentTypeService;
private readonly IFileService _fileService;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPublishedRouter _publishedRouter;
private readonly ILocalizationService _localizationService;
private readonly ILogger _logger;
private readonly IUserService _userService;
private readonly TabsAndPropertiesMapper<IContent> _tabsAndPropertiesMapper;
private readonly ContentSavedStateMapper<ContentPropertyDisplay> _stateMapper;
private readonly ContentBasicSavedStateMapper<ContentPropertyBasic> _basicStateMapper;
private readonly ContentVariantMapper _contentVariantMapper;
public ContentMapperProfile(CommonMapper commonMapper, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService,
IFileService fileService, IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, ILocalizationService localizationService, ILogger logger,
IUserService userService)
{
// create, capture, cache
var contentOwnerResolver = new OwnerResolver<IContent>(userService);
var creatorResolver = new CreatorResolver(userService);
var actionButtonsResolver = new ActionButtonsResolver(userService, contentService);
var childOfListViewResolver = new ContentChildOfListViewResolver(contentService, contentTypeService);
var contentTypeBasicResolver = new ContentTypeBasicResolver<IContent, ContentItemDisplay>(contentTypeBaseServiceProvider);
var allowedTemplatesResolver = new AllowedTemplatesResolver(contentTypeService, localizedTextService);
var defaultTemplateResolver = new DefaultTemplateResolver();
var variantResolver = new ContentVariantResolver(localizationService);
var schedPublishReleaseDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Release);
var schedPublishExpireDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Expire);
_commonMapper = commonMapper;
_localizedTextService = localizedTextService;
_contentService = contentService;
_contentTypeService = contentTypeService;
_fileService = fileService;
_umbracoContextAccessor = umbracoContextAccessor;
_publishedRouter = publishedRouter;
_localizationService = localizationService;
_logger = logger;
_userService = userService;
//FROM IContent TO ContentItemDisplay
CreateMap<IContent, ContentItemDisplay>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(src.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, src.Key)))
.ForMember(dest => dest.Owner, opt => opt.MapFrom(src => contentOwnerResolver.Resolve(src)))
.ForMember(dest => dest.Updater, opt => opt.MapFrom(src => creatorResolver.Resolve(src)))
.ForMember(dest => dest.Variants, opt => opt.MapFrom(variantResolver))
.ForMember(dest => dest.ContentApps, opt => opt.MapFrom(contentAppResolver))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon))
.ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias))
.ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => localizedTextService.UmbracoDictionaryTranslate(src.ContentType.Name)))
.ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer))
.ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement))
.ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint))
.ForMember(dest => dest.IsChildOfListView, opt => opt.MapFrom(childOfListViewResolver))
.ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed))
.ForMember(dest => dest.TemplateAlias, opt => opt.MapFrom(defaultTemplateResolver))
.ForMember(dest => dest.Urls, opt => opt.MapFrom(contentUrlResolver))
.ForMember(dest => dest.AllowPreview, opt => opt.Ignore())
.ForMember(dest => dest.TreeNodeUrl, opt => opt.MapFrom(contentTreeNodeUrlResolver))
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.Errors, opt => opt.Ignore())
.ForMember(dest => dest.DocumentType, opt => opt.MapFrom(contentTypeBasicResolver))
.ForMember(dest => dest.AllowedTemplates, opt => opt.MapFrom(allowedTemplatesResolver))
.ForMember(dest => dest.AllowedActions, opt => opt.MapFrom(src => actionButtonsResolver.Resolve(src)))
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
CreateMap<IContent, ContentVariantDisplay>()
.ForMember(dest => dest.PublishDate, opt => opt.MapFrom(src => src.PublishDate))
.ForMember(dest => dest.ReleaseDate, opt => opt.MapFrom(schedPublishReleaseDateResolver))
.ForMember(dest => dest.ExpireDate, opt => opt.MapFrom(schedPublishExpireDateResolver))
.ForMember(dest => dest.Segment, opt => opt.Ignore())
.ForMember(dest => dest.Language, opt => opt.Ignore())
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.State, opt => opt.MapFrom<ContentSavedStateResolver<ContentPropertyDisplay>>())
.ForMember(dest => dest.Tabs, opt => opt.MapFrom(tabsAndPropertiesMapper));
//FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent>
CreateMap<IContent, ContentItemBasic<ContentPropertyBasic>>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src =>
Udi.Create(src.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, src.Key)))
.ForMember(dest => dest.Owner, opt => opt.MapFrom(src => contentOwnerResolver.Resolve(src)))
.ForMember(dest => dest.Updater, opt => opt.MapFrom(src => creatorResolver.Resolve(src)))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon))
.ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed))
.ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias))
.ForMember(dest => dest.Alias, opt => opt.Ignore())
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore())
.ForMember(dest => dest.UpdateDate, opt => opt.MapFrom<UpdateDateResolver>())
.ForMember(dest => dest.Name, opt => opt.MapFrom<NameResolver>())
.ForMember(dest => dest.State, opt => opt.MapFrom<ContentBasicSavedStateResolver<ContentPropertyBasic>>())
.ForMember(dest => dest.VariesByCulture, opt => opt.MapFrom(src => src.ContentType.VariesByCulture()));
//FROM IContent TO ContentPropertyCollectionDto
//NOTE: the property mapping for cultures relies on a culture being set in the mapping context
CreateMap<IContent, ContentPropertyCollectionDto>();
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IContent>(localizedTextService);
_stateMapper = new ContentSavedStateMapper<ContentPropertyDisplay>();
_basicStateMapper = new ContentBasicSavedStateMapper<ContentPropertyBasic>();
_contentVariantMapper = new ContentVariantMapper(_localizationService);
}
/// <summary>
/// Resolves the update date for a content item/content variant
/// </summary>
private class UpdateDateResolver : IValueResolver<IContent, ContentItemBasic<ContentPropertyBasic>, DateTime>
public void SetMaps(Mapper mapper)
{
public DateTime Resolve(IContent source, ContentItemBasic<ContentPropertyBasic> destination, DateTime destMember, ResolutionContext context)
{
// invariant = global date
if (!source.ContentType.VariesByCulture()) return source.UpdateDate;
// variant = depends on culture
var culture = context.Options.GetCulture();
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
if (culture == null)
throw new InvalidOperationException("Missing culture in mapping options.");
// if we don't have a date for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback date
var date = source.GetUpdateDate(culture);
return date ?? source.UpdateDate;
}
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);
}
/// <summary>
/// Resolves the name for a content item/content variant
/// </summary>
private class NameResolver : IValueResolver<IContent, ContentItemBasic<ContentPropertyBasic>, string>
// Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent
private void Map(IContent source, ContentItemDisplay target, MapperContext context)
{
public string Resolve(IContent source, ContentItemBasic<ContentPropertyBasic> destination, string destMember, ResolutionContext context)
{
// invariant = only 1 name
if (!source.ContentType.VariesByCulture()) return source.Name;
target.AllowedActions = GetActions(source);
target.AllowedTemplates = GetAllowedTemplates(source);
target.ContentApps = _commonMapper.GetContentApps(source);
target.ContentTypeAlias = source.ContentType.Alias;
target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(source.ContentType.Name);
target.DocumentType = _commonMapper.GetContentType(source, context.Mapper);
target.Icon = source.ContentType.Icon;
target.Id = source.Id;
target.IsBlueprint = source.Blueprint;
target.IsChildOfListView = DermineIsChildOfListView(source);
target.IsContainer = source.ContentType.IsContainer;
target.IsElement = source.ContentType.IsElement;
target.Key = source.Key;
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.SortOrder = source.SortOrder;
target.TemplateAlias = GetDefaultTemplate(source);
target.TemplateId = source.TemplateId ?? default;
target.Trashed = source.Trashed;
target.TreeNodeUrl = _commonMapper.GetTreeNodeUrl<ContentTreeController>(source);
target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key);
target.UpdateDate = source.UpdateDate;
target.Updater = _commonMapper.GetCreator(source, context.Mapper);
target.Urls = GetUrls(source);
target.Variants = _contentVariantMapper.Map(source, context);
// variant = depends on culture
var culture = context.Options.GetCulture();
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
if (culture == null)
throw new InvalidOperationException("Missing culture in mapping options.");
// if we don't have a name for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback name
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"({source.Name})";
}
target.ContentDto = new ContentPropertyCollectionDto();
target.ContentDto.Properties = source.Properties.Select(context.Mapper.Map<ContentPropertyDto>);
}
private class AllowedTemplatesResolver : IValueResolver<IContent, ContentItemDisplay, IDictionary<string, string>>
// Umbraco.Code.MapAll -Segment -Language
private void Map(IContent source, ContentVariantDisplay target, MapperContext context)
{
private readonly IContentTypeService _contentTypeService;
private readonly ILocalizedTextService _localizedTextService;
target.CreateDate = source.CreateDate;
target.ExpireDate = GetScheduledDate(source, ContentScheduleAction.Expire, context);
target.Name = source.Name;
target.PublishDate = source.PublishDate;
target.ReleaseDate = GetScheduledDate(source, ContentScheduleAction.Release, context);
target.State = _stateMapper.Map(source, context);
target.Tabs = _tabsAndPropertiesMapper.Map(source, context);
target.UpdateDate = source.UpdateDate;
}
public AllowedTemplatesResolver(IContentTypeService contentTypeService, ILocalizedTextService localizedTextService)
// Umbraco.Code.MapAll -Alias
private void Map(IContent source, ContentItemBasic<ContentPropertyBasic> target, MapperContext context)
{
target.ContentTypeAlias = source.ContentType.Alias;
target.CreateDate = source.CreateDate;
target.Edited = source.Edited;
target.Icon = source.ContentType.Icon;
target.Id = source.Id;
target.Key = source.Key;
target.Name = GetName(source, context);
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.SortOrder = source.SortOrder;
target.State = _basicStateMapper.Map(source, context);
target.Trashed = source.Trashed;
target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key);
target.UpdateDate = GetUpdateDate(source, context);
target.Updater = _commonMapper.GetCreator(source, context.Mapper);
target.VariesByCulture = source.ContentType.VariesByCulture();
}
private IEnumerable<string> GetActions(IContent source)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
//cannot check permissions without a context
if (umbracoContext == null)
return Enumerable.Empty<string>();
string path;
if (source.HasIdentity)
path = source.Path;
else
{
_contentTypeService = contentTypeService;
_localizedTextService = localizedTextService;
var parent = _contentService.GetById(source.ParentId);
path = parent == null ? "-1" : parent.Path;
}
public IDictionary<string, string> Resolve(IContent source, ContentItemDisplay destination, IDictionary<string, string> destMember, ResolutionContext context)
{
var contentType = _contentTypeService.Get(source.ContentTypeId);
// TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is
// with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null
// reference exception :(
return _userService.GetPermissionsForPath(umbracoContext.Security.CurrentUser, path).GetAllPermissions();
}
return contentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(t.Name));
private UrlInfo[] GetUrls(IContent source)
{
if (source.ContentType.IsElement)
return Array.Empty<UrlInfo>();
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
var urls = umbracoContext == null
? new[] { UrlInfo.Message("Cannot generate urls without a current Umbraco Context") }
: source.GetContentUrls(_publishedRouter, umbracoContext, _localizationService, _localizedTextService, _contentService, _logger).ToArray();
return urls;
}
private DateTime GetUpdateDate(IContent source, MapperContext context)
{
// invariant = global date
if (!source.ContentType.VariesByCulture()) return source.UpdateDate;
// variant = depends on culture
var culture = context.GetCulture();
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
if (culture == null)
throw new InvalidOperationException("Missing culture in mapping options.");
// if we don't have a date for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback date
var date = source.GetUpdateDate(culture);
return date ?? source.UpdateDate;
}
private string GetName(IContent source, MapperContext context)
{
// invariant = only 1 name
if (!source.ContentType.VariesByCulture()) return source.Name;
// variant = depends on culture
var culture = context.GetCulture();
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
if (culture == null)
throw new InvalidOperationException("Missing culture in mapping options.");
// if we don't have a name for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback name
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"({source.Name})";
}
private bool DermineIsChildOfListView(IContent source)
{
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
var parent = _contentService.GetParent(source);
return parent != null && (parent.ContentType.IsContainer || _contentTypeService.HasContainerInPath(parent.Path));
}
private DateTime? GetScheduledDate(IContent source, ContentScheduleAction action, MapperContext context)
{
var culture = context.GetCulture() ?? string.Empty;
var schedule = source.ContentSchedule.GetSchedule(culture, action);
return schedule.FirstOrDefault()?.Date; // take the first, it's ordered by date
}
private IDictionary<string, string> GetAllowedTemplates(IContent source)
{
var contentType = _contentTypeService.Get(source.ContentTypeId);
return contentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(t.Name));
}
private string GetDefaultTemplate(IContent source)
{
if (source == null)
return null;
// If no template id was set...
if (!source.TemplateId.HasValue)
{
// ... and no default template is set, return null...
// ... otherwise return the content type default template alias.
return string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)
? null
: source.ContentType.DefaultTemplate?.Alias;
}
var template = _fileService.GetTemplate(source.TemplateId.Value);
return template.Alias;
}
}
}
@@ -1,24 +1,23 @@
using System;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Returns the <see cref="ContentSavedState?"/> for an <see cref="IContent"/> item
/// </summary>
/// <typeparam name="T"></typeparam>
internal class ContentBasicSavedStateResolver<T> : IValueResolver<IContent, IContentProperties<T>, ContentSavedState?>
internal class ContentBasicSavedStateMapper<T>
where T : ContentPropertyBasic
{
private readonly ContentSavedStateResolver<T> _inner = new ContentSavedStateResolver<T>();
private readonly ContentSavedStateMapper<T> _inner = new ContentSavedStateMapper<T>();
public ContentSavedState? Resolve(IContent source, IContentProperties<T> destination, ContentSavedState? destMember, ResolutionContext context)
public ContentSavedState? Map(IContent source, MapperContext context)
{
return _inner.Resolve(source, destination, default, context);
return _inner.Map(source, context);
}
}
@@ -26,10 +25,10 @@ namespace Umbraco.Web.Models.Mapping
/// Returns the <see cref="ContentSavedState"/> for an <see cref="IContent"/> item
/// </summary>
/// <typeparam name="T"></typeparam>
internal class ContentSavedStateResolver<T> : IValueResolver<IContent, IContentProperties<T>, ContentSavedState>
internal class ContentSavedStateMapper<T>
where T : ContentPropertyBasic
{
public ContentSavedState Resolve(IContent source, IContentProperties<T> destination, ContentSavedState destMember, ResolutionContext context)
public ContentSavedState Map(IContent source, MapperContext context)
{
PublishedState publishedState;
bool isEdited;
@@ -38,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping
if (source.ContentType.VariesByCulture())
{
//Get the culture from the context which will be set during the mapping operation for each variant
var culture = context.Options.GetCulture();
var culture = context.GetCulture();
//a culture needs to be in the context for a variant content item
if (culture == null)
@@ -1,31 +0,0 @@
using System.Web.Mvc;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Trees;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Gets the tree node url for the content or media
/// </summary>
internal class ContentTreeNodeUrlResolver<TSource, TController> : IValueResolver<TSource, object, string>
where TSource : IContentBase
where TController : ContentTreeControllerBase
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public ContentTreeNodeUrlResolver(IUmbracoContextAccessor umbracoContextAccessor)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor));
}
public string Resolve(TSource source, object destination, string destMember, ResolutionContext context)
{
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));
}
}
}
@@ -1,43 +0,0 @@
using System;
using System.Linq;
using System.Web;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Resolves a <see cref="ContentTypeBasic"/> from the <see cref="IContent"/> item and checks if the current user
/// has access to see this data
/// </summary>
internal class ContentTypeBasicResolver<TSource, TDestination> : IValueResolver<TSource, TDestination, ContentTypeBasic>
where TSource : IContentBase
{
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
public ContentTypeBasicResolver(IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
public ContentTypeBasic Resolve(TSource source, TDestination destination, ContentTypeBasic destMember, ResolutionContext context)
{
// TODO: We can resolve the UmbracoContext from the IValueResolver options!
// OMG
if (HttpContext.Current != null && Current.UmbracoContext != null && Current.UmbracoContext.Security.CurrentUser != null
&& 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;
}
}
}
@@ -1,52 +0,0 @@
using System.Linq;
using AutoMapper;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Models.Mapping
{
internal class ContentUrlResolver : IValueResolver<IContent, ContentItemDisplay, UrlInfo[]>
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPublishedRouter _publishedRouter;
private readonly ILocalizationService _localizationService;
private readonly ILocalizedTextService _textService;
private readonly IContentService _contentService;
private readonly ILogger _logger;
public ContentUrlResolver(
IUmbracoContextAccessor umbracoContextAccessor,
IPublishedRouter publishedRouter,
ILocalizationService localizationService,
ILocalizedTextService textService,
IContentService contentService,
ILogger logger)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor));
_publishedRouter = publishedRouter ?? throw new System.ArgumentNullException(nameof(publishedRouter));
_localizationService = localizationService ?? throw new System.ArgumentNullException(nameof(localizationService));
_textService = textService ?? throw new System.ArgumentNullException(nameof(textService));
_contentService = contentService ?? throw new System.ArgumentNullException(nameof(contentService));
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
public UrlInfo[] Resolve(IContent source, ContentItemDisplay destination, UrlInfo[] destMember, ResolutionContext context)
{
if (source.ContentType.IsElement)
{
return new UrlInfo[0];
}
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
var urls = umbracoContext == null
? new[] { UrlInfo.Message("Cannot generate urls without a current Umbraco Context") }
: source.GetContentUrls(_publishedRouter, umbracoContext, _localizationService, _textService, _contentService, _logger).ToArray();
return urls;
}
}
}
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
@@ -10,16 +10,16 @@ using Language = Umbraco.Web.Models.ContentEditing.Language;
namespace Umbraco.Web.Models.Mapping
{
internal class ContentVariantResolver : IValueResolver<IContent, ContentItemDisplay, IEnumerable<ContentVariantDisplay>>
internal class ContentVariantMapper
{
private readonly ILocalizationService _localizationService;
public ContentVariantResolver(ILocalizationService localizationService)
public ContentVariantMapper(ILocalizationService localizationService)
{
_localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
}
public IEnumerable<ContentVariantDisplay> Resolve(IContent source, ContentItemDisplay destination, IEnumerable<ContentVariantDisplay> destMember, ResolutionContext context)
public IEnumerable<ContentVariantDisplay> Map(IContent source, MapperContext context)
{
var result = new List<ContentVariantDisplay>();
if (!source.ContentType.VariesByCulture())
@@ -39,7 +39,7 @@ namespace Umbraco.Web.Models.Mapping
{
//We need to set the culture in the mapping context since this is needed to ensure that the correct property values
//are resolved during the mapping
context.Options.SetCulture(x.IsoCode);
context.SetCulture(x.IsoCode);
return context.Mapper.Map<IContent, ContentVariantDisplay>(source, null, context);
}).ToList();
@@ -69,5 +69,4 @@ namespace Umbraco.Web.Models.Mapping
return result;
}
}
}
@@ -1,27 +0,0 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Maps the Creator for content
/// </summary>
internal class CreatorResolver
{
private readonly IUserService _userService;
public CreatorResolver(IUserService userService)
{
_userService = userService;
}
public UserProfile Resolve(IContent source)
{
return Mapper.Map<IProfile, UserProfile>(source.GetWriterProfile(_userService));
}
}
}
@@ -1,33 +0,0 @@
using AutoMapper;
using System.Web.Mvc;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class DefaultTemplateResolver : IValueResolver<IContent, ContentItemDisplay, string>
{
public string Resolve(IContent source, ContentItemDisplay destination, string destMember, ResolutionContext context)
{
if (source == null)
return null;
// If no template id was set...
if (!source.TemplateId.HasValue)
{
// ... and no default template is set, return null...
if (string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias))
return null;
// ... otherwise return the content type default template alias.
return source.ContentType.DefaultTemplate?.Alias;
}
var fileService = DependencyResolver.Current.GetService<IFileService>();
var template = fileService.GetTemplate(source.TemplateId.Value);
return template.Alias;
}
}
}
@@ -1,26 +0,0 @@
using AutoMapper;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Mapping extension methods for re-use with other mappers (saves code duplication)
/// </summary>
internal static class EntityProfileExtensions
{
/// <summary>
/// Ignores readonly properties and the date values
/// </summary>
/// <param name="mapping"></param>
/// <returns></returns>
public static IMappingExpression<TSource, TDest> IgnoreEntityCommonProperties<TSource, TDest>(this IMappingExpression<TSource, TDest> mapping)
where TDest : IEntity
{
return mapping
.IgnoreAllPropertiesWithAnInaccessibleSetter()
.ForMember(dest => dest.CreateDate, opt => opt.Ignore())
.ForMember(dest => dest.UpdateDate, opt => opt.Ignore())
.ForMember(dest => dest.DeleteDate, opt => opt.Ignore());
}
}
}
@@ -1,44 +0,0 @@
using AutoMapper;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Umbraco.Web.Models.Mapping
{
internal class LockedCompositionsResolver
{
private readonly IContentTypeService _contentTypeService;
public LockedCompositionsResolver(IContentTypeService contentTypeService)
{
_contentTypeService = contentTypeService;
}
public IEnumerable<string> Resolve(IContentTypeComposition source)
{
var aliases = new List<string>();
// get ancestor ids from path of parent if not root
if (source.ParentId != Constants.System.Root)
{
var parent = _contentTypeService.Get(source.ParentId);
if (parent != null)
{
var ancestorIds = parent.Path.Split(',').Select(int.Parse);
// loop through all content types and return ordered aliases of ancestors
var allContentTypes = _contentTypeService.GetAll().ToArray();
foreach (var ancestorId in ancestorIds)
{
var ancestor = allContentTypes.FirstOrDefault(x => x.Id == ancestorId);
if (ancestor != null)
{
aliases.Add(ancestor.Alias);
}
}
}
}
return aliases.OrderBy(x => x);
}
}
}
@@ -1,38 +0,0 @@
using AutoMapper;
namespace Umbraco.Web.Models.Mapping
{
// FIXME KILLE THIS CLASS
/// <summary>
/// Provides extension methods for AutoMapper's <see cref="IMappingOperationOptions"/>.
/// </summary>
internal static class MappingOperationOptionsExtensions
{
private const string CultureKey = "MappingOperationOptions.Culture";
private const string IncludedPropertiesKey = "MappingOperationOptions.IncludeProperties";
/// <summary>
/// Gets the context culture.
/// </summary>
public static string GetCulture(this IMappingOperationOptions options)
{
return options.Items.TryGetValue(CultureKey, out var obj) && obj is string s ? s : null;
}
/// <summary>
/// Sets a context culture.
/// </summary>
public static void SetCulture(this IMappingOperationOptions options, string culture)
{
options.Items[CultureKey] = culture;
}
/// <summary>
/// Get included properties.
/// </summary>
public static string[] GetIncludedProperties(this IMappingOperationOptions options)
{
return options.Items.TryGetValue(IncludedPropertiesKey, out var obj) && obj is string[] s ? s : null;
}
}
}
@@ -1,26 +0,0 @@
using System.Collections.Generic;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Models.ContentEditing;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
// injected into ContentMapperProfile,
// maps ContentApps when mapping IMedia to MediaItemDisplay
internal class MediaAppResolver : IValueResolver<IMedia, MediaItemDisplay, IEnumerable<ContentApp>>
{
private readonly ContentAppFactoryCollection _contentAppDefinitions;
public MediaAppResolver(ContentAppFactoryCollection contentAppDefinitions)
{
_contentAppDefinitions = contentAppDefinitions;
}
public IEnumerable<ContentApp> Resolve(IMedia source, MediaItemDisplay destination, IEnumerable<ContentApp> destMember, ResolutionContext context)
{
return _contentAppDefinitions.GetContentAppsFor(source);
}
}
}
@@ -1,26 +0,0 @@
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class MediaChildOfListViewResolver : IValueResolver<IMedia, MediaItemDisplay, bool>
{
private readonly IMediaService _mediaService;
private readonly IMediaTypeService _mediaTypeService;
public MediaChildOfListViewResolver(IMediaService mediaService, IMediaTypeService mediaTypeService)
{
_mediaService = mediaService;
_mediaTypeService = mediaTypeService;
}
public bool Resolve(IMedia source, MediaItemDisplay destination, bool destMember, ResolutionContext context)
{
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
var parent = _mediaService.GetParent(source);
return parent != null && (parent.ContentType.IsContainer || _mediaTypeService.HasContainerInPath(parent.Path));
}
}
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
@@ -7,6 +8,7 @@ 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;
@@ -21,26 +23,19 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
internal class MediaMapperProfile : IMapperProfile
{
private readonly CommonMapper _commonMapper;
private readonly ILogger _logger;
private readonly IUserService _userService;
private readonly IMediaService _mediaService;
private readonly IMediaTypeService _mediaTypeService;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private readonly ContentAppFactoryCollection _contentAppDefinitions;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly TabsAndPropertiesMapper<IMedia> _tabsAndPropertiesMapper;
public MediaMapperProfile(ILogger logger, IUserService userService, IMediaService mediaService, IMediaTypeService mediaTypeService,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, ContentAppFactoryCollection contentAppDefinitions,
IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService)
public MediaMapperProfile(ILogger logger, CommonMapper commonMapper, IMediaService mediaService, IMediaTypeService mediaTypeService,
ILocalizedTextService localizedTextService)
{
_logger = logger;
_userService = userService;
_commonMapper = commonMapper;
_mediaService = mediaService;
_mediaTypeService = mediaTypeService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_contentAppDefinitions = contentAppDefinitions;
_umbracoContextAccessor = umbracoContextAccessor;
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IMedia>(localizedTextService);
}
@@ -54,8 +49,8 @@ namespace Umbraco.Web.Models.Mapping
// Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer
private void Map(IMedia source, MediaItemDisplay target, MapperContext context)
{
target.ContentApps = _contentAppDefinitions.GetContentAppsFor(source);
target.ContentType = GetContentType(source, context.Mapper);
target.ContentApps = _commonMapper.GetContentApps(source);
target.ContentType = _commonMapper.GetContentType(source, context.Mapper);
target.ContentTypeAlias = source.ContentType.Alias;
target.ContentTypeName = source.ContentType.Name;
target.CreateDate = source.CreateDate;
@@ -65,14 +60,14 @@ namespace Umbraco.Web.Models.Mapping
target.Key = source.Key;
target.MediaLink = string.Join(",", source.GetUrls(Current.Configs.Settings().Content, _logger));
target.Name = source.Name;
target.Owner = GetOwner(source, context.Mapper);
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.SortOrder = source.SortOrder;
target.State = null;
target.Tabs = _tabsAndPropertiesMapper.Map(source, context);
target.Trashed = source.Trashed;
target.TreeNodeUrl = GetTreeNodeUrl<MediaTreeController>(source);
target.TreeNodeUrl = _commonMapper.GetTreeNodeUrl<MediaTreeController>(source);
target.Udi = Udi.Create(Constants.UdiEntityType.Media, source.Key);
target.UpdateDate = source.UpdateDate;
target.VariesByCulture = source.ContentType.VariesByCulture();
@@ -87,7 +82,7 @@ namespace Umbraco.Web.Models.Mapping
target.Id = source.Id;
target.Key = source.Key;
target.Name = source.Name;
target.Owner = GetOwner(source, context.Mapper);
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.Properties = context.Mapper.Map<IEnumerable<ContentPropertyBasic>>(source.Properties);
@@ -99,20 +94,46 @@ namespace Umbraco.Web.Models.Mapping
target.VariesByCulture = source.ContentType.VariesByCulture();
}
private UserProfile GetOwner(IContentBase source, Mapper mapper)
{
var profile = source.GetCreatorProfile(_userService);
return profile == null ? null : mapper.Map<IProfile, UserProfile>(profile);
}
private bool DermineIsChildOfListView(IMedia source)
{
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
var parent = _mediaService.GetParent(source);
return parent != null && (parent.ContentType.IsContainer || _mediaTypeService.HasContainerInPath(parent.Path));
}
}
private ContentTypeBasic GetContentType(IContentBase source, Mapper mapper)
// 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
@@ -128,7 +149,7 @@ namespace Umbraco.Web.Models.Mapping
return null;
}
private string GetTreeNodeUrl<TController>(IContentBase source)
public string GetTreeNodeUrl<TController>(IContentBase source)
where TController : ContentTreeControllerBase
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
@@ -137,5 +158,31 @@ namespace Umbraco.Web.Models.Mapping
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;
}
}
}
@@ -1,54 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// A resolver to map <see cref="IMember"/> properties to a collection of <see cref="ContentPropertyBasic"/>
/// </summary>
internal class MemberBasicPropertiesResolver : IValueResolver<IMember, MemberBasic, IEnumerable<ContentPropertyBasic>>
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IMemberTypeService _memberTypeService;
public MemberBasicPropertiesResolver(IUmbracoContextAccessor umbracoContextAccessor, IMemberTypeService memberTypeService)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService));
}
public IEnumerable<ContentPropertyBasic> Resolve(IMember source, MemberBasic destination, IEnumerable<ContentPropertyBasic> destMember, ResolutionContext context)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext == null) throw new InvalidOperationException("Cannot resolve value without an UmbracoContext available");
var result = Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyBasic>>(
// Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties.
source.Properties.OrderBy(prop => prop.PropertyType.SortOrder))
.ToList();
var memberType = _memberTypeService.Get(source.ContentTypeId);
//now update the IsSensitive value
foreach (var prop in result)
{
//check if this property is flagged as sensitive
var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias);
//check permissions for viewing sensitive data
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
{
//mark this property as sensitive
prop.IsSensitive = true;
//clear the value
prop.Value = null;
}
}
return result;
}
}
}
@@ -1,30 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// This ensures that the custom membership provider properties are not mapped - these property values are controller by the membership provider
/// </summary>
/// <remarks>
/// Because these properties don't exist on the form, if we don't remove them for this map we'll get validation errors when posting data
/// </remarks>
internal class MemberDtoPropertiesResolver
{
public IEnumerable<ContentPropertyDto> Resolve(IMember source)
{
var defaultProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
//remove all membership properties, these values are set with the membership provider.
var exclude = defaultProps.Select(x => x.Value.Alias).ToArray();
return source.Properties
.Where(x => exclude.Contains(x.Alias) == false)
.Select(Mapper.Map<Property, ContentPropertyDto>);
}
}
}
@@ -1,154 +1,185 @@
using System;
using System.Collections.Generic;
using System.Web.Security;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Core.Services.Implement;
using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Declares model mappings for members.
/// </summary>
internal class MemberMapperProfile : Profile
internal class MemberMapperProfile : IMapperProfile
{
public MemberMapperProfile(
MemberTabsAndPropertiesMapper tabsAndPropertiesMapper,
MemberTreeNodeUrlResolver memberTreeNodeUrlResolver,
MemberBasicPropertiesResolver memberBasicPropertiesResolver,
IUserService userService,
IMemberTypeService memberTypeService,
IMemberService memberService)
private readonly CommonMapper _commonMapper;
private readonly IMemberTypeService _memberTypeService;
private readonly TabsAndPropertiesMapper<IMember> _tabsAndPropertiesMapper;
public MemberMapperProfile(CommonMapper commonMapper, IMemberTypeService memberTypeService, ILocalizedTextService localizedTextService)
{
// create, capture, cache
var memberOwnerResolver = new OwnerResolver<IMember>(userService);
var memberProfiderFieldMappingResolver = new MemberProviderFieldResolver();
var membershipScenarioMappingResolver = new MembershipScenarioResolver(memberTypeService);
var memberDtoPropertiesResolver = new MemberDtoPropertiesResolver();
_commonMapper = commonMapper;
_memberTypeService = memberTypeService;
//FROM MembershipUser TO MediaItemDisplay - used when using a non-umbraco membership provider
CreateMap<MembershipUser, MemberDisplay>().ConvertUsing<MembershipUserTypeConverter>();
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IMember>(localizedTextService);
}
//FROM MembershipUser TO IMember - used when using a non-umbraco membership provider
CreateMap<MembershipUser, IMember>()
.ConstructUsing(src => MemberService.CreateGenericMembershipProviderMember(src.UserName, src.Email, src.UserName, ""))
//we're giving this entity an ID of int.MaxValue - TODO: SD: I can't remember why this mapping is here?
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue))
.ForMember(dest => dest.Comments, opt => opt.MapFrom(src => src.Comment))
.ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreationDate))
.ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.LastActivityDate))
.ForMember(dest => dest.LastPasswordChangeDate, opt => opt.MapFrom(src => src.LastPasswordChangedDate))
.ForMember(dest => dest.Key, opt => opt.MapFrom(src => src.ProviderUserKey.TryConvertTo<Guid>().Result.ToString("N")))
//This is a special case for password - we don't actually care what the password is but it either needs to be something or nothing
// so we'll set it to something if the member is actually created, otherwise nothing if it is a new member.
.ForMember(dest => dest.RawPasswordValue, opt => opt.MapFrom(src => src.CreationDate > DateTime.MinValue ? Guid.NewGuid().ToString("N") : ""))
.ForMember(dest => dest.Properties, opt => opt.Ignore())
.ForMember(dest => dest.CreatorId, opt => opt.Ignore())
.ForMember(dest => dest.Level, opt => opt.Ignore())
.ForMember(dest => dest.Name, opt => opt.Ignore())
.ForMember(dest => dest.CultureInfos, opt => opt.Ignore())
.ForMember(dest => dest.ParentId, opt => opt.Ignore())
.ForMember(dest => dest.Path, opt => opt.Ignore())
.ForMember(dest => dest.SortOrder, opt => opt.Ignore())
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore())
.ForMember(dest => dest.FailedPasswordAttempts, opt => opt.Ignore())
.ForMember(dest => dest.DeleteDate, opt => opt.Ignore())
.ForMember(dest => dest.WriterId, opt => opt.Ignore())
.ForMember(dest => dest.VersionId, opt => opt.Ignore())
// TODO: Support these eventually
.ForMember(dest => dest.PasswordQuestion, opt => opt.Ignore())
.ForMember(dest => dest.RawPasswordAnswerValue, opt => opt.Ignore());
public void SetMaps(Mapper mapper)
{
mapper.Define<MembershipUser, MemberDisplay>((source, context) => new MemberDisplay(), Map);
mapper.Define<MembershipUser, IMember>((source, context) => MemberService.CreateGenericMembershipProviderMember(source.UserName, source.Email, source.UserName, ""), Map);
mapper.Define<IMember, MemberDisplay>((source, context) => new MemberDisplay(), Map);
mapper.Define<IMember, MemberBasic>((source, context) => new MemberBasic(), Map);
mapper.Define<MembershipUser, MemberBasic>((source, context) => new MemberBasic(), Map);
mapper.Define<IMemberGroup, MemberGroupDisplay>((source, context) => new MemberGroupDisplay(), Map);
}
//FROM IMember TO MemberDisplay
CreateMap<IMember, MemberDisplay>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
.ForMember(dest => dest.Owner, opt => opt.MapFrom(src => memberOwnerResolver.Resolve(src)))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon))
.ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias))
.ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => src.ContentType.Name))
.ForMember(dest => dest.Properties, opt => opt.Ignore())
.ForMember(dest => dest.Tabs, opt => opt.MapFrom(tabsAndPropertiesMapper))
.ForMember(dest => dest.MemberProviderFieldMapping, opt => opt.MapFrom(src => memberProfiderFieldMappingResolver.Resolve(src)))
.ForMember(dest => dest.MembershipScenario, opt => opt.MapFrom(src => membershipScenarioMappingResolver.Resolve(src)))
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.Errors, opt => opt.Ignore())
.ForMember(dest => dest.State, opt => opt.MapFrom<ContentSavedState?>(_ => null))
.ForMember(dest => dest.Edited, opt => opt.Ignore())
.ForMember(dest => dest.Updater, opt => opt.Ignore())
.ForMember(dest => dest.Alias, opt => opt.Ignore())
.ForMember(dest => dest.IsChildOfListView, opt => opt.Ignore())
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
.ForMember(dest => dest.IsContainer, opt => opt.Ignore())
.ForMember(dest => dest.TreeNodeUrl, opt => opt.MapFrom(memberTreeNodeUrlResolver))
.ForMember(dest => dest.VariesByCulture, opt => opt.Ignore());
private void Map(MembershipUser source, MemberDisplay target, MapperContext context)
{
//first convert to IMember
var member = context.Mapper.Map<IMember>(source);
//then convert to MemberDisplay
context.Mapper.Map<IMember, MemberDisplay>(member);
}
//FROM IMember TO MemberBasic
CreateMap<IMember, MemberBasic>()
//we're giving this entity an ID of int.MaxValue - this is kind of a hack to force angular to use the Key instead of the Id in list views
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue))
.ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
.ForMember(dest => dest.Owner, opt => opt.MapFrom(src => memberOwnerResolver.Resolve(src)))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon))
.ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
.ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.Username))
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
.ForMember(dest => dest.State, opt => opt.MapFrom<ContentSavedState?>(_ => null))
.ForMember(dest => dest.Edited, opt => opt.Ignore())
.ForMember(dest => dest.Updater, opt => opt.Ignore())
.ForMember(dest => dest.Alias, opt => opt.Ignore())
.ForMember(dto => dto.Properties, expression => expression.MapFrom(memberBasicPropertiesResolver))
.ForMember(dest => dest.VariesByCulture, opt => opt.Ignore());
// TODO: SD: I can't remember why this mapping is here?
// Umbraco.Code.MapAll -Properties -CreatorId -Level -Name -CultureInfos -ParentId
// Umbraco.Code.MapAll -Path -SortOrder -DeleteDate -WriterId -VersionId -PasswordQuestion
// Umbraco.Code.MapAll -RawPasswordAnswerValue -FailedPasswordAttempts
private void Map(MembershipUser source, IMember target, MapperContext context)
{
target.Comments = source.Comment;
target.CreateDate = source.CreationDate;
target.Email = source.Email;
target.Id = int.MaxValue;
target.IsApproved = source.IsApproved;
target.IsLockedOut = source.IsLockedOut;
target.Key = source.ProviderUserKey.TryConvertTo<Guid>().Result;
target.LastLockoutDate = source.LastLockoutDate;
target.LastLoginDate = source.LastLoginDate;
target.LastPasswordChangeDate = source.LastPasswordChangedDate;
target.ProviderUserKey = source.ProviderUserKey;
target.RawPasswordValue = source.CreationDate > DateTime.MinValue ? Guid.NewGuid().ToString("N") : "";
target.UpdateDate = source.LastActivityDate;
target.Username = source.UserName;
}
//FROM MembershipUser TO MemberBasic
CreateMap<MembershipUser, MemberBasic>()
//we're giving this entity an ID of int.MaxValue - TODO: SD: I can't remember why this mapping is here?
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue))
.ForMember(dest => dest.Udi, opt => opt.Ignore())
.ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreationDate))
.ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.LastActivityDate))
.ForMember(dest => dest.Key, opt => opt.MapFrom(src => src.ProviderUserKey.TryConvertTo<Guid>().Result.ToString("N")))
.ForMember(dest => dest.Owner, opt => opt.MapFrom(_ => new UserProfile {Name = "Admin", UserId = -1 }))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(_ => "icon-user"))
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.UserName))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
.ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.UserName))
.ForMember(dest => dest.Properties, opt => opt.Ignore())
.ForMember(dest => dest.ParentId, opt => opt.Ignore())
.ForMember(dest => dest.Path, opt => opt.Ignore())
.ForMember(dest => dest.SortOrder, opt => opt.Ignore())
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore())
.ForMember(dest => dest.State, opt => opt.MapFrom(_ => ContentSavedState.Draft))
.ForMember(dest => dest.Edited, opt => opt.Ignore())
.ForMember(dest => dest.Updater, opt => opt.Ignore())
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
.ForMember(dest => dest.Alias, opt => opt.Ignore())
.ForMember(dest => dest.ContentTypeAlias, opt => opt.Ignore())
.ForMember(dest => dest.VariesByCulture, opt => opt.Ignore());
// Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsChildOfListView
// Umbraco.Code.MapAll -Trashed -IsContainer -VariesByCulture
private void Map(IMember source, MemberDisplay target, MapperContext context)
{
target.ContentTypeAlias = source.ContentType.Alias;
target.ContentTypeName = source.ContentType.Name;
target.CreateDate = source.CreateDate;
target.Email = source.Email;
target.Icon = source.ContentType.Icon;
target.Id = source.Id;
target.Key = source.Key;
target.MemberProviderFieldMapping = GetMemberProviderFieldMapping();
target.MembershipScenario = GetMembershipScenario();
target.Name = source.Name;
target.Owner = _commonMapper.GetOwner(source, context.Mapper);
target.ParentId = source.ParentId;
target.Path = source.Path;
target.SortOrder = source.SortOrder;
target.State = null;
target.Tabs = _tabsAndPropertiesMapper.Map(source, context);
target.TreeNodeUrl = _commonMapper.GetMemberTreeNodeUrl(source);
target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key);
target.UpdateDate = source.UpdateDate;
target.Username = source.Username;
}
//FROM IMember TO ContentItemDto<IMember>
CreateMap<IMember, ContentPropertyCollectionDto>()
//.ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
//.ForMember(dest => dest.Owner, opt => opt.MapFrom(src => memberOwnerResolver.Resolve(src)))
//.ForMember(dest => dest.Published, opt => opt.Ignore())
//.ForMember(dest => dest.Edited, opt => opt.Ignore())
//.ForMember(dest => dest.Updater, opt => opt.Ignore())
//.ForMember(dest => dest.Icon, opt => opt.Ignore())
//.ForMember(dest => dest.Alias, opt => opt.Ignore())
//do no map the custom member properties (currently anyways, they were never there in 6.x)
.ForMember(dest => dest.Properties, opt => opt.MapFrom(src => memberDtoPropertiesResolver.Resolve(src)));
// Umbraco.Code.MapAll -Trashed -Edited -Updater -Alias -VariesByCulture
private void Map(IMember source, MemberBasic target, MapperContext context)
{
target.ContentTypeAlias = source.ContentType.Alias;
target.CreateDate = source.CreateDate;
target.Email = source.Email;
target.Icon = source.ContentType.Icon;
target.Id = int.MaxValue;
target.Key = source.Key;
target.Name = source.Name;
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.SortOrder = source.SortOrder;
target.State = null;
target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key);
target.UpdateDate = source.UpdateDate;
target.Username = source.Username;
}
//FROM IMemberGroup TO MemberGroupDisplay
CreateMap<IMemberGroup, MemberGroupDisplay>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(Constants.UdiEntityType.MemberGroup, src.Key)))
.ForMember(dest => dest.Path, opt => opt.MapFrom(group => "-1," + group.Id))
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.Icon, opt => opt.Ignore())
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
.ForMember(dest => dest.ParentId, opt => opt.Ignore())
.ForMember(dest => dest.Alias, opt => opt.Ignore());
//TODO: SD: I can't remember why this mapping is here?
// Umbraco.Code.MapAll -Udi -Properties -ParentId -Path -SortOrder -Edited -Updater
// Umbraco.Code.MapAll -Trashed -Alias -ContentTypeAlias -VariesByCulture
private void Map(MembershipUser source, MemberBasic target, MapperContext context)
{
target.CreateDate = source.CreationDate;
target.Email = source.Email;
target.Icon = "icon-user";
target.Id = int.MaxValue;
target.Key = source.ProviderUserKey.TryConvertTo<Guid>().Result;
target.Name = source.UserName;
target.Owner = new UserProfile { Name = "Admin", UserId = -1 };
target.State = ContentSavedState.Draft;
target.UpdateDate = source.LastActivityDate;
target.Username = source.UserName;
}
// Umbraco.Code.MapAll -Icon -Trashed -ParentId -Alias
private void Map(IMemberGroup source, MemberGroupDisplay target, MapperContext context)
{
target.Id = source.Id;
target.Key = source.Key;
target.Name = source.Name;
target.Path = "-1" + source.Id;
target.Udi = Udi.Create(Constants.UdiEntityType.MemberGroup, source.Key);
}
private MembershipScenario GetMembershipScenario()
{
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
if (provider.IsUmbracoMembershipProvider())
{
return MembershipScenario.NativeUmbraco;
}
var memberType = _memberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias);
return memberType != null
? MembershipScenario.CustomProviderWithUmbracoLink
: MembershipScenario.StandaloneCustomProvider;
}
private static IDictionary<string, string> GetMemberProviderFieldMapping()
{
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
if (provider.IsUmbracoMembershipProvider() == false)
{
return new Dictionary<string, string>
{
{Constants.Conventions.Member.IsLockedOut, Constants.Conventions.Member.IsLockedOut},
{Constants.Conventions.Member.IsApproved, Constants.Conventions.Member.IsApproved},
{Constants.Conventions.Member.Comments, Constants.Conventions.Member.Comments}
};
}
var umbracoProvider = (IUmbracoMemberTypeMembershipProvider)provider;
return new Dictionary<string, string>
{
{Constants.Conventions.Member.IsLockedOut, umbracoProvider.LockPropertyTypeAlias},
{Constants.Conventions.Member.IsApproved, umbracoProvider.ApprovedPropertyTypeAlias},
{Constants.Conventions.Member.Comments, umbracoProvider.CommentPropertyTypeAlias}
};
}
}
}
@@ -1,39 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// A resolver to map the provider field aliases
/// </summary>
internal class MemberProviderFieldResolver
{
public IDictionary<string, string> Resolve(IMember source)
{
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
if (provider.IsUmbracoMembershipProvider() == false)
{
return new Dictionary<string, string>
{
{Constants.Conventions.Member.IsLockedOut, Constants.Conventions.Member.IsLockedOut},
{Constants.Conventions.Member.IsApproved, Constants.Conventions.Member.IsApproved},
{Constants.Conventions.Member.Comments, Constants.Conventions.Member.Comments}
};
}
else
{
var umbracoProvider = (IUmbracoMemberTypeMembershipProvider) provider;
return new Dictionary<string, string>
{
{Constants.Conventions.Member.IsLockedOut, umbracoProvider.LockPropertyTypeAlias},
{Constants.Conventions.Member.IsApproved, umbracoProvider.ApprovedPropertyTypeAlias},
{Constants.Conventions.Member.Comments, umbracoProvider.CommentPropertyTypeAlias}
};
}
}
}
}
@@ -1,30 +0,0 @@
using System.Web.Mvc;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Trees;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Gets the tree node url for the IMember
/// </summary>
internal class MemberTreeNodeUrlResolver : IValueResolver<IMember, MemberDisplay, string>
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public MemberTreeNodeUrlResolver(IUmbracoContextAccessor umbracoContextAccessor)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor));
}
public string Resolve(IMember source, MemberDisplay destination, string destMember, ResolutionContext context)
{
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));
}
}
}
@@ -1,33 +0,0 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
namespace Umbraco.Web.Models.Mapping
{
internal class MembershipScenarioResolver
{
private readonly IMemberTypeService _memberTypeService;
public MembershipScenarioResolver(IMemberTypeService memberTypeService)
{
_memberTypeService = memberTypeService;
}
public MembershipScenario Resolve(IMember source)
{
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
if (provider.IsUmbracoMembershipProvider())
{
return MembershipScenario.NativeUmbraco;
}
var memberType = _memberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias);
return memberType != null
? MembershipScenario.CustomProviderWithUmbracoLink
: MembershipScenario.StandaloneCustomProvider;
}
}
}
@@ -1,21 +0,0 @@
using System.Web.Security;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// A converter to go from a <see cref="MembershipUser"/> to a <see cref="MemberDisplay"/>
/// </summary>
internal class MembershipUserTypeConverter : ITypeConverter<MembershipUser, MemberDisplay>
{
public MemberDisplay Convert(MembershipUser source, MemberDisplay destination, ResolutionContext context)
{
//first convert to IMember
var member = Mapper.Map<IMember>(source);
//then convert to MemberDisplay
return Mapper.Map<MemberDisplay>(member);
}
}
}
@@ -1,30 +0,0 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Maps the Owner for IContentBase
/// </summary>
/// <typeparam name="TPersisted"></typeparam>
internal class OwnerResolver<TPersisted>
where TPersisted : IContentBase
{
private readonly IUserService _userService;
public OwnerResolver(IUserService userService)
{
_userService = userService;
}
public UserProfile Resolve(TPersisted source)
{
var profile = source.GetCreatorProfile(_userService);
return profile == null ? null : Mapper.Map<IProfile, UserProfile>(profile);
}
}
}
@@ -1,18 +0,0 @@
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>
where TSource : ContentTypeSave<TPropertyTypeSource>
where TPropertyTypeDestination : PropertyTypeDisplay
where TPropertyTypeSource : PropertyTypeBasic
{
public IEnumerable<PropertyGroupDisplay<TPropertyTypeDestination>> Resolve(TSource source)
{
return source.Groups.Select(Mapper.Map<PropertyGroupDisplay<TPropertyTypeDestination>>);
}
}
}
@@ -1,18 +0,0 @@
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
using ContentVariation = Umbraco.Core.Models.ContentVariation;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Returns the <see cref="ContentVariation"/> for a <see cref="PropertyType"/>
/// </summary>
internal class PropertyTypeVariationsResolver: IValueResolver<PropertyTypeBasic, PropertyType, ContentVariation>
{
public ContentVariation Resolve(PropertyTypeBasic source, PropertyType destination, ContentVariation destMember, ResolutionContext context)
{
return source.AllowCultureVariant ? ContentVariation.Culture : ContentVariation.Nothing;
}
}
}
@@ -1,27 +0,0 @@
using System;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class ScheduledPublishDateResolver : IValueResolver<IContent, ContentVariantDisplay, DateTime?>
{
private readonly ContentScheduleAction _changeType;
public ScheduledPublishDateResolver(ContentScheduleAction changeType)
{
_changeType = changeType;
}
public DateTime? Resolve(IContent source, ContentVariantDisplay destination, DateTime? destMember, ResolutionContext context)
{
var culture = context.Options.GetCulture();
var sched = source.ContentSchedule.GetSchedule(culture ?? string.Empty, _changeType);
foreach(var s in sched)
return s.Date; // take the first, it's ordered by date
return null;
}
}
}
@@ -1,12 +1,8 @@
using System.Net.Http;
using System.Security.Claims;
using System.Security.Principal;
using System.ServiceModel.Channels;
using System.Threading;
using System.Web;
using AutoMapper;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.Security
+7 -7
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web.Models;
@@ -64,37 +64,37 @@ namespace Umbraco.Web
/// <inheritdoc />
public IEnumerable<TagModel> GetAllTags(string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllTags(group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllTags(group, culture));
}
/// <inheritdoc />
public IEnumerable<TagModel> GetAllContentTags(string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllContentTags(group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllContentTags(group, culture));
}
/// <inheritdoc />
public IEnumerable<TagModel> GetAllMediaTags(string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllMediaTags(group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllMediaTags(group, culture));
}
/// <inheritdoc />
public IEnumerable<TagModel> GetAllMemberTags(string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllMemberTags(group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetAllMemberTags(group, culture));
}
/// <inheritdoc />
public IEnumerable<TagModel> GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetTagsForProperty(contentId, propertyTypeAlias, group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetTagsForProperty(contentId, propertyTypeAlias, group, culture));
}
/// <inheritdoc />
public IEnumerable<TagModel> GetTagsForEntity(int contentId, string group = null, string culture = null)
{
return Mapper.Map<IEnumerable<TagModel>>(_tagService.GetTagsForEntity(contentId, group, culture));
return Current.Mapper.Map<IEnumerable<TagModel>>(_tagService.GetTagsForEntity(contentId, group, culture));
}
}
}
+2 -26
View File
@@ -60,7 +60,6 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="ClientDependency" Version="1.9.7" />
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
<PackageReference Include="Examine" Version="1.0.0" />
@@ -245,12 +244,10 @@
<Compile Include="Models\ContentEditing\SearchResult.cs" />
<Compile Include="Models\ContentEditing\SearchResults.cs" />
<Compile Include="Models\ContentEditing\UnpublishContent.cs" />
<Compile Include="Models\Mapping\MappingOperationOptionsExtensions.cs" />
<Compile Include="ContentApps\ContentAppFactoryCollection.cs" />
<Compile Include="ContentApps\ContentAppFactoryCollectionBuilder.cs" />
<Compile Include="ContentApps\ContentEditorContentAppFactory.cs" />
<Compile Include="ContentApps\ContentInfoContentAppFactory.cs" />
<Compile Include="Models\Mapping\ScheduledPublishDateResolver.cs" />
<Compile Include="Services\ITreeService.cs" />
<Compile Include="Services\ISectionService.cs" />
<Compile Include="Sections\SectionCollection.cs" />
@@ -282,7 +279,7 @@
<Compile Include="Models\ContentEditing\ContentDomainsAndCulture.cs" />
<Compile Include="Models\ContentEditing\ContentSavedState.cs" />
<Compile Include="Trees\LogViewerTreeController.cs" />
<Compile Include="Models\Mapping\ContentSavedStateResolver.cs" />
<Compile Include="Models\Mapping\ContentSavedStateMapper.cs" />
<Compile Include="Mvc\ContainerControllerFactory.cs" />
<Compile Include="OwinExtensions.cs" />
<Compile Include="Security\BackOfficeCookieAuthenticationProvider.cs" />
@@ -421,31 +418,14 @@
<Compile Include="Models\ContentEditing\UserSave.cs" />
<Compile Include="Models\ContentEditing\Language.cs" />
<Compile Include="Models\ContentTypeImportModel.cs" />
<Compile Include="Models\Mapping\ActionButtonsResolver.cs" />
<Compile Include="Models\Mapping\AuditMapperProfile.cs" />
<Compile Include="Models\Mapping\ContentAppResolver.cs" />
<Compile Include="Models\Mapping\ContentChildOfListViewResolver.cs" />
<Compile Include="Models\Mapping\ContentUrlResolver.cs" />
<Compile Include="Models\Mapping\DefaultTemplateResolver.cs" />
<Compile Include="Models\Mapping\DictionaryMapperProfile.cs" />
<Compile Include="Models\Mapping\LanguageMapperProfile.cs" />
<Compile Include="Models\Mapping\MediaAppResolver.cs" />
<Compile Include="Models\Mapping\MediaChildOfListViewResolver.cs" />
<Compile Include="Models\Mapping\CodeFileMapperProfile.cs" />
<Compile Include="Models\Mapping\ContentTreeNodeUrlResolver.cs" />
<Compile Include="Models\Mapping\EntityProfileExtensions.cs" />
<Compile Include="Models\Mapping\ContentTypeBasicResolver.cs" />
<Compile Include="Models\Mapping\MemberBasicPropertiesResolver.cs" />
<Compile Include="Models\Mapping\MemberDtoPropertiesResolver.cs" />
<Compile Include="Models\Mapping\MemberProviderFieldResolver.cs" />
<Compile Include="Models\Mapping\MembershipScenarioResolver.cs" />
<Compile Include="Models\Mapping\MembershipUserTypeConverter.cs" />
<Compile Include="Models\Mapping\MemberTabsAndPropertiesMapper.cs" />
<Compile Include="Models\Mapping\MemberTreeNodeUrlResolver.cs" />
<Compile Include="Models\Mapping\PropertyTypeVariationsResolver.cs" />
<Compile Include="Models\Mapping\RedirectUrlMapperProfile.cs" />
<Compile Include="Models\Mapping\TemplateMapperProfile.cs" />
<Compile Include="Models\Mapping\ContentItemDisplayVariationResolver.cs" />
<Compile Include="Models\Mapping\ContentVariantMapper.cs" />
<Compile Include="Models\PublishedContent\HttpContextVariationContextAccessor.cs" />
<Compile Include="Models\PublishedContent\PublishedValueFallback.cs" />
<Compile Include="Models\SendCodeViewModel.cs" />
@@ -652,8 +632,6 @@
<Compile Include="Models\ContentEditing\PropertyTypeBasic.cs" />
<Compile Include="Models\ContentEditing\SimpleNotificationModel.cs" />
<Compile Include="Models\LocalPackageInstallModel.cs" />
<Compile Include="Models\Mapping\LockedCompositionsResolver.cs" />
<Compile Include="Models\Mapping\PropertyGroupDisplayResolver.cs" />
<Compile Include="Models\PackageInstallResult.cs" />
<Compile Include="Models\SetPasswordModel.cs" />
<Compile Include="Models\RequestPasswordResetModel.cs" />
@@ -967,11 +945,9 @@
<Compile Include="Models\Mapping\ContentPropertyDisplayMapper.cs" />
<Compile Include="Models\Mapping\ContentPropertyDtoMapper.cs" />
<Compile Include="Models\Mapping\ContentPropertyMapperProfile.cs" />
<Compile Include="Models\Mapping\CreatorResolver.cs" />
<Compile Include="Models\Mapping\MediaMapperProfile.cs" />
<Compile Include="Models\Mapping\ContentTypeMapperProfile.cs" />
<Compile Include="Models\Mapping\ContentMapperProfile.cs" />
<Compile Include="Models\Mapping\OwnerResolver.cs" />
<Compile Include="Models\Mapping\SectionMapperProfile.cs" />
<Compile Include="Models\Mapping\TabsAndPropertiesMapper.cs" />
<Compile Include="Models\Mapping\UserMapperProfile.cs" />