Merge remote-tracking branch 'origin/6.2.0' into 6.2.0-pubcontent

Conflicts:
	src/Umbraco.Tests/TestHelpers/BaseWebTest.cs
This commit is contained in:
Stephan
2013-10-10 15:52:09 +02:00
49 changed files with 1175 additions and 261 deletions
+51 -6
View File
@@ -35,12 +35,9 @@ namespace Umbraco.Core
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <param name="enableCache"></param>
internal ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache)
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache)
: this(enableCache)
{
if (dbContext == null) throw new ArgumentNullException("dbContext");
if (serviceContext == null) throw new ArgumentNullException("serviceContext");
_databaseContext = dbContext;
_services = serviceContext;
}
@@ -57,7 +54,7 @@ namespace Umbraco.Core
/// Constructor used to specify if we will enable application cache or not
/// </summary>
/// <param name="enableCache"></param>
internal ApplicationContext(bool enableCache)
public ApplicationContext(bool enableCache)
{
//create a new application cache from the HttpRuntime.Cache
ApplicationCache = HttpRuntime.Cache == null
@@ -65,7 +62,55 @@ namespace Umbraco.Core
: new CacheHelper(HttpRuntime.Cache, enableCache);
}
/// <summary>
/// <summary>
/// A method used to set and/or ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="appContext">
/// The instance to set on the global application singleton
/// </param>
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
if (ApplicationContext.Current != null)
{
if (!replaceContext)
return ApplicationContext.Current;
}
ApplicationContext.Current = appContext;
return ApplicationContext.Current;
}
/// <summary>
/// A method used to create and ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="enableCache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache, bool replaceContext)
{
if (ApplicationContext.Current != null)
{
if (!replaceContext)
return ApplicationContext.Current;
}
var ctx = new ApplicationContext(dbContext, serviceContext, enableCache);
ApplicationContext.Current = ctx;
return ApplicationContext.Current;
}
/// <summary>
/// Singleton accessor
/// </summary>
public static ApplicationContext Current { get; internal set; }
@@ -99,6 +99,10 @@ namespace Umbraco.Core
/// </summary>
public static class Member
{
public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider";
public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider";
/// <summary>
/// Property alias for a Members Password Question
/// </summary>
+1 -1
View File
@@ -28,7 +28,7 @@ namespace Umbraco.Core
private string _providerName;
private DatabaseSchemaResult _result;
internal DatabaseContext(IDatabaseFactory factory)
public DatabaseContext(IDatabaseFactory factory)
{
_factory = factory;
}
+13
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
@@ -50,6 +51,7 @@ namespace Umbraco.Core.Models
_contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture));
_properties = properties;
_properties.EnsurePropertyTypes(PropertyTypes);
_additionalData = new Dictionary<string, object>();
}
/// <summary>
@@ -73,6 +75,7 @@ namespace Umbraco.Core.Models
_contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture));
_properties = properties;
_properties.EnsurePropertyTypes(PropertyTypes);
_additionalData = new Dictionary<string, object>();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Name);
@@ -253,6 +256,16 @@ namespace Umbraco.Core.Models
}
}
private readonly IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData
{
get { return _additionalData; }
}
/// <summary>
/// List of PropertyGroups available on this Content object
/// </summary>
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
@@ -42,6 +43,7 @@ namespace Umbraco.Core.Models
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_propertyTypes = new PropertyTypeCollection();
_additionalData = new Dictionary<string, object>();
}
protected ContentTypeBase(IContentTypeBase parent)
@@ -52,6 +54,7 @@ namespace Umbraco.Core.Models
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_propertyTypes = new PropertyTypeCollection();
_additionalData = new Dictionary<string, object>();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
@@ -314,6 +317,16 @@ namespace Umbraco.Core.Models
}
}
private readonly IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData
{
get { return _additionalData; }
}
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>
+21 -1
View File
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
@@ -31,6 +33,7 @@ namespace Umbraco.Core.Models
{
_parentId = parentId;
_controlId = controlId;
_additionalData = new Dictionary<string, object>();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Name);
@@ -160,9 +163,11 @@ namespace Umbraco.Core.Models
_trashed = value;
return _trashed;
}, _trashed, TrashedSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["Trashed"] = value;
}
}
/// <summary>
/// Id of the DataType control
/// </summary>
@@ -177,6 +182,8 @@ namespace Umbraco.Core.Models
_controlId = value;
return _controlId;
}, _controlId, ControlIdSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["ControlId"] = value;
}
}
@@ -194,9 +201,22 @@ namespace Umbraco.Core.Models
_databaseType = value;
return _databaseType;
}, _databaseType, DatabaseTypeSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["DatabaseType"] = value;
}
}
private readonly IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData
{
get { return _additionalData; }
}
internal override void AddingEntity()
{
base.AddingEntity();
@@ -1,4 +1,6 @@
namespace Umbraco.Core.Models.EntityBase
using System.Collections.Generic;
namespace Umbraco.Core.Models.EntityBase
{
public interface IUmbracoEntity : IAggregateRoot
{
@@ -41,5 +43,10 @@
/// Not all entities support being trashed, they'll always return false.
/// </remarks>
bool Trashed { get; }
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
IDictionary<string, object> AdditionalData { get; }
}
}
+1 -1
View File
@@ -427,7 +427,7 @@ namespace Umbraco.Core.Models
public override void ChangeTrashedState(bool isTrashed, int parentId = -20)
{
throw new NotImplementedException("Members can't be trashed as no Recycle Bin exists, so use of this method is invalid");
throw new NotSupportedException("Members can't be trashed as no Recycle Bin exists, so use of this method is invalid");
}
/* Internal experiment - only used for mapping queries.
@@ -2,6 +2,8 @@
namespace Umbraco.Core.Models.Membership
{
//TODO: THere's still a bunch of properties that don't exist in this use that need to be mapped somehow.
internal class UmbracoMembershipMember : MembershipUser
{
private readonly IMember _member;
@@ -21,5 +23,44 @@ namespace Umbraco.Core.Models.Membership
get { return _member.Email; }
set { _member.Email = value; }
}
public override object ProviderUserKey
{
get { return _member.Key; }
}
public override System.DateTime CreationDate
{
get { return _member.CreateDate; }
}
public override string UserName
{
get { return _member.Username; }
}
public override string Comment
{
get { return _member.Comments; }
set { _member.Comments = value; }
}
public override bool IsApproved
{
get { return _member.IsApproved; }
set { _member.IsApproved = value; }
}
public override bool IsLockedOut
{
get { return _member.IsLockedOut; }
}
public override System.DateTime LastLoginDate
{
get { return _member.LastLoginDate; }
set { _member.LastLoginDate = value; }
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a paged result for a model collection
/// </summary>
/// <typeparam name="T"></typeparam>
[DataContract(Name = "pagedCollection", Namespace = "")]
public class PagedResult<T>
{
public PagedResult(long totalItems, long pageNumber, long pageSize)
{
TotalItems = totalItems;
PageNumber = pageNumber;
PageSize = pageSize;
if (pageSize > 0)
{
TotalPages = (long) Math.Ceiling(totalItems/(Decimal) pageSize);
}
else
{
TotalPages = 1;
}
}
[DataMember(Name = "pageNumber")]
public long PageNumber { get; private set; }
[DataMember(Name = "pageSize")]
public long PageSize { get; private set; }
[DataMember(Name = "totalPages")]
public long TotalPages { get; private set; }
[DataMember(Name = "totalItems")]
public long TotalItems { get; private set; }
[DataMember(Name = "items")]
public IEnumerable<T> Items { get; set; }
/// <summary>
/// Calculates the skip size based on the paged parameters specified
/// </summary>
/// <remarks>
/// Returns 0 if the page number or page size is zero
/// </remarks>
internal int SkipSize
{
get
{
if (PageNumber > 0 && PageSize > 0)
{
return Convert.ToInt32((PageNumber - 1)*PageSize);
}
return 0;
}
}
}
}
+34 -2
View File
@@ -44,10 +44,12 @@ namespace Umbraco.Core.Models
public UmbracoEntity()
{
AdditionalData = new Dictionary<string, object>();
}
public UmbracoEntity(bool trashed)
{
AdditionalData = new Dictionary<string, object>();
Trashed = trashed;
}
@@ -142,6 +144,9 @@ namespace Umbraco.Core.Models
}
}
public IDictionary<string, object> AdditionalData { get; private set; }
public bool HasChildren
{
get { return _hasChildren; }
@@ -152,6 +157,9 @@ namespace Umbraco.Core.Models
_hasChildren = value;
return _hasChildren;
}, _hasChildren, HasChildrenSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["HasChildren"] = value;
}
}
@@ -164,7 +172,10 @@ namespace Umbraco.Core.Models
{
_isPublished = value;
return _isPublished;
}, _isPublished, IsPublishedSelector);
}, _isPublished, IsPublishedSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["IsPublished"] = value;
}
}
@@ -178,6 +189,9 @@ namespace Umbraco.Core.Models
_isDraft = value;
return _isDraft;
}, _isDraft, IsDraftSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["IsDraft"] = value;
}
}
@@ -191,6 +205,9 @@ namespace Umbraco.Core.Models
_hasPendingChanges = value;
return _hasPendingChanges;
}, _hasPendingChanges, HasPendingChangesSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["HasPendingChanges"] = value;
}
}
@@ -204,6 +221,9 @@ namespace Umbraco.Core.Models
_contentTypeAlias = value;
return _contentTypeAlias;
}, _contentTypeAlias, ContentTypeAliasSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["ContentTypeAlias"] = value;
}
}
@@ -217,6 +237,9 @@ namespace Umbraco.Core.Models
_contentTypeIcon = value;
return _contentTypeIcon;
}, _contentTypeIcon, ContentTypeIconSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["ContentTypeIcon"] = value;
}
}
@@ -230,6 +253,9 @@ namespace Umbraco.Core.Models
_contentTypeThumbnail = value;
return _contentTypeThumbnail;
}, _contentTypeThumbnail, ContentTypeThumbnailSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["ContentTypeThumbnail"] = value;
}
}
@@ -242,10 +268,16 @@ namespace Umbraco.Core.Models
{
_nodeObjectTypeId = value;
return _nodeObjectTypeId;
}, _nodeObjectTypeId, NodeObjectTypeIdSelector);
}, _nodeObjectTypeId, NodeObjectTypeIdSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
AdditionalData["NodeObjectTypeId"] = value;
}
}
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
public IList<UmbracoProperty> UmbracoProperties { get; set; }
internal class UmbracoProperty
@@ -1,5 +1,7 @@
namespace Umbraco.Core.Persistence.Factories
{
//TODO: Not sure why we need this interface as it's never referenced in code.
internal interface IEntityFactory<TEntity, TDto>
where TEntity : class
where TDto : class
@@ -8,6 +8,45 @@ namespace Umbraco.Core.Persistence.Factories
{
internal class UmbracoEntityFactory : IEntityFactory<UmbracoEntity, EntityRepository.UmbracoEntityDto>
{
internal UmbracoEntity BuildEntityFromDynamic(dynamic d)
{
var entity = new UmbracoEntity(d.trashed)
{
CreateDate = d.createDate,
CreatorId = d.nodeUser,
Id = d.id,
Key = d.uniqueID,
Level = d.level,
Name = d.text,
NodeObjectTypeId = d.nodeObjectType,
ParentId = d.parentID,
Path = d.path,
SortOrder = d.sortOrder,
HasChildren = d.children > 0,
ContentTypeAlias = d.alias ?? string.Empty,
ContentTypeIcon = d.icon ?? string.Empty,
ContentTypeThumbnail = d.thumbnail ?? string.Empty,
UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>()
};
var asDictionary = (IDictionary<string, object>)d;
var publishedVersion = default(Guid);
//some content items don't have a published version
if (asDictionary.ContainsKey("publishedVersion") && asDictionary["publishedVersion"] != null)
{
Guid.TryParse(d.publishedVersion.ToString(), out publishedVersion);
}
var newestVersion = default(Guid);
Guid.TryParse(d.newestVersion.ToString(), out newestVersion);
entity.IsPublished = publishedVersion != default(Guid) || (newestVersion != default(Guid) && publishedVersion == newestVersion);
entity.IsDraft = newestVersion != default(Guid) && (publishedVersion == default(Guid) || publishedVersion != newestVersion);
entity.HasPendingChanges = (publishedVersion != default(Guid) && newestVersion != default(Guid)) && publishedVersion != newestVersion;
return entity;
}
public UmbracoEntity BuildEntity(EntityRepository.UmbracoEntityDto dto)
{
var entity = new UmbracoEntity(dto.Trashed)
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Persistence
/// <summary>
/// Used to create the UmbracoDatabase for use in the DatabaseContext
/// </summary>
internal interface IDatabaseFactory : IDisposable
public interface IDatabaseFactory : IDisposable
{
UmbracoDatabase CreateDatabase();
}
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -17,6 +18,19 @@ namespace Umbraco.Core.Persistence
internal static event CreateTableEventHandler NewTable;
/// <summary>
/// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter
/// </summary>
/// <param name="db"></param>
/// <param name="value"></param>
/// <returns></returns>
public static string EscapeAtSymbols(this Database db, string value)
{
//this fancy regex will only match a single @ not a double, etc...
var regex = new Regex("(?<!@)@(?!@)");
return regex.Replace(value, "@@");
}
public static void CreateTable<T>(this Database db)
where T : new()
{
@@ -38,7 +38,11 @@ namespace Umbraco.Core.Persistence.Relators
// Setup the new current MemberTypeReadOnlyDto
Current = a;
Current.PropertyTypes = new List<PropertyTypeReadOnlyDto>();
Current.PropertyTypes.Add(p);
//this can be null since we are doing a left join
if (p.Id.HasValue)
{
Current.PropertyTypes.Add(p);
}
Current.PropertyTypeGroups = new List<PropertyTypeGroupReadOnlyDto>();
if (g.Id.HasValue)
@@ -1,12 +1,18 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using Umbraco.Core.Models;
using Umbraco.Core;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -124,15 +130,43 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
var dtos = isMedia
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
new UmbracoEntityRelator().Map, sql)
: _work.Database.Fetch<UmbracoEntityDto>(sql);
var factory = new UmbracoEntityFactory();
var list = dtos.Select(factory.BuildEntity).Cast<IUmbracoEntity>().ToList();
return list;
if (isMedia)
{
//treat media differently for now
var dtos = _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
new UmbracoEntityRelator().Map, sql);
return dtos.Select(factory.BuildEntity).Cast<IUmbracoEntity>().ToArray();
}
else
{
//use dynamic so that we can get ALL properties from the SQL
//we'll have to stitch stuff together manually but we can get our
//additional data to put in the dictionary.
var dtos = _work.Database.Fetch<dynamic>(sql);
var entityProps = TypeHelper.GetPublicProperties(typeof (IUmbracoEntity)).Select(x => x.Name).ToArray();
var result = new List<IUmbracoEntity>();
foreach (var d in dtos)
{
//build the initial entity
IUmbracoEntity entity = factory.BuildEntityFromDynamic(d);
//convert the dynamic row to dictionary
var asDictionary = (IDictionary<string, object>) d;
//figure out what extra properties we have that are not on the IUmbracoEntity and add them to additional data
foreach (var k in asDictionary.Keys
.Select(x => new {orig = x, title = x.ConvertCase(StringAliasCaseType.PascalCase)})
.Where(x => entityProps.InvariantContains(x.title) == false))
{
entity.AdditionalData[k.title] = asDictionary[k.orig];
}
result.Add(entity);
}
return result;
}
}
#endregion
@@ -159,11 +193,12 @@ namespace Umbraco.Core.Persistence.Repositories
if (isContent || isMedia)
{
columns.Add("published.versionId as publishedVerison");
columns.Add("published.versionId as publishedVersion");
columns.Add("latest.versionId as newestVersion");
columns.Add("contenttype.alias");
columns.Add("contenttype.icon");
columns.Add("contenttype.thumbnail");
columns.Add("contenttype.isContainer");
}
if (isMedia)
@@ -251,6 +286,7 @@ namespace Umbraco.Core.Persistence.Repositories
columns.Add("contenttype.alias");
columns.Add("contenttype.icon");
columns.Add("contenttype.thumbnail");
columns.Add("contenttype.isContainer");
}
if (isMedia)
@@ -287,7 +323,7 @@ namespace Umbraco.Core.Persistence.Repositories
[Column("children")]
public int Children { get; set; }
[Column("publishedVerison")]
[Column("publishedVersion")]
public Guid PublishedVersion { get; set; }
[Column("newestVersion")]
@@ -11,5 +11,6 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="groupName"></param>
/// <returns></returns>
IEnumerable<IMember> GetByMemberGroup(string groupName);
}
}
@@ -298,11 +298,19 @@ namespace Umbraco.Core.Persistence.Repositories
//TODO ContentType for the Member entity
//Create the PropertyData for this version - cmsPropertyData
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
var propertyDataDtos = propertyFactory.BuildDto(((Member)entity).Properties);
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
var keyDictionary = new Dictionary<int, int>();
//Add Properties
// - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type
// - this can occur if the member type doesn't contain the built-in properties that the
// - member object contains.
var existingProperties = entity.Properties
.Where(property => entity.ContentType.PropertyTypes.Any(x => x.Alias == property.Alias && x.HasIdentity))
.ToList();
var propertyDataDtos = propertyFactory.BuildDto(existingProperties);
foreach (var propertyDataDto in propertyDataDtos)
{
if (propertyDataDto.Id > 0)
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Persistence.Repositories
.From<NodeDto>()
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, NodeDto>(left => left.ContentTypeId, right => right.NodeId)
.InnerJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.LeftJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeGroupDto, NodeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
@@ -122,7 +122,7 @@ namespace Umbraco.Core.Persistence.Repositories
.From<NodeDto>()
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, NodeDto>(left => left.ContentTypeId, right => right.NodeId)
.InnerJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.LeftJoin<MemberTypeDto>().On<MemberTypeDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeGroupDto, NodeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence
}
internal RepositoryFactory(bool disableAllCache)
public RepositoryFactory(bool disableAllCache)
{
_disableAllCache = disableAllCache;
}
+2 -1
View File
@@ -43,4 +43,5 @@ using System.Security.Permissions;
[assembly: InternalsVisibleTo("Concorde.Sync")]
[assembly: InternalsVisibleTo("Umbraco.Belle")]
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
[assembly: InternalsVisibleTo("umbraco.providers")]
+1 -1
View File
@@ -10,7 +10,7 @@ using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
public class EntityService : IService
public class EntityService : IService, IEntityService
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
+146
View File
@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Services
{
public interface IEntityService
{
/// <summary>
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
/// </summary>
/// <returns>
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
/// </returns>
/// <param name="id">Id of the object to retrieve</param>
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get(int id, bool loadBaseType = true);
/// <summary>
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
/// </summary>
/// <returns>
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
/// </returns>
/// <param name="id">Id of the object to retrieve</param>
/// <param name="umbracoObjectType">UmbracoObjectType of the entity to retrieve</param>
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
/// <summary>
/// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph.
/// </summary>
/// <returns>
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
/// </returns>
/// <typeparam name="T">Type of the model to retrieve. Must be based on an <see cref="IUmbracoEntity"/></typeparam>
/// <param name="id">Id of the object to retrieve</param>
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get<T>(int id, bool loadBaseType = true) where T : IUmbracoEntity;
/// <summary>
/// Gets the parent of entity by its id
/// </summary>
/// <param name="id">Id of the entity to retrieve the Parent for</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetParent(int id);
/// <summary>
/// Gets the parent of entity by its id and UmbracoObjectType
/// </summary>
/// <param name="id">Id of the entity to retrieve the Parent for</param>
/// <param name="umbracoObjectType">UmbracoObjectType of the parent to retrieve</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets a collection of children by the parents Id
/// </summary>
/// <param name="parentId">Id of the parent to retrieve children for</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetChildren(int parentId);
/// <summary>
/// Gets a collection of children by the parents Id and UmbracoObjectType
/// </summary>
/// <param name="parentId">Id of the parent to retrieve children for</param>
/// <param name="umbracoObjectType">UmbracoObjectType of the children to retrieve</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets a collection of descendents by the parents Id
/// </summary>
/// <param name="id">Id of entity to retrieve descendents for</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetDescendents(int id);
/// <summary>
/// Gets a collection of descendents by the parents Id
/// </summary>
/// <param name="id">Id of entity to retrieve descendents for</param>
/// <param name="umbracoObjectType">UmbracoObjectType of the descendents to retrieve</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets a collection of the entities at the root, which corresponds to the entities with a Parent Id of -1.
/// </summary>
/// <param name="umbracoObjectType">UmbracoObjectType of the root entities to retrieve</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetRootEntities(UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
/// </summary>
/// <typeparam name="T">Type of the entities to retrieve</typeparam>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetAll<T>() where T : IUmbracoEntity;
/// <summary>
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
/// </summary>
/// <param name="umbracoObjectType">UmbracoObjectType of the entities to return</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetAll(UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets a collection of <see cref="IUmbracoEntity"/>
/// </summary>
/// <param name="objectTypeId">Guid id of the UmbracoObjectType</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId);
/// <summary>
/// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity.
/// </summary>
/// <param name="id">Id of the entity</param>
/// <returns><see cref="UmbracoObjectTypes"/></returns>
UmbracoObjectTypes GetObjectType(int id);
/// <summary>
/// Gets the UmbracoObjectType from an IUmbracoEntity.
/// </summary>
/// <param name="entity"><see cref="IUmbracoEntity"/></param>
/// <returns><see cref="UmbracoObjectTypes"/></returns>
UmbracoObjectTypes GetObjectType(IUmbracoEntity entity);
/// <summary>
/// Gets the Type of an entity by its Id
/// </summary>
/// <param name="id">Id of the entity</param>
/// <returns>Type of the entity</returns>
Type GetEntityType(int id);
/// <summary>
/// Gets the Type of an entity by its <see cref="UmbracoObjectTypes"/>
/// </summary>
/// <param name="umbracoObjectType"><see cref="UmbracoObjectTypes"/></param>
/// <returns>Type of the entity</returns>
Type GetEntityType(UmbracoObjectTypes umbracoObjectType);
}
}
@@ -35,5 +35,7 @@ namespace Umbraco.Core.Services
void Delete(IMember membershipUser);
void Save(IMember membershipUser);
IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch);
}
}
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
internal interface IMemberTypeService : IService
{
/// <summary>
/// Gets a list of all available <see cref="IContentType"/> objects
/// </summary>
/// <param name="ids">Optional list of ids</param>
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids);
}
}
@@ -108,6 +108,25 @@ namespace Umbraco.Core.Services
}
}
/// <summary>
/// Does a search for members that contain the specified string in their email address
/// </summary>
/// <param name="emailStringToMatch"></param>
/// <returns></returns>
public IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
var query = new Query<IMember>();
query.Where(member => member.Email.Contains(emailStringToMatch));
return repository.GetByQuery(query);
}
}
/// <summary>
/// Gets a list of Members with a certain string property value
/// </summary>
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
internal class MemberTypeService : IMemberTypeService
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
public MemberTypeService()
: this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory())
{}
public MemberTypeService(RepositoryFactory repositoryFactory)
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
{ }
public MemberTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
{
if (provider == null) throw new ArgumentNullException("provider");
if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory");
_uowProvider = provider;
_repositoryFactory = repositoryFactory;
}
public IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids)
{
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
{
return repository.GetAll(ids);
}
}
}
}
+2 -2
View File
@@ -13,10 +13,10 @@ namespace Umbraco.Core.Services
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
private readonly EntityService _entityService;
private readonly IEntityService _entityService;
public RelationService(IDatabaseUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory,
EntityService entityService)
IEntityService entityService)
{
_uowProvider = uowProvider;
_repositoryFactory = repositoryFactory;
+89 -51
View File
@@ -12,41 +12,67 @@ namespace Umbraco.Core.Services
/// </summary>
public class ServiceContext
{
private Lazy<ContentService> _contentService;
private Lazy<UserService> _userService;
private Lazy<MemberService> _memberService;
private Lazy<MediaService> _mediaService;
private Lazy<ContentTypeService> _contentTypeService;
private Lazy<DataTypeService> _dataTypeService;
private Lazy<FileService> _fileService;
private Lazy<LocalizationService> _localizationService;
private Lazy<IContentService> _contentService;
private Lazy<IUserService> _userService;
private Lazy<IMemberService> _memberService;
private Lazy<IMediaService> _mediaService;
private Lazy<IContentTypeService> _contentTypeService;
private Lazy<IDataTypeService> _dataTypeService;
private Lazy<IFileService> _fileService;
private Lazy<ILocalizationService> _localizationService;
private Lazy<PackagingService> _packagingService;
private Lazy<ServerRegistrationService> _serverRegistrationService;
private Lazy<EntityService> _entityService;
private Lazy<IEntityService> _entityService;
private Lazy<RelationService> _relationService;
private Lazy<IMemberTypeService> _memberTypeService;
/// <summary>
/// Constructor
/// </summary>
/// <param name="dbUnitOfWorkProvider"></param>
/// <param name="fileUnitOfWorkProvider"></param>
/// <param name="publishingStrategy"></param>
internal ServiceContext(IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy)
{
BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, publishingStrategy,
//this needs to be lazy because when we create the service context it's generally before the
//resolvers have been initialized!
new Lazy<RepositoryFactory>(() => RepositoryResolver.Current.Factory));
}
/// <summary>
/// public ctor - will generally just be used for unit testing
/// </summary>
/// <param name="contentService"></param>
/// <param name="mediaService"></param>
/// <param name="contentTypeService"></param>
/// <param name="dataTypeService"></param>
/// <param name="fileService"></param>
/// <param name="localizationService"></param>
/// <param name="packagingService"></param>
/// <param name="entityService"></param>
/// <param name="relationService"></param>
public ServiceContext(IContentService contentService, IMediaService mediaService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, PackagingService packagingService, IEntityService entityService, RelationService relationService)
{
_contentService = new Lazy<IContentService>(() => contentService);
_mediaService = new Lazy<IMediaService>(() => mediaService);
_contentTypeService = new Lazy<IContentTypeService>(() => contentTypeService);
_dataTypeService = new Lazy<IDataTypeService>(() => dataTypeService);
_fileService = new Lazy<IFileService>(() => fileService);
_localizationService = new Lazy<ILocalizationService>(() => localizationService);
_packagingService = new Lazy<PackagingService>(() => packagingService);
_entityService = new Lazy<IEntityService>(() => entityService);
_relationService = new Lazy<RelationService>(() => relationService);
}
/// <summary>
/// Constructor used to instantiate the core services
/// </summary>
/// <param name="dbUnitOfWorkProvider"></param>
/// <param name="fileUnitOfWorkProvider"></param>
/// <param name="publishingStrategy"></param>
internal ServiceContext(IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy)
{
BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, publishingStrategy,
//this needs to be lazy because when we create the service context it's generally before the
//resolvers have been initialized!
new Lazy<RepositoryFactory>(() => RepositoryResolver.Current.Factory));
}
/// <summary>
/// Builds the various services
/// </summary>
private void BuildServiceCache(
IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider,
IUnitOfWorkProvider fileUnitOfWorkProvider,
BasePublishingStrategy publishingStrategy,
Lazy<RepositoryFactory> repositoryFactory)
private void BuildServiceCache(
IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider,
IUnitOfWorkProvider fileUnitOfWorkProvider,
BasePublishingStrategy publishingStrategy,
Lazy<RepositoryFactory> repositoryFactory)
{
var provider = dbUnitOfWorkProvider;
var fileProvider = fileUnitOfWorkProvider;
@@ -54,38 +80,41 @@ namespace Umbraco.Core.Services
if (_serverRegistrationService == null)
_serverRegistrationService = new Lazy<ServerRegistrationService>(() => new ServerRegistrationService(provider, repositoryFactory.Value));
if (_userService == null)
_userService = new Lazy<UserService>(() => new UserService(provider, repositoryFactory.Value));
if (_userService == null)
_userService = new Lazy<IUserService>(() => new UserService(provider, repositoryFactory.Value));
if (_memberService == null)
_memberService = new Lazy<MemberService>(() => new MemberService(provider, repositoryFactory.Value));
_memberService = new Lazy<IMemberService>(() => new MemberService(provider, repositoryFactory.Value));
if (_contentService == null)
_contentService = new Lazy<ContentService>(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy));
_contentService = new Lazy<IContentService>(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy));
if(_mediaService == null)
_mediaService = new Lazy<MediaService>(() => new MediaService(provider, repositoryFactory.Value));
if (_mediaService == null)
_mediaService = new Lazy<IMediaService>(() => new MediaService(provider, repositoryFactory.Value));
if(_contentTypeService == null)
_contentTypeService = new Lazy<ContentTypeService>(() => new ContentTypeService(provider, repositoryFactory.Value, _contentService.Value, _mediaService.Value));
if (_contentTypeService == null)
_contentTypeService = new Lazy<IContentTypeService>(() => new ContentTypeService(provider, repositoryFactory.Value, _contentService.Value, _mediaService.Value));
if(_dataTypeService == null)
_dataTypeService = new Lazy<DataTypeService>(() => new DataTypeService(provider, repositoryFactory.Value));
if (_dataTypeService == null)
_dataTypeService = new Lazy<IDataTypeService>(() => new DataTypeService(provider, repositoryFactory.Value));
if(_fileService == null)
_fileService = new Lazy<FileService>(() => new FileService(fileProvider, provider, repositoryFactory.Value));
if (_fileService == null)
_fileService = new Lazy<IFileService>(() => new FileService(fileProvider, provider, repositoryFactory.Value));
if(_localizationService == null)
_localizationService = new Lazy<LocalizationService>(() => new LocalizationService(provider, repositoryFactory.Value));
if (_localizationService == null)
_localizationService = new Lazy<ILocalizationService>(() => new LocalizationService(provider, repositoryFactory.Value));
if(_packagingService == null)
if (_packagingService == null)
_packagingService = new Lazy<PackagingService>(() => new PackagingService(_contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, repositoryFactory.Value, provider));
if (_entityService == null)
_entityService = new Lazy<EntityService>(() => new EntityService(provider, repositoryFactory.Value, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value));
_entityService = new Lazy<IEntityService>(() => new EntityService(provider, repositoryFactory.Value, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value));
if(_relationService == null)
if (_relationService == null)
_relationService = new Lazy<RelationService>(() => new RelationService(provider, repositoryFactory.Value, _entityService.Value));
if (_memberTypeService == null)
_memberTypeService = new Lazy<IMemberTypeService>(() => new MemberTypeService(provider, repositoryFactory.Value));
}
/// <summary>
@@ -99,7 +128,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Gets the <see cref="EntityService"/>
/// </summary>
public EntityService EntityService
public IEntityService EntityService
{
get { return _entityService.Value; }
}
@@ -125,7 +154,7 @@ namespace Umbraco.Core.Services
/// </summary>
public IContentTypeService ContentTypeService
{
get { return _contentTypeService.Value; }
get { return _contentTypeService.Value; }
}
/// <summary>
@@ -133,7 +162,7 @@ namespace Umbraco.Core.Services
/// </summary>
public IDataTypeService DataTypeService
{
get { return _dataTypeService.Value; }
get { return _dataTypeService.Value; }
}
/// <summary>
@@ -141,7 +170,7 @@ namespace Umbraco.Core.Services
/// </summary>
public IFileService FileService
{
get { return _fileService.Value; }
get { return _fileService.Value; }
}
/// <summary>
@@ -149,7 +178,7 @@ namespace Umbraco.Core.Services
/// </summary>
public ILocalizationService LocalizationService
{
get { return _localizationService.Value; }
get { return _localizationService.Value; }
}
/// <summary>
@@ -157,7 +186,7 @@ namespace Umbraco.Core.Services
/// </summary>
public IMediaService MediaService
{
get { return _mediaService.Value; }
get { return _mediaService.Value; }
}
/// <summary>
@@ -173,7 +202,7 @@ namespace Umbraco.Core.Services
/// </summary>
internal IUserService UserService
{
get { return _userService.Value; }
get { return _userService.Value; }
}
/// <summary>
@@ -183,5 +212,14 @@ namespace Umbraco.Core.Services
{
get { return _memberService.Value; }
}
/// <summary>
/// Gets the MemberTypeService
/// </summary>
internal IMemberTypeService MemberTypeService
{
get { return _memberTypeService.Value; }
}
}
}
+47
View File
@@ -203,6 +203,53 @@ namespace Umbraco.Core
});
}
/// <summary>
/// Returns all public properties including inherited properties even for interfaces
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <remarks>
/// taken from http://stackoverflow.com/questions/358835/getproperties-to-return-all-properties-for-an-interface-inheritance-hierarchy
/// </remarks>
public static PropertyInfo[] GetPublicProperties(Type type)
{
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
var subType = queue.Dequeue();
foreach (var subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface)) continue;
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
var typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
var newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
}
return propertyInfos.ToArray();
}
return type.GetProperties(BindingFlags.FlattenHierarchy
| BindingFlags.Public | BindingFlags.Instance);
}
/// <summary>
/// Gets (and caches) <see cref="FieldInfo"/> discoverable in the current <see cref="AppDomain"/> for a given <paramref name="type"/>.
/// </summary>
+4
View File
@@ -235,6 +235,7 @@
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
<Compile Include="Models\MemberType.cs" />
<Compile Include="Models\PagedResult.cs" />
<Compile Include="Models\Rdbms\MemberReadOnlyDto.cs" />
<Compile Include="Models\Rdbms\MemberTypeReadOnlyDto.cs" />
<Compile Include="Models\Rdbms\PropertyDataReadOnlyDto.cs" />
@@ -737,16 +738,19 @@
<Compile Include="Services\IContentService.cs" />
<Compile Include="Services\IContentTypeService.cs" />
<Compile Include="Services\IDataTypeService.cs" />
<Compile Include="Services\IEntityService.cs" />
<Compile Include="Services\IFileService.cs" />
<Compile Include="Services\ILocalizationService.cs" />
<Compile Include="Services\IMediaService.cs" />
<Compile Include="Services\IMemberService.cs" />
<Compile Include="Services\IMembershipUserService.cs" />
<Compile Include="Services\IMemberTypeService.cs" />
<Compile Include="Services\IService.cs" />
<Compile Include="Services\IUserService.cs" />
<Compile Include="Services\LocalizationService.cs" />
<Compile Include="Services\MediaService.cs" />
<Compile Include="Services\MemberService.cs" />
<Compile Include="Services\MemberTypeService.cs" />
<Compile Include="Services\RelationService.cs" />
<Compile Include="Services\ServerRegistrationService.cs" />
<Compile Include="Services\PackagingService.cs" />
+124
View File
@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
using Moq;
using Umbraco.Web;
namespace Umbraco.Tests
{
[TestFixture]
public class MockTests
{
[Test]
public void Can_Create_Empty_App_Context()
{
var appCtx = new ApplicationContext(false);
Assert.Pass();
}
[Test]
public void Can_Create_Service_Context()
{
var svcCtx = new ServiceContext(
new Mock<IContentService>().Object,
new Mock<IMediaService>().Object,
new Mock<IContentTypeService>().Object,
new Mock<IDataTypeService>().Object,
new Mock<IFileService>().Object,
new Mock<ILocalizationService>().Object,
new PackagingService(
new Mock<IContentService>().Object,
new Mock<IContentTypeService>().Object,
new Mock<IMediaService>().Object,
new Mock<IDataTypeService>().Object,
new Mock<IFileService>().Object,
new Mock<ILocalizationService>().Object,
new RepositoryFactory(true),
new Mock<IDatabaseUnitOfWorkProvider>().Object),
new Mock<IEntityService>().Object,
new RelationService(
new Mock<IDatabaseUnitOfWorkProvider>().Object,
new RepositoryFactory(true),
new Mock<IEntityService>().Object));
Assert.Pass();
}
[Test]
public void Can_Create_Db_Context()
{
var dbCtx = new DatabaseContext(new Mock<IDatabaseFactory>().Object);
Assert.Pass();
}
[Test]
public void Can_Create_App_Context_With_Services()
{
var appCtx = new ApplicationContext(
new DatabaseContext(new Mock<IDatabaseFactory>().Object),
new ServiceContext(
new Mock<IContentService>().Object,
new Mock<IMediaService>().Object,
new Mock<IContentTypeService>().Object,
new Mock<IDataTypeService>().Object,
new Mock<IFileService>().Object,
new Mock<ILocalizationService>().Object,
new PackagingService(
new Mock<IContentService>().Object,
new Mock<IContentTypeService>().Object,
new Mock<IMediaService>().Object,
new Mock<IDataTypeService>().Object,
new Mock<IFileService>().Object,
new Mock<ILocalizationService>().Object,
new RepositoryFactory(true),
new Mock<IDatabaseUnitOfWorkProvider>().Object),
new Mock<IEntityService>().Object,
new RelationService(
new Mock<IDatabaseUnitOfWorkProvider>().Object,
new RepositoryFactory(true),
new Mock<IEntityService>().Object)),
false);
Assert.Pass();
}
[Test]
public void Can_Assign_App_Context_Singleton()
{
var appCtx = new ApplicationContext(false);
var result = ApplicationContext.EnsureContext(appCtx, true);
Assert.AreEqual(appCtx, result);
}
[Test]
public void Does_Not_Overwrite_App_Context_Singleton()
{
ApplicationContext.EnsureContext(new ApplicationContext(false), true);
var appCtx = new ApplicationContext(false);
var result = ApplicationContext.EnsureContext(appCtx, false);
Assert.AreNotEqual(appCtx, result);
}
[NUnit.Framework.Ignore("Need to fix more stuff up, this is ignore because an exception occurs because it wants to ensure we have a resolver initialized - need to make that process better for testability")]
[Test]
public void Can_Get_Umbraco_Context()
{
var appCtx = new ApplicationContext(false);
ApplicationContext.EnsureContext(appCtx, true);
var umbCtx = UmbracoContext.EnsureContext(
new Mock<HttpContextBase>().Object,
appCtx,
true);
Assert.AreEqual(umbCtx, UmbracoContext.Current);
}
}
}
@@ -1,35 +1,35 @@
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Auditing;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Auditing
{
[TestFixture]
public class AuditTests : BaseDatabaseFactoryTest
{
[SetUp]
public override void Initialize()
{
base.Initialize();
}
[Test]
public void Can_Add_Audit_Entry()
{
Audit.Add(AuditTypes.System, "This is a System audit trail", 0, -1);
var dtos = DatabaseContext.Database.Fetch<LogDto>("WHERE id > -1");
Assert.That(dtos.Any(), Is.True);
Assert.That(dtos.First().Comment, Is.EqualTo("This is a System audit trail"));
}
[TearDown]
public override void TearDown()
{
base.TearDown();
}
}
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Auditing;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence.Auditing
{
[TestFixture]
public class AuditTests : BaseDatabaseFactoryTest
{
[SetUp]
public override void Initialize()
{
base.Initialize();
}
[Test]
public void Can_Add_Audit_Entry()
{
Audit.Add(AuditTypes.System, "This is a System audit trail", 0, -1);
var dtos = DatabaseContext.Database.Fetch<LogDto>("WHERE id > -1");
Assert.That(dtos.Any(), Is.True);
Assert.That(dtos.First().Comment, Is.EqualTo("This is a System audit trail"));
}
[TearDown]
public override void TearDown()
{
base.TearDown();
}
}
}
@@ -45,7 +45,7 @@ namespace Umbraco.Tests.Persistence.Repositories
}
[Test]
public void MemberRepository_Can_Persist_Member()
public void MemberRepository_Can_Persist_Member_Type()
{
IMemberType sut;
var provider = new PetaPocoUnitOfWorkProvider();
@@ -67,6 +67,56 @@ namespace Umbraco.Tests.Persistence.Repositories
}
}
[Test]
public void MemberRepository_Can_Get_All_Member_Types()
{
var provider = new PetaPocoUnitOfWorkProvider();
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
repository.AddOrUpdate(memberType1);
unitOfWork.Commit();
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
memberType2.Name = "AnotherType";
memberType2.Alias = "anotherType";
repository.AddOrUpdate(memberType2);
unitOfWork.Commit();
var result = repository.GetAll();
//there are 3 because of the Member type created for init data
Assert.AreEqual(3, result.Count());
}
}
[Test]
public void MemberRepository_Can_Get_All_Member_When_No_Properties()
{
var provider = new PetaPocoUnitOfWorkProvider();
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
var memberType1 = MockedContentTypes.CreateSimpleMemberType();
memberType1.PropertyTypeCollection.Clear();
repository.AddOrUpdate(memberType1);
unitOfWork.Commit();
var memberType2 = MockedContentTypes.CreateSimpleMemberType();
memberType2.PropertyTypeCollection.Clear();
memberType2.Name = "AnotherType";
memberType2.Alias = "anotherType";
repository.AddOrUpdate(memberType2);
unitOfWork.Commit();
var result = repository.GetAll();
//there are 3 because of the Member type created for init data
Assert.AreEqual(3, result.Count());
}
}
[Test, NUnit.Framework.Ignore]
public void MemberTypeRepository_Can_Get_MemberType_By_Id()
{
@@ -3,8 +3,8 @@ using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Tests.Stubs;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
@@ -3,9 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Umbraco.Tests.Stubs;
using Umbraco.Tests.TestHelpers;
using System.Configuration;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Routing;
@@ -21,7 +21,6 @@ using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
using Umbraco.Tests.Stubs;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
@@ -4,7 +4,7 @@ using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Tests.Stubs;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Routing;
@@ -14,7 +14,6 @@ using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
using Umbraco.Tests.PublishedContent;
using Umbraco.Tests.Stubs;
using Umbraco.Web;
using Umbraco.Web.Routing;
using umbraco.BusinessLogic;
@@ -1,12 +1,12 @@
using Umbraco.Web.Routing;
namespace Umbraco.Tests.Stubs
{
internal class FakeLastChanceFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest docRequest)
{
return false;
}
}
using Umbraco.Web.Routing;
namespace Umbraco.Tests.TestHelpers.Stubs
{
internal class FakeLastChanceFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest docRequest)
{
return false;
}
}
}
@@ -1,40 +1,40 @@
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Umbraco.Core;
namespace Umbraco.Tests.Stubs
{
/// <summary>
/// Used in place of the UmbracoControllerFactory which relies on BuildManager which throws exceptions in a unit test context
/// </summary>
internal class TestControllerFactory : IControllerFactory
{
public IController CreateController(RequestContext requestContext, string controllerName)
{
var types = TypeFinder.FindClassesOfType<ControllerBase>(new[] { Assembly.GetExecutingAssembly() });
var controllerTypes = types.Where(x => x.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase));
var t = controllerTypes.SingleOrDefault();
if (t == null)
return null;
return Activator.CreateInstance(t) as IController;
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return SessionStateBehavior.Disabled;
}
public void ReleaseController(IController controller)
{
controller.DisposeIfDisposable();
}
}
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Umbraco.Core;
namespace Umbraco.Tests.TestHelpers.Stubs
{
/// <summary>
/// Used in place of the UmbracoControllerFactory which relies on BuildManager which throws exceptions in a unit test context
/// </summary>
internal class TestControllerFactory : IControllerFactory
{
public IController CreateController(RequestContext requestContext, string controllerName)
{
var types = TypeFinder.FindClassesOfType<ControllerBase>(new[] { Assembly.GetExecutingAssembly() });
var controllerTypes = types.Where(x => x.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase));
var t = controllerTypes.SingleOrDefault();
if (t == null)
return null;
return Activator.CreateInstance(t) as IController;
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return SessionStateBehavior.Disabled;
}
public void ReleaseController(IController controller)
{
controller.DisposeIfDisposable();
}
}
}
+4 -3
View File
@@ -144,7 +144,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AttemptTests.cs" />
<Compile Include="Auditing\AuditTests.cs" />
<Compile Include="MockTests.cs" />
<Compile Include="Persistence\Auditing\AuditTests.cs" />
<Compile Include="BootManagers\CoreBootManagerTests.cs" />
<Compile Include="BusinessLogic\DictionaryTest.cs" />
<Compile Include="Cache\CacheHelperTests.cs" />
@@ -359,7 +360,7 @@
<Compile Include="Routing\NiceUrlProviderTests.cs" />
<Compile Include="Routing\RenderRouteHandlerTests.cs" />
<Compile Include="Routing\RouteTestExtensions.cs" />
<Compile Include="Stubs\TestControllerFactory.cs" />
<Compile Include="TestHelpers\Stubs\TestControllerFactory.cs" />
<Compile Include="TestHelpers\BaseUsingSqlCeSyntax.cs" />
<Compile Include="TestHelpers\BaseWebTest.cs" />
<Compile Include="TestHelpers\BaseDatabaseTest.cs" />
@@ -395,7 +396,7 @@
<Compile Include="Resolvers\PackageActionsResolverTests.cs" />
<Compile Include="PluginManagerExtensions.cs" />
<Compile Include="PluginManagerTests.cs" />
<Compile Include="Stubs\FakeLastChanceFinder.cs" />
<Compile Include="TestHelpers\Stubs\FakeLastChanceFinder.cs" />
<Compile Include="TestHelpers\TestHelper.cs" />
<Compile Include="EnumerableExtensionsTests.cs" />
<Compile Include="IO\AbstractFileSystemTests.cs" />
@@ -1,6 +1,8 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
using System.Configuration.Provider;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -8,6 +10,7 @@ using System.Web.Hosting;
using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Models.Membership;
@@ -254,8 +257,9 @@ namespace Umbraco.Web.Security.Providers
}
/// <summary>
/// Adds a new membership user to the data source.
/// Adds a new membership user to the data source with the specified member type
/// </summary>
/// <param name="memberType">A specific member type to create the member for</param>
/// <param name="username">The user name for the new user.</param>
/// <param name="password">The password for the new user.</param>
/// <param name="email">The e-mail address for the new user.</param>
@@ -267,16 +271,16 @@ namespace Umbraco.Web.Security.Providers
/// <returns>
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
/// </returns>
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,
public MembershipUser CreateUser(string memberType, string username, string password, string email, string passwordQuestion, string passwordAnswer,
bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
LogHelper.Debug<MembersMembershipProvider>("Member signup requested: username -> " + username + ". email -> " +email);
LogHelper.Debug<MembersMembershipProvider>("Member signup requested: username -> " + username + ". email -> " + email);
// Validate password
if (IsPasswordValid(password) == false)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
status = MembershipCreateStatus.InvalidPassword;
return null;
}
// Validate email
@@ -324,18 +328,41 @@ namespace Umbraco.Web.Security.Providers
return null;
}
var member = MemberService.CreateMember(email, username, password, DefaultMemberTypeAlias);
var member = MemberService.CreateMember(email, username, password, memberType);
member.IsApproved = isApproved;
member.PasswordQuestion = passwordQuestion;
member.PasswordAnswer = passwordAnswer;
//encrypts/hashes the password depending on the settings
member.Password = EncryptOrHashPassword(member.Password);
MemberService.Save(member);
status = MembershipCreateStatus.Success;
return member.AsConcreteMembershipUser();
}
/// <summary>
/// Adds a new membership user to the data source.
/// </summary>
/// <param name="username">The user name for the new user.</param>
/// <param name="password">The password for the new user.</param>
/// <param name="email">The e-mail address for the new user.</param>
/// <param name="passwordQuestion">The password question for the new user.</param>
/// <param name="passwordAnswer">The password answer for the new user</param>
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
/// <returns>
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
/// </returns>
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,
bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
return CreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
}
/// <summary>
/// Processes a request to update the password question and answer for a membership user.
/// </summary>
@@ -360,7 +387,7 @@ namespace Umbraco.Web.Security.Providers
}
var member = MemberService.GetByUsername(username);
var encodedPassword = EncodePassword(password);
var encodedPassword = EncryptOrHashPassword(password);
if (member.Password == encodedPassword)
{
@@ -427,12 +454,12 @@ namespace Umbraco.Web.Security.Providers
var member = MemberService.GetByUsername(username);
if (member == null) return false;
var encodedPassword = EncodePassword(oldPassword);
var encodedPassword = EncryptOrHashPassword(oldPassword);
if (member.Password == encodedPassword)
{
member.Password = EncodePassword(newPassword);
member.Password = EncryptOrHashPassword(newPassword);
MemberService.Save(member);
return true;
@@ -464,7 +491,7 @@ namespace Umbraco.Web.Security.Providers
if (_requiresQuestionAndAnswer == false || (_requiresQuestionAndAnswer && answer == member.PasswordAnswer))
{
member.Password =
EncodePassword(Membership.GeneratePassword(_minRequiredPasswordLength,
EncryptOrHashPassword(Membership.GeneratePassword(_minRequiredPasswordLength,
_minRequiredNonAlphanumericCharacters));
MemberService.Save(member);
}
@@ -505,7 +532,7 @@ namespace Umbraco.Web.Security.Providers
if (member.IsLockedOut)
throw new ProviderException("The member is locked out.");
var encodedPassword = EncodePassword(password);
var encodedPassword = EncryptOrHashPassword(password);
var authenticated = (encodedPassword == member.Password);
@@ -687,7 +714,16 @@ namespace Umbraco.Web.Security.Providers
/// </returns>
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new System.NotImplementedException();
var byEmail = MemberService.FindMembersByEmail(emailToMatch).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
{
collection.Add(m.AsConcreteMembershipUser());
}
return collection;
}
#region Private methods
@@ -714,11 +750,9 @@ namespace Umbraco.Web.Security.Providers
private bool IsEmaiValid(string email)
{
const string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
+ @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
+ @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";
var validator = new EmailAddressAttribute();
return Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
return validator.IsValid(email);
}
/// <summary>
@@ -726,7 +760,7 @@ namespace Umbraco.Web.Security.Providers
/// </summary>
/// <param name="password">The password.</param>
/// <returns>The encoded password.</returns>
private string EncodePassword(string password)
private string EncryptOrHashPassword(string password)
{
var encodedPassword = password;
switch (PasswordFormat)
+25 -22
View File
@@ -2,8 +2,10 @@ using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Data;
using System.Threading;
using System.Xml;
using System.Linq;
using Umbraco.Core;
using umbraco.cms.businesslogic.language;
using umbraco.DataLayer;
using umbraco.BusinessLogic;
@@ -19,7 +21,7 @@ namespace umbraco.cms.businesslogic
public class Dictionary
{
private static volatile bool _cacheIsEnsured = false;
private static readonly object Locker = new object();
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
private static readonly ConcurrentDictionary<string, DictionaryItem> DictionaryItems = new ConcurrentDictionary<string, DictionaryItem>();
private static readonly Guid TopLevelParent = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde");
@@ -33,30 +35,28 @@ namespace umbraco.cms.businesslogic
/// </summary>
private static void EnsureCache()
{
if (!_cacheIsEnsured)
using (var lck = new UpgradeableReadLock(Locker))
{
lock (Locker)
if (_cacheIsEnsured) return;
lck.UpgradeToWriteLock();
using (var dr = SqlHelper.ExecuteReader("Select pk, id, [key], parent from cmsDictionary"))
{
if (!_cacheIsEnsured)
while (dr.Read())
{
using (IRecordsReader dr = SqlHelper.ExecuteReader("Select pk, id, [key], parent from cmsDictionary"))
{
while (dr.Read())
{
//create new dictionaryitem object and put in cache
var item = new DictionaryItem(dr.GetInt("pk"),
dr.GetString("key"),
dr.GetGuid("id"),
dr.GetGuid("parent"));
//create new dictionaryitem object and put in cache
var item = new DictionaryItem(dr.GetInt("pk"),
dr.GetString("key"),
dr.GetGuid("id"),
dr.GetGuid("parent"));
DictionaryItems.TryAdd(item.key, item);
}
}
_cacheIsEnsured = true;
DictionaryItems.TryAdd(item.key, item);
}
}
}
_cacheIsEnsured = true;
}
}
/// <summary>
@@ -64,9 +64,12 @@ namespace umbraco.cms.businesslogic
/// </summary>
internal static void ClearCache()
{
DictionaryItems.Clear();
//ensure the flag is reset so that EnsureCache will re-cache everything
_cacheIsEnsured = false;
using (new WriteLock(Locker))
{
DictionaryItems.Clear();
//ensure the flag is reset so that EnsureCache will re-cache everything
_cacheIsEnsured = false;
}
}
/// <summary>
@@ -30,8 +30,8 @@ namespace umbraco.cms.businesslogic.member
public class Member : Content
{
#region Constants and static members
public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider";
public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider";
public static readonly string UmbracoMemberProviderName = Constants.Conventions.Member.UmbracoMemberProviderName;
public static readonly string UmbracoRoleProviderName = Constants.Conventions.Member.UmbracoRoleProviderName;
public static readonly Guid _objectType = new Guid(Constants.ObjectTypes.Member);
private static readonly object m_Locker = new object();
@@ -211,6 +211,8 @@ namespace umbraco.cms.businesslogic.member
/// <returns>The new member</returns>
public static Member MakeNew(string Name, string LoginName, string Email, MemberType mbt, User u)
{
if (mbt == null) throw new ArgumentNullException("mbt");
var loginName = (!String.IsNullOrEmpty(LoginName)) ? LoginName : Name;
if (String.IsNullOrEmpty(loginName))
@@ -1,20 +1,26 @@
#region namespace
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Configuration;
using Umbraco.Core;
using Umbraco.Core.Models;
using umbraco.BusinessLogic;
using System.Security.Cryptography;
using System.Web.Util;
using System.Collections.Specialized;
using System.Configuration.Provider;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.member;
using System.Security;
using System.Security.Permissions;
using System.Runtime.CompilerServices;
using Member = umbraco.cms.businesslogic.member.Member;
using MemberType = umbraco.cms.businesslogic.member.MemberType;
using Umbraco.Core.Models.Membership;
using User = umbraco.BusinessLogic.User;
#endregion
namespace umbraco.providers.members
@@ -354,6 +360,68 @@ namespace umbraco.providers.members
}
}
/// <summary>
/// Adds a new membership user to the data source.
/// </summary>
/// <param name="memberTypeAlias"></param>
/// <param name="username">The user name for the new user.</param>
/// <param name="password">The password for the new user.</param>
/// <param name="email">The e-mail address for the new user.</param>
/// <param name="passwordQuestion">The password question for the new user.</param>
/// <param name="passwordAnswer">The password answer for the new user</param>
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
/// <returns>
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
/// </returns>
public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
if (Member.GetMemberFromLoginName(username) != null)
status = MembershipCreateStatus.DuplicateUserName;
else if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
status = MembershipCreateStatus.DuplicateEmail;
else
{
var memberType = MemberType.GetByAlias(memberTypeAlias);
if (memberType == null)
{
throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias + ". Ensure your membership provider configuration is up to date and that the default member type exists.");
}
Member m = Member.MakeNew(username, email, memberType, User.GetUser(0));
m.Password = password;
MembershipUser mUser =
ConvertToMembershipUser(m);
// custom fields
if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias))
UpdateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias))
UpdateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias))
UpdateMemberProperty(m, m_ApprovedPropertyTypeAlias, isApproved);
if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias))
{
mUser.LastActivityDate = DateTime.Now;
UpdateMemberProperty(m, m_LastLoginPropertyTypeAlias, mUser.LastActivityDate);
}
// save
m.Save();
status = MembershipCreateStatus.Success;
return mUser;
}
return null;
}
/// <summary>
/// Adds a new membership user to the data source.
/// </summary>
@@ -371,41 +439,7 @@ namespace umbraco.providers.members
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
if (Member.GetMemberFromLoginName(username) != null)
status = MembershipCreateStatus.DuplicateUserName;
else if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
status = MembershipCreateStatus.DuplicateEmail;
else
{
Member m = Member.MakeNew(username, email, MemberType.GetByAlias(m_DefaultMemberTypeAlias), User.GetUser(0));
m.Password = password;
MembershipUser mUser =
ConvertToMembershipUser(m);
// custom fields
if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias))
UpdateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias))
UpdateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias))
UpdateMemberProperty(m, m_ApprovedPropertyTypeAlias, isApproved);
if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias)) {
mUser.LastActivityDate = DateTime.Now;
UpdateMemberProperty(m, m_LastLoginPropertyTypeAlias, mUser.LastActivityDate);
}
// save
m.Save();
status = MembershipCreateStatus.Success;
return mUser;
}
return null;
return CreateUser(m_DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
}
/// <summary>
@@ -439,7 +473,16 @@ namespace umbraco.providers.members
/// </returns>
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new Exception("The method or operation is not implemented.");
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch).ToArray();
totalRecords = byEmail.Length;
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
var collection = new MembershipUserCollection();
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
{
collection.Add(m.AsConcreteMembershipUser());
}
return collection;
}
/// <summary>
@@ -751,7 +794,7 @@ namespace umbraco.providers.members
return null;
}
/// <summary>
/// Verifies that the specified user name and password exist in the data source.
/// </summary>
@@ -973,6 +1016,7 @@ namespace umbraco.providers.members
DateTime.Now, DateTime.Now, DateTime.Now);
}
}
#endregion
}
}
@@ -97,6 +97,10 @@
<Project>{ccd75ec3-63db-4184-b49d-51c1dd337230}</Project>
<Name>umbraco.cms</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
<Project>{31785bc3-256c-4613-b2f5-a1b0bdded8c1}</Project>
<Name>Umbraco.Core</Name>
</ProjectReference>
<ProjectReference Include="..\umbraco.datalayer\umbraco.datalayer.csproj">
<Project>{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}</Project>
<Name>umbraco.datalayer</Name>
+4 -3
View File
@@ -1,7 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.20827.3
MinimumVisualStudioVersion = 10.0.40219.1
# Visual Studio 2012
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2849E9D4-3B4E-40A3-A309-F3CB4F0E125F}"
ProjectSection(SolutionItems) = preProject
..\build\Build.bat = ..\build\Build.bat
@@ -159,4 +157,7 @@ Global
{73529637-28F5-419C-A6BB-D094E39DE614} = {DD32977B-EF54-475B-9A1B-B97A502C6E58}
{B555AAE6-0F56-442F-AC9F-EF497DB38DE7} = {DD32977B-EF54-475B-9A1B-B97A502C6E58}
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal