Merge branch 'refs/heads/dev-v7.6' into temp-u4-7318

# Conflicts:
#	src/Umbraco.Web.UI/config/umbracoSettings.config
#	src/Umbraco.Web/Umbraco.Web.csproj
This commit is contained in:
Shannon
2017-03-01 15:04:00 +01:00
855 changed files with 33678 additions and 10475 deletions

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "scriptFile", Namespace = "")]
public class CodeFileDisplay : INotificationModel
{
/// <summary>
/// VirtualPath is the path to the file on disk
/// /views/partials/file.cshtml
/// </summary>
[DataMember(Name = "virtualPath", IsRequired = true)]
public string VirtualPath { get; set; }
/// <summary>
/// Path represents the path used by the backoffice tree
/// For files stored on disk, this is a urlencoded, comma seperated
/// path to the file, always starting with -1.
///
/// -1,Partials,Parials%2FFolder,Partials%2FFolder%2FFile.cshtml
/// </summary>
[DataMember(Name = "path")]
[ReadOnly(true)]
public string Path { get; set; }
[DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
[DataMember(Name = "content", IsRequired = true)]
public string Content { get; set; }
[DataMember(Name = "fileType", IsRequired = true)]
public string FileType { get; set; }
[DataMember(Name = "snippet")]
[ReadOnly(true)]
public string Snippet { get; set; }
[DataMember(Name = "id")]
[ReadOnly(true)]
public string Id { get; set; }
public List<Notification> Notifications { get; private set; }
}
}

View File

@@ -84,17 +84,21 @@ namespace Umbraco.Web.Models.ContentEditing
}
/// <summary>
/// The real persisted content object
/// The real persisted content object - used during inbound model binding
/// </summary>
/// <remarks>
/// This is not used for outgoing model information.
/// </remarks>
[JsonIgnore]
internal TPersisted PersistedContent { get; set; }
/// <summary>
/// The DTO object used to gather all required content data including data type information etc... for use with validation
/// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding
/// </summary>
/// <remarks>
/// We basically use this object to hydrate all required data from the database into one object so we can validate everything we need
/// instead of having to look up all the data individually.
/// This is not used for outgoing model information.
/// </remarks>
[JsonIgnore]
internal ContentItemDto<TPersisted> ContentDto { get; set; }

View File

@@ -6,7 +6,10 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models.Validation;
using Umbraco.Core.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -25,7 +28,12 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "id", IsRequired = true)]
[Required]
public object Id { get; set; }
[DataMember(Name = "udi")]
[ReadOnly(true)]
[JsonConverter(typeof(UdiJsonConverter))]
public Udi Udi { get; set; }
[DataMember(Name = "icon")]
public string Icon { get; set; }

View File

@@ -3,7 +3,18 @@ namespace Umbraco.Web.Models.ContentEditing
public class GetAvailableCompositionsFilter
{
public int ContentTypeId { get; set; }
/// <summary>
/// This is normally an empty list but if additional property type aliases are passed in, any content types that have these aliases will be filtered out.
/// This is required because in the case of creating/modifying a content type because new property types being added to it are not yet persisted so cannot
/// be looked up via the db, they need to be passed in.
/// </summary>
public string[] FilterPropertyTypes { get; set; }
/// <summary>
/// This is normally an empty list but if additional content type aliases are passed in, any content types containing those aliases will be filtered out
/// along with any content types that have matching property types that are included in the filtered content types
/// </summary>
public string[] FilterContentTypes { get; set; }
}
}

View File

@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -33,5 +34,11 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "view", IsRequired = true)]
public string View { get; set; }
/// <summary>
/// This allows for custom configuration to be injected into the pre-value editor
/// </summary>
[DataMember(Name = "config")]
public IDictionary<string, object> Config { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "scriptFile", Namespace = "")]
public class SnippetDisplay
{
[DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
[DataMember(Name = "fileName", IsRequired = true)]
public string FileName { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Models.Validation;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "template", Namespace = "")]
public class TemplateDisplay : INotificationModel
{
[DataMember(Name = "id")]
public int Id { get; set; }
[Required]
[DataMember(Name = "name")]
public string Name { get; set; }
[Required]
[DataMember(Name = "alias")]
public string Alias { get; set; }
[DataMember(Name = "content")]
public string Content { get; set; }
[DataMember(Name = "path")]
public string Path { get; set; }
[DataMember(Name = "virtualPath")]
public string VirtualPath { get; set; }
[DataMember(Name = "masterTemplateAlias")]
public string MasterTemplateAlias { get; set; }
[DataMember(Name = "isMasterTemplate")]
public bool IsMasterTemplate { get; set; }
/// <summary>
/// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes.
/// </summary>
[DataMember(Name = "notifications")]
public List<Notification> Notifications { get; private set; }
}
}

View File

@@ -1,4 +1,7 @@
namespace Umbraco.Web.Models.ContentEditing
using System;
using System.ComponentModel;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Represents the type's of Umbraco entities that can be resolved from the EntityController
@@ -53,6 +56,8 @@
/// <summary>
/// Content Item
/// </summary>
[Obsolete("This is not used and will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
ContentItem,
/// <summary>

View File

@@ -46,9 +46,7 @@ namespace Umbraco.Web.Models
{
var route = umbracoContext == null
? null // for tests only
: umbracoContext.ContentCache.GetRouteById(contentId); // cached
if (route != null && route.StartsWith("err/")) route = null;
: umbracoContext.ContentCache.GetRouteById(contentId); // may be cached
var domainHelper = new DomainHelper(domainService);
IDomain domain;
@@ -73,7 +71,7 @@ namespace Umbraco.Web.Models
}
else
{
// if content is published then we have a (cached) route
// if content is published then we have a route
// from which we can figure out the domain
var pos = route.IndexOf('/');

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web.Models.ContentEditing;
@@ -10,9 +11,22 @@ namespace Umbraco.Web.Models.Mapping
{
internal class AvailablePropertyEditorsResolver : ValueResolver<IDataTypeDefinition, IEnumerable<PropertyEditorBasic>>
{
private readonly IContentSection _contentSection;
public AvailablePropertyEditorsResolver(IContentSection contentSection)
{
_contentSection = contentSection;
}
protected override IEnumerable<PropertyEditorBasic> ResolveCore(IDataTypeDefinition source)
{
return PropertyEditorResolver.Current.PropertyEditors
.Where(x =>
{
if (_contentSection.ShowDeprecatedPropertyEditors)
return true;
return source.PropertyEditorAlias == x.Alias || x.IsDeprecated == false;
})
.OrderBy(x => x.Name)
.Select(Mapper.Map<PropertyEditorBasic>);
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models.Mapping;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
public class CodeFileDisplayMapper : MapperConfiguration
{
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
{
config.CreateMap<IPartialView, CodeFileDisplay>()
.ForMember(x => x.FileType, exp => exp.Ignore())
.ForMember(x => x.Notifications, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.Snippet, exp => exp.Ignore());
config.CreateMap<Script, CodeFileDisplay>()
.ForMember(x => x.FileType, exp => exp.Ignore())
.ForMember(x => x.Notifications, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.Snippet, exp => exp.Ignore());
config.CreateMap<CodeFileDisplay, IPartialView>()
.ForMember(x => x.Id, exp => exp.Ignore())
.ForMember(x => x.Key, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.CreateDate, exp => exp.Ignore())
.ForMember(x => x.UpdateDate, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.Alias, exp => exp.Ignore())
.ForMember(x => x.Name, exp => exp.Ignore())
.ForMember(x => x.OriginalPath, exp => exp.Ignore())
.ForMember(x => x.HasIdentity, exp => exp.Ignore());
config.CreateMap<CodeFileDisplay, Script>()
.ForMember(x => x.Id, exp => exp.Ignore())
.ForMember(x => x.Key, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.CreateDate, exp => exp.Ignore())
.ForMember(x => x.UpdateDate, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.Alias, exp => exp.Ignore())
.ForMember(x => x.Name, exp => exp.Ignore())
.ForMember(x => x.OriginalPath, exp => exp.Ignore())
.ForMember(x => x.HasIdentity, exp => exp.Ignore());
}
}
}

View File

@@ -28,6 +28,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IContent TO ContentItemDisplay
config.CreateMap<IContent, ContentItemDisplay>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
.ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
.ForMember(display => display.Updater, expression => expression.ResolveUsing(new CreatorResolver()))
.ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
@@ -58,6 +59,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent>
config.CreateMap<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
.ForMember(dto => dto.Updater, expression => expression.ResolveUsing(new CreatorResolver()))
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
@@ -68,6 +70,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IContent TO ContentItemDto<IContent>
config.CreateMap<IContent, ContentItemDto<IContent>>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
.ForMember(dto => dto.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion))
.ForMember(dto => dto.Updater, expression => expression.Ignore())
@@ -115,7 +118,7 @@ namespace Umbraco.Web.Models.Mapping
//map the tree node url
if (HttpContext.Current != null)
{
var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
var url = urlHelper.GetUmbracoApiService<ContentTreeController>(controller => controller.GetTreeNode(display.Id.ToString(), null));
display.TreeNodeUrl = url;
}
@@ -178,16 +181,10 @@ namespace Umbraco.Web.Models.Mapping
{
{"items", templateItemConfig}
}
},
new ContentPropertyDisplay
{
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("content/urls"),
Value = string.Join(",", display.Urls),
View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
}
};
TabsAndPropertiesResolver.MapGenericProperties(content, display, localizedText, properties.ToArray(),
genericProperties =>
{
@@ -219,6 +216,15 @@ namespace Umbraco.Web.Models.Mapping
//TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
docTypeProperty.View = "urllist";
}
// inject 'Link to document' as the first generic property
genericProperties.Insert(0, new ContentPropertyDisplay
{
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("content/urls"),
Value = string.Join(",", display.Urls),
View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
});
});
}

View File

@@ -161,9 +161,12 @@ namespace Umbraco.Web.Models.Mapping
});
config.CreateMap<IMemberType, ContentTypeBasic>();
config.CreateMap<IMediaType, ContentTypeBasic>();
config.CreateMap<IContentType, ContentTypeBasic>();
config.CreateMap<IMemberType, ContentTypeBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MemberType, content.Key)));
config.CreateMap<IMediaType, ContentTypeBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MediaType, content.Key)));
config.CreateMap<IContentType, ContentTypeBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DocumentType, content.Key)));
config.CreateMap<PropertyTypeBasic, PropertyType>()

View File

@@ -126,6 +126,7 @@ namespace Umbraco.Web.Models.Mapping
where TPropertyTypeDisplay : PropertyTypeDisplay, new()
{
return mapping
.ForMember(x => x.Udi, expression => expression.ResolveUsing(new ContentTypeUdiResolver()))
.ForMember(display => display.Notifications, expression => expression.Ignore())
.ForMember(display => display.Errors, expression => expression.Ignore())
.ForMember(display => display.AllowAsRoot, expression => expression.MapFrom(type => type.AllowedAsRoot))

View File

@@ -0,0 +1,23 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Resolves a UDI for a content type based on it's type
/// </summary>
internal class ContentTypeUdiResolver : ValueResolver<IContentTypeComposition, Udi>
{
protected override Udi ResolveCore(IContentTypeComposition source)
{
if (source == null) return null;
return Udi.Create(
source.GetType() == typeof(IMemberType)
? Constants.UdiEntityType.MemberType
: source.GetType() == typeof(IMediaType)
? Constants.UdiEntityType.MediaType : Constants.UdiEntityType.DocumentType, source.Key);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using AutoMapper;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Mapping;
using Umbraco.Core.PropertyEditors;
@@ -34,6 +35,7 @@ namespace Umbraco.Web.Models.Mapping
};
config.CreateMap<PropertyEditor, DataTypeBasic>()
.ForMember(x => x.Udi, expression => expression.Ignore())
.ForMember(x => x.HasPrevalues, expression => expression.Ignore())
.ForMember(x => x.IsSystemDataType, expression => expression.Ignore())
.ForMember(x => x.Id, expression => expression.Ignore())
@@ -44,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.AdditionalData, expression => expression.Ignore());
config.CreateMap<IDataTypeDefinition, DataTypeBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DataType, content.Key)))
.ForMember(x => x.HasPrevalues, expression => expression.Ignore())
.ForMember(x => x.Icon, expression => expression.Ignore())
.ForMember(x => x.Alias, expression => expression.Ignore())
@@ -61,7 +64,8 @@ namespace Umbraco.Web.Models.Mapping
});
config.CreateMap<IDataTypeDefinition, DataTypeDisplay>()
.ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing(new AvailablePropertyEditorsResolver()))
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DataType, content.Key)))
.ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing(new AvailablePropertyEditorsResolver(UmbracoConfig.For.UmbracoSettings().Content)))
.ForMember(display => display.PreValues, expression => expression.ResolveUsing(
new PreValueDisplayResolver(lazyDataTypeService)))
.ForMember(display => display.SelectedEditor, expression => expression.MapFrom(

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Examine;
using Examine.LuceneEngine.Providers;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Mapping;
@@ -17,11 +18,20 @@ namespace Umbraco.Web.Models.Mapping
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
{
config.CreateMap<UmbracoEntity, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(x.NodeObjectTypeId), x.Key)))
.ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon))
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
.ForMember(x => x.Alias, expression => expression.Ignore());
.ForMember(x => x.Alias, expression => expression.Ignore())
.AfterMap((entity, basic) =>
{
if (entity.NodeObjectTypeId == Constants.ObjectTypes.MemberGuid && basic.Icon.IsNullOrWhiteSpace())
{
basic.Icon = "icon-user";
}
});
config.CreateMap<PropertyType, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.Ignore())
.ForMember(basic => basic.Icon, expression => expression.UseValue("icon-box"))
.ForMember(basic => basic.Path, expression => expression.UseValue(""))
.ForMember(basic => basic.ParentId, expression => expression.UseValue(-1))
@@ -29,6 +39,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.AdditionalData, expression => expression.Ignore());
config.CreateMap<PropertyGroup, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.Ignore())
.ForMember(basic => basic.Icon, expression => expression.UseValue("icon-tab"))
.ForMember(basic => basic.Path, expression => expression.UseValue(""))
.ForMember(basic => basic.ParentId, expression => expression.UseValue(-1))
@@ -38,6 +49,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.AdditionalData, expression => expression.Ignore());
config.CreateMap<IUser, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.Ignore())
.ForMember(basic => basic.Icon, expression => expression.UseValue("icon-user"))
.ForMember(basic => basic.Path, expression => expression.UseValue(""))
.ForMember(basic => basic.ParentId, expression => expression.UseValue(-1))
@@ -46,6 +58,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.AdditionalData, expression => expression.Ignore());
config.CreateMap<ITemplate, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(Constants.UdiEntityType.Template, x.Key)))
.ForMember(basic => basic.Icon, expression => expression.UseValue("icon-layout"))
.ForMember(basic => basic.Path, expression => expression.MapFrom(template => template.Path))
.ForMember(basic => basic.ParentId, expression => expression.UseValue(-1))
@@ -70,6 +83,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.SortOrder, expression => expression.Ignore());
config.CreateMap<IContentTypeComposition, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.ResolveUsing(new ContentTypeUdiResolver()))
.ForMember(basic => basic.Path, expression => expression.MapFrom(x => x.Path))
.ForMember(basic => basic.ParentId, expression => expression.MapFrom(x => x.ParentId))
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
@@ -77,6 +91,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap<SearchResult, EntityBasic>()
//default to document icon
.ForMember(x => x.Udi, expression => expression.Ignore())
.ForMember(x => x.Icon, expression => expression.Ignore())
.ForMember(x => x.Id, expression => expression.MapFrom(result => result.Id))
.ForMember(x => x.Name, expression => expression.Ignore())
@@ -87,21 +102,40 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
.ForMember(x => x.AdditionalData, expression => expression.Ignore())
.AfterMap((result, basic) =>
{
{
//get the icon if there is one
basic.Icon = result.Fields.ContainsKey(UmbracoContentIndexer.IconFieldName)
? result.Fields[UmbracoContentIndexer.IconFieldName]
: "icon-document";
basic.Name = result.Fields.ContainsKey("nodeName") ? result.Fields["nodeName"] : "[no name]";
if (result.Fields.ContainsKey("__NodeKey"))
if (result.Fields.ContainsKey(UmbracoContentIndexer.NodeKeyFieldName))
{
Guid key;
if (Guid.TryParse(result.Fields["__NodeKey"], out key))
if (Guid.TryParse(result.Fields[UmbracoContentIndexer.NodeKeyFieldName], out key))
{
basic.Key = key;
//need to set the UDI
if (result.Fields.ContainsKey(LuceneIndexer.IndexTypeFieldName))
{
switch (result.Fields[LuceneIndexer.IndexTypeFieldName])
{
case IndexTypes.Member:
basic.Udi = new GuidUdi(Constants.UdiEntityType.Member, basic.Key);
break;
case IndexTypes.Content:
basic.Udi = new GuidUdi(Constants.UdiEntityType.Document, basic.Key);
break;
case IndexTypes.Media:
basic.Udi = new GuidUdi(Constants.UdiEntityType.Media, basic.Key);
break;
}
}
}
}
if (result.Fields.ContainsKey("parentID"))
{
int parentId;
@@ -114,7 +148,7 @@ namespace Umbraco.Web.Models.Mapping
basic.ParentId = -1;
}
}
basic.Path = result.Fields.ContainsKey("__Path") ? result.Fields["__Path"] : "";
basic.Path = result.Fields.ContainsKey(UmbracoContentIndexer.IndexPathFieldName) ? result.Fields[UmbracoContentIndexer.IndexPathFieldName] : "";
if (result.Fields.ContainsKey(UmbracoContentIndexer.NodeTypeAliasFieldName))
{
@@ -124,6 +158,9 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap<ISearchResults, IEnumerable<EntityBasic>>()
.ConvertUsing(results => results.Select(Mapper.Map<EntityBasic>).ToList());
config.CreateMap<IEnumerable<SearchResult>, IEnumerable<EntityBasic>>()
.ConvertUsing(results => results.Select(Mapper.Map<EntityBasic>).ToList());
}
}
}

