Merge branch 'v8/dev' into v8/bugfix/5129-ui-app-header-focus
This commit is contained in:
@@ -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)" />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
// no binding redirect for now = de-activate
|
||||
//[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Core
|
||||
// this only gets called when an assembly can't be resolved
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
/// </summary>
|
||||
@@ -27,14 +27,19 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
// When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another.
|
||||
|
||||
// keep here for reference - we don't use AutoMapper
|
||||
/*
|
||||
//AutoMapper:
|
||||
// this is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
|
||||
// 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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -13,11 +12,6 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public static NoCacheRepositoryCachePolicy<TEntity, TId> Instance { get; } = new NoCacheRepositoryCachePolicy<TEntity, TId>();
|
||||
|
||||
public IRepositoryCachePolicy<TEntity, TId> Scoped(IAppPolicyCache runtimeCache, IScope scope)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
{
|
||||
return performGet(id);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
@@ -8,7 +8,9 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
{
|
||||
public static Composition ComposeCoreMappingProfiles(this Composition composition)
|
||||
{
|
||||
composition.Register<Profile, IdentityMapperProfile>();
|
||||
composition.RegisterUnique<UmbracoMapper>();
|
||||
composition.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
|
||||
.Add<IdentityMapDefinition>();
|
||||
return composition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
composition.RegisterUnique<IPartialViewRepository, PartialViewRepository>();
|
||||
composition.RegisterUnique<IScriptRepository, ScriptRepository>();
|
||||
composition.RegisterUnique<IStylesheetRepository, StylesheetRepository>();
|
||||
composition.RegisterUnique<IContentTypeCommonRepository, ContentTypeCommonRepository>();
|
||||
|
||||
return composition;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PackageActions;
|
||||
using Umbraco.Core.Packaging;
|
||||
@@ -103,6 +104,9 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
#region Getters
|
||||
|
||||
public static UmbracoMapper Mapper
|
||||
=> _factory.GetInstance<UmbracoMapper>();
|
||||
|
||||
public static IShortStringHelper ShortStringHelper
|
||||
=> _shortStringHelper ?? (_shortStringHelper = _factory?.TryGetInstance<IShortStringHelper>()
|
||||
?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(Configs.Settings())));
|
||||
|
||||
@@ -9,6 +9,10 @@ namespace Umbraco.Core.Composing
|
||||
/// <typeparam name="TBuilder">The type of the builder.</typeparam>
|
||||
/// <typeparam name="TCollection">The type of the collection.</typeparam>
|
||||
/// <typeparam name="TItem">The type of the items.</typeparam>
|
||||
/// <remarks>
|
||||
/// <para>A set collection builder is the most basic collection builder,
|
||||
/// where items are not ordered.</para>
|
||||
/// </remarks>
|
||||
public abstract class SetCollectionBuilderBase<TBuilder, TCollection, TItem> : CollectionBuilderBase<TBuilder, TCollection, TItem>
|
||||
where TBuilder : SetCollectionBuilderBase<TBuilder, TCollection, TItem>
|
||||
where TCollection : class, IBuilderCollection<TItem>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines maps for <see cref="UmbracoMapper"/>.
|
||||
/// </summary>
|
||||
public interface IMapDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines maps.
|
||||
/// </summary>
|
||||
void DefineMaps(UmbracoMapper mapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
public class MapDefinitionCollection : BuilderCollectionBase<IMapDefinition>
|
||||
{
|
||||
public MapDefinitionCollection(IEnumerable<IMapDefinition> items)
|
||||
: base(items)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
public class MapDefinitionCollectionBuilder : SetCollectionBuilderBase<MapDefinitionCollectionBuilder, MapDefinitionCollection, IMapDefinition>
|
||||
{
|
||||
protected override MapDefinitionCollectionBuilder This => this;
|
||||
|
||||
protected override Lifetime CollectionLifetime => Lifetime.Transient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a mapper context.
|
||||
/// </summary>
|
||||
public class MapperContext
|
||||
{
|
||||
private readonly UmbracoMapper _mapper;
|
||||
private IDictionary<string, object> _items;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MapperContext"/> class.
|
||||
/// </summary>
|
||||
public MapperContext(UmbracoMapper mapper)
|
||||
{
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the context has items.
|
||||
/// </summary>
|
||||
public bool HasItems => _items != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the context items.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Items => _items ?? (_items = new Dictionary<string, object>());
|
||||
|
||||
#region Map
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source)
|
||||
=> _mapper.Map<TTarget>(source, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map<TTarget>(source, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source)
|
||||
=> _mapper.Map<TSource, TTarget>(source, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map<TSource, TTarget>(source, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target)
|
||||
=> _mapper.Map(source, target, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map(source, target, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source)
|
||||
{
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
// notes:
|
||||
// AutoMapper maps null to empty arrays, lists, etc
|
||||
|
||||
// TODO:
|
||||
// when mapping from TSource, and no map is found, consider the actual source.GetType()?
|
||||
// when mapping to TTarget, and no map is found, consider the actual target.GetType()?
|
||||
// not sure we want to add magic to this simple mapper class, though
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco Mapper.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper automatically knows how to map
|
||||
/// from IEnumerable{TSource} to IEnumerable{TTarget} (using a List{TTarget}) and to TTarget[].</para>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper automatically uses that map
|
||||
/// for any source type that inherits from, or implements, TSource.</para>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper can map to TTarget exclusively
|
||||
/// and cannot re-use that map for types that would inherit from, or implement, TTarget.</para>
|
||||
/// <para>When using the Map{TSource, TTarget}(TSource source, ...) overloads, TSource is explicit. When
|
||||
/// using the Map{TTarget}(object source, ...) TSource is defined as source.GetType().</para>
|
||||
/// <para>In both cases, TTarget is explicit and not typeof(target).</para>
|
||||
/// </remarks>
|
||||
public class UmbracoMapper
|
||||
{
|
||||
private readonly Dictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>> _ctors
|
||||
= new Dictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>>();
|
||||
|
||||
private readonly Dictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>> _maps
|
||||
= new Dictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoMapper"/> class.
|
||||
/// </summary>
|
||||
/// <param name="profiles"></param>
|
||||
public UmbracoMapper(MapDefinitionCollection profiles)
|
||||
{
|
||||
foreach (var profile in profiles)
|
||||
profile.DefineMaps(this);
|
||||
}
|
||||
|
||||
#region Define
|
||||
|
||||
private static TTarget ThrowCtor<TSource, TTarget>(TSource source, MapperContext context)
|
||||
=> throw new InvalidOperationException($"Don't know how to create {typeof(TTarget).FullName} instances.");
|
||||
|
||||
private static void Identity<TSource, TTarget>(TSource source, TTarget target, MapperContext context)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
public void Define<TSource, TTarget>()
|
||||
=> Define<TSource, TTarget>(ThrowCtor<TSource, TTarget>, Identity);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="map">A mapping method.</param>
|
||||
public void Define<TSource, TTarget>(Action<TSource, TTarget, MapperContext> map)
|
||||
=> Define(ThrowCtor<TSource, TTarget>, map);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="ctor">A constructor method.</param>
|
||||
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor)
|
||||
=> Define(ctor, Identity);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="ctor">A constructor method.</param>
|
||||
/// <param name="map">A mapping method.</param>
|
||||
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor, Action<TSource, TTarget, MapperContext> map)
|
||||
{
|
||||
var sourceType = typeof(TSource);
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var sourceCtors = DefineCtors(sourceType);
|
||||
if (ctor != null)
|
||||
sourceCtors[targetType] = (source, context) => ctor((TSource)source, context);
|
||||
|
||||
var sourceMaps = DefineMaps(sourceType);
|
||||
sourceMaps[targetType] = (source, target, context) => map((TSource)source, (TTarget)target, context);
|
||||
}
|
||||
|
||||
private Dictionary<Type, Func<object, MapperContext, object>> DefineCtors(Type sourceType)
|
||||
{
|
||||
if (!_ctors.TryGetValue(sourceType, out var sourceCtor))
|
||||
sourceCtor = _ctors[sourceType] = new Dictionary<Type, Func<object, MapperContext, object>>();
|
||||
return sourceCtor;
|
||||
}
|
||||
|
||||
private Dictionary<Type, Action<object, object, MapperContext>> DefineMaps(Type sourceType)
|
||||
{
|
||||
if (!_maps.TryGetValue(sourceType, out var sourceMap))
|
||||
sourceMap = _maps[sourceType] = new Dictionary<Type, Action<object, object, MapperContext>>();
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Map
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source)
|
||||
=> Map<TTarget>(source, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map<TTarget>(source, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, MapperContext context)
|
||||
=> Map<TTarget>(source, source?.GetType(), context);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source)
|
||||
=> Map<TSource, TTarget>(source, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map<TSource, TTarget>(source, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, MapperContext context)
|
||||
=> Map<TTarget>(source, typeof(TSource), context);
|
||||
|
||||
private TTarget Map<TTarget>(object source, Type sourceType, MapperContext context)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var ctor = GetCtor(sourceType, targetType);
|
||||
var map = GetMap(sourceType, targetType);
|
||||
|
||||
// if there is a direct constructor, map
|
||||
if (ctor != null && map != null)
|
||||
{
|
||||
var target = ctor(source, context);
|
||||
map(source, target, context);
|
||||
return (TTarget)target;
|
||||
}
|
||||
|
||||
// otherwise, see if we can deal with enumerable
|
||||
|
||||
var ienumerableOfT = typeof(IEnumerable<>);
|
||||
|
||||
bool IsIEnumerableOfT(Type type) =>
|
||||
type.IsGenericType &&
|
||||
type.GenericTypeArguments.Length == 1 &&
|
||||
type.GetGenericTypeDefinition() == ienumerableOfT;
|
||||
|
||||
// try to get source as an IEnumerable<T>
|
||||
var sourceIEnumerable = IsIEnumerableOfT(sourceType) ? sourceType : sourceType.GetInterfaces().FirstOrDefault(IsIEnumerableOfT);
|
||||
|
||||
// if source is an IEnumerable<T> and target is T[] or IEnumerable<T>, we can create a map
|
||||
if (sourceIEnumerable != null && IsEnumerableOrArrayOfType(targetType))
|
||||
{
|
||||
var sourceGenericArg = sourceIEnumerable.GenericTypeArguments[0];
|
||||
var targetGenericArg = GetEnumerableOrArrayTypeArgument(targetType);
|
||||
|
||||
ctor = GetCtor(sourceGenericArg, targetGenericArg);
|
||||
map = GetMap(sourceGenericArg, targetGenericArg);
|
||||
|
||||
// if there is a constructor for the underlying type, create & invoke the map
|
||||
if (ctor != null && map != null)
|
||||
{
|
||||
// register (for next time) and do it now (for this time)
|
||||
object NCtor(object s, MapperContext c) => MapEnumerableInternal<TTarget>((IEnumerable) s, targetGenericArg, ctor, map, c);
|
||||
DefineCtors(sourceType)[targetType] = NCtor;
|
||||
DefineMaps(sourceType)[targetType] = Identity;
|
||||
return (TTarget) NCtor(source, context);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {sourceGenericArg.FullName} to {targetGenericArg.FullName}, so don't know how to map {sourceType.FullName} to {targetType.FullName}.");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
|
||||
}
|
||||
|
||||
private TTarget MapEnumerableInternal<TTarget>(IEnumerable source, Type targetGenericArg, Func<object, MapperContext, object> ctor, Action<object, object, MapperContext> map, MapperContext context)
|
||||
{
|
||||
var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg));
|
||||
|
||||
foreach (var sourceItem in source)
|
||||
{
|
||||
var targetItem = ctor(sourceItem, context);
|
||||
map(sourceItem, targetItem, context);
|
||||
targetList.Add(targetItem);
|
||||
}
|
||||
|
||||
object target = targetList;
|
||||
|
||||
if (typeof(TTarget).IsArray)
|
||||
{
|
||||
var elementType = typeof(TTarget).GetElementType();
|
||||
if (elementType == null) throw new Exception("panic");
|
||||
var targetArray = Array.CreateInstance(elementType, targetList.Count);
|
||||
targetList.CopyTo(targetArray, 0);
|
||||
target = targetArray;
|
||||
}
|
||||
|
||||
return (TTarget) target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target)
|
||||
=> Map(source, target, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map(source, target, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, MapperContext context)
|
||||
{
|
||||
var sourceType = typeof(TSource);
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var map = GetMap(sourceType, targetType);
|
||||
|
||||
// if there is a direct map, map
|
||||
if (map != null)
|
||||
{
|
||||
map(source, target, context);
|
||||
return target;
|
||||
}
|
||||
|
||||
// we cannot really map to an existing enumerable - give up
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {typeof(TSource).FullName} to {typeof(TTarget).FullName}.");
|
||||
}
|
||||
|
||||
private Func<object, MapperContext, object> GetCtor(Type sourceType, Type targetType)
|
||||
{
|
||||
if (_ctors.TryGetValue(sourceType, out var sourceCtor) && sourceCtor.TryGetValue(targetType, out var ctor))
|
||||
return ctor;
|
||||
|
||||
ctor = null;
|
||||
foreach (var (stype, sctors) in _ctors)
|
||||
{
|
||||
if (!stype.IsAssignableFrom(sourceType)) continue;
|
||||
if (!sctors.TryGetValue(targetType, out ctor)) continue;
|
||||
|
||||
sourceCtor = sctors;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctor == null) return null;
|
||||
|
||||
_ctors[sourceType] = sourceCtor;
|
||||
return ctor;
|
||||
}
|
||||
|
||||
private Action<object, object, MapperContext> GetMap(Type sourceType, Type targetType)
|
||||
{
|
||||
if (_maps.TryGetValue(sourceType, out var sourceMap) && sourceMap.TryGetValue(targetType, out var map))
|
||||
return map;
|
||||
|
||||
map = null;
|
||||
foreach (var (stype, smap) in _maps)
|
||||
{
|
||||
if (!stype.IsAssignableFrom(sourceType)) continue;
|
||||
|
||||
// TODO: consider looking for assignable types for target too?
|
||||
if (!smap.TryGetValue(targetType, out map)) continue;
|
||||
|
||||
sourceMap = smap;
|
||||
break;
|
||||
}
|
||||
|
||||
if (map == null) return null;
|
||||
|
||||
_maps[sourceType] = sourceMap;
|
||||
return map;
|
||||
}
|
||||
|
||||
private static bool IsEnumerableOrArrayOfType(Type type)
|
||||
{
|
||||
if (type.IsArray && type.GetArrayRank() == 1) return true;
|
||||
if (type.IsGenericType && type.GenericTypeArguments.Length == 1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Type GetEnumerableOrArrayTypeArgument(Type type)
|
||||
{
|
||||
if (type.IsArray) return type.GetElementType();
|
||||
if (type.IsGenericType) return type.GenericTypeArguments[0];
|
||||
throw new Exception("panic");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source)
|
||||
{
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return source.Select(x => Map<TSourceElement, TTargetElement>(x, context)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source, MapperContext context)
|
||||
{
|
||||
return source.Select(x => Map<TSourceElement, TTargetElement>(x, context)).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
typeof (LogDto),
|
||||
typeof (MacroDto),
|
||||
typeof (MacroPropertyDto),
|
||||
typeof (MemberTypeDto),
|
||||
typeof (MemberPropertyTypeDto),
|
||||
typeof (MemberDto),
|
||||
typeof (Member2MemberGroupDto),
|
||||
typeof (PropertyTypeGroupDto),
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_7_9_0
|
||||
{
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
|
||||
|
||||
if (columns.Any(x => x.TableName.InvariantEquals(Constants.DatabaseSchema.Tables.MemberType) && x.ColumnName.InvariantEquals("isSensitive")) == false)
|
||||
AddColumn<MemberTypeDto>("isSensitive");
|
||||
if (columns.Any(x => x.TableName.InvariantEquals(Constants.DatabaseSchema.Tables.MemberPropertyType) && x.ColumnName.InvariantEquals("isSensitive")) == false)
|
||||
AddColumn<MemberPropertyTypeDto>("isSensitive");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,9 +210,7 @@ namespace Umbraco.Core.Models
|
||||
return Variations.ValidateVariation(culture, segment, false, true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of PropertyGroups available on this ContentType
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// <para>A PropertyGroup corresponds to a Tab in the UI</para>
|
||||
/// <para>Marked DoNotClone because we will manually deal with cloning and the event handlers</para>
|
||||
@@ -230,9 +228,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all property types, across all property groups.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
public IEnumerable<PropertyType> PropertyTypes
|
||||
@@ -243,12 +239,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property types that are not in a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Marked DoNotClone because we will manually deal with cloning and the event handlers
|
||||
/// </remarks>
|
||||
/// <inheritdoc />
|
||||
[DoNotClone]
|
||||
public IEnumerable<PropertyType> NoGroupPropertyTypes
|
||||
{
|
||||
|
||||
@@ -43,9 +43,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property groups for the entire composition.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<PropertyGroup> CompositionPropertyGroups
|
||||
{
|
||||
@@ -76,9 +74,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property types for the entire composition.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<PropertyType> CompositionPropertyTypes
|
||||
{
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace Umbraco.Core.Models
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (savingCultures == null) throw new ArgumentNullException(nameof(savingCultures));
|
||||
if (savingCultures.Length == 0) throw new ArgumentException(nameof(savingCultures));
|
||||
if (defaultCulture == null) throw new ArgumentNullException(nameof(defaultCulture));
|
||||
|
||||
var cultureForInvariantErrors = savingCultures.Any(x => x.InvariantEquals(defaultCulture))
|
||||
//the default culture is being flagged for saving so use it
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Models
|
||||
/// * when the setter performs additional required logic other than just setting the underlying field
|
||||
///
|
||||
/// </remarks>
|
||||
internal class DoNotCloneAttribute : Attribute
|
||||
public class DoNotCloneAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -96,17 +96,17 @@ namespace Umbraco.Core.Models
|
||||
IEnumerable<ContentTypeSort> AllowedContentTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets a collection of Property Groups
|
||||
/// Gets or sets the local property groups.
|
||||
/// </summary>
|
||||
PropertyGroupCollection PropertyGroups { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all property types, across all property groups.
|
||||
/// Gets all local property types belonging to a group, across all local property groups.
|
||||
/// </summary>
|
||||
IEnumerable<PropertyType> PropertyTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property types that are not in a group.
|
||||
/// Gets or sets the local property types that do not belong to a group.
|
||||
/// </summary>
|
||||
IEnumerable<PropertyType> NoGroupPropertyTypes { get; set; }
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(username));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture));
|
||||
|
||||
var user = new BackOfficeIdentityUser();
|
||||
var user = new BackOfficeIdentityUser(Array.Empty<IReadOnlyUserGroup>());
|
||||
user.DisableChangeTracking();
|
||||
user._userName = username;
|
||||
user._email = email;
|
||||
@@ -54,16 +54,19 @@ namespace Umbraco.Core.Models.Identity
|
||||
return user;
|
||||
}
|
||||
|
||||
private BackOfficeIdentityUser()
|
||||
private BackOfficeIdentityUser(IReadOnlyUserGroup[] groups)
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_startMediaIds = Array.Empty<int>();
|
||||
_startContentIds = Array.Empty<int>();
|
||||
_allowedSections = Array.Empty<string>();
|
||||
_culture = Current.Configs.Global().DefaultUILanguage; // TODO: inject
|
||||
_groups = new IReadOnlyUserGroup[0];
|
||||
|
||||
// must initialize before setting groups
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>();
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
|
||||
// use the property setters - they do more than just setting a field
|
||||
Groups = groups;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -72,19 +75,10 @@ namespace Umbraco.Core.Models.Identity
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groups"></param>
|
||||
public BackOfficeIdentityUser(int userId, IEnumerable<IReadOnlyUserGroup> groups)
|
||||
: this(groups.ToArray())
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_culture = Current.Configs.Global().DefaultUILanguage; // TODO: inject
|
||||
_groups = groups.ToArray();
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>(_groups.Select(x => new IdentityUserRole<string>
|
||||
{
|
||||
RoleId = x.Alias,
|
||||
UserId = userId.ToString()
|
||||
}));
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
// use the property setters - they do more than just setting a field
|
||||
Id = userId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -226,6 +220,8 @@ namespace Umbraco.Core.Models.Identity
|
||||
//so they recalculate
|
||||
_allowedSections = null;
|
||||
|
||||
_groups = value;
|
||||
|
||||
//now clear all roles and re-add them
|
||||
_roles.CollectionChanged -= _roles_CollectionChanged;
|
||||
_roles.Clear();
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class IdentityMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly IEntityService _entityService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public IdentityMapDefinition(ILocalizedTextService textService, IEntityService entityService, IGlobalSettings globalSettings)
|
||||
{
|
||||
_textService = textService;
|
||||
_entityService = entityService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IUser, BackOfficeIdentityUser>(
|
||||
(source, context) =>
|
||||
{
|
||||
var target = new BackOfficeIdentityUser(source.Id, source.Groups);
|
||||
target.DisableChangeTracking();
|
||||
return target;
|
||||
},
|
||||
(source, target, context) =>
|
||||
{
|
||||
Map(source, target);
|
||||
target.ResetDirtyProperties(true);
|
||||
target.EnableChangeTracking();
|
||||
});
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -Id -Groups -LockoutEnabled -PhoneNumber -PhoneNumberConfirmed -TwoFactorEnabled
|
||||
private void Map(IUser source, BackOfficeIdentityUser target)
|
||||
{
|
||||
// well, the ctor has been fixed
|
||||
/*
|
||||
// these two are already set in ctor but BackOfficeIdentityUser ctor is CompletelyBroken
|
||||
target.Id = source.Id;
|
||||
target.Groups = source.Groups.ToArray();
|
||||
*/
|
||||
|
||||
target.CalculatedMediaStartNodeIds = source.CalculateMediaStartNodeIds(_entityService);
|
||||
target.CalculatedContentStartNodeIds = source.CalculateContentStartNodeIds(_entityService);
|
||||
target.Email = source.Email;
|
||||
target.UserName = source.Username;
|
||||
target.LastPasswordChangeDateUtc = source.LastPasswordChangeDate.ToUniversalTime();
|
||||
target.LastLoginDateUtc = source.LastLoginDate.ToUniversalTime();
|
||||
target.EmailConfirmed = source.EmailConfirmedDate.HasValue;
|
||||
target.Name = source.Name;
|
||||
target.AccessFailedCount = source.FailedPasswordAttempts;
|
||||
target.PasswordHash = GetPasswordHash(source.RawPasswordValue);
|
||||
target.StartContentIds = source.StartContentIds;
|
||||
target.StartMediaIds = source.StartMediaIds;
|
||||
target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); // project CultureInfo to string
|
||||
target.IsApproved = source.IsApproved;
|
||||
target.SecurityStamp = source.SecurityStamp;
|
||||
target.LockoutEndDateUtc = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null;
|
||||
|
||||
// this was in AutoMapper but does not have a setter anyways
|
||||
//target.AllowedSections = source.AllowedSections.ToArray(),
|
||||
|
||||
// these were marked as ignored for AutoMapper but don't have a setter anyways
|
||||
//target.Logins =;
|
||||
//target.Claims =;
|
||||
//target.Roles =;
|
||||
}
|
||||
|
||||
private static string GetPasswordHash(string storedPass)
|
||||
{
|
||||
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class IdentityMapperProfile : Profile
|
||||
{
|
||||
public IdentityMapperProfile(ILocalizedTextService textService, IEntityService entityService, IGlobalSettings globalSettings)
|
||||
{
|
||||
CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.BeforeMap((src, dest) =>
|
||||
{
|
||||
dest.DisableChangeTracking();
|
||||
})
|
||||
.ConstructUsing(src => new BackOfficeIdentityUser(src.Id, src.Groups))
|
||||
.ForMember(dest => dest.LastLoginDateUtc, opt => opt.MapFrom(src => src.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(user => user.LastPasswordChangeDateUtc, expression => expression.MapFrom(user => user.LastPasswordChangeDate.ToUniversalTime()))
|
||||
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
|
||||
.ForMember(dest => dest.EmailConfirmed, opt => opt.MapFrom(src => src.EmailConfirmedDate.HasValue))
|
||||
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
|
||||
.ForMember(dest => dest.LockoutEndDateUtc, opt => opt.MapFrom(src => src.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null))
|
||||
.ForMember(dest => dest.IsApproved, opt => opt.MapFrom(src => src.IsApproved))
|
||||
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Username))
|
||||
.ForMember(dest => dest.PasswordHash, opt => opt.MapFrom(user => GetPasswordHash(user.RawPasswordValue)))
|
||||
.ForMember(dest => dest.Culture, opt => opt.MapFrom(src => src.GetUserCulture(textService, globalSettings)))
|
||||
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
|
||||
.ForMember(dest => dest.StartMediaIds, opt => opt.MapFrom(src => src.StartMediaIds))
|
||||
.ForMember(dest => dest.StartContentIds, opt => opt.MapFrom(src => src.StartContentIds))
|
||||
.ForMember(dest => dest.AccessFailedCount, opt => opt.MapFrom(src => src.FailedPasswordAttempts))
|
||||
.ForMember(dest => dest.CalculatedContentStartNodeIds, opt => opt.MapFrom(src => src.CalculateContentStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.CalculatedMediaStartNodeIds, opt => opt.MapFrom(src => src.CalculateMediaStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.AllowedSections, opt => opt.MapFrom(src => src.AllowedSections.ToArray()))
|
||||
.ForMember(dest => dest.LockoutEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Logins, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.PhoneNumber, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.PhoneNumberConfirmed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.TwoFactorEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Roles, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Claims, opt => opt.Ignore())
|
||||
.AfterMap((src, dest) =>
|
||||
{
|
||||
dest.ResetDirtyProperties(true);
|
||||
dest.EnableChangeTracking();
|
||||
});
|
||||
}
|
||||
|
||||
private static string GetPasswordHash(string storedPass)
|
||||
{
|
||||
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Core
|
||||
public const string MacroProperty = /*TableNamePrefix*/ "cms" + "MacroProperty";
|
||||
|
||||
public const string Member = /*TableNamePrefix*/ "cms" + "Member";
|
||||
public const string MemberType = /*TableNamePrefix*/ "cms" + "MemberType";
|
||||
public const string MemberPropertyType = /*TableNamePrefix*/ "cms" + "MemberType";
|
||||
public const string Member2MemberGroup = /*TableNamePrefix*/ "cms" + "Member2MemberGroup";
|
||||
|
||||
public const string Access = TableNamePrefix + "Access";
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "NodeId")]
|
||||
public NodeDto NodeDto { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
public string Configuration { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "DataTypeId")]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "NodeId")]
|
||||
public NodeDto NodeDto { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,10 +3,10 @@ using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Dtos
|
||||
{
|
||||
[TableName(Constants.DatabaseSchema.Tables.MemberType)]
|
||||
[TableName(Constants.DatabaseSchema.Tables.MemberPropertyType)]
|
||||
[PrimaryKey("pk")]
|
||||
[ExplicitColumns]
|
||||
internal class MemberTypeDto
|
||||
internal class MemberPropertyTypeDto
|
||||
{
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn]
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPoco;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Dtos
|
||||
{
|
||||
[TableName(Constants.DatabaseSchema.Tables.Node)]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class MemberTypeReadOnlyDto
|
||||
{
|
||||
/* from umbracoNode */
|
||||
[Column("id")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("trashed")]
|
||||
public bool Trashed { get; set; }
|
||||
|
||||
[Column("parentID")]
|
||||
public int ParentId { get; set; }
|
||||
|
||||
[Column("nodeUser")]
|
||||
public int? UserId { get; set; }
|
||||
|
||||
[Column("level")]
|
||||
public short Level { get; set; }
|
||||
|
||||
[Column("path")]
|
||||
public string Path { get; set; }
|
||||
|
||||
[Column("sortOrder")]
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
[Column("uniqueID")]
|
||||
public Guid? UniqueId { get; set; }
|
||||
|
||||
[Column("text")]
|
||||
public string Text { get; set; }
|
||||
|
||||
[Column("nodeObjectType")]
|
||||
public Guid? NodeObjectType { get; set; }
|
||||
|
||||
[Column("createDate")]
|
||||
public DateTime CreateDate { get; set; }
|
||||
|
||||
/* cmsContentType */
|
||||
[Column("pk")]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Column("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Column("thumbnail")]
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("isContainer")]
|
||||
public bool IsContainer { get; set; }
|
||||
|
||||
[Column("allowAtRoot")]
|
||||
public bool AllowAtRoot { get; set; }
|
||||
|
||||
/* PropertyTypes */
|
||||
// TODO: Add PropertyTypeDto (+MemberTypeDto and DataTypeDto as one) ReadOnly list
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.Many, ReferenceMemberName = "ContentTypeId")]
|
||||
public List<PropertyTypeReadOnlyDto> PropertyTypes { get; set; }
|
||||
|
||||
/* PropertyTypeGroups */
|
||||
// TODO: Add PropertyTypeGroupDto ReadOnly list
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.Many, ReferenceMemberName = "ContentTypeNodeId")]
|
||||
public List<PropertyTypeGroupReadOnlyDto> PropertyTypeGroups { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using NPoco;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Dtos
|
||||
{
|
||||
// this is PropertyTypeDto + the special property type fields for members
|
||||
// it is used for querying everything needed for a property type, at once
|
||||
internal class PropertyTypeCommonDto : PropertyTypeDto
|
||||
{
|
||||
[Column("memberCanEdit")]
|
||||
public bool CanEdit { get; set; }
|
||||
|
||||
[Column("viewOnProfile")]
|
||||
public bool ViewOnProfile { get; set; }
|
||||
|
||||
[Column("isSensitive")]
|
||||
public bool IsSensitive { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -67,16 +67,28 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
public static IMemberType BuildMemberTypeEntity(ContentTypeDto dto)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var contentType = new MemberType(dto.NodeDto.ParentId);
|
||||
try
|
||||
{
|
||||
contentType.DisableChangeTracking();
|
||||
BuildCommonEntity(contentType, dto, false);
|
||||
contentType.ResetDirtyProperties(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
contentType.EnableChangeTracking();
|
||||
}
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static IEnumerable<MemberTypeDto> BuildMemberTypeDtos(IMemberType entity)
|
||||
public static IEnumerable<MemberPropertyTypeDto> BuildMemberPropertyTypeDtos(IMemberType entity)
|
||||
{
|
||||
var memberType = entity as MemberType;
|
||||
if (memberType == null || memberType.PropertyTypes.Any() == false)
|
||||
return Enumerable.Empty<MemberTypeDto>();
|
||||
return Enumerable.Empty<MemberPropertyTypeDto>();
|
||||
|
||||
var dtos = memberType.PropertyTypes.Select(x => new MemberTypeDto
|
||||
var dtos = memberType.PropertyTypes.Select(x => new MemberPropertyTypeDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
PropertyTypeId = x.Id,
|
||||
@@ -91,7 +103,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
#region Common
|
||||
|
||||
private static void BuildCommonEntity(ContentTypeBase entity, ContentTypeDto dto)
|
||||
private static void BuildCommonEntity(ContentTypeBase entity, ContentTypeDto dto, bool setVariations = true)
|
||||
{
|
||||
entity.Id = dto.NodeDto.NodeId;
|
||||
entity.Key = dto.NodeDto.UniqueId;
|
||||
@@ -102,6 +114,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.SortOrder = dto.NodeDto.SortOrder;
|
||||
entity.Description = dto.Description;
|
||||
entity.CreateDate = dto.NodeDto.CreateDate;
|
||||
entity.UpdateDate = dto.NodeDto.CreateDate;
|
||||
entity.Path = dto.NodeDto.Path;
|
||||
entity.Level = dto.NodeDto.Level;
|
||||
entity.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId;
|
||||
@@ -109,7 +122,9 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.IsContainer = dto.IsContainer;
|
||||
entity.IsElement = dto.IsElement;
|
||||
entity.Trashed = dto.NodeDto.Trashed;
|
||||
entity.Variations = (ContentVariation) dto.Variations;
|
||||
|
||||
if (setVariations)
|
||||
entity.Variations = (ContentVariation) dto.Variations;
|
||||
}
|
||||
|
||||
public static ContentTypeDto BuildContentTypeDto(IContentTypeBase entity)
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal static class MemberTypeReadOnlyFactory
|
||||
{
|
||||
public static IMemberType BuildEntity(MemberTypeReadOnlyDto dto, out bool needsSaving)
|
||||
{
|
||||
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
needsSaving = false;
|
||||
|
||||
var memberType = new MemberType(dto.ParentId);
|
||||
|
||||
try
|
||||
{
|
||||
memberType.DisableChangeTracking();
|
||||
|
||||
memberType.Alias = dto.Alias;
|
||||
memberType.AllowedAsRoot = dto.AllowAtRoot;
|
||||
memberType.CreateDate = dto.CreateDate;
|
||||
memberType.CreatorId = dto.UserId.HasValue ? dto.UserId.Value : 0;
|
||||
memberType.Description = dto.Description;
|
||||
memberType.Icon = dto.Icon;
|
||||
memberType.Id = dto.NodeId;
|
||||
memberType.IsContainer = dto.IsContainer;
|
||||
memberType.Key = dto.UniqueId.Value;
|
||||
memberType.Level = dto.Level;
|
||||
memberType.Name = dto.Text;
|
||||
memberType.Path = dto.Path;
|
||||
memberType.SortOrder = dto.SortOrder;
|
||||
memberType.Thumbnail = dto.Thumbnail;
|
||||
memberType.Trashed = dto.Trashed;
|
||||
memberType.UpdateDate = dto.CreateDate;
|
||||
memberType.AllowedContentTypes = Enumerable.Empty<ContentTypeSort>();
|
||||
|
||||
var propertyTypeGroupCollection = GetPropertyTypeGroupCollection(dto, memberType, standardPropertyTypes);
|
||||
memberType.PropertyGroups = propertyTypeGroupCollection;
|
||||
|
||||
var propertyTypes = GetPropertyTypes(dto, memberType, standardPropertyTypes);
|
||||
|
||||
//By Convention we add 9 standard PropertyTypes - This is only here to support loading of types that didn't have these conventions before.
|
||||
foreach (var standardPropertyType in standardPropertyTypes)
|
||||
{
|
||||
if (dto.PropertyTypes.Any(x => x.Alias.Equals(standardPropertyType.Key))) continue;
|
||||
|
||||
// beware!
|
||||
// means that we can return a memberType "from database" that has some property types
|
||||
// that do *not* come from the database and therefore are incomplete eg have no key,
|
||||
// no id, no dataTypeDefinitionId - ouch! - better notify caller of the situation
|
||||
needsSaving = true;
|
||||
|
||||
//Add the standard PropertyType to the current list
|
||||
propertyTypes.Add(standardPropertyType.Value);
|
||||
|
||||
//Internal dictionary for adding "MemberCanEdit", "VisibleOnProfile", "IsSensitive" properties to each PropertyType
|
||||
memberType.MemberTypePropertyTypes.Add(standardPropertyType.Key,
|
||||
new MemberTypePropertyProfileAccess(false, false, false));
|
||||
}
|
||||
memberType.NoGroupPropertyTypes = propertyTypes;
|
||||
|
||||
return memberType;
|
||||
}
|
||||
finally
|
||||
{
|
||||
memberType.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
private static PropertyGroupCollection GetPropertyTypeGroupCollection(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary<string, PropertyType> standardProps)
|
||||
{
|
||||
// see PropertyGroupFactory, repeating code here...
|
||||
|
||||
var propertyGroups = new PropertyGroupCollection();
|
||||
foreach (var groupDto in dto.PropertyTypeGroups.Where(x => x.Id.HasValue))
|
||||
{
|
||||
var group = new PropertyGroup(MemberType.SupportsPublishingConst);
|
||||
|
||||
// if the group is defined on the current member type,
|
||||
// assign its identifier, else it will be zero
|
||||
if (groupDto.ContentTypeNodeId == memberType.Id)
|
||||
{
|
||||
// note: no idea why Id is nullable here, but better check
|
||||
if (groupDto.Id.HasValue == false)
|
||||
throw new Exception("GroupDto.Id has no value.");
|
||||
group.Id = groupDto.Id.Value;
|
||||
}
|
||||
|
||||
group.Key = groupDto.UniqueId;
|
||||
group.Name = groupDto.Text;
|
||||
group.SortOrder = groupDto.SortOrder;
|
||||
group.PropertyTypes = new PropertyTypeCollection(MemberType.SupportsPublishingConst);
|
||||
|
||||
//Because we are likely to have a group with no PropertyTypes we need to ensure that these are excluded
|
||||
var localGroupDto = groupDto;
|
||||
var typeDtos = dto.PropertyTypes.Where(x => x.Id.HasValue && x.Id > 0 && x.PropertyTypeGroupId.HasValue && x.PropertyTypeGroupId.Value == localGroupDto.Id.Value);
|
||||
foreach (var typeDto in typeDtos)
|
||||
{
|
||||
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
|
||||
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
|
||||
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit, typeDto.IsSensitive));
|
||||
|
||||
var tempGroupDto = groupDto;
|
||||
|
||||
//ensures that any built-in membership properties have their correct dbtype assigned no matter
|
||||
//what the underlying data type is
|
||||
var propDbType = MemberTypeRepository.GetDbTypeForBuiltInProperty(
|
||||
typeDto.Alias,
|
||||
typeDto.DbType.EnumParse<ValueStorageType>(true),
|
||||
standardProps);
|
||||
|
||||
var propertyType = new PropertyType(
|
||||
typeDto.PropertyEditorAlias,
|
||||
propDbType.Result,
|
||||
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
|
||||
// which is what we want for the built-in properties.
|
||||
propDbType.Success,
|
||||
typeDto.Alias)
|
||||
{
|
||||
DataTypeId = typeDto.DataTypeId,
|
||||
Description = typeDto.Description,
|
||||
Id = typeDto.Id.Value,
|
||||
Name = typeDto.Name,
|
||||
Mandatory = typeDto.Mandatory,
|
||||
SortOrder = typeDto.SortOrder,
|
||||
ValidationRegExp = typeDto.ValidationRegExp,
|
||||
PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id.Value),
|
||||
CreateDate = memberType.CreateDate,
|
||||
UpdateDate = memberType.UpdateDate,
|
||||
Key = typeDto.UniqueId
|
||||
};
|
||||
|
||||
// reset dirty initial properties (U4-1946)
|
||||
propertyType.ResetDirtyProperties(false);
|
||||
group.PropertyTypes.Add(propertyType);
|
||||
}
|
||||
|
||||
// reset dirty initial properties (U4-1946)
|
||||
group.ResetDirtyProperties(false);
|
||||
propertyGroups.Add(group);
|
||||
}
|
||||
|
||||
return propertyGroups;
|
||||
}
|
||||
|
||||
private static List<PropertyType> GetPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary<string, PropertyType> standardProps)
|
||||
{
|
||||
//Find PropertyTypes that does not belong to a PropertyTypeGroup
|
||||
var propertyTypes = new List<PropertyType>();
|
||||
foreach (var typeDto in dto.PropertyTypes.Where(x => (x.PropertyTypeGroupId.HasValue == false || x.PropertyTypeGroupId.Value == 0) && x.Id.HasValue))
|
||||
{
|
||||
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
|
||||
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
|
||||
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit, typeDto.IsSensitive));
|
||||
|
||||
//ensures that any built-in membership properties have their correct dbtype assigned no matter
|
||||
//what the underlying data type is
|
||||
var propDbType = MemberTypeRepository.GetDbTypeForBuiltInProperty(
|
||||
typeDto.Alias,
|
||||
typeDto.DbType.EnumParse<ValueStorageType>(true),
|
||||
standardProps);
|
||||
|
||||
var propertyType = new PropertyType(
|
||||
typeDto.PropertyEditorAlias,
|
||||
propDbType.Result,
|
||||
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
|
||||
// which is what we want for the built-in properties.
|
||||
propDbType.Success,
|
||||
typeDto.Alias)
|
||||
{
|
||||
DataTypeId = typeDto.DataTypeId,
|
||||
Description = typeDto.Description,
|
||||
Id = typeDto.Id.Value,
|
||||
Mandatory = typeDto.Mandatory,
|
||||
Name = typeDto.Name,
|
||||
SortOrder = typeDto.SortOrder,
|
||||
ValidationRegExp = typeDto.ValidationRegExp,
|
||||
PropertyGroupId = null,
|
||||
CreateDate = dto.CreateDate,
|
||||
UpdateDate = dto.CreateDate,
|
||||
Key = typeDto.UniqueId
|
||||
};
|
||||
|
||||
propertyTypes.Add(propertyType);
|
||||
}
|
||||
return propertyTypes;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
// TODO
|
||||
// this should be IContentTypeRepository, and what is IContentTypeRepository at the moment should
|
||||
// become IDocumentTypeRepository - but since these interfaces are public, that would be breaking
|
||||
|
||||
/// <summary>
|
||||
/// Represents the content types common repository, dealing with document, media and member types.
|
||||
/// </summary>
|
||||
public interface IContentTypeCommonRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets and cache all types.
|
||||
/// </summary>
|
||||
IEnumerable<IContentTypeComposition> GetAllTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cache.
|
||||
/// </summary>
|
||||
void ClearCache();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IMediaTypeRepository : IContentTypeRepositoryBase<IMediaType>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns>An enumerable list of <see cref="IContentType"/> objects</returns>
|
||||
IEnumerable<IMediaType> GetByQuery(IQuery<PropertyType> query);
|
||||
}
|
||||
{ }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements <see cref="IContentTypeCommonRepository"/>.
|
||||
/// </summary>
|
||||
internal class ContentTypeCommonRepository : IContentTypeCommonRepository
|
||||
{
|
||||
private const string CacheKey = "Umbraco.Core.Persistence.Repositories.Implement.ContentTypeCommonRepository::AllTypes";
|
||||
|
||||
private readonly AppCaches _appCaches;
|
||||
private readonly IScopeAccessor _scopeAccessor;
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IContentTypeCommonRepository"/> class.
|
||||
/// </summary>
|
||||
public ContentTypeCommonRepository(IScopeAccessor scopeAccessor, ITemplateRepository templateRepository, AppCaches appCaches)
|
||||
{
|
||||
_scopeAccessor = scopeAccessor;
|
||||
_templateRepository = templateRepository;
|
||||
_appCaches = appCaches;
|
||||
}
|
||||
|
||||
private IScope AmbientScope => _scopeAccessor.AmbientScope;
|
||||
private IUmbracoDatabase Database => AmbientScope.Database;
|
||||
private ISqlContext SqlContext => AmbientScope.SqlContext;
|
||||
private Sql<ISqlContext> Sql() => SqlContext.Sql();
|
||||
//private Sql<ISqlContext> Sql(string sql, params object[] args) => SqlContext.Sql(sql, args);
|
||||
//private ISqlSyntaxProvider SqlSyntax => SqlContext.SqlSyntax;
|
||||
//private IQuery<T> Query<T>() => SqlContext.Query<T>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IContentTypeComposition> GetAllTypes()
|
||||
{
|
||||
// use a 5 minutes sliding cache - same as FullDataSet cache policy
|
||||
return _appCaches.RuntimeCache.GetCacheItem(CacheKey, GetAllTypesInternal, TimeSpan.FromMinutes(5), true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearCache()
|
||||
{
|
||||
_appCaches.RuntimeCache.Clear(CacheKey);
|
||||
}
|
||||
|
||||
private IEnumerable<IContentTypeComposition> GetAllTypesInternal()
|
||||
{
|
||||
var contentTypes = new Dictionary<int, IContentTypeComposition>();
|
||||
|
||||
// get content types
|
||||
var sql1 = Sql()
|
||||
.Select<ContentTypeDto>(r => r.Select(x => x.NodeDto))
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>().On<ContentTypeDto, NodeDto>((ct, n) => ct.NodeId == n.NodeId)
|
||||
.OrderBy<ContentTypeDto>(x => x.NodeId);
|
||||
|
||||
var contentTypeDtos = Database.Fetch<ContentTypeDto>(sql1);
|
||||
|
||||
// get allowed content types
|
||||
var sql2 = Sql()
|
||||
.Select<ContentTypeAllowedContentTypeDto>()
|
||||
.From<ContentTypeAllowedContentTypeDto>()
|
||||
.OrderBy<ContentTypeAllowedContentTypeDto>(x => x.Id);
|
||||
|
||||
var allowedDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(sql2);
|
||||
|
||||
// prepare
|
||||
// note: same alias could be used for media, content... but always different ids = ok
|
||||
var aliases = contentTypeDtos.ToDictionary(x => x.NodeId, x => x.Alias);
|
||||
|
||||
// create
|
||||
var allowedDtoIx = 0;
|
||||
foreach (var contentTypeDto in contentTypeDtos)
|
||||
{
|
||||
// create content type
|
||||
IContentTypeComposition contentType;
|
||||
if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.MediaType)
|
||||
contentType = ContentTypeFactory.BuildMediaTypeEntity(contentTypeDto);
|
||||
else if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.DocumentType)
|
||||
contentType = ContentTypeFactory.BuildContentTypeEntity(contentTypeDto);
|
||||
else if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.MemberType)
|
||||
contentType = ContentTypeFactory.BuildMemberTypeEntity(contentTypeDto);
|
||||
else throw new Exception("panic");
|
||||
contentTypes.Add(contentType.Id, contentType);
|
||||
|
||||
// map allowed content types
|
||||
var allowedContentTypes = new List<ContentTypeSort>();
|
||||
while (allowedDtoIx < allowedDtos.Count && allowedDtos[allowedDtoIx].Id == contentTypeDto.NodeId)
|
||||
{
|
||||
var allowedDto = allowedDtos[allowedDtoIx];
|
||||
if (!aliases.TryGetValue(allowedDto.AllowedId, out var alias)) continue;
|
||||
allowedContentTypes.Add(new ContentTypeSort(new Lazy<int>(() => allowedDto.AllowedId), allowedDto.SortOrder, alias));
|
||||
allowedDtoIx++;
|
||||
}
|
||||
contentType.AllowedContentTypes = allowedContentTypes;
|
||||
}
|
||||
|
||||
MapTemplates(contentTypes);
|
||||
MapComposition(contentTypes);
|
||||
MapGroupsAndProperties(contentTypes);
|
||||
|
||||
// finalize
|
||||
foreach (var contentType in contentTypes.Values)
|
||||
{
|
||||
contentType.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
return contentTypes.Values;
|
||||
}
|
||||
|
||||
private void MapTemplates(Dictionary<int, IContentTypeComposition> contentTypes)
|
||||
{
|
||||
// get templates
|
||||
var sql1 = Sql()
|
||||
.Select<ContentTypeTemplateDto>()
|
||||
.From<ContentTypeTemplateDto>()
|
||||
.OrderBy<ContentTypeTemplateDto>(x => x.ContentTypeNodeId);
|
||||
|
||||
var templateDtos = Database.Fetch<ContentTypeTemplateDto>(sql1);
|
||||
//var templates = templateRepository.GetMany(templateDtos.Select(x => x.TemplateNodeId).ToArray()).ToDictionary(x => x.Id, x => x);
|
||||
var templates = _templateRepository.GetMany().ToDictionary(x => x.Id, x => x);
|
||||
var templateDtoIx = 0;
|
||||
|
||||
foreach (var c in contentTypes.Values)
|
||||
{
|
||||
if (!(c is ContentType contentType)) continue;
|
||||
|
||||
// map allowed templates
|
||||
var allowedTemplates = new List<ITemplate>();
|
||||
var defaultTemplateId = 0;
|
||||
while (templateDtoIx < templateDtos.Count && templateDtos[templateDtoIx].ContentTypeNodeId == contentType.Id)
|
||||
{
|
||||
var allowedDto = templateDtos[templateDtoIx];
|
||||
if (!templates.TryGetValue(allowedDto.TemplateNodeId, out var template)) continue;
|
||||
allowedTemplates.Add(template);
|
||||
templateDtoIx++;
|
||||
|
||||
if (allowedDto.IsDefault)
|
||||
defaultTemplateId = template.Id;
|
||||
}
|
||||
contentType.AllowedTemplates = allowedTemplates;
|
||||
contentType.DefaultTemplateId = defaultTemplateId;
|
||||
}
|
||||
}
|
||||
|
||||
private void MapComposition(IDictionary<int, IContentTypeComposition> contentTypes)
|
||||
{
|
||||
// get parent/child
|
||||
var sql1 = Sql()
|
||||
.Select<ContentType2ContentTypeDto>()
|
||||
.From<ContentType2ContentTypeDto>()
|
||||
.OrderBy<ContentType2ContentTypeDto>(x => x.ChildId);
|
||||
|
||||
var compositionDtos = Database.Fetch<ContentType2ContentTypeDto>(sql1);
|
||||
|
||||
// map
|
||||
var compositionIx = 0;
|
||||
foreach (var contentType in contentTypes.Values)
|
||||
{
|
||||
while (compositionIx < compositionDtos.Count && compositionDtos[compositionIx].ChildId == contentType.Id)
|
||||
{
|
||||
var parentDto = compositionDtos[compositionIx];
|
||||
if (!contentTypes.TryGetValue(parentDto.ParentId, out var parentContentType)) continue;
|
||||
contentType.AddContentType(parentContentType);
|
||||
compositionIx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MapGroupsAndProperties(IDictionary<int, IContentTypeComposition> contentTypes)
|
||||
{
|
||||
var sql1 = Sql()
|
||||
.Select<PropertyTypeGroupDto>()
|
||||
.From<PropertyTypeGroupDto>()
|
||||
.InnerJoin<ContentTypeDto>().On<PropertyTypeGroupDto, ContentTypeDto>((ptg, ct) => ptg.ContentTypeNodeId == ct.NodeId)
|
||||
.OrderBy<ContentTypeDto>(x => x.NodeId)
|
||||
.AndBy<PropertyTypeGroupDto>(x => x.SortOrder, x => x.Id);
|
||||
|
||||
var groupDtos = Database.Fetch<PropertyTypeGroupDto>(sql1);
|
||||
|
||||
var sql2 = Sql()
|
||||
.Select<PropertyTypeDto>(r => r.Select(x => x.DataTypeDto))
|
||||
.AndSelect<MemberPropertyTypeDto>()
|
||||
.From<PropertyTypeDto>()
|
||||
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>((pt, dt) => pt.DataTypeId == dt.NodeId)
|
||||
.InnerJoin<ContentTypeDto>().On<PropertyTypeDto, ContentTypeDto>((pt, ct) => pt.ContentTypeId == ct.NodeId)
|
||||
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeDto, PropertyTypeGroupDto>((pt, ptg) => pt.PropertyTypeGroupId == ptg.Id)
|
||||
.LeftJoin<MemberPropertyTypeDto>().On<PropertyTypeDto, MemberPropertyTypeDto>((pt, mpt) => pt.Id == mpt.PropertyTypeId)
|
||||
.OrderBy<ContentTypeDto>(x => x.NodeId)
|
||||
.AndBy<PropertyTypeGroupDto>(x => x.SortOrder, x => x.Id) // NULLs will come first or last, never mind, we deal with it below
|
||||
.AndBy<PropertyTypeDto>(x => x.SortOrder, x => x.Id);
|
||||
|
||||
var propertyDtos = Database.Fetch<PropertyTypeCommonDto>(sql2);
|
||||
var builtinProperties = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
|
||||
var groupIx = 0;
|
||||
var propertyIx = 0;
|
||||
foreach (var contentType in contentTypes.Values)
|
||||
{
|
||||
// only IContentType is publishing
|
||||
var isPublishing = contentType is IContentType;
|
||||
|
||||
// get group-less properties (in case NULL is ordered first)
|
||||
var noGroupPropertyTypes = new PropertyTypeCollection(isPublishing);
|
||||
while (propertyIx < propertyDtos.Count && propertyDtos[propertyIx].ContentTypeId == contentType.Id && propertyDtos[propertyIx].PropertyTypeGroupId == null)
|
||||
{
|
||||
noGroupPropertyTypes.Add(MapPropertyType(contentType, propertyDtos[propertyIx], builtinProperties));
|
||||
propertyIx++;
|
||||
}
|
||||
|
||||
// get groups and their properties
|
||||
var groupCollection = new PropertyGroupCollection();
|
||||
while (groupIx < groupDtos.Count && groupDtos[groupIx].ContentTypeNodeId == contentType.Id)
|
||||
{
|
||||
var group = MapPropertyGroup(groupDtos[groupIx], isPublishing);
|
||||
groupCollection.Add(group);
|
||||
groupIx++;
|
||||
|
||||
while (propertyIx < propertyDtos.Count && propertyDtos[propertyIx].ContentTypeId == contentType.Id && propertyDtos[propertyIx].PropertyTypeGroupId == group.Id)
|
||||
{
|
||||
group.PropertyTypes.Add(MapPropertyType(contentType, propertyDtos[propertyIx], builtinProperties));
|
||||
propertyIx++;
|
||||
}
|
||||
}
|
||||
contentType.PropertyGroups = groupCollection;
|
||||
|
||||
// get group-less properties (in case NULL is ordered last)
|
||||
while (propertyIx < propertyDtos.Count && propertyDtos[propertyIx].ContentTypeId == contentType.Id && propertyDtos[propertyIx].PropertyTypeGroupId == null)
|
||||
{
|
||||
noGroupPropertyTypes.Add(MapPropertyType(contentType, propertyDtos[propertyIx], builtinProperties));
|
||||
propertyIx++;
|
||||
}
|
||||
contentType.NoGroupPropertyTypes = noGroupPropertyTypes;
|
||||
}
|
||||
}
|
||||
|
||||
private PropertyGroup MapPropertyGroup(PropertyTypeGroupDto dto, bool isPublishing)
|
||||
{
|
||||
return new PropertyGroup(new PropertyTypeCollection(isPublishing))
|
||||
{
|
||||
Id = dto.Id,
|
||||
Name = dto.Text,
|
||||
SortOrder = dto.SortOrder,
|
||||
Key = dto.UniqueId
|
||||
};
|
||||
}
|
||||
|
||||
private PropertyType MapPropertyType(IContentTypeComposition contentType, PropertyTypeCommonDto dto, IDictionary<string, PropertyType> builtinProperties)
|
||||
{
|
||||
var groupId = dto.PropertyTypeGroupId;
|
||||
|
||||
var readonlyStorageType = builtinProperties.TryGetValue(dto.Alias, out var propertyType);
|
||||
var storageType = readonlyStorageType ? propertyType.ValueStorageType : Enum<ValueStorageType>.Parse(dto.DataTypeDto.DbType);
|
||||
|
||||
if (contentType is MemberType memberType)
|
||||
{
|
||||
var access = new MemberTypePropertyProfileAccess(dto.ViewOnProfile, dto.CanEdit, dto.IsSensitive);
|
||||
memberType.MemberTypePropertyTypes.Add(dto.Alias, access);
|
||||
}
|
||||
|
||||
return new PropertyType(dto.DataTypeDto.EditorAlias, storageType, readonlyStorageType, dto.Alias)
|
||||
{
|
||||
Description = dto.Description,
|
||||
DataTypeId = dto.DataTypeId,
|
||||
Id = dto.Id,
|
||||
Key = dto.UniqueId,
|
||||
Mandatory = dto.Mandatory,
|
||||
Name = dto.Name,
|
||||
PropertyGroupId = groupId.HasValue ? new Lazy<int>(() => groupId.Value) : null,
|
||||
SortOrder = dto.SortOrder,
|
||||
ValidationRegExp = dto.ValidationRegExp,
|
||||
Variations = (ContentVariation)dto.Variations
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// </summary>
|
||||
internal class ContentTypeRepository : ContentTypeRepositoryBase<IContentType>, IContentTypeRepository
|
||||
{
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
|
||||
public ContentTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, ITemplateRepository templateRepository)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
{
|
||||
_templateRepository = templateRepository;
|
||||
}
|
||||
public ContentTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IContentTypeCommonRepository commonRepository)
|
||||
: base(scopeAccessor, cache, logger, commonRepository)
|
||||
{ }
|
||||
|
||||
protected override bool SupportsPublishing => ContentType.SupportsPublishingConst;
|
||||
|
||||
@@ -32,75 +28,81 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
return new FullDataSetRepositoryCachePolicy<IContentType, int>(GlobalIsolatedCache, ScopeAccessor, GetEntityId, /*expires:*/ true);
|
||||
}
|
||||
|
||||
// every GetExists method goes cachePolicy.GetSomething which in turns goes PerformGetAll,
|
||||
// since this is a FullDataSet policy - and everything is cached
|
||||
// so here,
|
||||
// every PerformGet/Exists just GetMany() and then filters
|
||||
// except PerformGetAll which is the one really doing the job
|
||||
|
||||
// TODO: the filtering is highly inefficient as we deep-clone everything
|
||||
// there should be a way to GetMany(predicate) right from the cache policy!
|
||||
// and ah, well, this all caching should be refactored + the cache refreshers
|
||||
// should to repository.Clear() not deal with magic caches by themselves
|
||||
|
||||
protected override IContentType PerformGet(int id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Id == id);
|
||||
|
||||
protected override IContentType PerformGet(Guid id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Key == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id);
|
||||
|
||||
protected override IContentType PerformGet(string alias)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
|
||||
protected override bool PerformExists(Guid id)
|
||||
{
|
||||
return GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
|
||||
protected override IEnumerable<IContentType> PerformGetAll(params int[] ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
//NOTE: This logic should never be executed according to our cache policy
|
||||
return ContentTypeQueryMapper.GetContentTypes(Database, SqlSyntax, SupportsPublishing, this, _templateRepository)
|
||||
.Where(x => ids.Contains(x.Id));
|
||||
}
|
||||
|
||||
return ContentTypeQueryMapper.GetContentTypes(Database, SqlSyntax, SupportsPublishing, this, _templateRepository);
|
||||
// the cache policy will always want everything
|
||||
// even GetMany(ids) gets everything and filters afterwards
|
||||
if (ids.Any()) throw new Exception("panic");
|
||||
return CommonRepository.GetAllTypes().OfType<IContentType>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<IContentType> PerformGetAll(params Guid[] ids)
|
||||
{
|
||||
// use the underlying GetAll which will force cache all content types
|
||||
return ids.Any() ? GetMany().Where(x => ids.Contains(x.Key)) : GetMany();
|
||||
var all = GetMany();
|
||||
return ids.Any() ? all.Where(x => ids.Contains(x.Key)) : all;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IContentType> PerformGetByQuery(IQuery<IContentType> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IContentType>(sqlClause, query);
|
||||
var baseQuery = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IContentType>(baseQuery, query);
|
||||
var sql = translator.Translate();
|
||||
var ids = Database.Fetch<int>(sql).Distinct().ToArray();
|
||||
|
||||
var dtos = Database.Fetch<ContentTypeTemplateDto>(sql);
|
||||
|
||||
return
|
||||
//This returns a lookup from the GetAll cached lookup
|
||||
(dtos.Any()
|
||||
? GetMany(dtos.DistinctBy(x => x.ContentTypeDto.NodeId).Select(x => x.ContentTypeDto.NodeId).ToArray())
|
||||
: Enumerable.Empty<IContentType>())
|
||||
//order the result by name
|
||||
.OrderBy(x => x.Name);
|
||||
return ids.Length > 0 ? GetMany(ids).OrderBy(x => x.Name) : Enumerable.Empty<IContentType>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns>An enumerable list of <see cref="IContentType"/> objects</returns>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IContentType> GetByQuery(IQuery<PropertyType> query)
|
||||
{
|
||||
var ints = PerformGetByQuery(query).ToArray();
|
||||
return ints.Any()
|
||||
? GetMany(ints)
|
||||
: Enumerable.Empty<IContentType>();
|
||||
return ints.Length > 0 ? GetMany(ints) : Enumerable.Empty<IContentType>();
|
||||
}
|
||||
|
||||
protected IEnumerable<int> PerformGetByQuery(IQuery<PropertyType> query)
|
||||
{
|
||||
// used by DataTypeService to remove properties
|
||||
// from content types if they have a deleted data type - see
|
||||
// notes in DataTypeService.Delete as it's a bit weird
|
||||
|
||||
var sqlClause = Sql()
|
||||
.SelectAll()
|
||||
.From<PropertyTypeGroupDto>()
|
||||
.RightJoin<PropertyTypeDto>()
|
||||
.On<PropertyTypeGroupDto, PropertyTypeDto>(left => left.Id, right => right.PropertyTypeGroupId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.NodeId);
|
||||
|
||||
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId);
|
||||
|
||||
return Database
|
||||
.FetchOneToMany<PropertyTypeGroupDto>(x => x.PropertyTypeDtos, sql)
|
||||
.Select(x => x.ContentTypeNodeId).Distinct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,7 +143,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
if (aliases.Length == 0) return Enumerable.Empty<int>();
|
||||
|
||||
var sql = Sql()
|
||||
.Select("cmsContentType.nodeId")
|
||||
.Select<ContentTypeDto>(x => x.NodeId)
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentTypeDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
@@ -156,14 +158,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
sql = isCount
|
||||
? sql.SelectCount()
|
||||
: sql.Select<ContentTypeTemplateDto>(r => r.Select(x => x.ContentTypeDto, r1 => r1.Select(x => x.NodeDto)));
|
||||
: sql.Select<ContentTypeDto>(x => x.NodeId);
|
||||
|
||||
sql
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.LeftJoin<ContentTypeTemplateDto>()
|
||||
.On<ContentTypeTemplateDto, ContentTypeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>().On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.LeftJoin<ContentTypeTemplateDto>().On<ContentTypeTemplateDto, ContentTypeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
|
||||
return sql;
|
||||
|
||||
@@ -10,11 +10,9 @@ using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -28,9 +26,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
internal abstract class ContentTypeRepositoryBase<TEntity> : NPocoRepositoryBase<int, TEntity>, IReadRepository<Guid, TEntity>
|
||||
where TEntity : class, IContentTypeComposition
|
||||
{
|
||||
protected ContentTypeRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger)
|
||||
protected ContentTypeRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IContentTypeCommonRepository commonRepository)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
{ }
|
||||
{
|
||||
CommonRepository = commonRepository;
|
||||
}
|
||||
|
||||
protected IContentTypeCommonRepository CommonRepository { get; }
|
||||
|
||||
protected abstract bool SupportsPublishing { get; }
|
||||
|
||||
@@ -82,38 +84,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
return moveInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the content type ids that match the query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
protected IEnumerable<int> PerformGetByQuery(IQuery<PropertyType> query)
|
||||
|
||||
protected virtual PropertyType CreatePropertyType(string propertyEditorAlias, ValueStorageType storageType, string propertyTypeAlias)
|
||||
{
|
||||
// used by DataTypeDefinitionRepository to remove properties
|
||||
// from content types if they have a deleted data type - see
|
||||
// notes in DataTypeDefinitionRepository.Delete as it's a bit
|
||||
// weird
|
||||
|
||||
var sqlClause = Sql()
|
||||
.SelectAll()
|
||||
.From<PropertyTypeGroupDto>()
|
||||
.RightJoin<PropertyTypeDto>()
|
||||
.On<PropertyTypeGroupDto, PropertyTypeDto>(left => left.Id, right => right.PropertyTypeGroupId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.NodeId);
|
||||
|
||||
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId);
|
||||
|
||||
return Database
|
||||
.FetchOneToMany<PropertyTypeGroupDto>(x => x.PropertyTypeDtos, sql)
|
||||
.Select(x => x.ContentTypeNodeId).Distinct();
|
||||
return new PropertyType(propertyEditorAlias, storageType, propertyTypeAlias);
|
||||
}
|
||||
|
||||
protected virtual PropertyType CreatePropertyType(string propertyEditorAlias, ValueStorageType dbType, string propertyTypeAlias)
|
||||
protected override void PersistDeletedItem(TEntity entity)
|
||||
{
|
||||
return new PropertyType(propertyEditorAlias, dbType, propertyTypeAlias);
|
||||
base.PersistDeletedItem(entity);
|
||||
CommonRepository.ClearCache(); // always
|
||||
}
|
||||
|
||||
protected void PersistNewBaseContentType(IContentTypeComposition entity)
|
||||
@@ -228,6 +208,8 @@ AND umbracoNode.nodeObjectType = @objectType",
|
||||
propertyType.PropertyEditorAlias = dataTypeDto.EditorAlias;
|
||||
propertyType.ValueStorageType = dataTypeDto.DbType.EnumParse<ValueStorageType>(true);
|
||||
}
|
||||
|
||||
CommonRepository.ClearCache(); // always
|
||||
}
|
||||
|
||||
protected void PersistUpdatedBaseContentType(IContentTypeComposition entity)
|
||||
@@ -532,6 +514,8 @@ AND umbracoNode.id <> @id",
|
||||
if (orphanPropertyTypeIds != null)
|
||||
foreach (var id in orphanPropertyTypeIds)
|
||||
DeletePropertyType(entity.Id, id);
|
||||
|
||||
CommonRepository.ClearCache(); // always
|
||||
}
|
||||
|
||||
private IEnumerable<IContentTypeComposition> GetImpactedContentTypes(IContentTypeComposition contentType, IEnumerable<IContentTypeComposition> all)
|
||||
@@ -992,74 +976,6 @@ AND umbracoNode.id <> @id",
|
||||
new { Id = contentTypeId, PropertyTypeId = propertyTypeId });
|
||||
}
|
||||
|
||||
protected IEnumerable<ContentTypeSort> GetAllowedContentTypeIds(int id)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<ContentTypeAllowedContentTypeDto>()
|
||||
.LeftJoin<ContentTypeDto>()
|
||||
.On<ContentTypeAllowedContentTypeDto, ContentTypeDto>(left => left.AllowedId, right => right.NodeId)
|
||||
.Where<ContentTypeAllowedContentTypeDto>(x => x.Id == id);
|
||||
|
||||
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(sql);
|
||||
return allowedContentTypeDtos.Select(x => new ContentTypeSort(new Lazy<int>(() => x.AllowedId), x.SortOrder, x.ContentTypeDto.Alias)).ToList();
|
||||
}
|
||||
|
||||
protected PropertyGroupCollection GetPropertyGroupCollection(int id, DateTime createDate, DateTime updateDate)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<PropertyTypeGroupDto>()
|
||||
.LeftJoin<PropertyTypeDto>()
|
||||
.On<PropertyTypeGroupDto, PropertyTypeDto>(left => left.Id, right => right.PropertyTypeGroupId)
|
||||
.LeftJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.NodeId)
|
||||
.Where<PropertyTypeGroupDto>(x => x.ContentTypeNodeId == id)
|
||||
.OrderBy<PropertyTypeGroupDto>(x => x.Id);
|
||||
|
||||
|
||||
var dtos = Database
|
||||
.Fetch<PropertyTypeGroupDto>(sql);
|
||||
|
||||
var propertyGroups = PropertyGroupFactory.BuildEntity(dtos, SupportsPublishing, id, createDate, updateDate,CreatePropertyType);
|
||||
|
||||
return new PropertyGroupCollection(propertyGroups);
|
||||
}
|
||||
|
||||
protected PropertyTypeCollection GetPropertyTypeCollection(int id, DateTime createDate, DateTime updateDate)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<PropertyTypeDto>()
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.NodeId)
|
||||
.Where<PropertyTypeDto>(x => x.ContentTypeId == id);
|
||||
|
||||
var dtos = Database.Fetch<PropertyTypeDto>(sql);
|
||||
|
||||
// TODO: Move this to a PropertyTypeFactory
|
||||
var list = new List<PropertyType>();
|
||||
foreach (var dto in dtos.Where(x => x.PropertyTypeGroupId <= 0))
|
||||
{
|
||||
var propType = CreatePropertyType(dto.DataTypeDto.EditorAlias, dto.DataTypeDto.DbType.EnumParse<ValueStorageType>(true), dto.Alias);
|
||||
propType.DataTypeId = dto.DataTypeId;
|
||||
propType.Description = dto.Description;
|
||||
propType.Id = dto.Id;
|
||||
propType.Key = dto.UniqueId;
|
||||
propType.Name = dto.Name;
|
||||
propType.Mandatory = dto.Mandatory;
|
||||
propType.SortOrder = dto.SortOrder;
|
||||
propType.ValidationRegExp = dto.ValidationRegExp;
|
||||
propType.CreateDate = createDate;
|
||||
propType.UpdateDate = updateDate;
|
||||
list.Add(propType);
|
||||
}
|
||||
//Reset dirty properties
|
||||
Parallel.ForEach(list, currentFile => currentFile.ResetDirtyProperties(false));
|
||||
|
||||
return new PropertyTypeCollection(SupportsPublishing, list);
|
||||
}
|
||||
|
||||
protected void ValidateAlias(PropertyType pt)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pt.Alias))
|
||||
@@ -1114,589 +1030,6 @@ AND umbracoNode.id <> @id",
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ContentTypeQueryMapper
|
||||
{
|
||||
public class AssociatedTemplate
|
||||
{
|
||||
public AssociatedTemplate(int templateId, string alias, string templateName)
|
||||
{
|
||||
TemplateId = templateId;
|
||||
Alias = alias;
|
||||
TemplateName = templateName;
|
||||
}
|
||||
|
||||
public int TemplateId { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public string TemplateName { get; set; }
|
||||
|
||||
protected bool Equals(AssociatedTemplate other)
|
||||
{
|
||||
return TemplateId == other.TemplateId;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((AssociatedTemplate)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return TemplateId;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<IMediaType> GetMediaTypes<TRepo>(
|
||||
IDatabase db, ISqlSyntaxProvider sqlSyntax, bool isPublishing,
|
||||
TRepo contentTypeRepository)
|
||||
where TRepo : IReadRepository<int, TEntity>
|
||||
{
|
||||
IDictionary<int, List<int>> allParentMediaTypeIds;
|
||||
var mediaTypes = MapMediaTypes(db, sqlSyntax, out allParentMediaTypeIds)
|
||||
.ToArray();
|
||||
|
||||
MapContentTypeChildren(mediaTypes, db, sqlSyntax, isPublishing, contentTypeRepository, allParentMediaTypeIds);
|
||||
|
||||
return mediaTypes;
|
||||
}
|
||||
|
||||
public static IEnumerable<IContentType> GetContentTypes<TRepo>(
|
||||
IDatabase db, ISqlSyntaxProvider sqlSyntax, bool isPublishing,
|
||||
TRepo contentTypeRepository,
|
||||
ITemplateRepository templateRepository)
|
||||
where TRepo : IReadRepository<int, TEntity>
|
||||
{
|
||||
IDictionary<int, List<AssociatedTemplate>> allAssociatedTemplates;
|
||||
IDictionary<int, List<int>> allParentContentTypeIds;
|
||||
var contentTypes = MapContentTypes(db, sqlSyntax, out allAssociatedTemplates, out allParentContentTypeIds)
|
||||
.ToArray();
|
||||
|
||||
if (contentTypes.Any())
|
||||
{
|
||||
MapContentTypeTemplates(
|
||||
contentTypes, db, contentTypeRepository, templateRepository, allAssociatedTemplates);
|
||||
|
||||
MapContentTypeChildren(contentTypes, db, sqlSyntax, isPublishing, contentTypeRepository, allParentContentTypeIds);
|
||||
}
|
||||
|
||||
return contentTypes;
|
||||
}
|
||||
|
||||
internal static void MapContentTypeChildren<TRepo>(IContentTypeComposition[] contentTypes,
|
||||
IDatabase db, ISqlSyntaxProvider sqlSyntax, bool isPublishing,
|
||||
TRepo contentTypeRepository,
|
||||
IDictionary<int, List<int>> allParentContentTypeIds)
|
||||
where TRepo : IReadRepository<int, TEntity>
|
||||
{
|
||||
//NOTE: SQL call #2
|
||||
|
||||
var ids = contentTypes.Select(x => x.Id).ToArray();
|
||||
IDictionary<int, PropertyGroupCollection> allPropGroups;
|
||||
IDictionary<int, PropertyTypeCollection> allPropTypes;
|
||||
MapGroupsAndProperties(ids, db, sqlSyntax, isPublishing, out allPropTypes, out allPropGroups);
|
||||
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
contentType.PropertyGroups = allPropGroups[contentType.Id];
|
||||
contentType.NoGroupPropertyTypes = allPropTypes[contentType.Id];
|
||||
}
|
||||
|
||||
//NOTE: SQL call #3++
|
||||
|
||||
if (allParentContentTypeIds != null)
|
||||
{
|
||||
var allParentIdsAsArray = allParentContentTypeIds.SelectMany(x => x.Value).Distinct().ToArray();
|
||||
if (allParentIdsAsArray.Any())
|
||||
{
|
||||
var allParentContentTypes = contentTypes.Where(x => allParentIdsAsArray.Contains(x.Id)).ToArray();
|
||||
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
var entityId = contentType.Id;
|
||||
|
||||
var parentContentTypes = allParentContentTypes.Where(x =>
|
||||
{
|
||||
var parentEntityId = x.Id;
|
||||
|
||||
return allParentContentTypeIds[entityId].Contains(parentEntityId);
|
||||
});
|
||||
foreach (var parentContentType in parentContentTypes)
|
||||
{
|
||||
var result = contentType.AddContentType(parentContentType);
|
||||
//Do something if adding fails? (Should hopefully not be possible unless someone created a circular reference)
|
||||
}
|
||||
|
||||
// reset dirty initial properties (U4-1946)
|
||||
((EntityBase)contentType).ResetDirtyProperties(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal static void MapContentTypeTemplates<TRepo>(IContentType[] contentTypes,
|
||||
IDatabase db,
|
||||
TRepo contentTypeRepository,
|
||||
ITemplateRepository templateRepository,
|
||||
IDictionary<int, List<AssociatedTemplate>> associatedTemplates)
|
||||
where TRepo : IReadRepository<int, TEntity>
|
||||
{
|
||||
if (associatedTemplates == null || associatedTemplates.Any() == false) return;
|
||||
|
||||
//NOTE: SQL call #3++
|
||||
//SEE: http://issues.umbraco.org/issue/U4-5174 to fix this
|
||||
|
||||
var templateIds = associatedTemplates.SelectMany(x => x.Value).Select(x => x.TemplateId)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
var templates = (templateIds.Any()
|
||||
? templateRepository.GetMany(templateIds)
|
||||
: Enumerable.Empty<ITemplate>()).ToArray();
|
||||
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
var entityId = contentType.Id;
|
||||
|
||||
var associatedTemplateIds = associatedTemplates[entityId].Select(x => x.TemplateId)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
contentType.AllowedTemplates = (associatedTemplateIds.Any()
|
||||
? templates.Where(x => associatedTemplateIds.Contains(x.Id))
|
||||
: Enumerable.Empty<ITemplate>()).ToArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal static IEnumerable<IMediaType> MapMediaTypes(IDatabase db, ISqlSyntaxProvider sqlSyntax,
|
||||
out IDictionary<int, List<int>> parentMediaTypeIds)
|
||||
{
|
||||
if (db == null) throw new ArgumentNullException(nameof(db));
|
||||
|
||||
var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations,
|
||||
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
|
||||
AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
|
||||
ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey,
|
||||
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
|
||||
umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed,
|
||||
umbracoNode.uniqueID as nUniqueId
|
||||
FROM cmsContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType.nodeId = umbracoNode.id
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentTypeAllowedContentType.Id, cmsContentTypeAllowedContentType.AllowedId, cmsContentType.alias, cmsContentTypeAllowedContentType.SortOrder
|
||||
FROM cmsContentTypeAllowedContentType
|
||||
INNER JOIN cmsContentType
|
||||
ON cmsContentTypeAllowedContentType.AllowedId = cmsContentType.nodeId
|
||||
) AllowedTypes
|
||||
ON AllowedTypes.Id = cmsContentType.nodeId
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentType2ContentType.parentContentTypeId, umbracoNode.uniqueID AS parentContentTypeKey, cmsContentType2ContentType.childContentTypeId
|
||||
FROM cmsContentType2ContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType2ContentType.parentContentTypeId = umbracoNode." + sqlSyntax.GetQuotedColumnName("id") + @"
|
||||
) ParentTypes
|
||||
ON ParentTypes.childContentTypeId = cmsContentType.nodeId
|
||||
WHERE (umbracoNode.nodeObjectType = @nodeObjectType)
|
||||
ORDER BY ctId";
|
||||
|
||||
var result = db.Fetch<dynamic>(sql, new { nodeObjectType = Constants.ObjectTypes.MediaType });
|
||||
|
||||
if (result.Any() == false)
|
||||
{
|
||||
parentMediaTypeIds = null;
|
||||
return Enumerable.Empty<IMediaType>();
|
||||
}
|
||||
|
||||
parentMediaTypeIds = new Dictionary<int, List<int>>();
|
||||
var mappedMediaTypes = new List<IMediaType>();
|
||||
|
||||
//loop through each result and fill in our required values, each row will contain different required data than the rest.
|
||||
// it is much quicker to iterate each result and populate instead of looking up the values over and over in the result like
|
||||
// we used to do.
|
||||
var queue = new Queue<dynamic>(result);
|
||||
var currAllowedContentTypes = new List<ContentTypeSort>();
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var ct = queue.Dequeue();
|
||||
|
||||
//check for allowed content types
|
||||
int? allowedCtId = ct.ctaAllowedId;
|
||||
int? allowedCtSort = ct.ctaSortOrder;
|
||||
string allowedCtAlias = ct.ctaAlias;
|
||||
if (allowedCtId.HasValue && allowedCtSort.HasValue && allowedCtAlias != null)
|
||||
{
|
||||
var ctSort = new ContentTypeSort(new Lazy<int>(() => allowedCtId.Value), allowedCtSort.Value, allowedCtAlias);
|
||||
if (currAllowedContentTypes.Contains(ctSort) == false)
|
||||
{
|
||||
currAllowedContentTypes.Add(ctSort);
|
||||
}
|
||||
}
|
||||
|
||||
//always ensure there's a list for this content type
|
||||
if (parentMediaTypeIds.ContainsKey(ct.ctId) == false)
|
||||
parentMediaTypeIds[ct.ctId] = new List<int>();
|
||||
|
||||
//check for parent ids and assign to the outgoing collection
|
||||
int? parentId = ct.chtParentId;
|
||||
if (parentId.HasValue)
|
||||
{
|
||||
var associatedParentIds = parentMediaTypeIds[ct.ctId];
|
||||
if (associatedParentIds.Contains(parentId.Value) == false)
|
||||
associatedParentIds.Add(parentId.Value);
|
||||
}
|
||||
|
||||
if (queue.Count == 0 || queue.Peek().ctId != ct.ctId)
|
||||
{
|
||||
//it's the last in the queue or the content type is changing (moving to the next one)
|
||||
var mediaType = CreateForMapping(ct, currAllowedContentTypes);
|
||||
mappedMediaTypes.Add(mediaType);
|
||||
|
||||
//Here we need to reset the current variables, we're now collecting data for a different content type
|
||||
currAllowedContentTypes = new List<ContentTypeSort>();
|
||||
}
|
||||
}
|
||||
|
||||
return mappedMediaTypes;
|
||||
}
|
||||
|
||||
private static IMediaType CreateForMapping(dynamic currCt, List<ContentTypeSort> currAllowedContentTypes)
|
||||
{
|
||||
// * create the DTO object
|
||||
// * create the content type object
|
||||
// * map the allowed content types
|
||||
// * add to the outgoing list
|
||||
|
||||
var contentTypeDto = new ContentTypeDto
|
||||
{
|
||||
Alias = currCt.ctAlias,
|
||||
AllowAtRoot = currCt.ctAllowAtRoot,
|
||||
Description = currCt.ctDesc,
|
||||
Icon = currCt.ctIcon,
|
||||
IsContainer = currCt.ctIsContainer,
|
||||
IsElement = currCt.ctIsElement,
|
||||
NodeId = currCt.ctId,
|
||||
PrimaryKey = currCt.ctPk,
|
||||
Thumbnail = currCt.ctThumb,
|
||||
Variations = (byte) currCt.ctVariations,
|
||||
//map the underlying node dto
|
||||
NodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = currCt.nCreateDate,
|
||||
Level = (short)currCt.nLevel,
|
||||
NodeId = currCt.ctId,
|
||||
NodeObjectType = currCt.nObjectType,
|
||||
ParentId = currCt.nParentId,
|
||||
Path = currCt.nPath,
|
||||
SortOrder = currCt.nSortOrder,
|
||||
Text = currCt.nName,
|
||||
Trashed = currCt.nTrashed,
|
||||
UniqueId = currCt.nUniqueId,
|
||||
UserId = currCt.nUser
|
||||
}
|
||||
};
|
||||
|
||||
//now create the content type object;
|
||||
var mediaType = ContentTypeFactory.BuildMediaTypeEntity(contentTypeDto);
|
||||
|
||||
//map the allowed content types
|
||||
mediaType.AllowedContentTypes = currAllowedContentTypes;
|
||||
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
internal static IEnumerable<IContentType> MapContentTypes(IDatabase db, ISqlSyntaxProvider sqlSyntax,
|
||||
out IDictionary<int, List<AssociatedTemplate>> associatedTemplates,
|
||||
out IDictionary<int, List<int>> parentContentTypeIds)
|
||||
{
|
||||
if (db == null) throw new ArgumentNullException(nameof(db));
|
||||
|
||||
var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId,
|
||||
cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations,
|
||||
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
|
||||
AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
|
||||
ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey,
|
||||
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
|
||||
umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed,
|
||||
umbracoNode.uniqueID as nUniqueId,
|
||||
Template.alias as tAlias, Template.nodeId as tId,Template.text as tText
|
||||
FROM cmsContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType.nodeId = umbracoNode.id
|
||||
LEFT JOIN cmsDocumentType
|
||||
ON cmsDocumentType.contentTypeNodeId = cmsContentType.nodeId
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentTypeAllowedContentType.Id, cmsContentTypeAllowedContentType.AllowedId, cmsContentType.alias, cmsContentTypeAllowedContentType.SortOrder
|
||||
FROM cmsContentTypeAllowedContentType
|
||||
INNER JOIN cmsContentType
|
||||
ON cmsContentTypeAllowedContentType.AllowedId = cmsContentType.nodeId
|
||||
) AllowedTypes
|
||||
ON AllowedTypes.Id = cmsContentType.nodeId
|
||||
LEFT JOIN (
|
||||
SELECT * FROM cmsTemplate
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsTemplate.nodeId = umbracoNode.id
|
||||
) as Template
|
||||
ON Template.nodeId = cmsDocumentType.templateNodeId
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentType2ContentType.parentContentTypeId, umbracoNode.uniqueID AS parentContentTypeKey, cmsContentType2ContentType.childContentTypeId
|
||||
FROM cmsContentType2ContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType2ContentType.parentContentTypeId = umbracoNode." + sqlSyntax.GetQuotedColumnName("id") + @"
|
||||
) ParentTypes
|
||||
ON ParentTypes.childContentTypeId = cmsContentType.nodeId
|
||||
WHERE (umbracoNode.nodeObjectType = @nodeObjectType)
|
||||
ORDER BY ctId";
|
||||
|
||||
var result = db.Fetch<dynamic>(sql, new { nodeObjectType = Constants.ObjectTypes.DocumentType });
|
||||
|
||||
if (result.Any() == false)
|
||||
{
|
||||
parentContentTypeIds = null;
|
||||
associatedTemplates = null;
|
||||
return Enumerable.Empty<IContentType>();
|
||||
}
|
||||
|
||||
parentContentTypeIds = new Dictionary<int, List<int>>();
|
||||
associatedTemplates = new Dictionary<int, List<AssociatedTemplate>>();
|
||||
var mappedContentTypes = new List<IContentType>();
|
||||
|
||||
var queue = new Queue<dynamic>(result);
|
||||
var currDefaultTemplate = -1;
|
||||
var currAllowedContentTypes = new List<ContentTypeSort>();
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var ct = queue.Dequeue();
|
||||
|
||||
//check for default templates
|
||||
bool? isDefaultTemplate = Convert.ToBoolean(ct.dtIsDefault);
|
||||
int? templateId = ct.dtTemplateId;
|
||||
if (currDefaultTemplate == -1 && isDefaultTemplate.HasValue && isDefaultTemplate.Value && templateId.HasValue)
|
||||
{
|
||||
currDefaultTemplate = templateId.Value;
|
||||
}
|
||||
|
||||
//always ensure there's a list for this content type
|
||||
if (associatedTemplates.ContainsKey(ct.ctId) == false)
|
||||
associatedTemplates[ct.ctId] = new List<AssociatedTemplate>();
|
||||
|
||||
//check for associated templates and assign to the outgoing collection
|
||||
if (ct.tId != null)
|
||||
{
|
||||
var associatedTemplate = new AssociatedTemplate(ct.tId, ct.tAlias, ct.tText);
|
||||
var associatedList = associatedTemplates[ct.ctId];
|
||||
|
||||
if (associatedList.Contains(associatedTemplate) == false)
|
||||
associatedList.Add(associatedTemplate);
|
||||
}
|
||||
|
||||
//check for allowed content types
|
||||
int? allowedCtId = ct.ctaAllowedId;
|
||||
int? allowedCtSort = ct.ctaSortOrder;
|
||||
string allowedCtAlias = ct.ctaAlias;
|
||||
if (allowedCtId.HasValue && allowedCtSort.HasValue && allowedCtAlias != null)
|
||||
{
|
||||
var ctSort = new ContentTypeSort(new Lazy<int>(() => allowedCtId.Value), allowedCtSort.Value, allowedCtAlias);
|
||||
if (currAllowedContentTypes.Contains(ctSort) == false)
|
||||
{
|
||||
currAllowedContentTypes.Add(ctSort);
|
||||
}
|
||||
}
|
||||
|
||||
//always ensure there's a list for this content type
|
||||
if (parentContentTypeIds.ContainsKey(ct.ctId) == false)
|
||||
parentContentTypeIds[ct.ctId] = new List<int>();
|
||||
|
||||
//check for parent ids and assign to the outgoing collection
|
||||
int? parentId = ct.chtParentId;
|
||||
if (parentId.HasValue)
|
||||
{
|
||||
var associatedParentIds = parentContentTypeIds[ct.ctId];
|
||||
|
||||
if (associatedParentIds.Contains(parentId.Value) == false)
|
||||
associatedParentIds.Add(parentId.Value);
|
||||
}
|
||||
|
||||
if (queue.Count == 0 || queue.Peek().ctId != ct.ctId)
|
||||
{
|
||||
//it's the last in the queue or the content type is changing (moving to the next one)
|
||||
var contentType = CreateForMapping(ct, currAllowedContentTypes, currDefaultTemplate);
|
||||
mappedContentTypes.Add(contentType);
|
||||
|
||||
//Here we need to reset the current variables, we're now collecting data for a different content type
|
||||
currDefaultTemplate = -1;
|
||||
currAllowedContentTypes = new List<ContentTypeSort>();
|
||||
}
|
||||
}
|
||||
|
||||
return mappedContentTypes;
|
||||
}
|
||||
|
||||
private static IContentType CreateForMapping(dynamic currCt, List<ContentTypeSort> currAllowedContentTypes, int currDefaultTemplate)
|
||||
{
|
||||
// * set the default template to the first one if a default isn't found
|
||||
// * create the DTO object
|
||||
// * create the content type object
|
||||
// * map the allowed content types
|
||||
// * add to the outgoing list
|
||||
|
||||
var dtDto = new ContentTypeTemplateDto
|
||||
{
|
||||
//create the content type dto
|
||||
ContentTypeDto = new ContentTypeDto
|
||||
{
|
||||
Alias = currCt.ctAlias,
|
||||
AllowAtRoot = currCt.ctAllowAtRoot,
|
||||
Description = currCt.ctDesc,
|
||||
Icon = currCt.ctIcon,
|
||||
IsContainer = currCt.ctIsContainer,
|
||||
IsElement = currCt.ctIsElement,
|
||||
NodeId = currCt.ctId,
|
||||
PrimaryKey = currCt.ctPk,
|
||||
Thumbnail = currCt.ctThumb,
|
||||
Variations = (byte) currCt.ctVariations,
|
||||
//map the underlying node dto
|
||||
NodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = currCt.nCreateDate,
|
||||
Level = (short)currCt.nLevel,
|
||||
NodeId = currCt.ctId,
|
||||
NodeObjectType = currCt.nObjectType,
|
||||
ParentId = currCt.nParentId,
|
||||
Path = currCt.nPath,
|
||||
SortOrder = currCt.nSortOrder,
|
||||
Text = currCt.nName,
|
||||
Trashed = currCt.nTrashed,
|
||||
UniqueId = currCt.nUniqueId,
|
||||
UserId = currCt.nUser
|
||||
}
|
||||
},
|
||||
ContentTypeNodeId = currCt.ctId,
|
||||
IsDefault = currDefaultTemplate != -1,
|
||||
TemplateNodeId = currDefaultTemplate != -1 ? currDefaultTemplate : 0,
|
||||
};
|
||||
|
||||
//now create the content type object
|
||||
var contentType = ContentTypeFactory.BuildContentTypeEntity(dtDto.ContentTypeDto);
|
||||
|
||||
// NOTE
|
||||
// that was done by the factory but makes little sense, moved here, so
|
||||
// now we have to reset dirty props again (as the factory does it) and yet,
|
||||
// we are not managing allowed templates... the whole thing is weird.
|
||||
((ContentType)contentType).DefaultTemplateId = dtDto.TemplateNodeId;
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
//map the allowed content types
|
||||
contentType.AllowedContentTypes = currAllowedContentTypes;
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
internal static void MapGroupsAndProperties(int[] contentTypeIds, IDatabase db, ISqlSyntaxProvider sqlSyntax, bool isPublishing,
|
||||
out IDictionary<int, PropertyTypeCollection> allPropertyTypeCollection,
|
||||
out IDictionary<int, PropertyGroupCollection> allPropertyGroupCollection)
|
||||
{
|
||||
allPropertyGroupCollection = new Dictionary<int, PropertyGroupCollection>();
|
||||
allPropertyTypeCollection = new Dictionary<int, PropertyTypeCollection>();
|
||||
|
||||
// query below is not safe + pointless if array is empty
|
||||
if (contentTypeIds.Length == 0) return;
|
||||
|
||||
var sqlGroups = @"SELECT
|
||||
pg.contenttypeNodeId AS contentTypeId,
|
||||
pg.id AS id, pg.uniqueID AS " + sqlSyntax.GetQuotedColumnName("key") + @",
|
||||
pg.sortOrder AS sortOrder, pg." + sqlSyntax.GetQuotedColumnName("text") + @" AS text
|
||||
FROM cmsPropertyTypeGroup pg
|
||||
WHERE pg.contenttypeNodeId IN (@ids)
|
||||
ORDER BY contentTypeId, id";
|
||||
|
||||
var sqlProps = @"SELECT
|
||||
pt.contentTypeId AS contentTypeId,
|
||||
pt.id AS id, pt.uniqueID AS " + sqlSyntax.GetQuotedColumnName("key") + @",
|
||||
pt.propertyTypeGroupId AS groupId,
|
||||
pt.Alias AS alias, pt." + sqlSyntax.GetQuotedColumnName("Description") + @" AS " + sqlSyntax.GetQuotedColumnName("desc") + $@", pt.mandatory AS mandatory,
|
||||
pt.Name AS name, pt.sortOrder AS sortOrder, pt.validationRegExp AS regexp, pt.variations as variations,
|
||||
dt.nodeId as dataTypeId, dt.dbType as dbType, dt.propertyEditorAlias as editorAlias
|
||||
FROM cmsPropertyType pt
|
||||
INNER JOIN {Constants.DatabaseSchema.Tables.DataType} as dt ON pt.dataTypeId = dt.nodeId
|
||||
WHERE pt.contentTypeId IN (@ids)
|
||||
ORDER BY contentTypeId, groupId, id";
|
||||
|
||||
if (contentTypeIds.Length > 2000)
|
||||
throw new InvalidOperationException("Cannot perform this lookup, too many sql parameters");
|
||||
|
||||
var groups = db.Fetch<dynamic>(sqlGroups, new { ids = contentTypeIds });
|
||||
var groupsEnumerator = groups.GetEnumerator();
|
||||
var group = groupsEnumerator.MoveNext() ? groupsEnumerator.Current : null;
|
||||
|
||||
var props = db.Fetch<dynamic>(sqlProps, new { ids = contentTypeIds });
|
||||
var propsEnumerator = props.GetEnumerator();
|
||||
var prop = propsEnumerator.MoveNext() ? propsEnumerator.Current : null;
|
||||
|
||||
// groups are ordered by content type, group id
|
||||
// props are ordered by content type, group id, prop id
|
||||
|
||||
foreach (var contentTypeId in contentTypeIds)
|
||||
{
|
||||
var propertyTypeCollection = allPropertyTypeCollection[contentTypeId] = new PropertyTypeCollection(isPublishing);
|
||||
var propertyGroupCollection = allPropertyGroupCollection[contentTypeId] = new PropertyGroupCollection();
|
||||
|
||||
while (prop != null && prop.contentTypeId == contentTypeId && prop.groupId == null)
|
||||
{
|
||||
AddPropertyType(propertyTypeCollection, prop);
|
||||
prop = propsEnumerator.MoveNext() ? propsEnumerator.Current : null;
|
||||
}
|
||||
|
||||
while (group != null && group.contentTypeId == contentTypeId)
|
||||
{
|
||||
var propertyGroup = new PropertyGroup(new PropertyTypeCollection(isPublishing))
|
||||
{
|
||||
Id = group.id,
|
||||
Name = group.text,
|
||||
SortOrder = group.sortOrder,
|
||||
Key = group.key
|
||||
};
|
||||
propertyGroupCollection.Add(propertyGroup);
|
||||
|
||||
while (prop != null && prop.groupId == group.id)
|
||||
{
|
||||
AddPropertyType(propertyGroup.PropertyTypes, prop, propertyGroup);
|
||||
prop = propsEnumerator.MoveNext() ? propsEnumerator.Current : null;
|
||||
}
|
||||
|
||||
group = groupsEnumerator.MoveNext() ? groupsEnumerator.Current : null;
|
||||
}
|
||||
}
|
||||
|
||||
propsEnumerator.Dispose();
|
||||
groupsEnumerator.Dispose();
|
||||
}
|
||||
|
||||
private static void AddPropertyType(PropertyTypeCollection propertyTypes, dynamic prop, PropertyGroup propertyGroup = null)
|
||||
{
|
||||
var propertyType = new PropertyType(prop.editorAlias, Enum<ValueStorageType>.Parse(prop.dbType), prop.alias)
|
||||
{
|
||||
Description = prop.desc,
|
||||
DataTypeId = prop.dataTypeId,
|
||||
Id = prop.id,
|
||||
Key = prop.key,
|
||||
Mandatory = Convert.ToBoolean(prop.mandatory),
|
||||
Name = prop.name,
|
||||
PropertyGroupId = propertyGroup == null ? null : new Lazy<int>(() => propertyGroup.Id),
|
||||
SortOrder = prop.sortOrder,
|
||||
ValidationRegExp = prop.regexp,
|
||||
Variations = (ContentVariation) prop.variations
|
||||
};
|
||||
propertyTypes.Add(propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract TEntity PerformGet(Guid id);
|
||||
protected abstract TEntity PerformGet(string alias);
|
||||
protected abstract IEnumerable<TEntity> PerformGetAll(params Guid[] ids);
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// </summary>
|
||||
internal class MediaTypeRepository : ContentTypeRepositoryBase<IMediaType>, IMediaTypeRepository
|
||||
{
|
||||
public MediaTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
public MediaTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IContentTypeCommonRepository commonRepository)
|
||||
: base(scopeAccessor, cache, logger, commonRepository)
|
||||
{ }
|
||||
|
||||
protected override bool SupportsPublishing => MediaType.SupportsPublishingConst;
|
||||
@@ -27,83 +27,46 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
return new FullDataSetRepositoryCachePolicy<IMediaType, int>(GlobalIsolatedCache, ScopeAccessor, GetEntityId, /*expires:*/ true);
|
||||
}
|
||||
|
||||
// every GetExists method goes cachePolicy.GetSomething which in turns goes PerformGetAll,
|
||||
// since this is a FullDataSet policy - and everything is cached
|
||||
// so here,
|
||||
// every PerformGet/Exists just GetMany() and then filters
|
||||
// except PerformGetAll which is the one really doing the job
|
||||
|
||||
protected override IMediaType PerformGet(int id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Id == id);
|
||||
|
||||
protected override IMediaType PerformGet(Guid id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Key == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id);
|
||||
|
||||
protected override bool PerformExists(Guid id)
|
||||
{
|
||||
return GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
|
||||
protected override IMediaType PerformGet(string alias)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
|
||||
protected override IEnumerable<IMediaType> PerformGetAll(params int[] ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
//NOTE: This logic should never be executed according to our cache policy
|
||||
return ContentTypeQueryMapper.GetMediaTypes(Database, SqlSyntax, SupportsPublishing, this)
|
||||
.Where(x => ids.Contains(x.Id));
|
||||
}
|
||||
|
||||
return ContentTypeQueryMapper.GetMediaTypes(Database, SqlSyntax, SupportsPublishing, this);
|
||||
// the cache policy will always want everything
|
||||
// even GetMany(ids) gets everything and filters afterwards
|
||||
if (ids.Any()) throw new Exception("panic");
|
||||
return CommonRepository.GetAllTypes().OfType<IMediaType>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<IMediaType> PerformGetAll(params Guid[] ids)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
return GetMany().Where(x => ids.Contains(x.Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetMany();
|
||||
}
|
||||
var all = GetMany();
|
||||
return ids.Any() ? all.Where(x => ids.Contains(x.Key)) : all;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IMediaType> PerformGetByQuery(IQuery<IMediaType> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IMediaType>(sqlClause, query);
|
||||
var baseQuery = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IMediaType>(baseQuery, query);
|
||||
var sql = translator.Translate();
|
||||
var ids = Database.Fetch<int>(sql).Distinct().ToArray();
|
||||
|
||||
var dtos = Database.Fetch<ContentTypeDto>(sql);
|
||||
|
||||
return
|
||||
//This returns a lookup from the GetAll cached lookup
|
||||
(dtos.Any()
|
||||
? GetMany(dtos.DistinctBy(x => x.NodeId).Select(x => x.NodeId).ToArray())
|
||||
: Enumerable.Empty<IMediaType>())
|
||||
//order the result by name
|
||||
.OrderBy(x => x.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns>An enumerable list of <see cref="IMediaType"/> objects</returns>
|
||||
public IEnumerable<IMediaType> GetByQuery(IQuery<PropertyType> query)
|
||||
{
|
||||
var ints = PerformGetByQuery(query).ToArray();
|
||||
return ints.Any()
|
||||
? GetMany(ints)
|
||||
: Enumerable.Empty<IMediaType>();
|
||||
return ids.Length > 0 ? GetMany(ids).OrderBy(x => x.Name) : Enumerable.Empty<IMediaType>();
|
||||
}
|
||||
|
||||
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
|
||||
@@ -112,12 +75,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
sql = isCount
|
||||
? sql.SelectCount()
|
||||
: sql.Select<ContentTypeDto>(r => r.Select(x => x.NodeDto));
|
||||
: sql.Select<ContentTypeDto>(x => x.NodeId);
|
||||
|
||||
sql
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentTypeDto, NodeDto>( left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>().On<ContentTypeDto, NodeDto>( left => left.NodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
|
||||
return sql;
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// </summary>
|
||||
internal class MemberTypeRepository : ContentTypeRepositoryBase<IMemberType>, IMemberTypeRepository
|
||||
{
|
||||
public MemberTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
public MemberTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IContentTypeCommonRepository commonRepository)
|
||||
: base(scopeAccessor, cache, logger, commonRepository)
|
||||
{ }
|
||||
|
||||
protected override bool SupportsPublishing => MemberType.SupportsPublishingConst;
|
||||
@@ -28,108 +28,49 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
return new FullDataSetRepositoryCachePolicy<IMemberType, int>(GlobalIsolatedCache, ScopeAccessor, GetEntityId, /*expires:*/ true);
|
||||
}
|
||||
|
||||
// every GetExists method goes cachePolicy.GetSomething which in turns goes PerformGetAll,
|
||||
// since this is a FullDataSet policy - and everything is cached
|
||||
// so here,
|
||||
// every PerformGet/Exists just GetMany() and then filters
|
||||
// except PerformGetAll which is the one really doing the job
|
||||
|
||||
protected override IMemberType PerformGet(int id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Id == id);
|
||||
|
||||
protected override IMemberType PerformGet(Guid id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Key == id);
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id);
|
||||
|
||||
protected override IEnumerable<IMemberType> PerformGetAll(params Guid[] ids)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
return GetMany().Where(x => ids.Contains(x.Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetMany();
|
||||
}
|
||||
var all = GetMany();
|
||||
return ids.Any() ? all.Where(x => ids.Contains(x.Key)) : all;
|
||||
}
|
||||
|
||||
protected override bool PerformExists(Guid id)
|
||||
{
|
||||
return GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Key == id) != null;
|
||||
|
||||
protected override IMemberType PerformGet(string alias)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all content types
|
||||
return GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
}
|
||||
=> GetMany().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
|
||||
protected override IEnumerable<IMemberType> PerformGetAll(params int[] ids)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
if (ids.Any())
|
||||
{
|
||||
//NOTE: This logic should never be executed according to our cache policy
|
||||
var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x)));
|
||||
sql.Where(statement);
|
||||
}
|
||||
sql.OrderByDescending<NodeDto>(x => x.NodeId);
|
||||
|
||||
var dtos = Database
|
||||
.Fetch<MemberTypeReadOnlyDto>(sql) // cannot use FetchOneToMany because we have 2 collections!
|
||||
.Transform(MapOneToManies)
|
||||
.ToList();
|
||||
|
||||
return BuildFromDtos(dtos);
|
||||
// the cache policy will always want everything
|
||||
// even GetMany(ids) gets everything and filters afterwards
|
||||
if (ids.Any()) throw new Exception("panic");
|
||||
return CommonRepository.GetAllTypes().OfType<IMemberType>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<IMemberType> PerformGetByQuery(IQuery<IMemberType> query)
|
||||
{
|
||||
var sqlSubquery = GetSubquery();
|
||||
var translator = new SqlTranslator<IMemberType>(sqlSubquery, query);
|
||||
var subquery = translator.Translate();
|
||||
var subQuery = GetSubquery();
|
||||
var translator = new SqlTranslator<IMemberType>(subQuery, query);
|
||||
var subSql = translator.Translate();
|
||||
var sql = GetBaseQuery(false)
|
||||
.Append("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments)
|
||||
.WhereIn<NodeDto>(x => x.NodeId, subSql)
|
||||
.OrderBy<NodeDto>(x => x.SortOrder);
|
||||
var ids = Database.Fetch<int>(sql).Distinct().ToArray();
|
||||
|
||||
var dtos = Database
|
||||
.Fetch<MemberTypeReadOnlyDto>(sql) // cannot use FetchOneToMany because we have 2 collections!
|
||||
.Transform(MapOneToManies)
|
||||
.ToList();
|
||||
|
||||
return BuildFromDtos(dtos);
|
||||
}
|
||||
|
||||
private IEnumerable<MemberTypeReadOnlyDto> MapOneToManies(IEnumerable<MemberTypeReadOnlyDto> dtos)
|
||||
{
|
||||
MemberTypeReadOnlyDto acc = null;
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
if (acc == null)
|
||||
{
|
||||
acc = dto;
|
||||
}
|
||||
else if (acc.UniqueId == dto.UniqueId)
|
||||
{
|
||||
var prop = dto.PropertyTypes.SingleOrDefault();
|
||||
var group = dto.PropertyTypeGroups.SingleOrDefault();
|
||||
|
||||
if (prop != null && prop.Id.HasValue && acc.PropertyTypes.Any(x => x.Id == prop.Id.Value) == false)
|
||||
acc.PropertyTypes.Add(prop);
|
||||
|
||||
if (group != null && group.Id.HasValue && acc.PropertyTypeGroups.Any(x => x.Id == group.Id.Value) == false)
|
||||
acc.PropertyTypeGroups.Add(group);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return acc;
|
||||
acc = dto;
|
||||
}
|
||||
}
|
||||
|
||||
if (acc != null)
|
||||
yield return acc;
|
||||
return ids.Length > 0 ? GetMany(ids).OrderBy(x => x.Name) : Enumerable.Empty<IMemberType>();
|
||||
}
|
||||
|
||||
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
|
||||
@@ -144,18 +85,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
}
|
||||
|
||||
var sql = Sql()
|
||||
.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias",
|
||||
"cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", "cmsPropertyType.UniqueID",
|
||||
"cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder",
|
||||
"cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId",
|
||||
"cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile", "cmsMemberType.isSensitive",
|
||||
$"{Constants.DatabaseSchema.Tables.DataType}.propertyEditorAlias", $"{Constants.DatabaseSchema.Tables.DataType}.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId",
|
||||
"cmsPropertyTypeGroup.text AS PropertyGroupName", "cmsPropertyTypeGroup.uniqueID AS PropertyGroupUniqueID",
|
||||
"cmsPropertyTypeGroup.sortorder AS PropertyGroupSortOrder", "cmsPropertyTypeGroup.contenttypeNodeId")
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, NodeDto>(left => left.ContentTypeId, right => right.NodeId)
|
||||
.LeftJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
|
||||
.LeftJoin<MemberPropertyTypeDto>().On<MemberPropertyTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
|
||||
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.NodeId, right => right.DataTypeId)
|
||||
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeGroupDto, NodeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
@@ -170,7 +104,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, NodeDto>(left => left.ContentTypeId, right => right.NodeId)
|
||||
.LeftJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
|
||||
.LeftJoin<MemberPropertyTypeDto>().On<MemberPropertyTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
|
||||
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.NodeId, right => right.DataTypeId)
|
||||
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeGroupDto, NodeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
@@ -212,12 +146,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
{
|
||||
entity.AddPropertyType(standardPropertyType.Value, Constants.Conventions.Member.StandardPropertiesGroupName);
|
||||
}
|
||||
|
||||
|
||||
EnsureExplicitDataTypeForBuiltInProperties(entity);
|
||||
PersistNewBaseContentType(entity);
|
||||
|
||||
//Handles the MemberTypeDto (cmsMemberType table)
|
||||
var memberTypeDtos = ContentTypeFactory.BuildMemberTypeDtos(entity);
|
||||
var memberTypeDtos = ContentTypeFactory.BuildMemberPropertyTypeDtos(entity);
|
||||
foreach (var memberTypeDto in memberTypeDtos)
|
||||
{
|
||||
Database.Insert(memberTypeDto);
|
||||
@@ -245,13 +179,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
|
||||
entity.SortOrder = maxSortOrder + 1;
|
||||
}
|
||||
|
||||
|
||||
EnsureExplicitDataTypeForBuiltInProperties(entity);
|
||||
PersistUpdatedBaseContentType(entity);
|
||||
|
||||
// remove and insert - handle cmsMemberType table
|
||||
Database.Delete<MemberTypeDto>("WHERE NodeId = @Id", new { Id = entity.Id });
|
||||
var memberTypeDtos = ContentTypeFactory.BuildMemberTypeDtos(entity);
|
||||
Database.Delete<MemberPropertyTypeDto>("WHERE NodeId = @Id", new { Id = entity.Id });
|
||||
var memberTypeDtos = ContentTypeFactory.BuildMemberPropertyTypeDtos(entity);
|
||||
foreach (var memberTypeDto in memberTypeDtos)
|
||||
{
|
||||
Database.Insert(memberTypeDto);
|
||||
@@ -264,19 +198,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// Override so we can specify explicit db type's on any property types that are built-in.
|
||||
/// </summary>
|
||||
/// <param name="propertyEditorAlias"></param>
|
||||
/// <param name="dbType"></param>
|
||||
/// <param name="storageType"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
protected override PropertyType CreatePropertyType(string propertyEditorAlias, ValueStorageType dbType, string propertyTypeAlias)
|
||||
protected override PropertyType CreatePropertyType(string propertyEditorAlias, ValueStorageType storageType, string propertyTypeAlias)
|
||||
{
|
||||
//custom property type constructor logic to set explicit dbtype's for built in properties
|
||||
var stdProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
var propDbType = GetDbTypeForBuiltInProperty(propertyTypeAlias, dbType, stdProps);
|
||||
return new PropertyType(propertyEditorAlias, propDbType.Result,
|
||||
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
|
||||
// which is what we want for the built-in properties.
|
||||
propDbType.Success,
|
||||
propertyTypeAlias);
|
||||
var builtinProperties = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
var readonlyStorageType = builtinProperties.TryGetValue(propertyTypeAlias, out var propertyType);
|
||||
storageType = readonlyStorageType ? propertyType.ValueStorageType : storageType;
|
||||
return new PropertyType(propertyEditorAlias, storageType, readonlyStorageType, propertyTypeAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -286,62 +217,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// <param name="memberType"></param>
|
||||
private static void EnsureExplicitDataTypeForBuiltInProperties(IContentTypeBase memberType)
|
||||
{
|
||||
var stdProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
var builtinProperties = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
foreach (var propertyType in memberType.PropertyTypes)
|
||||
{
|
||||
var dbTypeAttempt = GetDbTypeForBuiltInProperty(propertyType.Alias, propertyType.ValueStorageType, stdProps);
|
||||
if (dbTypeAttempt)
|
||||
if (builtinProperties.ContainsKey(propertyType.Alias))
|
||||
{
|
||||
//this reset's it's current data type reference which will be re-assigned based on the property editor assigned on the next line
|
||||
//this reset's its current data type reference which will be re-assigned based on the property editor assigned on the next line
|
||||
propertyType.DataTypeId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a collection of entities from a collection of Dtos
|
||||
/// </summary>
|
||||
/// <param name="dtos"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<IMemberType> BuildFromDtos(List<MemberTypeReadOnlyDto> dtos)
|
||||
{
|
||||
if (dtos == null || dtos.Any() == false)
|
||||
return Enumerable.Empty<IMemberType>();
|
||||
|
||||
return dtos.Select(x =>
|
||||
{
|
||||
bool needsSaving;
|
||||
var memberType = MemberTypeReadOnlyFactory.BuildEntity(x, out needsSaving);
|
||||
if (needsSaving) PersistUpdatedItem(memberType);
|
||||
return memberType;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If this is one of our internal properties - we will manually assign the data type since they must
|
||||
/// always correspond to the correct db type no matter what the backing data type is assigned.
|
||||
/// </summary>
|
||||
/// <param name="propAlias"></param>
|
||||
/// <param name="dbType"></param>
|
||||
/// <param name="standardProps"></param>
|
||||
/// <returns>
|
||||
/// Successful attempt if it was a built in property
|
||||
/// </returns>
|
||||
internal static Attempt<ValueStorageType> GetDbTypeForBuiltInProperty(
|
||||
string propAlias,
|
||||
ValueStorageType dbType,
|
||||
Dictionary<string, PropertyType> standardProps)
|
||||
{
|
||||
var aliases = standardProps.Select(x => x.Key).ToArray();
|
||||
|
||||
//check if it is built in
|
||||
if (aliases.Contains(propAlias))
|
||||
{
|
||||
//return the pre-determined db type for this property
|
||||
return Attempt<ValueStorageType>.Succeed(standardProps.Single(x => x.Key == propAlias).Value.ValueStorageType);
|
||||
}
|
||||
|
||||
return Attempt<ValueStorageType>.Fail(dbType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,51 +78,24 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: but now that we have 1 unique repository?
|
||||
// this is a *bad* idea because PerformCount captures the current repository and its UOW
|
||||
//
|
||||
//private static RepositoryCachePolicyOptions _defaultOptions;
|
||||
//protected virtual RepositoryCachePolicyOptions DefaultOptions
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return _defaultOptions ?? (_defaultOptions
|
||||
// = new RepositoryCachePolicyOptions(() =>
|
||||
// {
|
||||
// // get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
// // create query once if it is needed (no need for locking here) - query is static!
|
||||
// var query = _hasIdQuery ?? (_hasIdQuery = Query<TEntity>.Builder.Where(x => x.Id != 0));
|
||||
// return PerformCount(query);
|
||||
// }));
|
||||
// }
|
||||
//}
|
||||
|
||||
// ReSharper disable once StaticMemberInGenericType
|
||||
private static RepositoryCachePolicyOptions _defaultOptions;
|
||||
// ReSharper disable once InconsistentNaming
|
||||
protected virtual RepositoryCachePolicyOptions DefaultOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new RepositoryCachePolicyOptions(() =>
|
||||
{
|
||||
// get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
// create query once if it is needed (no need for locking here) - query is static!
|
||||
var query = _hasIdQuery ?? (_hasIdQuery = AmbientScope.SqlContext.Query<TEntity>().Where(x => x.Id != 0));
|
||||
return PerformCount(query);
|
||||
});
|
||||
return _defaultOptions ?? (_defaultOptions
|
||||
= new RepositoryCachePolicyOptions(() =>
|
||||
{
|
||||
// get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
// create query once if it is needed (no need for locking here) - query is static!
|
||||
var query = _hasIdQuery ?? (_hasIdQuery = AmbientScope.SqlContext.Query<TEntity>().Where(x => x.Id != 0));
|
||||
return PerformCount(query);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// this would be better for perfs BUT it breaks the tests - l8tr
|
||||
//
|
||||
//private static IRepositoryCachePolicy<TEntity, TId> _defaultCachePolicy;
|
||||
//protected virtual IRepositoryCachePolicy<TEntity, TId> DefaultCachePolicy
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return _defaultCachePolicy ?? (_defaultCachePolicy
|
||||
// = new DefaultRepositoryCachePolicy<TEntity, TId>(IsolatedCache, DefaultOptions));
|
||||
// }
|
||||
//}
|
||||
|
||||
protected IRepositoryCachePolicy<TEntity, TId> CachePolicy
|
||||
{
|
||||
get
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
_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");
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -12,10 +10,8 @@ using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Logging.Serilog;
|
||||
using Umbraco.Core.Migrations.Upgrade;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Runtime
|
||||
@@ -70,15 +66,19 @@ namespace Umbraco.Core.Runtime
|
||||
// objects.
|
||||
|
||||
using (var timer = profilingLogger.TraceDuration<CoreRuntime>(
|
||||
$"Booting Umbraco {UmbracoVersion.SemanticVersion.ToSemanticString()} on {NetworkHelper.MachineName}.",
|
||||
$"Booting Umbraco {UmbracoVersion.SemanticVersion.ToSemanticString()}.",
|
||||
"Booted.",
|
||||
"Boot failed."))
|
||||
{
|
||||
logger.Info<CoreRuntime>("Booting site '{HostingSiteName}', app '{HostingApplicationID}', path '{HostingPhysicalPath}', server '{MachineName}'.",
|
||||
HostingEnvironment.SiteName,
|
||||
HostingEnvironment.ApplicationID,
|
||||
HostingEnvironment.ApplicationPhysicalPath,
|
||||
NetworkHelper.MachineName);
|
||||
logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
|
||||
|
||||
// application environment
|
||||
ConfigureUnhandledException();
|
||||
ConfigureAssemblyResolve();
|
||||
ConfigureApplicationRootPath();
|
||||
|
||||
Boot(register, timer);
|
||||
@@ -211,20 +211,6 @@ namespace Umbraco.Core.Runtime
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual void ConfigureAssemblyResolve()
|
||||
{
|
||||
// When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another.
|
||||
// This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
|
||||
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
|
||||
{
|
||||
// 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;
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual void ConfigureApplicationRootPath()
|
||||
{
|
||||
var path = GetApplicationRootPath();
|
||||
|
||||
@@ -252,7 +252,7 @@ namespace Umbraco.Core
|
||||
FinalMigrationState = upgrader.Plan.FinalState;
|
||||
}
|
||||
|
||||
logger.Debug<RuntimeState>("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", CurrentMigrationState, FinalMigrationState ?? "<null>");
|
||||
logger.Debug<RuntimeState>("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", FinalMigrationState, CurrentMigrationState ?? "<null>");
|
||||
|
||||
return CurrentMigrationState == FinalMigrationState;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.Owin;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -19,7 +17,7 @@ using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public class BackOfficeUserStore : DisposableObjectSlim,
|
||||
public class BackOfficeUserStore : DisposableObjectSlim,
|
||||
IUserStore<BackOfficeIdentityUser, int>,
|
||||
IUserPasswordStore<BackOfficeIdentityUser, int>,
|
||||
IUserEmailStore<BackOfficeIdentityUser, int>,
|
||||
@@ -40,9 +38,10 @@ namespace Umbraco.Core.Security
|
||||
private readonly IEntityService _entityService;
|
||||
private readonly IExternalLoginService _externalLoginService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly UmbracoMapper _mapper;
|
||||
private bool _disposed = false;
|
||||
|
||||
public BackOfficeUserStore(IUserService userService, IMemberTypeService memberTypeService, IEntityService entityService, IExternalLoginService externalLoginService, IGlobalSettings globalSettings, MembershipProviderBase usersMembershipProvider)
|
||||
public BackOfficeUserStore(IUserService userService, IMemberTypeService memberTypeService, IEntityService entityService, IExternalLoginService externalLoginService, IGlobalSettings globalSettings, MembershipProviderBase usersMembershipProvider, UmbracoMapper mapper)
|
||||
{
|
||||
_userService = userService;
|
||||
_memberTypeService = memberTypeService;
|
||||
@@ -52,6 +51,7 @@ namespace Umbraco.Core.Security
|
||||
if (userService == null) throw new ArgumentNullException("userService");
|
||||
if (usersMembershipProvider == null) throw new ArgumentNullException("usersMembershipProvider");
|
||||
if (externalLoginService == null) throw new ArgumentNullException("externalLoginService");
|
||||
_mapper = mapper;
|
||||
|
||||
_userService = userService;
|
||||
_externalLoginService = externalLoginService;
|
||||
@@ -185,7 +185,8 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return await Task.FromResult(AssignLoginsCallback(Mapper.Map<BackOfficeIdentityUser>(user)));
|
||||
|
||||
return await Task.FromResult(AssignLoginsCallback(_mapper.Map<BackOfficeIdentityUser>(user)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -202,7 +203,7 @@ namespace Umbraco.Core.Security
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = AssignLoginsCallback(Mapper.Map<BackOfficeIdentityUser>(user));
|
||||
var result = AssignLoginsCallback(_mapper.Map<BackOfficeIdentityUser>(user));
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
@@ -314,7 +315,7 @@ namespace Umbraco.Core.Security
|
||||
var user = _userService.GetByEmail(email);
|
||||
var result = user == null
|
||||
? null
|
||||
: Mapper.Map<BackOfficeIdentityUser>(user);
|
||||
: _mapper.Map<BackOfficeIdentityUser>(user);
|
||||
|
||||
return Task.FromResult(AssignLoginsCallback(result));
|
||||
}
|
||||
@@ -391,7 +392,7 @@ namespace Umbraco.Core.Security
|
||||
var user = _userService.GetUserById(l.UserId);
|
||||
if (user != null)
|
||||
{
|
||||
output = Mapper.Map<BackOfficeIdentityUser>(user);
|
||||
output = _mapper.Map<BackOfficeIdentityUser>(user);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +424,6 @@ namespace Umbraco.Core.Services.Implement
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// find ContentTypes using this IDataTypeDefinition on a PropertyType, and delete
|
||||
// TODO: media and members?!
|
||||
// TODO: non-group properties?!
|
||||
|
||||
@@ -55,7 +55,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="AutoMapper" Version="8.0.0" />
|
||||
<PackageReference Include="Umbraco.Code">
|
||||
<Version>1.0.5</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="LightInject" Version="5.4.0" />
|
||||
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
|
||||
<PackageReference Include="LightInject.Web" Version="2.0.0" />
|
||||
@@ -208,10 +212,18 @@
|
||||
<Compile Include="Composing\TypeHelper.cs" />
|
||||
<Compile Include="Composing\TypeLoader.cs" />
|
||||
<Compile Include="IO\MediaPathSchemes\UniqueMediaPathScheme.cs" />
|
||||
<Compile Include="Mapping\MapperContext.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\MergeDateAndDateTimePropertyEditor.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_1\ChangeNuCacheJsonFormat.cs" />
|
||||
<Compile Include="Mapping\MapDefinitionCollection.cs" />
|
||||
<Compile Include="Mapping\MapDefinitionCollectionBuilder.cs" />
|
||||
<Compile Include="Mapping\IMapDefinition.cs" />
|
||||
<Compile Include="Mapping\UmbracoMapper.cs" />
|
||||
<Compile Include="Models\CultureImpact.cs" />
|
||||
<Compile Include="Models\PublishedContent\ILivePublishedModelFactory.cs" />
|
||||
<Compile Include="Persistence\Dtos\PropertyTypeCommonDto.cs" />
|
||||
<Compile Include="Persistence\Repositories\Implement\ContentTypeCommonRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\IContentTypeCommonRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\Implement\LanguageRepositoryExtensions.cs" />
|
||||
<Compile Include="PropertyEditors\DateTimeConfiguration.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameLabelAndRichTextPropertyEditorAliases.cs" />
|
||||
@@ -441,7 +453,7 @@
|
||||
<Compile Include="Models\IAuditItem.cs" />
|
||||
<Compile Include="Models\IConsent.cs" />
|
||||
<Compile Include="Models\ISimpleContentType.cs" />
|
||||
<Compile Include="Models\Identity\IdentityMapperProfile.cs" />
|
||||
<Compile Include="Models\Identity\IdentityMapDefinition.cs" />
|
||||
<Compile Include="Models\Membership\MemberExportModel.cs" />
|
||||
<Compile Include="Models\Membership\MemberExportProperty.cs" />
|
||||
<Compile Include="Models\NotificationEmailBodyParams.cs" />
|
||||
@@ -855,8 +867,7 @@
|
||||
<Compile Include="Persistence\Dtos\MacroPropertyDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\Member2MemberGroupDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\MemberDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\MemberTypeDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\MemberTypeReadOnlyDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\MemberPropertyTypeDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\NodeDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\PropertyDataDto.cs" />
|
||||
<Compile Include="Persistence\Dtos\PropertyTypeDto.cs" />
|
||||
@@ -951,7 +962,6 @@
|
||||
<Compile Include="Persistence\Factories\MacroFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\ContentBaseFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\MemberGroupFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\MemberTypeReadOnlyFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\PropertyFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\PropertyGroupFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\PublicAccessEntryFactory.cs" />
|
||||
|
||||
@@ -54,62 +54,46 @@
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Tests.Mapping
|
||||
{
|
||||
[TestFixture]
|
||||
public class MappingTests
|
||||
{
|
||||
[Test]
|
||||
public void SimpleMap()
|
||||
{
|
||||
var definitions = new MapDefinitionCollection(new IMapDefinition[]
|
||||
{
|
||||
new MapperDefinition1(),
|
||||
});
|
||||
var mapper = new UmbracoMapper(definitions);
|
||||
|
||||
var thing1 = new Thing1 { Value = "value" };
|
||||
var thing2 = mapper.Map<Thing1, Thing2>(thing1);
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
|
||||
thing2 = mapper.Map<Thing2>(thing1);
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
|
||||
thing2 = new Thing2();
|
||||
mapper.Map(thing1, thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnumerableMap()
|
||||
{
|
||||
var definitions = new MapDefinitionCollection(new IMapDefinition[]
|
||||
{
|
||||
new MapperDefinition1(),
|
||||
});
|
||||
var mapper = new UmbracoMapper(definitions);
|
||||
|
||||
var thing1A = new Thing1 { Value = "valueA" };
|
||||
var thing1B = new Thing1 { Value = "valueB" };
|
||||
var thing1 = new[] { thing1A, thing1B };
|
||||
var thing2 = mapper.Map<IEnumerable<Thing1>, IEnumerable<Thing2>>(thing1).ToList();
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual(2, thing2.Count);
|
||||
Assert.AreEqual("valueA", thing2[0].Value);
|
||||
Assert.AreEqual("valueB", thing2[1].Value);
|
||||
|
||||
thing2 = mapper.Map<IEnumerable<Thing2>>(thing1).ToList();
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual(2, thing2.Count);
|
||||
Assert.AreEqual("valueA", thing2[0].Value);
|
||||
Assert.AreEqual("valueB", thing2[1].Value);
|
||||
|
||||
thing2 = mapper.MapEnumerable<Thing1, Thing2>(thing1).ToList();
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual(2, thing2.Count);
|
||||
Assert.AreEqual("valueA", thing2[0].Value);
|
||||
Assert.AreEqual("valueB", thing2[1].Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InheritedMap()
|
||||
{
|
||||
var definitions = new MapDefinitionCollection(new IMapDefinition[]
|
||||
{
|
||||
new MapperDefinition1(),
|
||||
});
|
||||
var mapper = new UmbracoMapper(definitions);
|
||||
|
||||
var thing3 = new Thing3 { Value = "value" };
|
||||
var thing2 = mapper.Map<Thing3, Thing2>(thing3);
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
|
||||
thing2 = mapper.Map<Thing2>(thing3);
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
|
||||
thing2 = new Thing2();
|
||||
mapper.Map(thing3, thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CollectionsMap()
|
||||
{
|
||||
var definitions = new MapDefinitionCollection(new IMapDefinition[]
|
||||
{
|
||||
new MapperDefinition2(),
|
||||
});
|
||||
var mapper = new UmbracoMapper(definitions);
|
||||
|
||||
// can map a PropertyCollection
|
||||
var source = new PropertyCollection();
|
||||
var target = mapper.Map<IEnumerable<ContentPropertyDto>>(source);
|
||||
}
|
||||
|
||||
private class Thing1
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
private class Thing3 : Thing1
|
||||
{ }
|
||||
|
||||
private class Thing2
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
private class MapperDefinition1 : IMapDefinition
|
||||
{
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<Thing1, Thing2>((source, context) => new Thing2(), Map);
|
||||
}
|
||||
|
||||
private void Map(Thing1 source, Thing2 target, MapperContext context)
|
||||
{
|
||||
target.Value = source.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private class MapperDefinition2 : IMapDefinition
|
||||
{
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<Property, ContentPropertyDto>((source, context) => new ContentPropertyDto(), Map);
|
||||
}
|
||||
|
||||
private static void Map(Property source, ContentPropertyDto target, MapperContext context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Umbraco.Tests.Models.Mapping
|
||||
{
|
||||
[TestFixture]
|
||||
public class AutoMapper6Tests
|
||||
{
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
ThingProfile.CtorCount = 0;
|
||||
Assert.AreEqual(0, ThingProfile.CtorCount);
|
||||
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.AddProfile<ThingProfile1>();
|
||||
});
|
||||
|
||||
Assert.AreEqual(1, ThingProfile.CtorCount);
|
||||
Assert.AreEqual(0, MemberValueResolver.CtorCount);
|
||||
|
||||
var mapper = config.CreateMapper();
|
||||
|
||||
Assert.AreEqual(1, ThingProfile.CtorCount);
|
||||
Assert.AreEqual(0, MemberValueResolver.CtorCount);
|
||||
|
||||
var thingA = new ThingA { ValueInt = 42, ValueString = "foo" };
|
||||
var thingB = mapper.Map<ThingA, ThingB>(thingA);
|
||||
Assert.AreEqual(42, thingB.ValueInt);
|
||||
Assert.AreEqual("!!foo!!", thingB.ValueString);
|
||||
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
Assert.AreEqual(1, ThingProfile.CtorCount); // one single profile
|
||||
Assert.AreEqual(4, MemberValueResolver.CtorCount); // many resolvers
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test2()
|
||||
{
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.AddProfile<ThingProfile2>();
|
||||
});
|
||||
|
||||
var mapper = config.CreateMapper();
|
||||
|
||||
Assert.AreEqual(0, ValueResolver.CtorCount);
|
||||
|
||||
var thingA = new ThingA { ValueInt = 42, ValueString = "foo" };
|
||||
var thingB = mapper.Map<ThingA, ThingB>(thingA);
|
||||
Assert.AreEqual(42, thingB.ValueInt);
|
||||
Assert.AreEqual("!!foo!!", thingB.ValueString);
|
||||
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
Assert.AreEqual(4, ValueResolver.CtorCount); // many resolvers
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test3()
|
||||
{
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.AddProfile<ThingProfile3>();
|
||||
});
|
||||
|
||||
var mapper = config.CreateMapper();
|
||||
|
||||
var thingA = new ThingA { ValueInt = 42, ValueString = "foo" };
|
||||
var thingB = mapper.Map<ThingA, ThingB>(thingA);
|
||||
Assert.AreEqual(42, thingB.ValueInt);
|
||||
Assert.AreEqual("!!foo!!", thingB.ValueString);
|
||||
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
mapper.Map<ThingA, ThingB>(thingA);
|
||||
}
|
||||
|
||||
// Resolve destination member using a custom value resolver
|
||||
// void ResolveUsing<TValueResolver>()
|
||||
// where TValueResolver : IValueResolver<TSource, TDestination, TDestMember>;
|
||||
|
||||
// Resolve destination member using a custom value resolver from a source member
|
||||
// void ResolveUsing<TValueResolver, TSourceMember>(Expression<Func<TSource, TSourceMember>> sourceMember)
|
||||
// where TValueResolver : IMemberValueResolver<TSource, TDestination, TSourceMember, TMember>;
|
||||
// void ResolveUsing<TValueResolver, TSourceMember>(string sourceMemberName)
|
||||
// where TValueResolver : IMemberValueResolver<TSource, TDestination, TSourceMember, TMember>;
|
||||
|
||||
// Resolve destination member using a custom value resolver instance
|
||||
// void ResolveUsing(IValueResolver<TSource, TDestination, TMember> valueResolver);
|
||||
// void ResolveUsing<TSourceMember>(IMemberValueResolver<TSource, TDestination, TSourceMember, TMember> valueResolver, Expression<Func<TSource, TSourceMember>> sourceMember);
|
||||
|
||||
// Resolve destination member using a custom value resolver callback
|
||||
// void ResolveUsing<TResult>(Func<TSource, TResult> resolver);
|
||||
// void ResolveUsing<TResult>(Func<TSource, TDestination, TResult> resolver);
|
||||
// void ResolveUsing<TResult>(Func<TSource, TDestination, TMember, TResult> resolver);
|
||||
// void ResolveUsing<TResult>(Func<TSource, TDestination, TMember, ResolutionContext, TResult> resolver);
|
||||
|
||||
// read https://stackoverflow.com/questions/14875075/automapper-what-is-the-difference-between-mapfrom-and-resolveusing
|
||||
// about the diff between MapFrom and ResolveUsing... keeping ResolveUsing in our code
|
||||
|
||||
public class ThingProfile : Profile
|
||||
{
|
||||
public static int CtorCount { get; set; }
|
||||
|
||||
public ThingProfile(int ver)
|
||||
{
|
||||
CtorCount++;
|
||||
|
||||
var map = CreateMap<ThingA, ThingB>()
|
||||
.ForMember(dest => dest.ValueInt, opt => opt.MapFrom(src => src.ValueInt));
|
||||
|
||||
switch (ver)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
map
|
||||
.ForMember(dest => dest.ValueString, opt => opt.MapFrom<MemberValueResolver, string>(src => src.ValueString));
|
||||
break;
|
||||
case 2:
|
||||
map
|
||||
.ForMember(dest => dest.ValueString, opt => opt.MapFrom<ValueResolver>());
|
||||
break;
|
||||
case 3:
|
||||
// in most cases that should be perfectly enough?
|
||||
map
|
||||
.ForMember(dest => dest.ValueString, opt => opt.MapFrom(source => "!!" + source.ValueString + "!!"));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(ver));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ThingProfile1 : ThingProfile
|
||||
{
|
||||
public ThingProfile1() : base(1) { }
|
||||
}
|
||||
|
||||
public class ThingProfile2 : ThingProfile
|
||||
{
|
||||
public ThingProfile2() : base(2) { }
|
||||
}
|
||||
|
||||
public class ThingProfile3 : ThingProfile
|
||||
{
|
||||
public ThingProfile3() : base(3) { }
|
||||
}
|
||||
|
||||
public class ValueResolver : IValueResolver<ThingA, ThingB, string>
|
||||
{
|
||||
public static int CtorCount { get; set; }
|
||||
|
||||
public ValueResolver()
|
||||
{
|
||||
CtorCount++;
|
||||
}
|
||||
|
||||
public string Resolve(ThingA source, ThingB destination, string destMember, ResolutionContext context)
|
||||
{
|
||||
return "!!" + source.ValueString + "!!";
|
||||
}
|
||||
}
|
||||
|
||||
public class MemberValueResolver : IMemberValueResolver<ThingA, ThingB, string, string>
|
||||
{
|
||||
public static int CtorCount { get; set; }
|
||||
|
||||
public MemberValueResolver()
|
||||
{
|
||||
CtorCount++;
|
||||
}
|
||||
|
||||
public string Resolve(ThingA source, ThingB destination, string sourceMember, string destMember, ResolutionContext context)
|
||||
{
|
||||
return "!!" + sourceMember + "!!";
|
||||
}
|
||||
}
|
||||
|
||||
public class ThingA
|
||||
{
|
||||
public int ValueInt { get; set; }
|
||||
public string ValueString { get; set; }
|
||||
}
|
||||
|
||||
public class ThingB
|
||||
{
|
||||
public int ValueInt { get; set; }
|
||||
public string ValueString { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Models.Mapping
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(WithApplication = true)]
|
||||
public class AutoMapperTests : UmbracoTestBase
|
||||
{
|
||||
protected override void Compose()
|
||||
{
|
||||
base.Compose();
|
||||
|
||||
var manifestBuilder = new ManifestParser(
|
||||
AppCaches.Disabled,
|
||||
new ManifestValueValidatorCollection(Enumerable.Empty<IManifestValueValidator>()),
|
||||
Composition.Logger)
|
||||
{
|
||||
Path = TestHelper.CurrentAssemblyDirectory
|
||||
};
|
||||
Composition.RegisterUnique(_ => manifestBuilder);
|
||||
|
||||
Func<IEnumerable<Type>> typeListProducerList = Enumerable.Empty<Type>;
|
||||
Composition.WithCollectionBuilder<DataEditorCollectionBuilder>()
|
||||
.Clear()
|
||||
.Add(typeListProducerList);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssertConfigurationIsValid()
|
||||
{
|
||||
var profiles = Factory.GetAllInstances<Profile>().ToArray();
|
||||
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
foreach (var profile in profiles)
|
||||
cfg.AddProfile(profile);
|
||||
});
|
||||
|
||||
// validate each profile (better granularity for error reports)
|
||||
|
||||
Console.WriteLine("Validate each profile:");
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
config.AssertConfigurationIsValid(profile.GetType().FullName);
|
||||
//Console.WriteLine("OK " + profile.GetType().FullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("KO " + profile.GetType().FullName);
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Validate each profile and throw:");
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
config.AssertConfigurationIsValid(profile.GetType().FullName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("KO " + profile.GetType().FullName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// validate the global config
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Validate global config:");
|
||||
config.AssertConfigurationIsValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -11,7 +10,6 @@ using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Models.Mapping;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Tests.Models.Mapping
|
||||
@@ -28,22 +26,6 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
private readonly Mock<IFileService> _fileService = new Mock<IFileService>();
|
||||
private Mock<PropertyEditorCollection> _editorsMock;
|
||||
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
// FIXME: are we initializing mappers that... have already been?
|
||||
Mapper.Reset();
|
||||
Mapper.Initialize(configuration =>
|
||||
{
|
||||
//initialize our content type mapper
|
||||
var profile1 = new ContentTypeMapperProfile(_editorsMock.Object, _dataTypeService.Object, _fileService.Object, _contentTypeService.Object, Mock.Of<IMediaTypeService>(), Mock.Of<ILogger>());
|
||||
configuration.AddProfile(profile1);
|
||||
var profile2 = new EntityMapperProfile();
|
||||
configuration.AddProfile(profile2);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Compose()
|
||||
{
|
||||
base.Compose();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -22,7 +21,7 @@ using Current = Umbraco.Web.Composing.Current;
|
||||
namespace Umbraco.Tests.Models.Mapping
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
[UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
public class ContentWebModelMappingTests : TestWithDatabaseBase
|
||||
{
|
||||
private IContentTypeService _contentTypeService;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -10,7 +9,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
namespace Umbraco.Tests.Models.Mapping
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
[UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
public class UserModelMapperTests : TestWithDatabaseBase
|
||||
{
|
||||
[Test]
|
||||
|
||||
@@ -1,200 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Testing;
|
||||
// fixme - does it make any sense to keep these tests here?
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using NPoco;
|
||||
//using NUnit.Framework;
|
||||
//using Umbraco.Core;
|
||||
//using Umbraco.Core.Models;
|
||||
//using Umbraco.Core.Persistence.Dtos;
|
||||
//using Umbraco.Core.Persistence.Repositories;
|
||||
//using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
//using Umbraco.Tests.TestHelpers;
|
||||
//using Umbraco.Tests.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
public class ContentTypeSqlMappingTests : TestWithDatabaseBase
|
||||
{
|
||||
[Test]
|
||||
public void Can_Map_Content_Type_Templates_And_Allowed_Types()
|
||||
{
|
||||
IDictionary<int, List<ContentTypeRepository.ContentTypeQueryMapper.AssociatedTemplate>> allAssociatedTemplates;
|
||||
IDictionary<int, List<int>> allParentContentTypeIds;
|
||||
IContentType[] contentTypes;
|
||||
//namespace Umbraco.Tests.Persistence.Querying
|
||||
//{
|
||||
// [TestFixture]
|
||||
// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
// public class ContentTypeSqlMappingTests : TestWithDatabaseBase
|
||||
// {
|
||||
// [Test]
|
||||
// public void Can_Map_Content_Type_Templates_And_Allowed_Types()
|
||||
// {
|
||||
// IDictionary<int, List<ContentTypeQueryMapper<IContentType>.AssociatedTemplate>> allAssociatedTemplates;
|
||||
// IDictionary<int, List<int>> allParentContentTypeIds;
|
||||
// IContentType[] contentTypes;
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55554, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55554", SortOrder = 1, UniqueId = new Guid("87D1EAB6-AB27-4852-B3DF-DE8DBA4A1AA0"), Text = "Template 1", NodeObjectType = Constants.ObjectTypes.Template, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55555, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55555", SortOrder = 1, UniqueId = new Guid("3390BDF4-C974-4211-AA95-3812A8CE7C46"), Text = "Template 2", NodeObjectType = Constants.ObjectTypes.Template, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99997, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99997", SortOrder = 0, UniqueId = new Guid("BB3241D5-6842-4EFA-A82A-5F56885CF528"), Text = "Test Content Type 1", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99998, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99998", SortOrder = 0, UniqueId = new Guid("EEA66B06-302E-49BA-A8B2-EDF07248BC59"), Text = "Test Content Type 2", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("C45CC083-BB27-4C1C-B448-6F703CC9B799"), Text = "Test Content Type 2", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// using (var scope = ScopeProvider.CreateScope())
|
||||
// {
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55554, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55554", SortOrder = 1, UniqueId = new Guid("87D1EAB6-AB27-4852-B3DF-DE8DBA4A1AA0"), Text = "Template 1", NodeObjectType = Constants.ObjectTypes.Template, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55555, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55555", SortOrder = 1, UniqueId = new Guid("3390BDF4-C974-4211-AA95-3812A8CE7C46"), Text = "Template 2", NodeObjectType = Constants.ObjectTypes.Template, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99997, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99997", SortOrder = 0, UniqueId = new Guid("BB3241D5-6842-4EFA-A82A-5F56885CF528"), Text = "Test Content Type 1", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99998, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99998", SortOrder = 0, UniqueId = new Guid("EEA66B06-302E-49BA-A8B2-EDF07248BC59"), Text = "Test Content Type 2", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("C45CC083-BB27-4C1C-B448-6F703CC9B799"), Text = "Test Content Type 2", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsTemplate"))));
|
||||
scope.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55554, Alias = "testTemplate1", PrimaryKey = 22221});
|
||||
scope.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55555, Alias = "testTemplate2", PrimaryKey = 22222 });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsTemplate"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsTemplate"))));
|
||||
// scope.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55554, Alias = "testTemplate1", PrimaryKey = 22221});
|
||||
// scope.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55555, Alias = "testTemplate2", PrimaryKey = 22222 });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsTemplate"))));
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88887, NodeId = 99997, Alias = "TestContentType1", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99998, Alias = "TestContentType2", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88889, NodeId = 99999, Alias = "TestContentType3", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88887, NodeId = 99997, Alias = "TestContentType1", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99998, Alias = "TestContentType2", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88889, NodeId = 99999, Alias = "TestContentType3", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
|
||||
scope.Database.Insert(new ContentTypeTemplateDto { ContentTypeNodeId = 99997, IsDefault = true, TemplateNodeId = 55555 });
|
||||
scope.Database.Insert(new ContentTypeTemplateDto { ContentTypeNodeId = 99997, IsDefault = false, TemplateNodeId = 55554 });
|
||||
// scope.Database.Insert(new ContentTypeTemplateDto { ContentTypeNodeId = 99997, IsDefault = true, TemplateNodeId = 55555 });
|
||||
// scope.Database.Insert(new ContentTypeTemplateDto { ContentTypeNodeId = 99997, IsDefault = false, TemplateNodeId = 55554 });
|
||||
|
||||
scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99998, Id = 99997, SortOrder = 1 });
|
||||
scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99999, Id = 99997, SortOrder = 2});
|
||||
// scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99998, Id = 99997, SortOrder = 1 });
|
||||
// scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99999, Id = 99997, SortOrder = 2});
|
||||
|
||||
scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99999, ParentId = 99997});
|
||||
scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99998, ParentId = 99997 });
|
||||
// scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99999, ParentId = 99997});
|
||||
// scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99998, ParentId = 99997 });
|
||||
|
||||
contentTypes = ContentTypeRepository.ContentTypeQueryMapper.MapContentTypes(
|
||||
scope.Database, SqlSyntax, out allAssociatedTemplates, out allParentContentTypeIds)
|
||||
.Where(x => new[] { 99997, 99998 }.Contains(x.Id))
|
||||
.ToArray();
|
||||
// contentTypes = ContentTypeQueryMapper.GetContentTypes(
|
||||
// scope.Database, out allAssociatedTemplates, out allParentContentTypeIds)
|
||||
// .Where(x => new[] { 99997, 99998 }.Contains(x.Id))
|
||||
// .ToArray();
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
// scope.Complete();
|
||||
// }
|
||||
|
||||
var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997);
|
||||
Assert.IsNotNull(contentType1);
|
||||
// var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997);
|
||||
// Assert.IsNotNull(contentType1);
|
||||
|
||||
var associatedTemplates1 = allAssociatedTemplates[contentType1.Id];
|
||||
var parentContentTypes1 = allParentContentTypeIds[contentType1.Id];
|
||||
// var associatedTemplates1 = allAssociatedTemplates[contentType1.Id];
|
||||
// var parentContentTypes1 = allParentContentTypeIds[contentType1.Id];
|
||||
|
||||
Assert.AreEqual(2, contentType1.AllowedContentTypes.Count());
|
||||
Assert.AreEqual(2, associatedTemplates1.Count());
|
||||
Assert.AreEqual(0, parentContentTypes1.Count());
|
||||
// Assert.AreEqual(2, contentType1.AllowedContentTypes.Count());
|
||||
// Assert.AreEqual(2, associatedTemplates1.Count());
|
||||
// Assert.AreEqual(0, parentContentTypes1.Count());
|
||||
|
||||
var contentType2 = contentTypes.SingleOrDefault(x => x.Id == 99998);
|
||||
Assert.IsNotNull(contentType2);
|
||||
// var contentType2 = contentTypes.SingleOrDefault(x => x.Id == 99998);
|
||||
// Assert.IsNotNull(contentType2);
|
||||
|
||||
var associatedTemplates2 = allAssociatedTemplates[contentType2.Id];
|
||||
var parentContentTypes2 = allParentContentTypeIds[contentType2.Id];
|
||||
// var associatedTemplates2 = allAssociatedTemplates[contentType2.Id];
|
||||
// var parentContentTypes2 = allParentContentTypeIds[contentType2.Id];
|
||||
|
||||
Assert.AreEqual(0, contentType2.AllowedContentTypes.Count());
|
||||
Assert.AreEqual(0, associatedTemplates2.Count());
|
||||
Assert.AreEqual(1, parentContentTypes2.Count());
|
||||
}
|
||||
// Assert.AreEqual(0, contentType2.AllowedContentTypes.Count());
|
||||
// Assert.AreEqual(0, associatedTemplates2.Count());
|
||||
// Assert.AreEqual(1, parentContentTypes2.Count());
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void Can_Map_Media_Type_And_Allowed_Types()
|
||||
{
|
||||
IDictionary<int, List<int>> allParentContentTypeIds;
|
||||
IMediaType[] contentTypes;
|
||||
// [Test]
|
||||
// public void Can_Map_Media_Type_And_Allowed_Types()
|
||||
// {
|
||||
// IDictionary<int, List<int>> allParentContentTypeIds;
|
||||
// IMediaType[] contentTypes;
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99997, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99997", SortOrder = 0, UniqueId = new Guid("BB3241D5-6842-4EFA-A82A-5F56885CF528"), Text = "Test Media Type 1", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99998, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99998", SortOrder = 0, UniqueId = new Guid("EEA66B06-302E-49BA-A8B2-EDF07248BC59"), Text = "Test Media Type 2", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("C45CC083-BB27-4C1C-B448-6F703CC9B799"), Text = "Test Media Type 2", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// using (var scope = ScopeProvider.CreateScope())
|
||||
// {
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99997, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99997", SortOrder = 0, UniqueId = new Guid("BB3241D5-6842-4EFA-A82A-5F56885CF528"), Text = "Test Media Type 1", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99998, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99998", SortOrder = 0, UniqueId = new Guid("EEA66B06-302E-49BA-A8B2-EDF07248BC59"), Text = "Test Media Type 2", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("C45CC083-BB27-4C1C-B448-6F703CC9B799"), Text = "Test Media Type 2", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88887, NodeId = 99997, Alias = "TestContentType1", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99998, Alias = "TestContentType2", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88889, NodeId = 99999, Alias = "TestContentType3", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88887, NodeId = 99997, Alias = "TestContentType1", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99998, Alias = "TestContentType2", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88889, NodeId = 99999, Alias = "TestContentType3", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
|
||||
scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99998, Id = 99997, SortOrder = 1 });
|
||||
scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99999, Id = 99997, SortOrder = 2 });
|
||||
// scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99998, Id = 99997, SortOrder = 1 });
|
||||
// scope.Database.Insert(new ContentTypeAllowedContentTypeDto { AllowedId = 99999, Id = 99997, SortOrder = 2 });
|
||||
|
||||
scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99999, ParentId = 99997 });
|
||||
scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99998, ParentId = 99997 });
|
||||
// scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99999, ParentId = 99997 });
|
||||
// scope.Database.Insert(new ContentType2ContentTypeDto { ChildId = 99998, ParentId = 99997 });
|
||||
|
||||
contentTypes = ContentTypeRepository.ContentTypeQueryMapper.MapMediaTypes(
|
||||
scope.Database, SqlSyntax, out allParentContentTypeIds)
|
||||
.Where(x => (new[] { 99997, 99998 }).Contains(x.Id))
|
||||
.ToArray();
|
||||
// contentTypes = ContentTypeQueryMapper<IContentType>.MapMediaTypes(
|
||||
// scope.Database, SqlSyntax, out allParentContentTypeIds)
|
||||
// .Where(x => (new[] { 99997, 99998 }).Contains(x.Id))
|
||||
// .ToArray();
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
// scope.Complete();
|
||||
// }
|
||||
|
||||
var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997);
|
||||
Assert.IsNotNull(contentType1);
|
||||
// var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997);
|
||||
// Assert.IsNotNull(contentType1);
|
||||
|
||||
var parentContentTypes1 = allParentContentTypeIds[contentType1.Id];
|
||||
// var parentContentTypes1 = allParentContentTypeIds[contentType1.Id];
|
||||
|
||||
Assert.AreEqual(2, contentType1.AllowedContentTypes.Count());
|
||||
Assert.AreEqual(0, parentContentTypes1.Count());
|
||||
// Assert.AreEqual(2, contentType1.AllowedContentTypes.Count());
|
||||
// Assert.AreEqual(0, parentContentTypes1.Count());
|
||||
|
||||
var contentType2 = contentTypes.SingleOrDefault(x => x.Id == 99998);
|
||||
Assert.IsNotNull(contentType2);
|
||||
// var contentType2 = contentTypes.SingleOrDefault(x => x.Id == 99998);
|
||||
// Assert.IsNotNull(contentType2);
|
||||
|
||||
var parentContentTypes2 = allParentContentTypeIds[contentType2.Id];
|
||||
// var parentContentTypes2 = allParentContentTypeIds[contentType2.Id];
|
||||
|
||||
Assert.AreEqual(0, contentType2.AllowedContentTypes.Count());
|
||||
Assert.AreEqual(1, parentContentTypes2.Count());
|
||||
// Assert.AreEqual(0, contentType2.AllowedContentTypes.Count());
|
||||
// Assert.AreEqual(1, parentContentTypes2.Count());
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void Can_Map_All_Property_Groups_And_Types()
|
||||
{
|
||||
IDictionary<int, PropertyTypeCollection> allPropTypeCollection;
|
||||
IDictionary<int, PropertyGroupCollection> allPropGroupCollection;
|
||||
// [Test]
|
||||
// public void Can_Map_All_Property_Groups_And_Types()
|
||||
// {
|
||||
// IDictionary<int, PropertyTypeCollection> allPropTypeCollection;
|
||||
// IDictionary<int, PropertyGroupCollection> allPropGroupCollection;
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55555, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55555", SortOrder = 1, UniqueId = new Guid("3390BDF4-C974-4211-AA95-3812A8CE7C46"), Text = "Test Data Type", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("129241F0-D24E-4FC3-92D1-BC2D48B7C431"), Text = "Test Content Type", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// using (var scope = ScopeProvider.CreateScope())
|
||||
// {
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 55555, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,55555", SortOrder = 1, UniqueId = new Guid("3390BDF4-C974-4211-AA95-3812A8CE7C46"), Text = "Test Data Type", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("129241F0-D24E-4FC3-92D1-BC2D48B7C431"), Text = "Test Content Type", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode"))));
|
||||
|
||||
scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 55555, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" });
|
||||
// scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 55555, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" });
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99999, Alias = "TestContentType", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
// scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99999, Alias = "TestContentType", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsContentType"))));
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsPropertyTypeGroup"))));
|
||||
scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77776, UniqueId = 77776.ToGuid(), ContentTypeNodeId = 99999, Text = "Group1", SortOrder = 1 });
|
||||
scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77777, UniqueId = 77777.ToGuid(), ContentTypeNodeId = 99999, Text = "Group2", SortOrder = 2 });
|
||||
scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77778, UniqueId = 77778.ToGuid(), ContentTypeNodeId = 99999, Text = "Group3", SortOrder = 3 });
|
||||
scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77779, UniqueId = 77779.ToGuid(), ContentTypeNodeId = 99999, Text = "Group4", SortOrder = 4 });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsPropertyTypeGroup"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsPropertyTypeGroup"))));
|
||||
// scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77776, UniqueId = 77776.ToGuid(), ContentTypeNodeId = 99999, Text = "Group1", SortOrder = 1 });
|
||||
// scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77777, UniqueId = 77777.ToGuid(), ContentTypeNodeId = 99999, Text = "Group2", SortOrder = 2 });
|
||||
// scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77778, UniqueId = 77778.ToGuid(), ContentTypeNodeId = 99999, Text = "Group3", SortOrder = 3 });
|
||||
// scope.Database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 77779, UniqueId = 77779.ToGuid(), ContentTypeNodeId = 99999, Text = "Group4", SortOrder = 4 });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsPropertyTypeGroup"))));
|
||||
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsPropertyType"))));
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66662, UniqueId = 66662.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77776, Alias = "property1", Name = "Property 1", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66663, UniqueId = 66663.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77776, Alias = "property2", Name = "Property 2", SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66664, UniqueId = 66664.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77777, Alias = "property3", Name = "Property 3", SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66665, UniqueId = 66665.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77777, Alias = "property4", Name = "Property 4", SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66666, UniqueId = 66666.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = null, Alias = "property5", Name = "Property 5", SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66667, UniqueId = 66667.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77778, Alias = "property6", Name = "Property 6", SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66668, UniqueId = 66668.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77778, Alias = "property7", Name = "Property 7", SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsPropertyType"))));
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsPropertyType"))));
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66662, UniqueId = 66662.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77776, Alias = "property1", Name = "Property 1", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66663, UniqueId = 66663.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77776, Alias = "property2", Name = "Property 2", SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66664, UniqueId = 66664.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77777, Alias = "property3", Name = "Property 3", SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66665, UniqueId = 66665.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77777, Alias = "property4", Name = "Property 4", SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66666, UniqueId = 66666.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = null, Alias = "property5", Name = "Property 5", SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66667, UniqueId = 66667.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77778, Alias = "property6", Name = "Property 6", SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 66668, UniqueId = 66668.ToGuid(), DataTypeId = 55555, ContentTypeId = 99999, PropertyTypeGroupId = 77778, Alias = "property7", Name = "Property 7", SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
// scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("cmsPropertyType"))));
|
||||
|
||||
ContentTypeRepository.ContentTypeQueryMapper.MapGroupsAndProperties(new[] { 99999 }, scope.Database, SqlSyntax, true, out allPropTypeCollection, out allPropGroupCollection);
|
||||
// ContentTypeQueryMapper<IContentType>.MapGroupsAndProperties_(new[] { 99999 }, scope.Database, SqlSyntax, true, out allPropTypeCollection, out allPropGroupCollection);
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
// scope.Complete();
|
||||
// }
|
||||
|
||||
var propGroupCollection = allPropGroupCollection[99999];
|
||||
var propTypeCollection = allPropTypeCollection[99999];
|
||||
// var propGroupCollection = allPropGroupCollection[99999];
|
||||
// var propTypeCollection = allPropTypeCollection[99999];
|
||||
|
||||
Assert.AreEqual(4, propGroupCollection.Count);
|
||||
Assert.AreEqual(2, propGroupCollection["Group1"].PropertyTypes.Count);
|
||||
Assert.IsTrue(propGroupCollection["Group1"].PropertyTypes.Contains("property1"));
|
||||
Assert.IsTrue(propGroupCollection["Group1"].PropertyTypes.Contains("property2"));
|
||||
Assert.AreEqual(2, propGroupCollection["Group2"].PropertyTypes.Count);
|
||||
Assert.IsTrue(propGroupCollection["Group2"].PropertyTypes.Contains("property3"));
|
||||
Assert.IsTrue(propGroupCollection["Group2"].PropertyTypes.Contains("property4"));
|
||||
Assert.AreEqual(2, propGroupCollection["Group3"].PropertyTypes.Count);
|
||||
Assert.IsTrue(propGroupCollection["Group3"].PropertyTypes.Contains("property6"));
|
||||
Assert.IsTrue(propGroupCollection["Group3"].PropertyTypes.Contains("property7"));
|
||||
Assert.AreEqual(0, propGroupCollection["Group4"].PropertyTypes.Count);
|
||||
// Assert.AreEqual(4, propGroupCollection.Count);
|
||||
// Assert.AreEqual(2, propGroupCollection["Group1"].PropertyTypes.Count);
|
||||
// Assert.IsTrue(propGroupCollection["Group1"].PropertyTypes.Contains("property1"));
|
||||
// Assert.IsTrue(propGroupCollection["Group1"].PropertyTypes.Contains("property2"));
|
||||
// Assert.AreEqual(2, propGroupCollection["Group2"].PropertyTypes.Count);
|
||||
// Assert.IsTrue(propGroupCollection["Group2"].PropertyTypes.Contains("property3"));
|
||||
// Assert.IsTrue(propGroupCollection["Group2"].PropertyTypes.Contains("property4"));
|
||||
// Assert.AreEqual(2, propGroupCollection["Group3"].PropertyTypes.Count);
|
||||
// Assert.IsTrue(propGroupCollection["Group3"].PropertyTypes.Contains("property6"));
|
||||
// Assert.IsTrue(propGroupCollection["Group3"].PropertyTypes.Contains("property7"));
|
||||
// Assert.AreEqual(0, propGroupCollection["Group4"].PropertyTypes.Count);
|
||||
|
||||
Assert.AreEqual(1, propTypeCollection.Count);
|
||||
Assert.IsTrue(propTypeCollection.Contains("property5"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// Assert.AreEqual(1, propTypeCollection.Count);
|
||||
// Assert.IsTrue(propTypeCollection.Contains("property5"));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
@@ -20,7 +17,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
[UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
public class ContentTypeRepositoryTest : TestWithDatabaseBase
|
||||
{
|
||||
public override void SetUp()
|
||||
@@ -32,25 +29,28 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository)
|
||||
{
|
||||
var cacheHelper = AppCaches.Disabled;
|
||||
var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository);
|
||||
var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger);
|
||||
var repository = new DocumentRepository(scopeAccessor, cacheHelper, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(scopeAccessor, AppCaches.Disabled, Logger);
|
||||
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled);
|
||||
contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository(scopeAccessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
}
|
||||
|
||||
private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor)
|
||||
{
|
||||
var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled);
|
||||
var contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
return contentTypeRepository;
|
||||
}
|
||||
|
||||
private MediaTypeRepository CreateMediaTypeRepository(IScopeAccessor scopeAccessor)
|
||||
{
|
||||
var contentTypeRepository = new MediaTypeRepository(scopeAccessor, AppCaches.Disabled, Logger);
|
||||
var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled);
|
||||
var contentTypeRepository = new MediaTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
return contentTypeRepository;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
|
||||
// TODO: Add test to verify SetDefaultTemplates updates both AllowedTemplates and DefaultTemplate(id).
|
||||
|
||||
|
||||
[Test]
|
||||
public void Maps_Templates_Correctly()
|
||||
{
|
||||
@@ -80,13 +80,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
templateRepo.Save(template);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
contentType.AllowedTemplates = new[] { templates[0], templates[1] };
|
||||
contentType.SetDefaultTemplate(templates[0]);
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
//re-get
|
||||
var result = repository.Get(contentType.Id);
|
||||
@@ -107,16 +107,16 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var repository = CreateRepository((IScopeAccessor) provider);
|
||||
var container1 = new EntityContainer(Constants.ObjectTypes.DocumentType) { Name = "blah1" };
|
||||
containerRepository.Save(container1);
|
||||
|
||||
|
||||
|
||||
var container2 = new EntityContainer(Constants.ObjectTypes.DocumentType) { Name = "blah2", ParentId = container1.Id };
|
||||
containerRepository.Save(container2);
|
||||
|
||||
|
||||
|
||||
var contentType = (IContentType)MockedContentTypes.CreateBasicContentType("asdfasdf");
|
||||
contentType.ParentId = container2.Id;
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
//create a
|
||||
var contentType2 = (IContentType)new ContentType(contentType, "hello")
|
||||
@@ -125,10 +125,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
};
|
||||
contentType.ParentId = contentType.Id;
|
||||
repository.Save(contentType2);
|
||||
|
||||
|
||||
|
||||
var result = repository.Move(contentType, container1).ToArray();
|
||||
|
||||
|
||||
|
||||
Assert.AreEqual(2, result.Count());
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var containerRepository = CreateContainerRepository((IScopeAccessor) provider, Constants.ObjectTypes.DocumentTypeContainer);
|
||||
var container = new EntityContainer(Constants.ObjectTypes.DocumentType) { Name = "blah" };
|
||||
containerRepository.Save(container);
|
||||
|
||||
|
||||
Assert.That(container.Id, Is.GreaterThan(0));
|
||||
|
||||
var found = containerRepository.Get(container.Id);
|
||||
@@ -176,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
containerRepository.Save(container2);
|
||||
container3 = new EntityContainer(Constants.ObjectTypes.DocumentType) { Name = "container3" };
|
||||
containerRepository.Save(container3);
|
||||
|
||||
|
||||
Assert.That(container1.Id, Is.GreaterThan(0));
|
||||
Assert.That(container2.Id, Is.GreaterThan(0));
|
||||
Assert.That(container3.Id, Is.GreaterThan(0));
|
||||
@@ -201,11 +201,11 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var containerRepository = CreateContainerRepository((IScopeAccessor) provider, Constants.ObjectTypes.DocumentTypeContainer);
|
||||
var container = new EntityContainer(Constants.ObjectTypes.DocumentType) { Name = "blah" };
|
||||
containerRepository.Save(container);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
containerRepository.Delete(container);
|
||||
|
||||
|
||||
|
||||
var found = containerRepository.Get(container.Id);
|
||||
Assert.IsNull(found);
|
||||
@@ -222,12 +222,12 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var repository = CreateRepository((IScopeAccessor) provider);
|
||||
var container = new EntityContainer(Constants.ObjectTypes.MediaType) { Name = "blah" };
|
||||
containerRepository.Save(container);
|
||||
|
||||
|
||||
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test", propertyGroupName: "testGroup");
|
||||
contentType.ParentId = container.Id;
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
Assert.AreEqual(container.Id, contentType.ParentId);
|
||||
}
|
||||
@@ -243,16 +243,16 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var repository = CreateMediaTypeRepository((IScopeAccessor) provider);
|
||||
var container = new EntityContainer(Constants.ObjectTypes.MediaType) { Name = "blah" };
|
||||
containerRepository.Save(container);
|
||||
|
||||
|
||||
|
||||
IMediaType contentType = MockedContentTypes.CreateSimpleMediaType("test", "Test", propertyGroupName: "testGroup");
|
||||
contentType.ParentId = container.Id;
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
containerRepository.Delete(container);
|
||||
|
||||
|
||||
|
||||
var found = containerRepository.Get(container.Id);
|
||||
Assert.IsNull(found);
|
||||
@@ -274,7 +274,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test", propertyGroupName: "testGroup");
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
var fetched = repository.Get(contentType.Id);
|
||||
|
||||
@@ -294,7 +294,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreNotEqual(propertyType.Key, Guid.Empty);
|
||||
}
|
||||
|
||||
TestHelper.AssertPropertyValuesAreEqual(contentType, fetched, "yyyy-MM-dd HH:mm:ss", ignoreProperties: new [] { "DefaultTemplate", "AllowedTemplates", "UpdateDate" });
|
||||
TestHelper.AssertPropertyValuesAreEqual(fetched, contentType, "yyyy-MM-dd HH:mm:ss", ignoreProperties: new [] { "DefaultTemplate", "AllowedTemplates", "UpdateDate" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual(4, mapped.PropertyTypes.Count());
|
||||
|
||||
repository.Save(mapped);
|
||||
|
||||
|
||||
|
||||
Assert.AreEqual(4, mapped.PropertyTypes.Count());
|
||||
|
||||
@@ -371,7 +371,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
DataTypeId = -88
|
||||
});
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
var dirty = contentType.IsDirty();
|
||||
|
||||
@@ -469,7 +469,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.IsTrue(mapped.PropertyTypes.Any(x => x.Alias == "subtitle"));
|
||||
|
||||
repository.Save(mapped);
|
||||
|
||||
|
||||
|
||||
var dirty = mapped.IsDirty();
|
||||
|
||||
@@ -500,11 +500,11 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
var contentType2 = repository.Get(contentType.Id);
|
||||
repository.Delete(contentType2);
|
||||
|
||||
|
||||
|
||||
var exists = repository.Exists(contentType.Id);
|
||||
|
||||
@@ -528,13 +528,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
repository.Save(ctMain);
|
||||
repository.Save(ctChild1);
|
||||
repository.Save(ctChild2);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
|
||||
var resolvedParent = repository.Get(ctMain.Id);
|
||||
repository.Delete(resolvedParent);
|
||||
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.That(repository.Exists(ctMain.Id), Is.False);
|
||||
@@ -546,19 +546,27 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Can_Perform_Query_On_ContentTypeRepository_Sort_By_Name()
|
||||
{
|
||||
IContentType contentType;
|
||||
|
||||
// Arrange
|
||||
var provider = TestObjects.GetScopeProvider(Logger);
|
||||
using (var scope = provider.CreateScope())
|
||||
{
|
||||
var repository = CreateRepository((IScopeAccessor) provider);
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
var child1 = MockedContentTypes.CreateSimpleContentType("abc", "abc", contentType, randomizeAliases: true);
|
||||
repository.Save(child1);
|
||||
var child3 = MockedContentTypes.CreateSimpleContentType("zyx", "zyx", contentType, randomizeAliases: true);
|
||||
repository.Save(child3);
|
||||
var child2 = MockedContentTypes.CreateSimpleContentType("a123", "a123", contentType, randomizeAliases: true);
|
||||
repository.Save(child2);
|
||||
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
using (var scope = provider.CreateScope())
|
||||
{
|
||||
var repository = CreateRepository((IScopeAccessor)provider);
|
||||
|
||||
// Act
|
||||
var contentTypes = repository.Get(scope.SqlContext.Query<IContentType>().Where(x => x.ParentId == contentType.Id));
|
||||
@@ -601,7 +609,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
var childContentType = MockedContentTypes.CreateSimpleContentType("blah", "Blah", contentType, randomizeAliases:true);
|
||||
repository.Save(childContentType);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var result = repository.Get(childContentType.Key);
|
||||
@@ -703,7 +711,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
contentType.PropertyGroups["Meta"].PropertyTypes.Remove("description");
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
var result = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
|
||||
@@ -779,7 +787,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
|
||||
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Assert
|
||||
var updated = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
@@ -804,7 +812,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var simpleSubpageContentType = MockedContentTypes.CreateSimpleContentType("umbSimpleSubpage", "Simple Subpage");
|
||||
repository.Save(subpageContentType);
|
||||
repository.Save(simpleSubpageContentType);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed);
|
||||
@@ -814,7 +822,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
new ContentTypeSort(new Lazy<int>(() => simpleSubpageContentType.Id), 1, simpleSubpageContentType.Alias)
|
||||
};
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
//Assert
|
||||
var updated = repository.Get(NodeDto.NodeIdSeed);
|
||||
@@ -838,12 +846,12 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.Save(subpage);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
contentType.RemovePropertyType("keywords");
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(3));
|
||||
@@ -865,13 +873,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.Save(subpage);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType("test", ValueStorageType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 });
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
|
||||
@@ -893,18 +901,18 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.Save(subpage);
|
||||
|
||||
|
||||
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType("test", ValueStorageType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 });
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var content = contentRepository.Get(subpage.Id);
|
||||
content.SetValue("metaAuthor", "John Doe");
|
||||
contentRepository.Save(content);
|
||||
|
||||
|
||||
|
||||
//Assert
|
||||
var updated = contentRepository.Get(subpage.Id);
|
||||
@@ -927,7 +935,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.Save(subpage);
|
||||
|
||||
|
||||
|
||||
//Remove PropertyType
|
||||
contentType.RemovePropertyType("keywords");
|
||||
@@ -935,13 +943,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType("test", ValueStorageType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 });
|
||||
repository.Save(contentType);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var content = contentRepository.Get(subpage.Id);
|
||||
content.SetValue("metaAuthor", "John Doe");
|
||||
contentRepository.Save(content);
|
||||
|
||||
|
||||
|
||||
//Assert
|
||||
var updated = contentRepository.Get(subpage.Id);
|
||||
|
||||
@@ -66,7 +66,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
templateRepository = new TemplateRepository(scopeAccessor, appCaches, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(scopeAccessor, appCaches, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches);
|
||||
contentTypeRepository = new ContentTypeRepository(scopeAccessor, appCaches, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger);
|
||||
var repository = new DocumentRepository(scopeAccessor, appCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
|
||||
@@ -22,7 +22,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
var templateRepository = new TemplateRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, Core.Cache.AppCaches.Disabled, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, commonRepository);
|
||||
languageRepository = new LanguageRepository(accessor, Core.Cache.AppCaches.Disabled, Logger);
|
||||
documentRepository = new DocumentRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
var domainRepository = new DomainRepository(accessor, Core.Cache.AppCaches.Disabled, Logger);
|
||||
|
||||
@@ -4,6 +4,7 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -35,7 +36,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
appCaches = appCaches ?? AppCaches;
|
||||
var scopeAccessor = (IScopeAccessor) provider;
|
||||
|
||||
mediaTypeRepository = new MediaTypeRepository(scopeAccessor, appCaches, Logger);
|
||||
var templateRepository = new TemplateRepository(scopeAccessor, appCaches, Logger, TestObjects.GetFileSystemsMock());
|
||||
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches);
|
||||
mediaTypeRepository = new MediaTypeRepository(scopeAccessor, appCaches, Logger, commonRepository);
|
||||
var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger);
|
||||
var repository = new MediaRepository(scopeAccessor, appCaches, Logger, mediaTypeRepository, tagRepository, Mock.Of<ILanguageRepository>());
|
||||
return repository;
|
||||
|
||||
@@ -6,7 +6,6 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
@@ -21,7 +20,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
private MediaTypeRepository CreateRepository(IScopeProvider provider)
|
||||
{
|
||||
return new MediaTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var cacheHelper = AppCaches.Disabled;
|
||||
var templateRepository = new TemplateRepository((IScopeAccessor)provider, cacheHelper, Logger, TestObjects.GetFileSystemsMock());
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, templateRepository, AppCaches);
|
||||
return new MediaTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository);
|
||||
}
|
||||
|
||||
private EntityContainerRepository CreateContainerRepository(IScopeProvider provider)
|
||||
|
||||
@@ -29,7 +29,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
private MemberRepository CreateRepository(IScopeProvider provider, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository)
|
||||
{
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
memberTypeRepository = new MemberTypeRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var templateRepository = Mock.Of<ITemplateRepository>();
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
memberTypeRepository = new MemberTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
memberGroupRepository = new MemberGroupRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var tagRepo = new TagRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var repository = new MemberRepository(accessor, AppCaches.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of<ILanguageRepository>());
|
||||
@@ -196,17 +198,17 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberTypeRepository.Save(memberType);
|
||||
|
||||
|
||||
|
||||
var member = MockedMember.CreateSimpleMember(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty");
|
||||
repository.Save(member);
|
||||
|
||||
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
//when the password is null it will not overwrite what is already there.
|
||||
sut.RawPasswordValue = null;
|
||||
repository.Save(sut);
|
||||
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
|
||||
Assert.That(sut.RawPasswordValue, Is.EqualTo("123"));
|
||||
@@ -226,17 +228,17 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberTypeRepository.Save(memberType);
|
||||
|
||||
|
||||
|
||||
var member = MockedMember.CreateSimpleMember(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty");
|
||||
repository.Save(member);
|
||||
|
||||
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
sut.Username = "This is new";
|
||||
sut.Email = "thisisnew@hello.com";
|
||||
repository.Save(sut);
|
||||
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
|
||||
Assert.That(sut.Email, Is.EqualTo("thisisnew@hello.com"));
|
||||
@@ -278,7 +280,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberTypeRepository.Save(memberType);
|
||||
|
||||
|
||||
}
|
||||
|
||||
var member = MockedMember.CreateSimpleMember(memberType, name ?? "Johnny Hefty", email ?? "johnny@example.com", password ?? "123", username ?? "hefty", key);
|
||||
|
||||
@@ -22,7 +22,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
private MemberTypeRepository CreateRepository(IScopeProvider provider)
|
||||
{
|
||||
return new MemberTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of<ILogger>());
|
||||
var templateRepository = Mock.Of<ITemplateRepository>();
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, templateRepository, AppCaches);
|
||||
return new MemberTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of<ILogger>(), commonRepository);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -35,7 +37,6 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType = (IMemberType) MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType);
|
||||
|
||||
|
||||
var sut = repository.Get(memberType.Id);
|
||||
|
||||
@@ -88,7 +89,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType.Alias = null;
|
||||
|
||||
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => repository.Save(memberType));
|
||||
}
|
||||
@@ -104,13 +105,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType1);
|
||||
|
||||
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType2.Name = "AnotherType";
|
||||
memberType2.Alias = "anotherType";
|
||||
repository.Save(memberType2);
|
||||
|
||||
|
||||
|
||||
var result = repository.GetMany();
|
||||
|
||||
@@ -129,13 +130,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType1);
|
||||
|
||||
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType2.Name = "AnotherType";
|
||||
memberType2.Alias = "anotherType";
|
||||
repository.Save(memberType2);
|
||||
|
||||
|
||||
|
||||
var result = ((IReadRepository<Guid, IMemberType>)repository).GetMany(memberType1.Key, memberType2.Key);
|
||||
|
||||
@@ -154,13 +155,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType1);
|
||||
|
||||
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType2.Name = "AnotherType";
|
||||
memberType2.Alias = "anotherType";
|
||||
repository.Save(memberType2);
|
||||
|
||||
|
||||
|
||||
var result = repository.Get(memberType1.Key);
|
||||
|
||||
@@ -183,14 +184,14 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType1.PropertyTypeCollection.Clear();
|
||||
repository.Save(memberType1);
|
||||
|
||||
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType2.PropertyTypeCollection.Clear();
|
||||
memberType2.Name = "AnotherType";
|
||||
memberType2.Alias = "anotherType";
|
||||
repository.Save(memberType2);
|
||||
|
||||
|
||||
|
||||
var result = repository.GetMany();
|
||||
|
||||
@@ -210,7 +211,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType);
|
||||
|
||||
|
||||
memberType = repository.Get(memberType.Id);
|
||||
Assert.That(memberType, Is.Not.Null);
|
||||
}
|
||||
@@ -226,7 +227,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType);
|
||||
|
||||
|
||||
memberType = repository.Get(memberType.Key);
|
||||
Assert.That(memberType, Is.Not.Null);
|
||||
}
|
||||
@@ -242,7 +243,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType);
|
||||
|
||||
|
||||
|
||||
memberType = repository.Get(memberType.Id);
|
||||
|
||||
@@ -265,7 +266,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
IMemberType memberType2 = MockedContentTypes.CreateSimpleMemberType("test2");
|
||||
repository.Save(memberType1);
|
||||
repository.Save(memberType2);
|
||||
|
||||
|
||||
|
||||
var m1Ids = memberType1.PropertyTypes.Select(x => x.Id).ToArray();
|
||||
var m2Ids = memberType2.PropertyTypes.Select(x => x.Id).ToArray();
|
||||
@@ -286,11 +287,11 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
repository.Save(memberType);
|
||||
|
||||
|
||||
|
||||
var contentType2 = repository.Get(memberType.Id);
|
||||
repository.Delete(contentType2);
|
||||
|
||||
|
||||
|
||||
var exists = repository.Exists(memberType.Id);
|
||||
|
||||
|
||||
@@ -307,7 +307,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
var templateRepository = new TemplateRepository(accessor, AppCaches, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, AppCaches, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(accessor, AppCaches, Logger);
|
||||
var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
|
||||
@@ -955,7 +955,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches.Disabled);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
@@ -964,8 +965,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
private MediaRepository CreateMediaRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository)
|
||||
{
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger);
|
||||
mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches.Disabled);
|
||||
mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
var repository = new MediaRepository(accessor, AppCaches.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of<ILanguageRepository>());
|
||||
return repository;
|
||||
}
|
||||
|
||||
@@ -238,7 +238,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var templateRepository = CreateRepository(ScopeProvider);
|
||||
|
||||
var tagRepository = new TagRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger);
|
||||
var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(ScopeProvider, templateRepository, AppCaches);
|
||||
var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger);
|
||||
var contentRepo = new DocumentRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
@@ -26,7 +24,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
private MediaRepository CreateMediaRepository(IScopeProvider provider, out IMediaTypeRepository mediaTypeRepository)
|
||||
{
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches, Mock.Of<ILogger>());
|
||||
var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches, Mock.Of<ILogger>(), commonRepository);
|
||||
var tagRepository = new TagRepository(accessor, AppCaches, Mock.Of<ILogger>());
|
||||
var repository = new MediaRepository(accessor, AppCaches, Mock.Of<ILogger>(), mediaTypeRepository, tagRepository, Mock.Of<ILanguageRepository>());
|
||||
return repository;
|
||||
@@ -43,7 +43,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
templateRepository = new TemplateRepository(accessor, AppCaches, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, AppCaches, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(accessor, AppCaches, Logger);
|
||||
var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
|
||||
@@ -316,7 +316,7 @@ namespace Umbraco.Tests.Persistence
|
||||
|
||||
helper.CreateTable<NodeDto>();
|
||||
helper.CreateTable<ContentTypeDto>();
|
||||
helper.CreateTable<MemberTypeDto>();
|
||||
helper.CreateTable<MemberPropertyTypeDto>();
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
@@ -165,7 +165,8 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, tRepository, AppCaches);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository);
|
||||
|
||||
@@ -198,7 +199,8 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, tRepository, AppCaches);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository);
|
||||
|
||||
@@ -229,7 +231,8 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor) provider, tRepository, AppCaches);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository);
|
||||
|
||||
@@ -263,7 +266,8 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, tRepository, AppCaches);
|
||||
var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository);
|
||||
|
||||
|
||||
@@ -757,7 +757,7 @@ namespace Umbraco.Tests.Services
|
||||
content = ServiceContext.ContentService.GetById(content.Id);
|
||||
Assert.IsFalse(content.IsCulturePublished(langFr.IsoCode));
|
||||
Assert.IsTrue(content.IsCulturePublished(langUk.IsoCode));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -784,7 +784,7 @@ namespace Umbraco.Tests.Services
|
||||
IContent content = new Content("content", Constants.System.Root, contentType);
|
||||
content.SetCultureName("content-en", langGB.IsoCode);
|
||||
content.SetCultureName("content-fr", langFr.IsoCode);
|
||||
|
||||
|
||||
Assert.IsTrue(ServiceContext.ContentService.SaveAndPublish(content, new []{ langGB.IsoCode , langFr.IsoCode }).Success);
|
||||
|
||||
//re-get
|
||||
@@ -1597,7 +1597,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
var contentType = MockedContentTypes.CreateAllTypesContentType("test", "test");
|
||||
ServiceContext.ContentTypeService.Save(contentType, Constants.Security.SuperUserId);
|
||||
|
||||
|
||||
object obj =
|
||||
new
|
||||
{
|
||||
@@ -3007,7 +3007,8 @@ namespace Umbraco.Tests.Services
|
||||
var accessor = (IScopeAccessor) provider;
|
||||
var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock());
|
||||
var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, templateRepository);
|
||||
var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches);
|
||||
contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository);
|
||||
var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger);
|
||||
var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository);
|
||||
return repository;
|
||||
|
||||
@@ -1654,17 +1654,31 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
// create 'page' content type with a 'Content_' group
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
|
||||
Assert.IsTrue(page.PropertyGroups.Contains("Content_"));
|
||||
Assert.AreEqual(1, page.PropertyGroups.Count);
|
||||
Assert.AreEqual("Content_", page.PropertyGroups.First().Name);
|
||||
Assert.AreEqual(3, page.PropertyTypes.Count());
|
||||
Assert.AreEqual("Title", page.PropertyTypes.First().Name);
|
||||
Assert.AreEqual("Body Text", page.PropertyTypes.Skip(1).First().Name);
|
||||
Assert.AreEqual("Author", page.PropertyTypes.Skip(2).First().Name);
|
||||
service.Save(page);
|
||||
|
||||
// create 'contentPage' content type as a child of 'page'
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
|
||||
Assert.AreEqual(1, page.PropertyGroups.Count);
|
||||
Assert.AreEqual("Content_", page.PropertyGroups.First().Name);
|
||||
Assert.AreEqual(3, contentPage.PropertyTypes.Count());
|
||||
Assert.AreEqual("Title", contentPage.PropertyTypes.First().Name);
|
||||
Assert.AreEqual("Body Text", contentPage.PropertyTypes.Skip(1).First().Name);
|
||||
Assert.AreEqual("Author", contentPage.PropertyTypes.Skip(2).First().Name);
|
||||
service.Save(contentPage);
|
||||
|
||||
// add 'Content' group to 'meta' content type
|
||||
var meta = MockedContentTypes.CreateMetaContentType();
|
||||
Assert.AreEqual(1, meta.PropertyGroups.Count);
|
||||
Assert.AreEqual("Meta", meta.PropertyGroups.First().Name);
|
||||
Assert.AreEqual(2, meta.PropertyTypes.Count());
|
||||
Assert.AreEqual("Meta Keywords", meta.PropertyTypes.First().Name);
|
||||
Assert.AreEqual("Meta Description", meta.PropertyTypes.Skip(1).First().Name);
|
||||
meta.AddPropertyGroup("Content");
|
||||
Assert.AreEqual(2, meta.PropertyTypes.Count());
|
||||
service.Save(meta);
|
||||
|
||||
@@ -12,17 +12,17 @@ namespace Umbraco.Tests.Testing
|
||||
/// <remarks>
|
||||
/// <para>Default is false.</para>
|
||||
/// <para>This is for tests that inherited from TestWithApplicationBase.</para>
|
||||
/// <para>Implies AutoMapper = true (, ResetPluginManager = false).</para>
|
||||
/// <para>Implies Mapper = true (, ResetPluginManager = false).</para>
|
||||
/// </remarks>
|
||||
public bool WithApplication { get => _withApplication.ValueOrDefault(false); set => _withApplication.Set(value); }
|
||||
private readonly Settable<bool> _withApplication = new Settable<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to compose and initialize AutoMapper.
|
||||
/// Gets or sets a value indicating whether to compose and initialize the mapper.
|
||||
/// </summary>
|
||||
/// <remarks>Default is false unless WithApplication is true, in which case default is true.</remarks>
|
||||
public bool AutoMapper { get => _autoMapper.ValueOrDefault(WithApplication); set => _autoMapper.Set(value); }
|
||||
private readonly Settable<bool> _autoMapper = new Settable<bool>();
|
||||
public bool Mapper { get => _mapper.ValueOrDefault(WithApplication); set => _mapper.Set(value); }
|
||||
private readonly Settable<bool> _mapper = new Settable<bool>();
|
||||
|
||||
// FIXME: to be completed
|
||||
/// <summary>
|
||||
@@ -59,7 +59,7 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
base.Merge(other);
|
||||
|
||||
_autoMapper.Set(attr._autoMapper);
|
||||
_mapper.Set(attr._mapper);
|
||||
_publishedRepositoryEvents.Set(attr._publishedRepositoryEvents);
|
||||
_logger.Set(attr._logger);
|
||||
_database.Set(attr._database);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using AutoMapper;
|
||||
using Examine;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@@ -37,6 +36,7 @@ using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Core.Composing.CompositionExtensions;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Web.Composing.CompositionExtensions;
|
||||
using Umbraco.Web.Sections;
|
||||
using Current = Umbraco.Core.Composing.Current;
|
||||
@@ -108,6 +108,8 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
protected IMapperCollection Mappers => Factory.GetInstance<IMapperCollection>();
|
||||
|
||||
protected UmbracoMapper Mapper => Factory.GetInstance<UmbracoMapper>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setup
|
||||
@@ -148,7 +150,7 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
protected virtual void Compose()
|
||||
{
|
||||
ComposeAutoMapper(Options.AutoMapper);
|
||||
ComposeMapper(Options.Mapper);
|
||||
ComposeDatabase(Options.Database);
|
||||
ComposeApplication(Options.WithApplication);
|
||||
|
||||
@@ -165,7 +167,6 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
InitializeAutoMapper(Options.AutoMapper);
|
||||
InitializeApplication(Options.WithApplication);
|
||||
}
|
||||
|
||||
@@ -249,7 +250,7 @@ namespace Umbraco.Tests.Testing
|
||||
Composition.WithCollectionBuilder<ContentAppFactoryCollectionBuilder>();
|
||||
}
|
||||
|
||||
protected virtual void ComposeAutoMapper(bool configure)
|
||||
protected virtual void ComposeMapper(bool configure)
|
||||
{
|
||||
if (configure == false) return;
|
||||
|
||||
@@ -371,18 +372,6 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
#region Initialize
|
||||
|
||||
protected virtual void InitializeAutoMapper(bool configure)
|
||||
{
|
||||
if (configure == false) return;
|
||||
|
||||
Mapper.Initialize(configuration =>
|
||||
{
|
||||
var profiles = Factory.GetAllInstances<Profile>();
|
||||
foreach (var profile in profiles)
|
||||
configuration.AddProfile(profile);
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void InitializeApplication(bool withApplication)
|
||||
{
|
||||
if (withApplication == false) return;
|
||||
@@ -430,8 +419,6 @@ namespace Umbraco.Tests.Testing
|
||||
UriUtility.ResetAppDomainAppVirtualPath();
|
||||
SettingsForTests.Reset(); // FIXME: should it be optional?
|
||||
|
||||
Mapper.Reset();
|
||||
|
||||
// clear static events
|
||||
DocumentRepository.ClearScopeEvents();
|
||||
MediaRepository.ClearScopeEvents();
|
||||
|
||||
@@ -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">
|
||||
@@ -131,6 +130,7 @@
|
||||
<Compile Include="LegacyXmlPublishedCache\PreviewXmlDto.cs" />
|
||||
<Compile Include="Logging\LogviewerTests.cs" />
|
||||
<Compile Include="Manifest\ManifestContentAppTests.cs" />
|
||||
<Compile Include="Mapping\MappingTests.cs" />
|
||||
<Compile Include="Migrations\MigrationPlanTests.cs" />
|
||||
<Compile Include="Migrations\MigrationTests.cs" />
|
||||
<Compile Include="Models\ContentScheduleTests.cs" />
|
||||
@@ -166,7 +166,6 @@
|
||||
<Compile Include="Issues\U9560.cs" />
|
||||
<Compile Include="Integration\ContentEventsTests.cs" />
|
||||
<Compile Include="Migrations\AdvancedMigrationTests.cs" />
|
||||
<Compile Include="Models\Mapping\AutoMapper6Tests.cs" />
|
||||
<Compile Include="Models\Mapping\UserModelMapperTests.cs" />
|
||||
<Compile Include="Packaging\PackageExtractionTests.cs" />
|
||||
<Compile Include="Persistence\NPocoTests\NPocoFetchTests.cs" />
|
||||
@@ -275,7 +274,6 @@
|
||||
<Compile Include="Migrations\Stubs\SixZeroMigration2.cs" />
|
||||
<Compile Include="Testing\TestingTests\MockTests.cs" />
|
||||
<Compile Include="Models\MacroTests.cs" />
|
||||
<Compile Include="Models\Mapping\AutoMapperTests.cs" />
|
||||
<Compile Include="Models\Collections\Item.cs" />
|
||||
<Compile Include="Models\Collections\OrderItem.cs" />
|
||||
<Compile Include="Models\Collections\SimpleOrder.cs" />
|
||||
|
||||
@@ -291,84 +291,3 @@ function appState(eventsService) {
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('appState', appState);
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Tracks the parent object for complex editors by exposing it as
|
||||
* an object reference via editorState.current.entity
|
||||
*
|
||||
* it is possible to modify this object, so should be used with care
|
||||
*/
|
||||
angular.module('umbraco.services').factory("editorState", function() {
|
||||
|
||||
var current = null;
|
||||
var state = {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#set
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Sets the current entity object for the currently active editor
|
||||
* This is only used when implementing an editor with a complex model
|
||||
* like the content editor, where the model is modified by several
|
||||
* child controllers.
|
||||
*/
|
||||
set: function (entity) {
|
||||
current = entity;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#reset
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Since the editorstate entity is read-only, you cannot set it to null
|
||||
* only through the reset() method
|
||||
*/
|
||||
reset: function() {
|
||||
current = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#getCurrent
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns an object reference to the current editor entity.
|
||||
* the entity is the root object of the editor.
|
||||
* EditorState is used by property/parameter editors that need
|
||||
* access to the entire entity being edited, not just the property/parameter
|
||||
*
|
||||
* editorState.current can not be overwritten, you should only read values from it
|
||||
* since modifying individual properties should be handled by the property editors
|
||||
*/
|
||||
getCurrent: function() {
|
||||
return current;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This shouldn't be removed! use getCurrent() method instead of a hacked readonly property which is confusing.
|
||||
|
||||
//create a get/set property but don't allow setting
|
||||
Object.defineProperty(state, "current", {
|
||||
get: function () {
|
||||
return current;
|
||||
},
|
||||
set: function (value) {
|
||||
throw "Use editorState.set to set the value of the current entity";
|
||||
}
|
||||
});
|
||||
|
||||
return state;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Tracks the parent object for complex editors by exposing it as
|
||||
* an object reference via editorState.current.entity
|
||||
*
|
||||
* it is possible to modify this object, so should be used with care
|
||||
*/
|
||||
angular.module('umbraco.services').factory("editorState", function() {
|
||||
|
||||
var current = null;
|
||||
var state = {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#set
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Sets the current entity object for the currently active editor
|
||||
* This is only used when implementing an editor with a complex model
|
||||
* like the content editor, where the model is modified by several
|
||||
* child controllers.
|
||||
*/
|
||||
set: function (entity) {
|
||||
current = entity;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#reset
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Since the editorstate entity is read-only, you cannot set it to null
|
||||
* only through the reset() method
|
||||
*/
|
||||
reset: function() {
|
||||
current = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#getCurrent
|
||||
* @methodOf umbraco.services.editorState
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns an object reference to the current editor entity.
|
||||
* the entity is the root object of the editor.
|
||||
* EditorState is used by property/parameter editors that need
|
||||
* access to the entire entity being edited, not just the property/parameter
|
||||
*
|
||||
* editorState.current can not be overwritten, you should only read values from it
|
||||
* since modifying individual properties should be handled by the property editors
|
||||
*/
|
||||
getCurrent: function() {
|
||||
return current;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This shouldn't be removed! use getCurrent() method instead of a hacked readonly property which is confusing.
|
||||
|
||||
//create a get/set property but don't allow setting
|
||||
Object.defineProperty(state, "current", {
|
||||
get: function () {
|
||||
return current;
|
||||
},
|
||||
set: function (value) {
|
||||
throw "Use editorState.set to set the value of the current entity";
|
||||
}
|
||||
});
|
||||
|
||||
return state;
|
||||
});
|
||||
@@ -397,6 +397,54 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.listViewHelper#selectAllItemsToggle
|
||||
* @methodOf umbraco.services.listViewHelper
|
||||
*
|
||||
* @description
|
||||
* Helper method for toggling the select state on all items.
|
||||
*
|
||||
* @param {Array} items Items to toggle selection on, should be $scope.items
|
||||
* @param {Array} selection Listview selection, available as $scope.selection
|
||||
*/
|
||||
|
||||
function selectAllItemsToggle(items, selection) {
|
||||
|
||||
if (!angular.isArray(items)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSelectedAll(items, selection)) {
|
||||
// unselect all items
|
||||
angular.forEach(items, function (item) {
|
||||
item.selected = false;
|
||||
});
|
||||
|
||||
// reset selection without loosing reference.
|
||||
selection.length = 0;
|
||||
|
||||
} else {
|
||||
|
||||
// reset selection without loosing reference.
|
||||
selection.length = 0;
|
||||
|
||||
// select all items
|
||||
angular.forEach(items, function (item) {
|
||||
var obj = {
|
||||
id: item.id
|
||||
};
|
||||
if (item.key) {
|
||||
obj.key = item.key;
|
||||
}
|
||||
item.selected = true;
|
||||
selection.push(obj);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -527,6 +575,7 @@
|
||||
deselectItem: deselectItem,
|
||||
clearSelection: clearSelection,
|
||||
selectAllItems: selectAllItems,
|
||||
selectAllItemsToggle: selectAllItemsToggle,
|
||||
isSelectedAll: isSelectedAll,
|
||||
setSortingDirection: setSortingDirection,
|
||||
setSorting: setSorting,
|
||||
|
||||
@@ -10,47 +10,111 @@
|
||||
}
|
||||
}
|
||||
|
||||
.umb-toggle:focus .umb-toggle__toggle{
|
||||
box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%);
|
||||
}
|
||||
|
||||
.umb-toggle__handler {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: @white;
|
||||
border-radius: 50px;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.umb-toggle__toggle {
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
background: @gray-8;
|
||||
border-radius: 90px;
|
||||
width: 38px;
|
||||
height: 18px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid @inputBorder;
|
||||
background-color: @inputBorder;
|
||||
position: relative;
|
||||
transition: box-shadow .3s;
|
||||
transition: background-color 120ms;
|
||||
|
||||
.umb-toggle:hover &,
|
||||
.umb-toggle:focus & {
|
||||
border-color: @inputBorderFocus;
|
||||
}
|
||||
|
||||
.umb-toggle.umb-toggle--checked & {
|
||||
border-color: @ui-btn;
|
||||
background-color: @ui-btn;
|
||||
|
||||
&:hover {
|
||||
background-color: @ui-btn-hover;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-toggle.umb-toggle--checked:focus & {
|
||||
border-color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-toggle--checked .umb-toggle__toggle {
|
||||
background-color: @green;
|
||||
|
||||
|
||||
|
||||
.umb-toggle__handler {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: @white;
|
||||
border-radius: 8px;
|
||||
transition: transform 120ms ease-in-out, background-color 120ms;
|
||||
|
||||
.umb-toggle.umb-toggle--checked & {
|
||||
transform: translateX(20px);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.umb-toggle--disabled .umb-toggle__toggle {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.8;
|
||||
|
||||
/* Icons */
|
||||
|
||||
.umb-toggle__icon {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
line-height: 1em;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.umb-toggle--checked .umb-toggle__handler {
|
||||
transform: translate3d(24px, 0, 0) rotate(0);
|
||||
.umb-toggle__icon--left {
|
||||
left: 5px;
|
||||
color: white;
|
||||
transition: opacity 120ms;
|
||||
opacity: 0;
|
||||
// .umb-toggle:hover & {
|
||||
// color: @ui-btn-hover;
|
||||
// }
|
||||
.umb-toggle--checked & {
|
||||
opacity: 1;
|
||||
}
|
||||
.umb-toggle.umb-toggle--checked:hover & {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-toggle__icon--right {
|
||||
right: 5px;
|
||||
color: @ui-btn;
|
||||
transition: opacity 120ms;
|
||||
.umb-toggle--checked & {
|
||||
opacity: 0;
|
||||
}
|
||||
.umb-toggle:hover & {
|
||||
color: @ui-btn-hover;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.umb-toggle.umb-toggle--disabled {
|
||||
.umb-toggle__toggle {
|
||||
cursor: not-allowed;
|
||||
border-color: @gray-5;
|
||||
}
|
||||
.umb-toggle__handler {
|
||||
background-color: @gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Labels */
|
||||
|
||||
.umb-toggle__label {
|
||||
@@ -64,22 +128,3 @@
|
||||
.umb-toggle__label--right {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
|
||||
.umb-toggle__icon {
|
||||
position: absolute;
|
||||
line-height: 1em;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.umb-toggle__icon--left {
|
||||
left: 7px;
|
||||
color: @white;
|
||||
}
|
||||
|
||||
.umb-toggle__icon--right {
|
||||
right: 7px;
|
||||
color: @gray-5;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
|
||||
.umb-editor-header__name-and-description {
|
||||
margin-right: 20px;
|
||||
.umb-panel-header-description {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.-split-view-active .umb-editor-header__name-and-description {
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid @gray-9;
|
||||
padding: 10px 15px;
|
||||
padding: 10px 15px 10px 10px;
|
||||
}
|
||||
|
||||
.umb-group-builder__group-title {
|
||||
@@ -112,7 +112,7 @@ input.umb-group-builder__group-title-input {
|
||||
}
|
||||
|
||||
input.umb-group-builder__group-title-input:disabled:hover {
|
||||
border: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.umb-group-builder__group-title-input:hover {
|
||||
@@ -135,12 +135,35 @@ input.umb-group-builder__group-title-input:disabled:hover {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.umb-group-builder__group-add-property {
|
||||
min-height: 46px;
|
||||
margin-right: 30px;
|
||||
margin-left: 270px;
|
||||
border-radius: 3px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border: 1px dashed @gray-7;
|
||||
background-color: transparent;
|
||||
color: @ui-action-type;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
&:hover {
|
||||
color:@ui-action-type-hover;
|
||||
text-decoration: none;
|
||||
border-color: @ui-active-type-hover;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- PROPERTIES ---------- */
|
||||
|
||||
.umb-group-builder__properties {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
padding-right: 5px;
|
||||
min-height: 35px; // the height of a sortable property
|
||||
}
|
||||
|
||||
@@ -228,6 +251,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
|
||||
overflow: hidden;
|
||||
border-color: transparent;
|
||||
background: transparent;
|
||||
&:focus {
|
||||
border-color: @inputBorderFocus;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-meta-label textarea.ng-invalid {
|
||||
@@ -247,6 +273,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
|
||||
overflow: hidden;
|
||||
border-color: transparent;
|
||||
background: transparent;
|
||||
&:focus {
|
||||
border-color: @inputBorderFocus;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-preview {
|
||||
@@ -265,21 +294,17 @@ input.umb-group-builder__group-title-input:disabled:hover {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0,0,0,0.1);
|
||||
background: rgba(225,225,225,.5);
|
||||
transition: opacity 120ms;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-preview:hover {
|
||||
.umb-group-builder__property-preview:not(.-not-clickable):hover {
|
||||
&::after {
|
||||
opacity: .8;
|
||||
opacity: .66;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-preview:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-preview.-not-clickable {
|
||||
cursor: auto;
|
||||
}
|
||||
@@ -301,23 +326,54 @@ input.umb-group-builder__group-title-input:disabled:hover {
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
|
||||
.umb-group-builder__open-settings {
|
||||
position: absolute;
|
||||
z-index:1;
|
||||
top: 0;
|
||||
bottom:0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
&:focus {
|
||||
outline:0;
|
||||
border: 1px solid @inputBorderFocus;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-actions {
|
||||
flex: 0 0 40px;
|
||||
text-align: center;
|
||||
margin: 15px 0 0 15px;
|
||||
flex: 0 0 44px;
|
||||
text-align: right;
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-action {
|
||||
margin: 0 0 10px 0;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: @ui-icon;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-action:hover {
|
||||
color: @ui-icon-hover;
|
||||
|
||||
position: relative;
|
||||
margin: 5px 0;
|
||||
|
||||
> button {
|
||||
border: none;
|
||||
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: @ui-icon;
|
||||
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
line-height: normal;
|
||||
outline: 0;
|
||||
-webkit-appearance: none;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: @ui-icon-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-group-builder__property-tags {
|
||||
@@ -439,7 +495,7 @@ input.umb-group-builder__group-sort-value {
|
||||
font-size: 14px;
|
||||
color: @ui-action-type;
|
||||
|
||||
&:hover {
|
||||
&:hover{
|
||||
text-decoration: none;
|
||||
color:@ui-action-type-hover;
|
||||
border-color:@ui-action-border-hover;
|
||||
|
||||
@@ -533,6 +533,10 @@ div.help {
|
||||
}
|
||||
|
||||
|
||||
table.domains .help-inline {
|
||||
color:@red;
|
||||
}
|
||||
|
||||
// INPUT GROUPS
|
||||
// ------------
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
hide-description="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
<umb-editor-container class="form-horizontal">
|
||||
|
||||
<umb-load-indicator
|
||||
ng-if="vm.loadingDataType">
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
</span>
|
||||
|
||||
<div class="umb-toggle__toggle">
|
||||
<i ng-show="checked && hideIcons !== 'true'" class="umb-toggle__icon umb-toggle__icon--left icon-check"></i>
|
||||
<div class="umb-toggle__handler shadow-depth-1"></div>
|
||||
<i ng-show="!checked && hideIcons !== 'true'" class="umb-toggle__icon umb-toggle__icon--right icon-wrong"></i>
|
||||
<i ng-show="hideIcons !== 'true'" class="umb-toggle__icon umb-toggle__icon--left icon-check"></i>
|
||||
<i ng-show="hideIcons !== 'true'" class="umb-toggle__icon umb-toggle__icon--right icon-wrong"></i>
|
||||
<div class="umb-toggle__handler"></div>
|
||||
</div>
|
||||
|
||||
<span ng-if="labelPosition === 'right' && showLabels === 'true'">
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
<!-- Add new property -->
|
||||
<a href=""
|
||||
data-element="property-add"
|
||||
class="btn btn-info"
|
||||
class="umb-group-builder__group-add-property"
|
||||
ng-if="property.propertyState=='init' && !sortingMode"
|
||||
hotkey="alt+shift+p"
|
||||
hotkey-when="{{tab.tabState === 'active' && property.propertyState=='init'}}"
|
||||
@@ -183,7 +183,7 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div tabindex="-1" class="umb-group-builder__property-preview" ng-click="editPropertyTypeSettings(property, tab)" ng-if="!sortingMode" ng-class="{'-not-clickable': !sortingMode && (property.inherited || property.locked)}">
|
||||
<div tabindex="-1" class="umb-group-builder__property-preview" ng-if="!sortingMode" ng-class="{'-not-clickable': !sortingMode && (property.inherited || property.locked)}">
|
||||
|
||||
<div class="umb-group-builder__property-tags">
|
||||
|
||||
@@ -234,29 +234,31 @@
|
||||
|
||||
</div>
|
||||
|
||||
<ng-form name="propertyEditorPreviewForm" umb-disable-form-validation>
|
||||
<umb-property-editor
|
||||
ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
</umb-property-editor>
|
||||
<ng-form inert class="umb-group-builder__property-preview-form" name="propertyEditorPreviewForm" umb-disable-form-validation ng-click="editPropertyTypeSettings(property, tab)">
|
||||
<umb-property-editor
|
||||
ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
</umb-property-editor>
|
||||
</ng-form>
|
||||
|
||||
<button class="umb-group-builder__open-settings" ng-if="!property.inherited && !property.locked" ng-click="editPropertyTypeSettings(property, tab)"></button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- row tools -->
|
||||
<div class="umb-group-builder__property-actions" ng-if="!sortingMode">
|
||||
<div class="umb-group-builder__property-actions">
|
||||
|
||||
<div ng-if="!property.inherited">
|
||||
|
||||
<!-- settings for property -->
|
||||
<div class="umb-group-builder__property-action" ng-click="editPropertyTypeSettings(property, tab)">
|
||||
<i class="icon icon-settings"></i>
|
||||
<div class="umb-group-builder__property-action">
|
||||
<button class="icon icon-settings" ng-click="editPropertyTypeSettings(property, tab)"></button>
|
||||
</div>
|
||||
|
||||
<!-- delete property -->
|
||||
<div ng-if="!property.locked" class="umb-group-builder__property-action">
|
||||
<i class="icon-trash" ng-click="togglePrompt(property)"></i>
|
||||
<button class="icon-trash" ng-click="togglePrompt(property)"></button>
|
||||
<umb-confirm-action
|
||||
ng-if="property.deletePrompt"
|
||||
direction="left"
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<div class="umb-table-head">
|
||||
<div class="umb-table-row">
|
||||
<div class="umb-table-cell">
|
||||
<input class="umb-table__input" type="checkbox"
|
||||
ng-show="vm.allowSelectAll"
|
||||
ng-click="vm.selectAll($event)"
|
||||
ng-checked="vm.isSelectedAll()">
|
||||
|
||||
<a href="" style="text-decoration: none;" ng-show="vm.allowSelectAll" ng-click="vm.selectAll()">
|
||||
<umb-checkmark checked="vm.isSelectedAll()" size="xs"></umb-checkmark>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="umb-table-cell umb-table__name">
|
||||
<localize key="general_name">Name</localize>
|
||||
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': vm.isSortDirection('Name', 'asc'), 'icon-navigation-down': vm.isSortDirection('Name', 'desc')}"></i>
|
||||
</a>
|
||||
<localize key="general_name">Name</localize>
|
||||
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': vm.isSortDirection('Name', 'asc'), 'icon-navigation-down': vm.isSortDirection('Name', 'desc')}"></i>
|
||||
</div>
|
||||
<div class="umb-table-cell" ng-show="vm.items[0].state">
|
||||
<localize key="general_status">Status</localize>
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageCompatibility">Compatibility</localize></div>
|
||||
<div class="umb-package-details__section-description"><localize key="packager_packageCompatibilityDescription">This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%</localize></div>
|
||||
<div class="umb-package-details__section-description"><localize key="packager_packageCompatibilityDescription">This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be guaranteed for versions reported below 100%</localize></div>
|
||||
<div class="umb-package-details__compatability" ng-repeat="compatibility in vm.package.compatibility | filter:percentage > 0">
|
||||
<div class="umb-package-details__compatability-label">
|
||||
<span class="umb-package-details__information-item-label">{{compatibility.version}}</span>
|
||||
|
||||
+50
-43
@@ -1,75 +1,84 @@
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListController",
|
||||
function ($scope) {
|
||||
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.configItems = [];
|
||||
vm.viewItems = [];
|
||||
vm.changed = changed;
|
||||
|
||||
function init() {
|
||||
|
||||
//we can't really do anything if the config isn't an object
|
||||
|
||||
// currently the property editor will onyl work if our input is an object.
|
||||
if (angular.isObject($scope.model.config.items)) {
|
||||
|
||||
//now we need to format the items in the dictionary because we always want to have an array
|
||||
var configItems = [];
|
||||
// formatting the items in the dictionary into an array
|
||||
var sortedItems = [];
|
||||
var vals = _.values($scope.model.config.items);
|
||||
var keys = _.keys($scope.model.config.items);
|
||||
for (var i = 0; i < vals.length; i++) {
|
||||
configItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: vals[i].value });
|
||||
sortedItems.push({ key: keys[i], sortOrder: vals[i].sortOrder, value: vals[i].value});
|
||||
}
|
||||
|
||||
//ensure the items are sorted by the provided sort order
|
||||
configItems.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
|
||||
|
||||
sortedItems.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
|
||||
|
||||
vm.configItems = sortedItems;
|
||||
|
||||
if ($scope.model.value === null || $scope.model.value === undefined) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
updateViewModel(configItems);
|
||||
|
||||
|
||||
// update view model.
|
||||
generateViewModel($scope.model.value);
|
||||
|
||||
//watch the model.value in case it changes so that we can keep our view model in sync
|
||||
$scope.$watchCollection("model.value",
|
||||
function (newVal) {
|
||||
updateViewModel(configItems);
|
||||
});
|
||||
$scope.$watchCollection("model.value", updateViewModel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateViewModel(configItems) {
|
||||
|
||||
function updateViewModel(newVal) {
|
||||
|
||||
//get the checked vals from the view model
|
||||
var selectedVals = _.map(
|
||||
_.filter($scope.selectedItems,
|
||||
function(f) {
|
||||
return f.checked;
|
||||
}
|
||||
),
|
||||
function(m) {
|
||||
return m.value;
|
||||
var i = vm.configItems.length;
|
||||
while(i--) {
|
||||
|
||||
var item = vm.configItems[i];
|
||||
|
||||
// are this item the same in the model
|
||||
if (item.checked !== (newVal.indexOf(item.value) !== -1)) {
|
||||
|
||||
// if not lets update the full model.
|
||||
generateViewModel(newVal);
|
||||
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
//if the length is zero, then we are in sync, just exit.
|
||||
if (_.difference($scope.model.value, selectedVals).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.selectedItems = [];
|
||||
|
||||
}
|
||||
|
||||
function generateViewModel(newVal) {
|
||||
|
||||
vm.viewItems = [];
|
||||
|
||||
var iConfigItem;
|
||||
for (var i = 0; i < configItems.length; i++) {
|
||||
iConfigItem = configItems[i];
|
||||
var isChecked = _.contains($scope.model.value, iConfigItem.value);
|
||||
$scope.selectedItems.push({
|
||||
for (var i = 0; i < vm.configItems.length; i++) {
|
||||
iConfigItem = vm.configItems[i];
|
||||
var isChecked = _.contains(newVal, iConfigItem.value);
|
||||
vm.viewItems.push({
|
||||
checked: isChecked,
|
||||
key: iConfigItem.id,
|
||||
val: iConfigItem.value
|
||||
key: iConfigItem.key,
|
||||
value: iConfigItem.value
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function changed(model, value) {
|
||||
|
||||
var index = $scope.model.value.indexOf(value);
|
||||
|
||||
if (model) {
|
||||
if (model === true) {
|
||||
//if it doesn't exist in the model, then add it
|
||||
if (index < 0) {
|
||||
$scope.model.value.push(value);
|
||||
@@ -80,11 +89,9 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro
|
||||
$scope.model.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.selectedItems = [];
|
||||
$scope.changed = changed;
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="umb-property-editor umb-checkboxlist" ng-controller="Umbraco.PropertyEditors.CheckboxListController">
|
||||
<div class="umb-property-editor umb-checkboxlist" ng-controller="Umbraco.PropertyEditors.CheckboxListController as vm">
|
||||
<ul class="unstyled">
|
||||
<li ng-repeat="item in selectedItems track by item.key">
|
||||
<umb-checkbox name="{{model.alias}}" value="{{item.val}}" model="item.checked" text="{{item.val}}" on-change="changed(model, value)" required="model.validation.mandatory && !model.value.length"></umb-checkbox>
|
||||
<li ng-repeat="item in vm.viewItems track by item.key">
|
||||
<umb-checkbox name="{{::model.alias}}" value="{{::item.value}}" model="item.checked" text="{{::item.value}}" on-change="vm.changed(model, value)" required="vm.model.validation.mandatory && !vm.model.value.length"></umb-checkbox>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
function selectAll($event) {
|
||||
listViewHelper.selectAllItems($scope.items, $scope.selection, $event);
|
||||
function selectAll() {
|
||||
listViewHelper.selectAllItemsToggle($scope.items, $scope.selection);
|
||||
}
|
||||
|
||||
function isSelectedAll() {
|
||||
|
||||
@@ -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" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Changes;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
@@ -14,14 +16,16 @@ namespace Umbraco.Web.Cache
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
private readonly IPublishedModelFactory _publishedModelFactory;
|
||||
private readonly IContentTypeCommonRepository _contentTypeCommonRepository;
|
||||
private readonly IdkMap _idkMap;
|
||||
|
||||
public ContentTypeCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IPublishedModelFactory publishedModelFactory, IdkMap idkMap)
|
||||
public ContentTypeCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IPublishedModelFactory publishedModelFactory, IdkMap idkMap, IContentTypeCommonRepository contentTypeCommonRepository)
|
||||
: base(appCaches)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService;
|
||||
_publishedModelFactory = publishedModelFactory;
|
||||
_idkMap = idkMap;
|
||||
_contentTypeCommonRepository = contentTypeCommonRepository;
|
||||
}
|
||||
|
||||
#region Define
|
||||
@@ -44,6 +48,8 @@ namespace Umbraco.Web.Cache
|
||||
// we should NOT directly clear caches here, but instead ask whatever class
|
||||
// is managing the cache to please clear that cache properly
|
||||
|
||||
_contentTypeCommonRepository.ClearCache(); // always
|
||||
|
||||
if (payloads.Any(x => x.ItemType == typeof(IContentType).Name))
|
||||
{
|
||||
ClearAllIsolatedCacheByEntityType<IContent>();
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Web.Models.Mapping;
|
||||
using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Web.Composing.CompositionExtensions
|
||||
{
|
||||
@@ -12,37 +9,28 @@ namespace Umbraco.Web.Composing.CompositionExtensions
|
||||
{
|
||||
public static Composition ComposeWebMappingProfiles(this Composition composition)
|
||||
{
|
||||
//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>();
|
||||
composition.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
|
||||
.Add<AuditMapDefinition>()
|
||||
.Add<CodeFileMapDefinition>()
|
||||
.Add<ContentMapDefinition>()
|
||||
.Add<ContentPropertyMapDefinition>()
|
||||
.Add<ContentTypeMapDefinition>()
|
||||
.Add<DataTypeMapDefinition>()
|
||||
.Add<EntityMapDefinition>()
|
||||
.Add<DictionaryMapDefinition>()
|
||||
.Add<MacroMapDefinition>()
|
||||
.Add<MediaMapDefinition>()
|
||||
.Add<MemberMapDefinition>()
|
||||
.Add<RedirectUrlMapDefinition>()
|
||||
.Add<RelationMapDefinition>()
|
||||
.Add<SectionMapDefinition>()
|
||||
.Add<TagMapDefinition>()
|
||||
.Add<TemplateMapDefinition>()
|
||||
.Add<UserMapDefinition>()
|
||||
.Add<LanguageMapDefinition>();
|
||||
|
||||
//register any resolvers, etc.. that the profiles use
|
||||
composition.Register<ContentUrlResolver>();
|
||||
composition.Register<ContentTreeNodeUrlResolver<IContent, ContentTreeController>>();
|
||||
composition.Register<TabsAndPropertiesResolver<IContent, ContentVariantDisplay>>();
|
||||
composition.Register<TabsAndPropertiesResolver<IMedia, MediaItemDisplay>>();
|
||||
composition.Register<ContentTreeNodeUrlResolver<IMedia, MediaTreeController>>();
|
||||
composition.Register<MemberTabsAndPropertiesResolver>();
|
||||
composition.Register<MemberTreeNodeUrlResolver>();
|
||||
composition.Register<MemberBasicPropertiesResolver>();
|
||||
composition.Register<MediaAppResolver>();
|
||||
composition.Register<ContentAppResolver>();
|
||||
composition.Register<CommonMapper>();
|
||||
composition.Register<MemberTabsAndPropertiesMapper>();
|
||||
|
||||
return composition;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.PackageActions;
|
||||
using Umbraco.Core.Packaging;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
@@ -164,6 +165,8 @@ namespace Umbraco.Web.Composing
|
||||
|
||||
// proxy Core for convenience
|
||||
|
||||
public static UmbracoMapper Mapper => CoreCurrent.Mapper;
|
||||
|
||||
public static IRuntimeState RuntimeState => CoreCurrent.RuntimeState;
|
||||
|
||||
public static TypeLoader TypeLoader => CoreCurrent.TypeLoader;
|
||||
|
||||
@@ -8,14 +8,12 @@ using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Mvc;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
@@ -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;
|
||||
@@ -53,14 +52,14 @@ namespace Umbraco.Web.Editors.Binders
|
||||
if (variant.Culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
//map the property dto collection (no culture is passed to the mapping context so it will be invariant)
|
||||
variant.PropertyCollectionDto = Mapper.Map<ContentPropertyCollectionDto>(model.PersistedContent);
|
||||
variant.PropertyCollectionDto = Current.Mapper.Map<ContentPropertyCollectionDto>(model.PersistedContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
//map the property dto collection with the culture of the current variant
|
||||
variant.PropertyCollectionDto = Mapper.Map<ContentPropertyCollectionDto>(
|
||||
variant.PropertyCollectionDto = Current.Mapper.Map<ContentPropertyCollectionDto>(
|
||||
model.PersistedContent,
|
||||
options => options.SetCulture(variant.Culture));
|
||||
context => context.SetCulture(variant.Culture));
|
||||
}
|
||||
|
||||
//now map all of the saved values to the dto
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -191,7 +190,7 @@ namespace Umbraco.Web.Editors
|
||||
//get all user groups and map their default permissions to the AssignedUserGroupPermissions model.
|
||||
//we do this because not all groups will have true assigned permissions for this node so if they don't have assigned permissions, we need to show the defaults.
|
||||
|
||||
var defaultPermissionsByGroup = Mapper.Map<IEnumerable<AssignedUserGroupPermissions>>(allUserGroups).ToArray();
|
||||
var defaultPermissionsByGroup = Mapper.MapEnumerable<IUserGroup, AssignedUserGroupPermissions>(allUserGroups);
|
||||
|
||||
var defaultPermissionsAsDictionary = defaultPermissionsByGroup
|
||||
.ToDictionary(x => Convert.ToInt32(x.Id), x => x);
|
||||
@@ -505,14 +504,14 @@ namespace Umbraco.Web.Editors
|
||||
var pagedResult = new PagedResult<ContentItemBasic<ContentPropertyBasic>>(totalChildren, pageNumber, pageSize);
|
||||
pagedResult.Items = children.Select(content =>
|
||||
Mapper.Map<IContent, ContentItemBasic<ContentPropertyBasic>>(content,
|
||||
opts =>
|
||||
context =>
|
||||
{
|
||||
|
||||
opts.SetCulture(cultureName);
|
||||
context.SetCulture(cultureName);
|
||||
|
||||
// if there's a list of property aliases to map - we will make sure to store this in the mapping context.
|
||||
if (!includeProperties.IsNullOrWhiteSpace())
|
||||
opts.SetIncludedProperties(includeProperties.Split(new[] { ", ", "," }, StringSplitOptions.RemoveEmptyEntries));
|
||||
context.SetIncludedProperties(includeProperties.Split(new[] { ", ", "," }, StringSplitOptions.RemoveEmptyEntries));
|
||||
}))
|
||||
.ToList(); // evaluate now
|
||||
|
||||
@@ -666,7 +665,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
//The default validation language will be either: The default languauge, else if the content is brand new and the default culture is
|
||||
// not marked to be saved, it will be the first culture in the list marked for saving.
|
||||
var defaultCulture = _allLangs.Value.First(x => x.Value.IsDefault).Key;
|
||||
var defaultCulture = _allLangs.Value.Values.FirstOrDefault(x => x.IsDefault)?.CultureName;
|
||||
var cultureForInvariantErrors = CultureImpact.GetCultureForInvariantErrors(
|
||||
contentItem.PersistedContent,
|
||||
contentItem.Variants.Where(x => x.Save).Select(x => x.Culture).ToArray(),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AutoMapper;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -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;
|
||||
@@ -15,7 +14,6 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
@@ -502,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)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
@@ -15,7 +12,6 @@ using Umbraco.Web.WebApi;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user