2017-07-19 13:42:47 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using AutoMapper;
|
|
|
|
|
|
using Examine;
|
|
|
|
|
|
using Examine.LuceneEngine.Providers;
|
|
|
|
|
|
using Examine.LuceneEngine;
|
|
|
|
|
|
using Umbraco.Core;
|
|
|
|
|
|
using Umbraco.Core.Models;
|
2018-01-15 11:32:30 +01:00
|
|
|
|
using Umbraco.Core.Models.Entities;
|
2017-07-19 13:42:47 +02:00
|
|
|
|
using Umbraco.Core.Models.Membership;
|
|
|
|
|
|
using Umbraco.Web.Models.ContentEditing;
|
2017-07-27 12:01:38 +02:00
|
|
|
|
using Umbraco.Examine;
|
2017-07-19 13:42:47 +02:00
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Web.Models.Mapping
|
|
|
|
|
|
{
|
2017-09-20 20:06:46 +02:00
|
|
|
|
internal class EntityMapperProfile : Profile
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
2018-01-15 11:32:30 +01:00
|
|
|
|
private static string GetContentTypeIcon(EntitySlim entity)
|
|
|
|
|
|
=> entity is ContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null;
|
|
|
|
|
|
|
2017-09-20 20:06:46 +02:00
|
|
|
|
public EntityMapperProfile()
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
// create, capture, cache
|
|
|
|
|
|
var contentTypeUdiResolver = new ContentTypeUdiResolver();
|
|
|
|
|
|
|
2018-01-15 11:32:30 +01:00
|
|
|
|
CreateMap<EntitySlim, EntityBasic>()
|
2018-09-26 16:27:34 +02:00
|
|
|
|
.ForMember(dest => dest.Name, opt => opt.ResolveUsing<NameResolver>())
|
2018-01-15 11:32:30 +01:00
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key)))
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => GetContentTypeIcon(src)))
|
2018-03-27 10:04:07 +02:00
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
.ForMember(dest => dest.Alias, opt => opt.Ignore())
|
|
|
|
|
|
.AfterMap((src, dest) =>
|
|
|
|
|
|
{
|
2018-01-12 10:48:36 +01:00
|
|
|
|
if (src.NodeObjectType == Constants.ObjectTypes.Member && dest.Icon.IsNullOrWhiteSpace())
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
dest.Icon = "icon-user";
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<PropertyType, EntityBasic>()
|
|
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.UseValue("icon-box"))
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.UseValue(""))
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.UseValue(-1))
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<PropertyGroup, EntityBasic>()
|
|
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.UseValue("icon-tab"))
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.UseValue(""))
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.UseValue(-1))
|
|
|
|
|
|
//in v6 the 'alias' is it's lower cased name so we'll stick to that.
|
|
|
|
|
|
.ForMember(dest => dest.Alias, opt => opt.MapFrom(src => src.Name.ToLowerInvariant()))
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<IUser, EntityBasic>()
|
|
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.UseValue("icon-user"))
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.UseValue(""))
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.UseValue(-1))
|
|
|
|
|
|
.ForMember(dest => dest.Alias, opt => opt.MapFrom(src => src.Username))
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<ITemplate, EntityBasic>()
|
|
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(Constants.UdiEntityType.Template, src.Key)))
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.UseValue("icon-layout"))
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.MapFrom(src => src.Path))
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.UseValue(-1))
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<EntityBasic, ContentTypeSort>()
|
|
|
|
|
|
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => new Lazy<int>(() => Convert.ToInt32(src.Id))))
|
|
|
|
|
|
.ForMember(dest => dest.SortOrder, opt => opt.Ignore());
|
|
|
|
|
|
|
|
|
|
|
|
CreateMap<IContentTypeComposition, EntityBasic>()
|
|
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.ResolveUsing(src => contentTypeUdiResolver.Resolve(src)))
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.MapFrom(src => src.Path))
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentId))
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
|
|
|
|
|
|
|
2018-12-04 14:25:37 +11:00
|
|
|
|
CreateMap<EntitySlim, SearchResultEntity>()
|
2018-01-15 11:32:30 +01:00
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key)))
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src=> GetContentTypeIcon(src)))
|
2017-09-12 16:22:16 +02:00
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Alias, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Score, opt => opt.Ignore())
|
|
|
|
|
|
.AfterMap((entity, basic) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (basic.Icon.IsNullOrWhiteSpace())
|
|
|
|
|
|
{
|
2018-01-12 10:48:36 +01:00
|
|
|
|
if (entity.NodeObjectType == Constants.ObjectTypes.Member)
|
2017-09-12 16:22:16 +02:00
|
|
|
|
basic.Icon = "icon-user";
|
2018-01-12 10:48:36 +01:00
|
|
|
|
else if (entity.NodeObjectType == Constants.ObjectTypes.DataType)
|
2017-09-12 16:22:16 +02:00
|
|
|
|
basic.Icon = "icon-autofill";
|
2018-01-12 10:48:36 +01:00
|
|
|
|
else if (entity.NodeObjectType == Constants.ObjectTypes.DocumentType)
|
2017-09-12 16:22:16 +02:00
|
|
|
|
basic.Icon = "icon-item-arrangement";
|
2018-01-12 10:48:36 +01:00
|
|
|
|
else if (entity.NodeObjectType == Constants.ObjectTypes.MediaType)
|
2017-09-12 16:22:16 +02:00
|
|
|
|
basic.Icon = "icon-thumbnails";
|
2018-01-12 10:48:36 +01:00
|
|
|
|
else if (entity.NodeObjectType == Constants.ObjectTypes.TemplateType)
|
2017-09-12 16:22:16 +02:00
|
|
|
|
basic.Icon = "icon-newspaper-alt";
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2018-12-04 14:25:37 +11:00
|
|
|
|
CreateMap<ISearchResult, SearchResultEntity>()
|
2017-07-19 13:42:47 +02:00
|
|
|
|
//default to document icon
|
2017-09-12 16:22:16 +02:00
|
|
|
|
.ForMember(dest => dest.Score, opt => opt.MapFrom(result => result.Score))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
.ForMember(dest => dest.Udi, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Icon, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
|
|
|
|
|
|
.ForMember(dest => dest.Name, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Key, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.ParentId, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Alias, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Path, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
|
|
|
|
|
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore())
|
|
|
|
|
|
.AfterMap((src, dest) =>
|
2017-07-20 11:21:28 +02:00
|
|
|
|
{
|
2018-12-11 17:54:10 +11:00
|
|
|
|
//TODO: Properly map this (not aftermap)
|
|
|
|
|
|
|
2017-07-19 13:42:47 +02:00
|
|
|
|
//get the icon if there is one
|
2018-12-10 13:06:39 +11:00
|
|
|
|
dest.Icon = src.Values.ContainsKey(UmbracoExamineIndex.IconFieldName)
|
|
|
|
|
|
? src.Values[UmbracoExamineIndex.IconFieldName]
|
2017-07-19 13:42:47 +02:00
|
|
|
|
: "icon-document";
|
|
|
|
|
|
|
2018-11-26 17:20:15 +11:00
|
|
|
|
dest.Name = src.Values.ContainsKey("nodeName") ? src.Values["nodeName"] : "[no name]";
|
2018-12-10 13:06:39 +11:00
|
|
|
|
if (src.Values.ContainsKey(UmbracoExamineIndex.NodeKeyFieldName))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
Guid key;
|
2018-12-10 13:06:39 +11:00
|
|
|
|
if (Guid.TryParse(src.Values[UmbracoExamineIndex.NodeKeyFieldName], out key))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
dest.Key = key;
|
|
|
|
|
|
|
|
|
|
|
|
//need to set the UDI
|
2018-11-29 13:55:51 +11:00
|
|
|
|
if (src.Values.ContainsKey(LuceneIndex.CategoryFieldName))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
2018-11-29 13:55:51 +11:00
|
|
|
|
switch (src.Values[LuceneIndex.CategoryFieldName])
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
case IndexTypes.Member:
|
|
|
|
|
|
dest.Udi = new GuidUdi(Constants.UdiEntityType.Member, dest.Key);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IndexTypes.Content:
|
|
|
|
|
|
dest.Udi = new GuidUdi(Constants.UdiEntityType.Document, dest.Key);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IndexTypes.Media:
|
|
|
|
|
|
dest.Udi = new GuidUdi(Constants.UdiEntityType.Media, dest.Key);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-26 17:20:15 +11:00
|
|
|
|
if (src.Values.ContainsKey("parentID"))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
int parentId;
|
2018-11-26 17:20:15 +11:00
|
|
|
|
if (int.TryParse(src.Values["parentID"], out parentId))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
|
|
|
|
|
dest.ParentId = parentId;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
dest.ParentId = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-12-10 13:06:39 +11:00
|
|
|
|
dest.Path = src.Values.ContainsKey(UmbracoExamineIndex.IndexPathFieldName) ? src.Values[UmbracoExamineIndex.IndexPathFieldName] : "";
|
2017-07-20 11:21:28 +02:00
|
|
|
|
|
2018-11-29 13:55:51 +11:00
|
|
|
|
if (src.Values.ContainsKey(LuceneIndex.ItemTypeFieldName))
|
2017-07-19 13:42:47 +02:00
|
|
|
|
{
|
2018-11-29 13:55:51 +11:00
|
|
|
|
dest.AdditionalData.Add("contentType", src.Values[LuceneIndex.ItemTypeFieldName]);
|
2017-07-19 13:42:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2018-12-04 14:25:37 +11:00
|
|
|
|
CreateMap<ISearchResults, IEnumerable<SearchResultEntity>>()
|
|
|
|
|
|
.ConvertUsing(results => results.Select(Mapper.Map<SearchResultEntity>).ToList());
|
2017-07-19 13:42:47 +02:00
|
|
|
|
|
2018-12-04 14:25:37 +11:00
|
|
|
|
CreateMap<IEnumerable<ISearchResult>, IEnumerable<SearchResultEntity>>()
|
|
|
|
|
|
.ConvertUsing(results => results.Select(Mapper.Map<SearchResultEntity>).ToList());
|
2017-07-19 13:42:47 +02:00
|
|
|
|
}
|
2018-09-26 16:27:34 +02:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Resolves the name for a content item/content variant
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private class NameResolver : IValueResolver<EntitySlim, EntityBasic, string>
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Resolve(EntitySlim source, EntityBasic destination, string destMember, ResolutionContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!(source is DocumentEntitySlim doc))
|
|
|
|
|
|
return source.Name;
|
|
|
|
|
|
|
|
|
|
|
|
// invariant = only 1 name
|
|
|
|
|
|
if (!doc.Variations.VariesByCulture()) return source.Name;
|
|
|
|
|
|
|
|
|
|
|
|
// 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.");
|
|
|
|
|
|
// fixme we should throw, but this is used in various places that won't set a culture yet
|
|
|
|
|
|
return source.Name;
|
|
|
|
|
|
|
|
|
|
|
|
// 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 doc.CultureNames.TryGetValue(culture, out var name) && !name.IsNullOrWhiteSpace() ? name : $"(({source.Name}))";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-07-19 13:42:47 +02:00
|
|
|
|
}
|
2017-07-20 11:21:28 +02:00
|
|
|
|
}
|