View File

@@ -20,6 +20,7 @@ namespace Umbraco.Web.Models.Mapping
{
//FROM IMacro TO EntityBasic
config.CreateMap<IMacro, EntityBasic>()
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Macro, content.Key)))
.ForMember(entityBasic => entityBasic.Icon, expression => expression.UseValue("icon-settings-alt"))
.ForMember(dto => dto.ParentId, expression => expression.UseValue(-1))
.ForMember(dto => dto.Path, expression => expression.ResolveUsing(macro => "-1," + macro.Id))

View File

@@ -25,6 +25,7 @@ namespace Umbraco.Web.Models.Mapping
{
//FROM IMedia TO MediaItemDisplay
config.CreateMap<IMedia, MediaItemDisplay>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key)))
.ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMedia>()))
.ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
.ForMember(display => display.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
@@ -45,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IMedia TO ContentItemBasic<ContentPropertyBasic, IMedia>
config.CreateMap<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMedia>()))
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
.ForMember(dto => dto.Trashed, expression => expression.MapFrom(content => content.Trashed))
@@ -56,6 +58,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IMedia TO ContentItemDto<IMedia>
config.CreateMap<IMedia, ContentItemDto<IMedia>>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMedia>()))
.ForMember(dto => dto.Published, expression => expression.Ignore())
.ForMember(dto => dto.Updater, expression => expression.Ignore())
@@ -66,8 +69,8 @@ namespace Umbraco.Web.Models.Mapping
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, ILogger logger)
{
// Adapted from ContentModelMapper
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
// Adapted from ContentModelMapper
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
if (media.HasIdentity)
{
@@ -92,20 +95,20 @@ namespace Umbraco.Web.Models.Mapping
display.IsChildOfListView = ancesctorListView != null;
}
}
//map the tree node url
if (HttpContext.Current != null)
{
var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
var url = urlHelper.GetUmbracoApiService<MediaTreeController>(controller => controller.GetTreeNode(display.Id.ToString(), null));
display.TreeNodeUrl = url;
}
if (media.ContentType.IsContainer)
{
TabsAndPropertiesResolver.AddListView(display, "media", dataTypeService, localizedText);
}
var genericProperties = new List<ContentPropertyDisplay>
{
new ContentPropertyDisplay
@@ -117,20 +120,6 @@ namespace Umbraco.Web.Models.Mapping
}
};
var links = media.GetUrls(UmbracoConfig.For.UmbracoSettings().Content, logger);
if (links.Any())
{
var link = new ContentPropertyDisplay
{
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("media/urls"),
Value = string.Join(",", links),
View = "urllist"
};
genericProperties.Add(link);
}
TabsAndPropertiesResolver.MapGenericProperties(media, display, localizedText, genericProperties, properties =>
{
if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null
@@ -152,6 +141,20 @@ namespace Umbraco.Web.Models.Mapping
};
docTypeProperty.View = "urllist";
}
// inject 'Link to media' as the first generic property
var links = media.GetUrls(UmbracoConfig.For.UmbracoSettings().Content, logger);
if (links.Any())
{
var link = new ContentPropertyDisplay
{
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("media/urls"),
Value = string.Join(",", links),
View = "urllist"
};
properties.Insert(0, link);
}
});
}
}

View File

@@ -61,6 +61,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IMember TO MediaItemDisplay
config.CreateMap<IMember, MemberDisplay>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
.ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
.ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
.ForMember(display => display.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
@@ -84,6 +85,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IMember TO MemberBasic
config.CreateMap<IMember, MemberBasic>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
.ForMember(dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
@@ -96,9 +98,10 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
//FROM MembershipUser TO MemberBasic
config.CreateMap<MembershipUser, MemberBasic>()
config.CreateMap<MembershipUser, MemberBasic>()
//we're giving this entity an ID of 0 - we cannot really map it but it needs an id so the system knows it's not a new entity
.ForMember(member => member.Id, expression => expression.MapFrom(user => int.MaxValue))
.ForMember(display => display.Udi, expression => expression.Ignore())
.ForMember(member => member.CreateDate, expression => expression.MapFrom(user => user.CreationDate))
.ForMember(member => member.UpdateDate, expression => expression.MapFrom(user => user.LastActivityDate))
.ForMember(member => member.Key, expression => expression.MapFrom(user => user.ProviderUserKey.TryConvertTo<Guid>().Result.ToString("N")))
@@ -121,6 +124,7 @@ namespace Umbraco.Web.Models.Mapping
//FROM IMember TO ContentItemDto<IMember>
config.CreateMap<IMember, ContentItemDto<IMember>>()
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
.ForMember(dto => dto.Published, expression => expression.Ignore())
.ForMember(dto => dto.Updater, expression => expression.Ignore())
@@ -148,7 +152,7 @@ namespace Umbraco.Web.Models.Mapping
//map the tree node url
if (HttpContext.Current != null)
{
var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
var url = urlHelper.GetUmbracoApiService<MemberTreeController>(controller => controller.GetTreeNode(display.Key.ToString("N"), null));
display.TreeNodeUrl = url;
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Web.Models.ContentEditing;

View File

@@ -229,7 +229,7 @@ namespace Umbraco.Web.Models.Mapping
var groupsGroupsByName = content.PropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name);
foreach (var groupsByName in groupsGroupsByName)
{
var properties = new List<ContentPropertyDisplay>();
var properties = new List<Property>();
// merge properties for groups with the same name
foreach (var group in groupsByName)
@@ -237,13 +237,16 @@ namespace Umbraco.Web.Models.Mapping
var groupProperties = content.GetPropertiesForGroup(group)
.Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored
properties.AddRange(Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyDisplay>>(groupProperties));
properties.AddRange(groupProperties);
}
if (properties.Count == 0)
continue;
TranslateProperties(properties);
// Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties.
var mappedProperties = Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyDisplay>>(properties.OrderBy(prop => prop.PropertyType.SortOrder));
TranslateProperties(mappedProperties);
// add the tab
// we need to pick an identifier... there is no "right" way...
@@ -256,7 +259,7 @@ namespace Umbraco.Web.Models.Mapping
Id = groupId,
Alias = groupName,
Label = _localizedTextService.UmbracoDictionaryTranslate(groupName),
Properties = properties,
Properties = mappedProperties,
IsActive = false
});
}

View File

@@ -0,0 +1,28 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Mapping;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
internal class TemplateModelMapper : MapperConfiguration
{
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
{
config.CreateMap<ITemplate, TemplateDisplay>()
.ForMember(x => x.Notifications, exp => exp.Ignore());
config.CreateMap<TemplateDisplay, Template>()
.ForMember(x => x.Key, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.CreateDate, exp => exp.Ignore())
.ForMember(x => x.UpdateDate, exp => exp.Ignore())
.ForMember(x => x.VirtualPath, exp => exp.Ignore())
.ForMember(x => x.Path, exp => exp.Ignore())
.ForMember(x => x.MasterTemplateId, exp => exp.Ignore()) // ok, assigned when creating the template
.ForMember(x => x.IsMasterTemplate, exp => exp.Ignore())
.ForMember(x => x.HasIdentity, exp => exp.Ignore());
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models
{
/// <summary>
/// Used for 2FA verification
/// </summary>
[DataContract(Name = "code", Namespace = "")]
public class Verify2FACodeModel
{
[Required]
[DataMember(Name = "code", IsRequired = true)]
public string Code { get; set; }
[Required]
[DataMember(Name = "provider", IsRequired = true)]
public string Provider { get; set; }
}
}

View File

@@ -11,16 +11,48 @@
internal static class QueryConditionExtensions
{
private static string MakeBinaryOperation(this QueryCondition condition, string operand, int token)
public static string BuildTokenizedCondition(this QueryCondition condition, int token)
{
return string.Format("{0}{1}@{2}", condition.Property.Name, operand, token);
return condition.BuildConditionString(string.Empty, token);
}
public static string BuildCondition(this QueryCondition condition, int token)
public static string BuildCondition(this QueryCondition condition, string parameterAlias)
{
return condition.BuildConditionString(parameterAlias + ".");
}
private static string BuildConditionString(this QueryCondition condition, string prefix, int token = -1)
{
var operand = string.Empty;
var value = string.Empty;
var constraintValue = string.Empty;
//if a token is used, use a token placeholder, otherwise, use the actual value
if(token >= 0){
constraintValue = string.Format("@{0}", token);
}else {
//modify the format of the constraint value
switch (condition.Property.Type)
{
case "string":
constraintValue = string.Format("\"{0}\"", condition.ConstraintValue);
break;
case "datetime":
constraintValue = string.Format("DateTime.Parse(\"{0}\")", condition.ConstraintValue);
break;
default:
constraintValue = condition.ConstraintValue;
break;
}
// constraintValue = condition.Property.Type == "string" ? string.Format("\"{0}\"", condition.ConstraintValue) : condition.ConstraintValue;
}
switch (condition.Term.Operathor)
{
@@ -43,17 +75,23 @@
operand = " <= ";
break;
case Operathor.Contains:
value = string.Format("{0}.Contains(@{1})", condition.Property.Name, token);
value = string.Format("{0}{1}.Contains({2})", prefix, condition.Property.Alias, constraintValue);
break;
case Operathor.NotContains:
value = string.Format("!{0}.Contains(@{1})", condition.Property.Name, token);
value = string.Format("!{0}{1}.Contains({2})", prefix, condition.Property.Alias, constraintValue);
break;
default :
operand = " == ";
break;
}
return string.IsNullOrEmpty(value) ? condition.MakeBinaryOperation(operand, token) : value;
if (string.IsNullOrEmpty(value) == false)
return value;
return string.Format("{0}{1}{2}{3}", prefix, condition.Property.Alias, operand, constraintValue);
}
}