diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
index 542cceac40..cab511962d 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
@@ -37,7 +37,7 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
///
- IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy);
+ IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Expression> orderBy);
///
diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
index 34d4100b3e..b97283542e 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
@@ -181,27 +181,27 @@ namespace Umbraco.Core.Persistence.Repositories
umbracoFileValue = string.Concat(mediaPath.Substring(0, underscoreIndex), mediaPath.Substring(dotIndex));
}
- Func createSql = url => Sql().SelectAll()
- .From()
- .InnerJoin()
- .On(left => left.PropertyTypeId, right => right.Id)
- .Where(x => x.Alias == "umbracoFile")
- .Where(x => x.VarChar == url);
-
- var sql = createSql(umbracoFileValue);
-
- var propertyDataDto = Database.Fetch(sql).FirstOrDefault();
-
// If the stripped-down url returns null, we try again with the original url.
// Previously, the function would fail on e.g. "my_x_image.jpg"
- if (propertyDataDto == null)
- {
- sql = createSql(mediaPath);
- propertyDataDto = Database.Fetch(sql).FirstOrDefault();
- }
+ var nodeId = GetMediaNodeIdByPath(umbracoFileValue);
+ if (nodeId < 0) nodeId = GetMediaNodeIdByPath(mediaPath);
- return propertyDataDto == null ? null : Get(propertyDataDto.NodeId);
+ return nodeId < 0 ? null : Get(nodeId);
}
+
+ private int GetMediaNodeIdByPath(string url)
+ {
+ var sql = Sql().SelectAll()
+ .From()
+ .InnerJoin()
+ .On(left => left.PropertyTypeId, right => right.Id)
+ .Where(x => x.Alias == "umbracoFile")
+ .Where(x => x.VarChar == url);
+
+ var dto = Database.Fetch(sql).FirstOrDefault();
+ return dto?.NodeId ?? -1;
+ }
+
protected override void PerformDeleteVersion(int id, Guid versionId)
{
Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs
index f36e69d747..497efdc5b2 100644
--- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs
@@ -322,7 +322,7 @@ namespace Umbraco.Core.Persistence.Repositories
///
/// The query supplied will ONLY work with data specifically on the umbracoUser table because we are using NPoco paging (SQL paging)
///
- public IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy)
+ public IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Expression> orderBy)
{
if (orderBy == null) throw new ArgumentNullException(nameof(orderBy));
diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index 3e4a67349b..c2f803e945 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -391,9 +391,9 @@ namespace Umbraco.Core.Services
{
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- var content = repository.GetAll(idsA);
+ var items = repository.GetAll(idsA);
uow.Complete();
- return content;
+ return items;
}
}
@@ -409,8 +409,7 @@ namespace Umbraco.Core.Services
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.Key == key);
- var contents = repository.GetByQuery(query);
- var content = contents.SingleOrDefault();
+ var content = repository.GetByQuery(query).SingleOrDefault();
uow.Complete();
return content;
}
@@ -428,9 +427,9 @@ namespace Umbraco.Core.Services
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.ContentTypeId == id);
- var content = repository.GetByQuery(query);
+ var items = repository.GetByQuery(query);
uow.Complete();
- return content;
+ return items;
}
}
@@ -460,9 +459,9 @@ namespace Umbraco.Core.Services
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.Level == level && x.Trashed == false);
- var content = repository.GetByQuery(query);
+ var items = repository.GetByQuery(query);
uow.Complete();
- return content;
+ return items;
}
}
@@ -494,9 +493,9 @@ namespace Umbraco.Core.Services
{
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- var content = repository.GetAllVersions(id);
+ var versions = repository.GetAllVersions(id);
uow.Complete();
- return content;
+ return versions;
}
}
@@ -590,12 +589,11 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- IQuery filterQuery = null;
- if (filter.IsNullOrWhiteSpace() == false)
- {
- filterQuery = repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
- }
+ var filterQuery = filter.IsNullOrWhiteSpace()
+ ? null
+ : repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery);
}
}
@@ -624,11 +622,9 @@ namespace Umbraco.Core.Services
var repository = uow.CreateRepository();
var query = repository.Query;
- //if the id is System Root, then just get all
- if (id != Constants.System.Root)
- {
- query.Where(x => x.ParentId == id);
- }
+ //if the id is System Root, then just get all - NO! does not make sense!
+ //if (id != Constants.System.Root)
+ query.Where(x => x.ParentId == id);
var children = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
uow.Complete();
return children;
@@ -650,12 +646,11 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- IQuery filterQuery = null;
- if (filter.IsNullOrWhiteSpace() == false)
- {
- filterQuery = repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
- }
+ var filterQuery = filter.IsNullOrWhiteSpace()
+ ? null
+ : repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery);
}
}
@@ -685,12 +680,10 @@ namespace Umbraco.Core.Services
var query = repository.Query;
//if the id is System Root, then just get all
if (id != Constants.System.Root)
- {
query.Where(x => x.Path.SqlContains($",{id},", TextColumnType.NVarchar));
- }
- var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
+ var descendants = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
uow.Complete();
- return contents;
+ return descendants;
}
}
@@ -817,9 +810,9 @@ namespace Umbraco.Core.Services
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.ParentId == Constants.System.Root);
- var content = repository.GetByQuery(query);
+ var items = repository.GetByQuery(query);
uow.Complete();
- return content;
+ return items;
}
}
@@ -894,7 +887,8 @@ namespace Umbraco.Core.Services
{
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.Path.Contains(Constants.System.RecycleBinContent.ToInvariantString()));
+ var bin = $"{Constants.System.Root},{Constants.System.RecycleBinContent},";
+ var query = repository.Query.Where(x => x.Path.StartsWith(bin));
var content = repository.GetByQuery(query);
uow.Complete();
return content;
@@ -1322,7 +1316,7 @@ namespace Umbraco.Core.Services
/// Optional Id of the User deleting the Content
public void Delete(IContent content, int userId = 0)
{
- ((IContentServiceOperations)this).Delete(content, userId);
+ ((IContentServiceOperations) this).Delete(content, userId);
}
///
@@ -1387,7 +1381,7 @@ namespace Umbraco.Core.Services
Deleted.RaiseEvent(args, this);
IOHelper.DeleteFiles(args.MediaFilesToDelete, // remove flagged files
- (file, e) => Logger.Error("An error occurred while deleting file attached to nodes: " + file, e));
+ (file, e) => Logger.Error("An error occurred while deleting file attached to nodes: " + file, e));
}
}
@@ -1466,7 +1460,7 @@ namespace Umbraco.Core.Services
/// Optional Id of the User deleting the Content
public void MoveToRecycleBin(IContent content, int userId = 0)
{
- ((IContentServiceOperations)this).MoveToRecycleBin(content, userId);
+ ((IContentServiceOperations) this).MoveToRecycleBin(content, userId);
}
///
@@ -2583,6 +2577,8 @@ namespace Umbraco.Core.Services
private IContentType GetContentType(string contentTypeAlias)
{
+ Mandate.ParameterNotNullOrEmpty(contentTypeAlias, nameof(contentTypeAlias));
+
using (var uow = UowProvider.CreateUnitOfWork())
{
uow.ReadLock(Constants.Locks.ContentTree);
@@ -2601,7 +2597,7 @@ namespace Umbraco.Core.Services
#endregion
- #region Xml - Shoud Move!
+ #region Xml - Should Move!
///
/// Returns the persisted content's XML structure
@@ -2658,7 +2654,6 @@ namespace Umbraco.Core.Services
}
Audit(AuditType.Publish, "ContentService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, Constants.System.Root);
-
}
#endregion
diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs
index 351035e285..b231119561 100644
--- a/src/Umbraco.Core/Services/IMediaService.cs
+++ b/src/Umbraco.Core/Services/IMediaService.cs
@@ -67,9 +67,9 @@ namespace Umbraco.Core.Services
///
void RebuildXmlStructures(params int[] contentTypeIds);
- int Count(string contentTypeAlias = null);
- int CountChildren(int parentId, string contentTypeAlias = null);
- int CountDescendants(int parentId, string contentTypeAlias = null);
+ int Count(string mediaTypeAlias = null);
+ int CountChildren(int parentId, string mediaTypeAlias = null);
+ int CountDescendants(int parentId, string mediaTypeAlias = null);
IEnumerable GetByIds(IEnumerable ids);
diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs
index a893d89feb..6591cc0b74 100644
--- a/src/Umbraco.Core/Services/IMemberService.cs
+++ b/src/Umbraco.Core/Services/IMemberService.cs
@@ -22,11 +22,6 @@ namespace Umbraco.Core.Services
///
void RebuildXmlStructures(params int[] contentTypeIds);
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords,
- string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "");
-
///
/// Gets a list of paged objects
///
@@ -183,10 +178,6 @@ namespace Umbraco.Core.Services
/// Id of the MemberType
void DeleteMembersOfType(int memberTypeId);
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- IEnumerable FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
-
///
/// Finds Members based on their display name
///
diff --git a/src/Umbraco.Core/Services/IMemberTypeService.cs b/src/Umbraco.Core/Services/IMemberTypeService.cs
index 6398ea62f9..3c0ed4d18f 100644
--- a/src/Umbraco.Core/Services/IMemberTypeService.cs
+++ b/src/Umbraco.Core/Services/IMemberTypeService.cs
@@ -1,5 +1,3 @@
-using System;
-using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -8,63 +6,7 @@ namespace Umbraco.Core.Services
/// Manages objects.
///
public interface IMemberTypeService : IContentTypeServiceBase
- {
- ///
- /// Gets a list of all available objects
- ///
- /// Optional list of ids
- /// An Enumerable list of objects
- IEnumerable GetAll(params int[] ids);
-
- ///
- /// Gets an object by its Id
- ///
- /// Id of the to retrieve
- ///
- IMemberType Get(int id);
-
- ///
- /// Gets an object by its Key
- ///
- /// Key of the to retrieve
- ///
- IMemberType Get(Guid key);
-
- ///
- /// Gets an object by its Alias
- ///
- /// Alias of the to retrieve
- ///
- IMemberType Get(string alias);
-
- ///
- /// Saves a single object
- ///
- /// to save
- /// Optional Id of the User saving the ContentType
- void Save(IMemberType memberType, int userId = 0);
-
- ///
- /// Saves a collection of objects
- ///
- /// Collection of to save
- /// Optional Id of the User saving the ContentTypes
- void Save(IEnumerable memberTypes, int userId = 0);
-
- ///
- /// Deletes a single object
- ///
- /// to delete
- /// Deleting a will delete all the objects based on this
- /// Optional Id of the User deleting the ContentType
- void Delete(IMemberType memberType, int userId = 0);
-
- ///
- /// Deletes a collection of objects
- ///
- /// Collection of to delete
- /// Deleting a will delete all the objects based on this
- /// Optional Id of the User deleting the ContentTypes
- void Delete(IEnumerable memberTypes, int userId = 0);
+ {
+ string GetDefault();
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs
index 801f88d9ac..4698ffd966 100644
--- a/src/Umbraco.Core/Services/IMembershipMemberService.cs
+++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs
@@ -131,7 +131,7 @@ namespace Umbraco.Core.Services
/// Total number of records found (out)
/// The type of match to make as . Default is
///
- IEnumerable FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
+ IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
///
/// Finds a list of objects by a partial username
@@ -143,7 +143,7 @@ namespace Umbraco.Core.Services
/// Total number of records found (out)
/// The type of match to make as . Default is
///
- IEnumerable FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
+ IEnumerable FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
///
/// Gets a list of paged objects
@@ -153,6 +153,6 @@ namespace Umbraco.Core.Services
/// Size of the page
/// Total number of records found (out)
///
- IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords);
+ IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs
index 2725d010ba..79f52d7b5c 100644
--- a/src/Umbraco.Core/Services/MediaService.cs
+++ b/src/Umbraco.Core/Services/MediaService.cs
@@ -2,12 +2,11 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Threading;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
@@ -21,218 +20,289 @@ namespace Umbraco.Core.Services
///
public class MediaService : RepositoryService, IMediaService, IMediaServiceOperations
{
-
- //Support recursive locks because some of the methods that require locking call other methods that require locking.
- //for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
- private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
private readonly IUserService _userService;
private readonly IEnumerable _urlSegmentProviders;
+ private IMediaTypeService _mediaTypeService;
- public MediaService(IDatabaseUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService, IEnumerable urlSegmentProviders)
+ #region Constructors
+
+ public MediaService(
+ IDatabaseUnitOfWorkProvider provider,
+ ILogger logger,
+ IEventMessagesFactory eventMessagesFactory,
+ IDataTypeService dataTypeService,
+ IUserService userService,
+ IEnumerable urlSegmentProviders)
: base(provider, logger, eventMessagesFactory)
{
- if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
- if (userService == null) throw new ArgumentNullException("userService");
+ if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService));
+ if (userService == null) throw new ArgumentNullException(nameof(userService));
+ if (urlSegmentProviders == null) throw new ArgumentNullException(nameof(urlSegmentProviders));
_dataTypeService = dataTypeService;
_userService = userService;
_urlSegmentProviders = urlSegmentProviders;
}
+ // don't change or remove this, will need it later
+ private IMediaTypeService MediaTypeService => _mediaTypeService;
+ //// handle circular dependencies
+ //internal IMediaTypeService MediaTypeService
+ //{
+ // get
+ // {
+ // if (_mediaTypeService == null)
+ // throw new InvalidOperationException("MediaService.MediaTypeService has not been initialized.");
+ // return _mediaTypeService;
+ // }
+ // set { _mediaTypeService = value; }
+ //}
+
+ #endregion
+
+ #region Count
+
+ public int Count(string mediaTypeAlias = null)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MediaTree);
+ var repo = uow.CreateRepository();
+ var count = repo.Count(mediaTypeAlias);
+ uow.Complete();
+ return count;
+ }
+ }
+
+ public int CountChildren(int parentId, string mediaTypeAlias = null)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MediaTree);
+ var repo = uow.CreateRepository();
+ var count = repo.CountChildren(parentId, mediaTypeAlias);
+ uow.Complete();
+ return count;
+ }
+ }
+
+ public int CountDescendants(int parentId, string mediaTypeAlias = null)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MediaTree);
+ var repo = uow.CreateRepository();
+ var count = repo.CountDescendants(parentId, mediaTypeAlias);
+ uow.Complete();
+ return count;
+ }
+ }
+
+ #endregion
+
+ #region Create
+
///
- /// Creates an object using the alias of the
- /// that this Media should based on.
+ /// Creates an object of a specified media type.
///
- ///
- /// Note that using this method will simply return a new IMedia without any identity
- /// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
- /// that does not invoke a save operation against the database.
+ /// This method simply returns a new, non-persisted, IMedia without any identity. It
+ /// is intended as a shortcut to creating new media objects that does not invoke a save
+ /// operation against the database.
///
- /// Name of the Media object
- /// Id of Parent for the new Media item
- /// Alias of the
- /// Optional id of the user creating the media item
- ///
+ /// The name of the media object.
+ /// The identifier of the parent, or -1.
+ /// The alias of the media type.
+ /// The optional id of the user creating the media.
+ /// The media object.
public IMedia CreateMedia(string name, int parentId, string mediaTypeAlias, int userId = 0)
{
- var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
+ var mediaType = GetMediaType(mediaTypeAlias);
+ if (mediaType == null)
+ throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias));
+ var parent = parentId > 0 ? GetById(parentId) : null;
+ if (parentId > 0 && parent == null)
+ throw new ArgumentException("No media with that id.", nameof(parentId));
+
var media = new Models.Media(name, parentId, mediaType);
- var parent = GetById(media.ParentId);
- media.Path = string.Concat(parent.IfNotNull(x => x.Path, media.ParentId.ToString()), ",", media.Id);
-
- if (Creating.IsRaisedEventCancelled(new NewEventArgs(media, mediaTypeAlias, parentId), this))
- {
- media.WasCancelled = true;
- return media;
- }
-
- media.CreatorId = userId;
-
- Created.RaiseEvent(new NewEventArgs(media, false, mediaTypeAlias, parentId), this);
-
- Audit(AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
+ CreateMedia(null, media, parent, userId, false);
return media;
}
///
- /// Creates an object using the alias of the
- /// that this Media should based on.
+ /// Creates an object of a specified media type, at root.
///
- ///
- /// Note that using this method will simply return a new IMedia without any identity
- /// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
- /// that does not invoke a save operation against the database.
+ /// This method simply returns a new, non-persisted, IMedia without any identity. It
+ /// is intended as a shortcut to creating new media objects that does not invoke a save
+ /// operation against the database.
///
- /// Name of the Media object
- /// Parent for the new Media item
- /// Alias of the
- /// Optional id of the user creating the media item
- ///
+ /// The name of the media object.
+ /// The alias of the media type.
+ /// The optional id of the user creating the media.
+ /// The media object.
+ public IMedia CreateMedia(string name, string mediaTypeAlias, int userId = 0)
+ {
+ // not locking since not saving anything
+
+ var mediaType = GetMediaType(mediaTypeAlias);
+ if (mediaType == null)
+ throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias));
+
+ var media = new Models.Media(name, -1, mediaType);
+ CreateMedia(null, media, null, userId, false);
+
+ return media;
+ }
+
+ ///
+ /// Creates an object of a specified media type, under a parent.
+ ///
+ /// This method simply returns a new, non-persisted, IMedia without any identity. It
+ /// is intended as a shortcut to creating new media objects that does not invoke a save
+ /// operation against the database.
+ ///
+ /// The name of the media object.
+ /// The parent media object.
+ /// The alias of the media type.
+ /// The optional id of the user creating the media.
+ /// The media object.
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
{
- if (parent == null) throw new ArgumentNullException("parent");
+ if (parent == null) throw new ArgumentNullException(nameof(parent));
- var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
- var media = new Models.Media(name, parent, mediaType);
- media.Path = string.Concat(parent.Path, ",", media.Id);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ // not locking since not saving anything
- if (Creating.IsRaisedEventCancelled(new NewEventArgs(media, mediaTypeAlias, parent), this))
+ var mediaType = GetMediaType(mediaTypeAlias);
+ if (mediaType == null)
+ throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
+
+ var media = new Models.Media(name, parent, mediaType);
+ CreateMedia(uow, media, parent, userId, false);
+
+ uow.Complete();
+ return media;
+ }
+ }
+
+ ///
+ /// Creates an object of a specified media type.
+ ///
+ /// This method returns a new, persisted, IMedia with an identity.
+ /// The name of the media object.
+ /// The identifier of the parent, or -1.
+ /// The alias of the media type.
+ /// The optional id of the user creating the media.
+ /// The media object.
+ public IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ // locking the media tree secures media types too
+ uow.WriteLock(Constants.Locks.MediaTree);
+
+ var mediaType = GetMediaType(mediaTypeAlias); // + locks
+ if (mediaType == null)
+ throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
+
+ var parent = parentId > 0 ? GetById(parentId) : null; // + locks
+ if (parentId > 0 && parent == null)
+ throw new ArgumentException("No media with that id.", nameof(parentId)); // causes rollback
+
+ var media = parentId > 0 ? new Models.Media(name, parent, mediaType) : new Models.Media(name, parentId, mediaType);
+ CreateMedia(uow, media, parent, userId, true);
+
+ uow.Complete();
+ return media;
+ }
+ }
+
+ ///
+ /// Creates an object of a specified media type, under a parent.
+ ///
+ /// This method returns a new, persisted, IMedia with an identity.
+ /// The name of the media object.
+ /// The parent media object.
+ /// The alias of the media type.
+ /// The optional id of the user creating the media.
+ /// The media object.
+ public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
+ {
+ if (parent == null) throw new ArgumentNullException(nameof(parent));
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ // locking the media tree secures media types too
+ uow.WriteLock(Constants.Locks.MediaTree);
+
+ var mediaType = GetMediaType(mediaTypeAlias); // + locks
+ if (mediaType == null)
+ throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
+
+ var media = new Models.Media(name, parent, mediaType);
+ CreateMedia(uow, media, parent, userId, true);
+
+ uow.Complete();
+ return media;
+ }
+ }
+
+ private void CreateMedia(IDatabaseUnitOfWork uow, Models.Media media, IMedia parent, int userId, bool withIdentity)
+ {
+ // NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
+ // out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
+ var newArgs = parent != null
+ ? new NewEventArgs(media, media.ContentType.Alias, parent)
+ : new NewEventArgs(media, media.ContentType.Alias, -1);
+
+ if (Creating.IsRaisedEventCancelled(newArgs, this))
{
media.WasCancelled = true;
- return media;
+ return;
}
media.CreatorId = userId;
- Created.RaiseEvent(new NewEventArgs(media, false, mediaTypeAlias, parent), this);
-
- Audit(AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
-
- return media;
- }
-
- ///
- /// Creates an object using the alias of the
- /// that this Media should based on.
- ///
- ///
- /// This method returns an object that has been persisted to the database
- /// and therefor has an identity.
- ///
- /// Name of the Media object
- /// Id of Parent for the new Media item
- /// Alias of the
- /// Optional id of the user creating the media item
- ///
- public IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0)
- {
- var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
- var media = new Models.Media(name, parentId, mediaType);
-
- //NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
- // out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
- if (Creating.IsRaisedEventCancelled(new NewEventArgs(media, mediaTypeAlias, parentId), this))
+ if (withIdentity)
{
- media.WasCancelled = true;
- return media;
- }
-
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(media), this))
- {
- media.WasCancelled = true;
- return media;
- }
-
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- media.CreatorId = userId;
- repository.AddOrUpdate(media);
-
- repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- // generate preview for blame history?
- if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
+ if (Saving.IsRaisedEventCancelled(new SaveEventArgs(media), this))
{
- repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
+ media.WasCancelled = true;
+ return;
}
- uow.Complete();
+ var repo = uow.CreateRepository();
+ repo.AddOrUpdate(media);
+ // FIXME contentXml?!
+ repo.AddOrUpdatePreviewXml(media, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, c));
+
+ Saved.RaiseEvent(new SaveEventArgs(media, false), this);
}
- Saved.RaiseEvent(new SaveEventArgs(media, false), this);
- Created.RaiseEvent(new NewEventArgs(media, false, mediaTypeAlias, parentId), this);
- Audit(AuditType.New, $"Media '{name}' was created with Id {media.Id}", media.CreatorId, media.Id);
+ Created.RaiseEvent(new NewEventArgs(media, false, media.ContentType.Alias, parent), this);
- return media;
+ var msg = withIdentity
+ ? "Media '{0}' was created with Id {1}"
+ : "Media '{0}' was created";
+ Audit(AuditType.New, string.Format(msg, media.Name, media.Id), media.CreatorId, media.Id);
}
- ///
- /// Creates an object using the alias of the
- /// that this Media should based on.
- ///
- ///
- /// This method returns an object that has been persisted to the database
- /// and therefor has an identity.
- ///
- /// Name of the Media object
- /// Parent for the new Media item
- /// Alias of the
- /// Optional id of the user creating the media item
- ///
- public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
- {
- if (parent == null) throw new ArgumentNullException("parent");
+ #endregion
- var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
- var media = new Models.Media(name, parent, mediaType);
-
- //NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
- // out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
- if (Creating.IsRaisedEventCancelled(new NewEventArgs(media, mediaTypeAlias, parent), this))
- {
- media.WasCancelled = true;
- return media;
- }
-
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(media), this))
- {
- media.WasCancelled = true;
- return media;
- }
-
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- media.CreatorId = userId;
- repository.AddOrUpdate(media);
- repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- // generate preview for blame history?
- if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
- repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- }
-
- uow.Complete();
- }
-
- Saved.RaiseEvent(new SaveEventArgs(media, false), this);
- Created.RaiseEvent(new NewEventArgs(media, false, mediaTypeAlias, parent), this);
- Audit(AuditType.New, $"Media '{name}' was created with Id {media.Id}", media.CreatorId, media.Id);
- return media;
- }
+ #region Get, Has, Is
///
/// Gets an object by Id
///
- /// Id of the Content to retrieve
+ /// Id of the Media to retrieve
///
public IMedia GetById(int id)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var media = repository.Get(id);
uow.Complete();
@@ -240,39 +310,6 @@ namespace Umbraco.Core.Services
}
}
- public int Count(string contentTypeAlias = null)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var count = repository.Count(contentTypeAlias);
- uow.Complete();
- return count;
- }
- }
-
- public int CountChildren(int parentId, string contentTypeAlias = null)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var count = repository.CountChildren(parentId, contentTypeAlias);
- uow.Complete();
- return count;
- }
- }
-
- public int CountDescendants(int parentId, string contentTypeAlias = null)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var count = repository.CountDescendants(parentId, contentTypeAlias);
- uow.Complete();
- return count;
- }
- }
-
///
/// Gets an object by Id
///
@@ -280,12 +317,14 @@ namespace Umbraco.Core.Services
///
public IEnumerable GetByIds(IEnumerable ids)
{
- if (ids.Any() == false) return Enumerable.Empty();
+ var idsA = ids.ToArray();
+ if (idsA.Length == 0) return Enumerable.Empty();
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var items = repository.GetAll(ids.ToArray());
+ var items = repository.GetAll(idsA);
uow.Complete();
return items;
}
@@ -300,11 +339,30 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.Key == key);
- var item = repository.GetByQuery(query).SingleOrDefault();
+ var media = repository.GetByQuery(query).SingleOrDefault();
uow.Complete();
- return item;
+ return media;
+ }
+ }
+
+ ///
+ /// Gets a collection of objects by the Id of the
+ ///
+ /// Id of the
+ /// An Enumerable list of objects
+ public IEnumerable GetMediaOfMediaType(int id)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query.Where(x => x.ContentTypeId == id);
+ var items = repository.GetByQuery(query);
+ uow.Complete();
+ return items;
}
}
@@ -313,15 +371,17 @@ namespace Umbraco.Core.Services
///
/// The level to retrieve Media from
/// An Enumerable list of objects
+ /// Contrary to most methods, this method filters out trashed media items.
public IEnumerable GetByLevel(int level)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.Level == level && x.Path.StartsWith("-21") == false);
- var contents = repository.GetByQuery(query);
+ var query = repository.Query.Where(x => x.Level == level && x.Trashed == false);
+ var items = repository.GetByQuery(query);
uow.Complete();
- return contents;
+ return items;
}
}
@@ -334,10 +394,11 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var item = repository.GetByVersion(versionId);
+ var media = repository.GetByVersion(versionId);
uow.Complete();
- return item;
+ return media;
}
}
@@ -350,6 +411,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var versions = repository.GetAllVersions(id);
uow.Complete();
@@ -364,6 +426,7 @@ namespace Umbraco.Core.Services
/// An Enumerable list of objects
public IEnumerable GetAncestors(int id)
{
+ // intentionnaly not locking
var media = GetById(id);
return GetAncestors(media);
}
@@ -375,16 +438,22 @@ namespace Umbraco.Core.Services
/// An Enumerable list of objects
public IEnumerable GetAncestors(IMedia media)
{
- var ids = media.Path.Split(',').Where(x => x != "-1" && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
+ //null check otherwise we get exceptions
+ if (media.Path.IsNullOrWhiteSpace()) return Enumerable.Empty();
+
+ var rootId = Constants.System.Root.ToInvariantString();
+ var ids = media.Path.Split(',')
+ .Where(x => x != rootId && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
if (ids.Any() == false)
return new List();
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var items = repository.GetAll(ids);
+ var ancestors = repository.GetAll(ids);
uow.Complete();
- return items;
+ return ancestors;
}
}
@@ -397,11 +466,12 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.ParentId == id);
- var medias = repository.GetByQuery(query);
+ var children = repository.GetByQuery(query).OrderBy(x => x.SortOrder);
uow.Complete();
- return medias;
+ return children;
}
}
@@ -415,18 +485,17 @@ namespace Umbraco.Core.Services
/// Field to order by
/// Direction to order by
/// Search text filter
- /// An Enumerable list of objects
+ /// An Enumerable list of objects
public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, string filter = "")
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- IQuery filterQuery = null;
- if (filter.IsNullOrWhiteSpace() == false)
- {
- filterQuery = repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
- }
+ var filterQuery = filter.IsNullOrWhiteSpace()
+ ? null
+ : repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery);
}
}
@@ -442,7 +511,7 @@ namespace Umbraco.Core.Services
/// Direction to order by
/// Flag to indicate when ordering by system field
///
- /// An Enumerable list of objects
+ /// An Enumerable list of objects
public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter)
{
@@ -450,18 +519,21 @@ namespace Umbraco.Core.Services
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var query = repository.Query;
+ //if the id is System Root, then just get all - NO! does not make sense!
+ //if (id != Constants.System.Root)
query.Where(x => x.ParentId == id);
- var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
+ var children = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
uow.Complete();
- return medias;
+ return children;
}
- }
+ }
///
- /// Gets a collection of objects by Parent Id
+ /// Gets a collection of objects by Parent Id
///
/// Id of the Parent to retrieve Descendants from
/// Page number
@@ -470,23 +542,22 @@ namespace Umbraco.Core.Services
/// Field to order by
/// Direction to order by
/// Search text filter
- /// An Enumerable list of objects
+ /// An Enumerable list of objects
public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- IQuery filterQuery = null;
- if (filter.IsNullOrWhiteSpace() == false)
- {
- filterQuery = repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
- }
+ var filterQuery = filter.IsNullOrWhiteSpace()
+ ? null
+ : repository.QueryFactory.Create().Where(x => x.Name.Contains(filter));
return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery);
}
}
///
- /// Gets a collection of objects by Parent Id
+ /// Gets a collection of objects by Parent Id
///
/// Id of the Parent to retrieve Descendants from
/// Page number
@@ -496,24 +567,24 @@ namespace Umbraco.Core.Services
/// Direction to order by
/// Flag to indicate when ordering by system field
///
- /// An Enumerable list of objects
+ /// An Enumerable list of objects
public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter)
{
- Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
- Mandate.ParameterCondition(pageSize > 0, "pageSize");
+ Mandate.ParameterCondition(pageIndex >= 0, nameof(pageIndex));
+ Mandate.ParameterCondition(pageSize > 0, nameof(pageSize));
+
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var query = repository.Query;
- //if the id is -1, then just get all
- if (id != -1)
- {
- query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
- }
- var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
+ //if the id is System Root, then just get all
+ if (id != Constants.System.Root)
+ query.Where(x => x.Path.SqlContains($",{id},", TextColumnType.NVarchar));
+ var descendants = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
uow.Complete();
- return contents;
+ return descendants;
}
}
@@ -524,12 +595,22 @@ namespace Umbraco.Core.Services
/// An Enumerable flat list of objects
public IEnumerable GetDescendants(int id)
{
- var media = GetById(id);
- if (media == null)
+ using (var uow = UowProvider.CreateUnitOfWork())
{
- return Enumerable.Empty();
+ uow.ReadLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+ var media = GetById(id);
+ if (media == null)
+ {
+ uow.Complete(); // else causes rollback
+ return Enumerable.Empty();
+ }
+ var pathMatch = media.Path + ",";
+ var query = repository.Query.Where(x => x.Id != media.Id && x.Path.StartsWith(pathMatch));
+ var descendants = repository.GetByQuery(query);
+ uow.Complete();
+ return descendants;
}
- return GetDescendants(media);
}
///
@@ -541,12 +622,13 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
var pathMatch = media.Path + ",";
- var query = repository.Query.Where(x => x.Path.StartsWith(pathMatch) && x.Id != media.Id);
- var medias = repository.GetByQuery(query);
+ var query = repository.Query.Where(x => x.Id != media.Id && x.Path.StartsWith(pathMatch));
+ var descendants = repository.GetByQuery(query);
uow.Complete();
- return medias;
+ return descendants;
}
}
@@ -557,6 +639,7 @@ namespace Umbraco.Core.Services
/// Parent object
public IMedia GetParent(int id)
{
+ // intentionnaly not locking
var media = GetById(id);
return GetParent(media);
}
@@ -568,29 +651,12 @@ namespace Umbraco.Core.Services
/// Parent object
public IMedia GetParent(IMedia media)
{
- if (media.ParentId == -1 || media.ParentId == -21)
+ if (media.ParentId == Constants.System.Root || media.ParentId == Constants.System.RecycleBinMedia)
return null;
return GetById(media.ParentId);
}
- ///
- /// Gets a collection of objects by the Id of the
- ///
- /// Id of the
- /// An Enumerable list of objects
- public IEnumerable GetMediaOfMediaType(int id)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.ContentTypeId == id);
- var medias = repository.GetByQuery(query);
- uow.Complete();
- return medias;
- }
- }
-
///
/// Gets a collection of objects, which reside at the first level / root
///
@@ -599,11 +665,12 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.ParentId == -1);
- var medias = repository.GetByQuery(query);
+ var query = repository.Query.Where(x => x.ParentId == Constants.System.Root);
+ var items = repository.GetByQuery(query);
uow.Complete();
- return medias;
+ return items;
}
}
@@ -615,30 +682,16 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.Path.Contains("-21"));
+ var bin = $"{Constants.System.Root},{Constants.System.RecycleBinMedia},";
+ var query = repository.Query.Where(x => x.Path.StartsWith(bin));
var medias = repository.GetByQuery(query);
uow.Complete();
return medias;
}
}
- ///
- /// Gets an object from the path stored in the 'umbracoFile' property.
- ///
- /// Path of the media item to retrieve (for example: /media/1024/koala_403x328.jpg)
- ///
- public IMedia GetMediaByPath(string mediaPath)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repo = uow.CreateRepository();
- var item = repo.GetMediaByPath(mediaPath);
- uow.Complete();
- return item;
- }
- }
-
///
/// Checks whether an item has any children
///
@@ -657,122 +710,34 @@ namespace Umbraco.Core.Services
}
///
- /// Moves an object to a new location
+ /// Gets an object from the path stored in the 'umbracoFile' property.
///
- /// The to move
- /// Id of the Media's new Parent
- /// Id of the User moving the Media
- public void Move(IMedia media, int parentId, int userId = 0)
+ /// Path of the media item to retrieve (for example: /media/1024/koala_403x328.jpg)
+ ///
+ public IMedia GetMediaByPath(string mediaPath)
{
- //TODO: This all needs to be on the repo layer in one transaction!
-
- if (media == null) throw new ArgumentNullException("media");
-
- using (new WriteLock(Locker))
- {
- //This ensures that the correct method is called if this method is used to Move to recycle bin.
- if (parentId == -21)
- {
- MoveToRecycleBin(media, userId);
- return;
- }
-
- var originalPath = media.Path;
-
- if (Moving.IsRaisedEventCancelled(
- new MoveEventArgs(
- new MoveEventInfo(media, originalPath, parentId)), this))
- {
- return;
- }
-
- media.ParentId = parentId;
- if (media.Trashed)
- {
- ((Models.Media)media).ChangeTrashedState(false, parentId);
- }
- Save(media, userId,
- //no events!
- false);
-
- //used to track all the moved entities to be given to the event
- var moveInfo = new List>
- {
- new MoveEventInfo(media, originalPath, parentId)
- };
-
- //Ensure that relevant properties are updated on children
- var children = GetChildren(media.Id).ToArray();
- if (children.Any())
- {
- var parentPath = media.Path;
- var parentLevel = media.Level;
- var parentTrashed = media.Trashed;
- var updatedDescendants = UpdatePropertiesOnChildren(children, parentPath, parentLevel, parentTrashed, moveInfo);
- Save(updatedDescendants, userId,
- //no events!
- false);
- }
-
- Moved.RaiseEvent(new MoveEventArgs(false, moveInfo.ToArray()), this);
-
- Audit(AuditType.Move, "Move Media performed by user", userId, media.Id);
- }
- }
-
- ///
- /// Deletes an object by moving it to the Recycle Bin
- ///
- /// The to delete
- /// Id of the User deleting the Media
- public void MoveToRecycleBin(IMedia media, int userId = 0)
- {
- ((IMediaServiceOperations)this).MoveToRecycleBin(media, userId);
- }
-
- ///
- /// Permanently deletes an object
- ///
- ///
- /// Please note that this method will completely remove the Media from the database,
- /// but current not from the file system.
- ///
- /// The to delete
- /// Id of the User deleting the Media
- Attempt IMediaServiceOperations.Delete(IMedia media, int userId)
- {
- //TODO: IT would be much nicer to mass delete all in one trans in the repo level!
- var evtMsgs = EventMessagesFactory.Get();
-
- if (Deleting.IsRaisedEventCancelled(
- new DeleteEventArgs(media, evtMsgs), this))
- {
- return OperationStatus.Attempt.Cancel(evtMsgs);
- }
-
- //Delete children before deleting the 'possible parent'
- var children = GetChildren(media.Id);
- foreach (var child in children)
- {
- Delete(child, userId);
- }
-
using (var uow = UowProvider.CreateUnitOfWork())
{
- var repository = uow.CreateRepository();
- repository.Delete(media);
+ var repo = uow.CreateRepository();
+ var item = repo.GetMediaByPath(mediaPath);
uow.Complete();
-
- var args = new DeleteEventArgs(media, false, evtMsgs);
- Deleted.RaiseEvent(args, this);
-
- //remove any flagged media files
- repository.DeleteMediaFiles(args.MediaFilesToDelete);
+ return item;
}
+ }
- Audit(AuditType.Delete, "Delete Media performed by user", userId, media.Id);
+ #endregion
- return OperationStatus.Attempt.Succeed(evtMsgs);
+ #region Save
+
+ ///
+ /// Saves a single object
+ ///
+ /// The to save
+ /// Id of the User saving the Media
+ /// Optional boolean indicating whether or not to raise events.
+ public void Save(IMedia media, int userId = 0, bool raiseEvents = true)
+ {
+ ((IMediaServiceOperations)this).Save(media, userId, raiseEvents);
}
///
@@ -785,28 +750,22 @@ namespace Umbraco.Core.Services
{
var evtMsgs = EventMessagesFactory.Get();
- if (raiseEvents)
- {
- if (Saving.IsRaisedEventCancelled(
- new SaveEventArgs(media, evtMsgs),
- this))
- {
- return OperationStatus.Attempt.Cancel(evtMsgs);
- }
-
- }
+ if (raiseEvents && Saving.IsRaisedEventCancelled(new SaveEventArgs(media, evtMsgs), this))
+ return OperationStatus.Attempt.Cancel(evtMsgs);
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MediaTree);
+
var repository = uow.CreateRepository();
- media.CreatorId = userId;
+ if (media.HasIdentity == false)
+ media.CreatorId = userId;
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
+
// generate preview for blame history?
if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- }
uow.Complete();
}
@@ -818,6 +777,17 @@ namespace Umbraco.Core.Services
return OperationStatus.Attempt.Succeed(evtMsgs);
}
+ ///
+ /// Saves a collection of objects
+ ///
+ /// Collection of to save
+ /// Id of the User saving the Media
+ /// Optional boolean indicating whether or not to raise events.
+ public void Save(IEnumerable medias, int userId = 0, bool raiseEvents = true)
+ {
+ ((IMediaServiceOperations) this).Save(medias, userId, raiseEvents);
+ }
+
///
/// Saves a collection of objects
///
@@ -826,191 +796,41 @@ namespace Umbraco.Core.Services
/// Optional boolean indicating whether or not to raise events.
Attempt IMediaServiceOperations.Save(IEnumerable medias, int userId, bool raiseEvents)
{
- var asArray = medias.ToArray();
var evtMsgs = EventMessagesFactory.Get();
+ var mediasA = medias.ToArray();
- if (raiseEvents)
- {
- if (Saving.IsRaisedEventCancelled(
- new SaveEventArgs(asArray, evtMsgs),
- this))
- {
- return OperationStatus.Attempt.Cancel(evtMsgs);
- }
- }
+ if (raiseEvents && Saving.IsRaisedEventCancelled(new SaveEventArgs(mediasA, evtMsgs), this))
+ return OperationStatus.Attempt.Cancel(evtMsgs);
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- foreach (var media in asArray)
+ foreach (var media in mediasA)
{
- media.CreatorId = userId;
+ if (media.HasIdentity == false)
+ media.CreatorId = userId;
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
+
// generate preview for blame history?
if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- }
}
- //commit the whole lot in one go
uow.Complete();
}
if (raiseEvents)
- Saved.RaiseEvent(new SaveEventArgs(asArray, false, evtMsgs), this);
- Audit(AuditType.Save, "Save Media items performed by user", userId, -1);
+ Saved.RaiseEvent(new SaveEventArgs(mediasA, false, evtMsgs), this);
+ Audit(AuditType.Save, "Bulk Save media performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
return OperationStatus.Attempt.Succeed(evtMsgs);
}
- ///
- /// Empties the Recycle Bin by deleting all that resides in the bin
- ///
- public void EmptyRecycleBin()
- {
- using (new WriteLock(Locker))
- {
- Dictionary> entities;
- List files;
- bool success;
- var nodeObjectType = new Guid(Constants.ObjectTypes.Media);
+ #endregion
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- //Create a dictionary of ids -> dictionary of property aliases + values
- entities = repository.GetEntitiesInRecycleBin()
- .ToDictionary(
- key => key.Id,
- val => (IEnumerable)val.Properties);
-
- files = ((MediaRepository)repository).GetFilesInRecycleBinForUploadField();
-
- if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, entities, files), this))
- return; // causes rollback
-
- success = repository.EmptyRecycleBin();
-
- EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, entities, files, success), this);
-
- if (success)
- repository.DeleteMediaFiles(files);
-
- uow.Complete();
- }
- }
- Audit(AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
- }
-
- ///
- /// Deletes all media of specified type. All children of deleted media is moved to Recycle Bin.
- ///
- /// This needs extra care and attention as its potentially a dangerous and extensive operation
- /// Id of the
- /// Optional id of the user deleting the media
- public void DeleteMediaOfType(int mediaTypeId, int userId = 0)
- {
- //TODO: This all needs to be done on the repo level in one trans
-
- using (new WriteLock(Locker))
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- //NOTE What about media that has the contenttype as part of its composition?
- //The ContentType has to be removed from the composition somehow as it would otherwise break
- //Dbl.check+test that the ContentType's Id is removed from the ContentType2ContentType table
- var query = repository.Query.Where(x => x.ContentTypeId == mediaTypeId);
- var contents = repository.GetByQuery(query).ToArray();
-
- if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(contents), this))
- return; // causes rollback
-
- foreach (var content in contents.OrderByDescending(x => x.ParentId))
- {
- //Look for children of current content and move that to trash before the current content is deleted
- var c = content;
- var childQuery = repository.Query.Where(x => x.Path.StartsWith(c.Path));
- var children = repository.GetByQuery(childQuery);
-
- foreach (var child in children)
- {
- if (child.ContentType.Id != mediaTypeId)
- MoveToRecycleBin(child, userId);
- }
-
- //Permanently delete the content
- Delete(content, userId);
- }
-
- uow.Complete();
- }
-
- Audit(AuditType.Delete, "Delete Media items by Type performed by user", userId, -1);
- }
- }
-
- ///
- /// Deletes an object by moving it to the Recycle Bin
- ///
- /// The to delete
- /// Id of the User deleting the Media
- Attempt IMediaServiceOperations.MoveToRecycleBin(IMedia media, int userId)
- {
- if (media == null) throw new ArgumentNullException("media");
-
- var originalPath = media.Path;
-
- var evtMsgs = EventMessagesFactory.Get();
-
- if (Trashing.IsRaisedEventCancelled(
- new MoveEventArgs(new MoveEventInfo(media, originalPath, Constants.System.RecycleBinMedia)), this))
- {
- return OperationStatus.Attempt.Cancel(evtMsgs);
- }
-
- var moveInfo = new List>
- {
- new MoveEventInfo(media, originalPath, Constants.System.RecycleBinMedia)
- };
-
- //Find Descendants, which will be moved to the recycle bin along with the parent/grandparent.
- var descendants = GetDescendants(media).OrderBy(x => x.Level).ToList();
-
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- //TODO: This should be part of the repo!
-
- //Remove 'published' xml from the cmsContentXml table for the unpublished media
- uow.Database.Delete("WHERE nodeId = @Id", new { Id = media.Id });
-
- ((Models.Media)media).ChangeTrashedState(true, Constants.System.RecycleBinMedia);
- repository.AddOrUpdate(media);
-
- //Loop through descendants to update their trash state, but ensuring structure by keeping the ParentId
- foreach (var descendant in descendants)
- {
- //Remove 'published' xml from the cmsContentXml table for the unpublished media
- uow.Database.Delete("WHERE nodeId = @Id", new { Id = descendant.Id });
-
- ((Models.Media)descendant).ChangeTrashedState(true, descendant.ParentId);
- repository.AddOrUpdate(descendant);
-
- moveInfo.Add(new MoveEventInfo(descendant, descendant.Path, descendant.ParentId));
- }
-
- uow.Complete();
- }
-
- Trashed.RaiseEvent(
- new MoveEventArgs(false, evtMsgs, moveInfo.ToArray()), this);
- Audit(AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
-
- return OperationStatus.Attempt.Succeed(evtMsgs);
- }
+ #region Delete
///
/// Permanently deletes an object as well as all of its Children.
@@ -1023,18 +843,83 @@ namespace Umbraco.Core.Services
/// Id of the User deleting the Media
public void Delete(IMedia media, int userId = 0)
{
- ((IMediaServiceOperations)this).Delete(media, userId);
+ ((IMediaServiceOperations) this).Delete(media, userId);
}
+ ///
+ /// Permanently deletes an object
+ ///
+ ///
+ /// Please note that this method will completely remove the Media from the database,
+ /// but current not from the file system.
+ /// FIXME uh?
+ ///
+ /// The to delete
+ /// Id of the User deleting the Media
+ Attempt IMediaServiceOperations.Delete(IMedia media, int userId)
+ {
+ var evtMsgs = EventMessagesFactory.Get();
+ if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(media, evtMsgs), this))
+ return OperationStatus.Attempt.Cancel(evtMsgs);
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+
+ DeleteLocked(repository, media);
+ uow.Complete();
+ }
+
+ Audit(AuditType.Delete, "Delete Media performed by user", userId, media.Id);
+
+ return OperationStatus.Attempt.Succeed(evtMsgs);
+ }
+
+ private void DeleteLocked(IMediaRepository repository, IMedia media)
+ {
+ // then recursively delete descendants, bottom-up
+ // just repository.Delete + an event
+ var stack = new Stack();
+ stack.Push(media);
+ var level = 1;
+ while (stack.Count > 0)
+ {
+ var c = stack.Peek();
+ IMedia[] cc;
+ if (c.Level == level)
+ while ((cc = c.Children().ToArray()).Length > 0)
+ {
+ foreach (var ci in cc)
+ stack.Push(ci);
+ c = cc[cc.Length - 1];
+ }
+ c = stack.Pop();
+ level = c.Level;
+
+ repository.Delete(c);
+ var args = new DeleteEventArgs(c, false); // raise event & get flagged files
+ Deleted.RaiseEvent(args, this);
+
+ IOHelper.DeleteFiles(args.MediaFilesToDelete, // remove flagged files
+ (file, e) => Logger.Error("An error occurred while deleting file attached to nodes: " + file, e));
+ }
+ }
+
+ //TODO:
+ // both DeleteVersions methods below have an issue. Sort of. They do NOT take care of files the way
+ // Delete does - for a good reason: the file may be referenced by other, non-deleted, versions. BUT,
+ // if that's not the case, then the file will never be deleted, because when we delete the media,
+ // the version referencing the file will not be there anymore. SO, we can leak files.
///
/// Permanently deletes versions from an object prior to a specific date.
- /// This method will never delete the latest version of a content item.
+ /// This method will never delete the latest version of a media item.
///
/// Id of the object to delete versions from
/// Latest version date
- /// Optional Id of the User deleting versions of a Content object
+ /// Optional Id of the User deleting versions of a Media object
public void DeleteVersions(int id, DateTime versionDate, int userId = 0)
{
if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, dateToRetain: versionDate), this))
@@ -1042,67 +927,233 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
repository.DeleteVersions(id, versionDate);
uow.Complete();
}
DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate), this);
- Audit(AuditType.Delete, "Delete Media by version date performed by user", userId, -1);
+
+ Audit(AuditType.Delete, "Delete Media by version date performed by user", userId, Constants.System.Root);
}
///
/// Permanently deletes specific version(s) from an object.
- /// This method will never delete the latest version of a content item.
+ /// This method will never delete the latest version of a media item.
///
/// Id of the object to delete a version from
/// Id of the version to delete
/// Boolean indicating whether to delete versions prior to the versionId
- /// Optional Id of the User deleting versions of a Content object
+ /// Optional Id of the User deleting versions of a Media object
public void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = 0)
{
- if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, specificVersion: versionId), this))
+ if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, /*specificVersion:*/ versionId), this))
return;
if (deletePriorVersions)
{
- var content = GetByVersion(versionId);
- DeleteVersions(id, content.UpdateDate, userId);
+ var media = GetByVersion(versionId);
+ DeleteVersions(id, media.UpdateDate, userId);
}
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
repository.DeleteVersion(versionId);
uow.Complete();
}
- DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, specificVersion: versionId), this);
- Audit(AuditType.Delete, "Delete Media by version performed by user", userId, -1);
+ DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, /*specificVersion:*/ versionId), this);
+ Audit(AuditType.Delete, "Delete Media by version performed by user", userId, Constants.System.Root);
+ }
+
+ #endregion
+
+ #region Move, RecycleBin
+
+ ///
+ /// Deletes an object by moving it to the Recycle Bin
+ ///
+ /// The to delete
+ /// Id of the User deleting the Media
+ public void MoveToRecycleBin(IMedia media, int userId = 0)
+ {
+ ((IMediaServiceOperations) this).MoveToRecycleBin(media, userId);
}
///
- /// Saves a single object
+ /// Deletes an object by moving it to the Recycle Bin
///
- /// The to save
- /// Id of the User saving the Content
- /// Optional boolean indicating whether or not to raise events.
- public void Save(IMedia media, int userId = 0, bool raiseEvents = true)
+ /// The to delete
+ /// Id of the User deleting the Media
+ Attempt IMediaServiceOperations.MoveToRecycleBin(IMedia media, int userId)
{
- ((IMediaServiceOperations)this).Save(media, userId, raiseEvents);
+ var evtMsgs = EventMessagesFactory.Get();
+ var moves = new List>();
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+
+ var originalPath = media.Path;
+ if (Trashing.IsRaisedEventCancelled(new MoveEventArgs(new MoveEventInfo(media, originalPath, Constants.System.RecycleBinMedia)), this))
+ return OperationStatus.Attempt.Cancel(evtMsgs); // causes rollback
+
+ PerformMoveLocked(repository, media, Constants.System.RecycleBinMedia, null, userId, moves, true);
+ uow.Complete();
+ }
+
+ var moveInfo = moves
+ .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId))
+ .ToArray();
+
+ Trashed.RaiseEvent(new MoveEventArgs(false, evtMsgs, moveInfo), this);
+ Audit(AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
+
+ return OperationStatus.Attempt.Succeed(evtMsgs);
}
///
- /// Saves a collection of objects
+ /// Moves an object to a new location
///
- /// Collection of to save
- /// Id of the User saving the Content
- /// Optional boolean indicating whether or not to raise events.
- public void Save(IEnumerable medias, int userId = 0, bool raiseEvents = true)
+ /// The to move
+ /// Id of the Media's new Parent
+ /// Id of the User moving the Media
+ public void Move(IMedia media, int parentId, int userId = 0)
{
- ((IMediaServiceOperations)this).Save(medias, userId, raiseEvents);
+ // if moving to the recycle bin then use the proper method
+ if (parentId == Constants.System.RecycleBinMedia)
+ {
+ MoveToRecycleBin(media, userId);
+ return;
+ }
+
+ var moves = new List>();
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+
+ var parent = parentId == Constants.System.Root ? null : GetById(parentId);
+ if (parentId != Constants.System.Root && (parent == null || parent.Trashed))
+ throw new InvalidOperationException("Parent does not exist or is trashed."); // causes rollback
+
+ if (Moving.IsRaisedEventCancelled(new MoveEventArgs(new MoveEventInfo(media, media.Path, parentId)), this))
+ return; // causes rollback
+
+ // if media was trashed, and since we're not moving to the recycle bin,
+ // indicate that the trashed status should be changed to false, else just
+ // leave it unchanged
+ var trashed = media.Trashed ? false : (bool?)null;
+
+ PerformMoveLocked(repository, media, parentId, parent, userId, moves, trashed);
+
+ uow.Complete();
+ }
+
+ var moveInfo = moves //changes
+ .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId))
+ .ToArray();
+
+ Moved.RaiseEvent(new MoveEventArgs(false, moveInfo), this);
+
+ Audit(AuditType.Move, "Move Media performed by user", userId, media.Id);
}
+ // MUST be called from within WriteLock
+ // trash indicates whether we are trashing, un-trashing, or not changing anything
+ private void PerformMoveLocked(IMediaRepository repository,
+ IMedia media, int parentId, IMedia parent, int userId,
+ ICollection> moves,
+ bool? trash)
+ {
+ media.ParentId = parentId;
+
+ // get the level delta (old pos to new pos)
+ var levelDelta = parent == null
+ ? 1 - media.Level + (parentId == Constants.System.RecycleBinMedia ? 1 : 0)
+ : parent.Level + 1 - media.Level;
+
+ var paths = new Dictionary();
+
+ moves.Add(Tuple.Create(media, media.Path)); // capture original path
+
+ // these will be updated by the repo because we changed parentId
+ //media.Path = (parent == null ? "-1" : parent.Path) + "," + media.Id;
+ //media.SortOrder = ((MediaRepository) repository).NextChildSortOrder(parentId);
+ //media.Level += levelDelta;
+ PerformMoveMediaLocked(repository, media, userId, trash);
+
+ // BUT media.Path will be updated only when the UOW commits, and
+ // because we want it now, we have to calculate it by ourselves
+ //paths[media.Id] = media.Path;
+ paths[media.Id] = (parent == null ? (parentId == Constants.System.RecycleBinMedia ? "-1,-21" : "-1") : parent.Path) + "," + media.Id;
+
+ var descendants = GetDescendants(media);
+ foreach (var descendant in descendants)
+ {
+ moves.Add(Tuple.Create(descendant, descendant.Path)); // capture original path
+
+ // update path and level since we do not update parentId
+ descendant.Path = paths[descendant.Id] = paths[descendant.ParentId] + "," + descendant.Id;
+ descendant.Level += levelDelta;
+ PerformMoveMediaLocked(repository, descendant, userId, trash);
+ }
+ }
+
+ private static void PerformMoveMediaLocked(IMediaRepository repository, IMedia media, int userId,
+ bool? trash)
+ {
+ if (trash.HasValue) ((ContentBase) media).Trashed = trash.Value;
+ repository.AddOrUpdate(media);
+ }
+
+ ///
+ /// Empties the Recycle Bin by deleting all that resides in the bin
+ ///
+ public void EmptyRecycleBin()
+ {
+ var nodeObjectType = new Guid(Constants.ObjectTypes.Media);
+ var deleted = new List();
+ var evtMsgs = EventMessagesFactory.Get(); // todo - and then?
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+
+ // v7 EmptyingRecycleBin and EmptiedRecycleBin events are greatly simplified since
+ // each deleted items will have its own deleting/deleted events. so, files and such
+ // are managed by Delete, and not here.
+
+ // no idea what those events are for, keep a simplified version
+ if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType), this))
+ return; // causes rollback
+
+ // emptying the recycle bin means deleting whetever is in there - do it properly!
+ var query = repository.Query.Where(x => x.ParentId == Constants.System.RecycleBinMedia);
+ var medias = repository.GetByQuery(query).ToArray();
+ foreach (var media in medias)
+ {
+ DeleteLocked(repository, media);
+ deleted.Add(media);
+ }
+
+ EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, true), this);
+ uow.Complete();
+ }
+
+ Audit(AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, Constants.System.RecycleBinMedia);
+ }
+
+ #endregion
+
+ #region Others
+
///
/// Sorts a collection of objects by updating the SortOrder according
/// to the ordering of items in the passed in .
@@ -1113,138 +1164,55 @@ namespace Umbraco.Core.Services
/// True if sorting succeeded, otherwise False
public bool Sort(IEnumerable items, int userId = 0, bool raiseEvents = true)
{
- var asArray = items.ToArray();
+ var itemsA = items.ToArray();
+ if (itemsA.Length == 0) return true;
- if (raiseEvents)
- {
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(asArray), this))
+ if (raiseEvents && Saving.IsRaisedEventCancelled(new SaveEventArgs(itemsA), this))
return false;
- }
+
+ var saved = new List();
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MediaTree);
var repository = uow.CreateRepository();
- int i = 0;
- foreach (var media in asArray)
+ var sortOrder = 0;
+
+ foreach (var media in itemsA)
{
- //If the current sort order equals that of the media
- //we don't need to update it, so just increment the sort order
- //and continue.
- if (media.SortOrder == i)
+ // if the current sort order equals that of the media we don't
+ // need to update it, so just increment the sort order and continue.
+ if (media.SortOrder == sortOrder)
{
- i++;
+ sortOrder++;
continue;
}
- media.SortOrder = i;
- i++;
-
+ // else update
+ media.SortOrder = sortOrder++;
+ // save
+ saved.Add(media);
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
+
// generate preview for blame history?
if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, m));
- }
}
uow.Complete();
}
if (raiseEvents)
- Saved.RaiseEvent(new SaveEventArgs(asArray, false), this);
+ Saved.RaiseEvent(new SaveEventArgs(saved, false), this);
Audit(AuditType.Sort, "Sorting Media performed by user", userId, 0);
return true;
}
- ///
- /// Rebuilds all xml content in the cmsContentXml table for all media
- ///
- ///
- /// Only rebuild the xml structures for the content type ids passed in, if none then rebuilds the structures
- /// for all media
- ///
- public void RebuildXmlStructures(params int[] contentTypeIds)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- repository.RebuildXmlStructures(
- media => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, media),
- contentTypeIds: contentTypeIds.Length == 0 ? null : contentTypeIds);
- uow.Complete();
- }
+ #endregion
- Audit(AuditType.Publish, "MediaService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
- }
-
- ///
- /// Updates the Path and Level on a collection of objects
- /// based on the Parent's Path and Level. Also change the trashed state if relevant.
- ///
- /// Collection of objects to update
- /// Path of the Parent media
- /// Level of the Parent media
- /// Indicates whether the Parent is trashed or not
- /// Used to track the objects to be used in the move event
- /// Collection of updated objects
- private IEnumerable UpdatePropertiesOnChildren(IEnumerable children, string parentPath, int parentLevel, bool parentTrashed, ICollection> eventInfo)
- {
- var list = new List();
- foreach (var child in children)
- {
- var originalPath = child.Path;
- child.Path = string.Concat(parentPath, ",", child.Id);
- child.Level = parentLevel + 1;
- if (parentTrashed != child.Trashed)
- {
- ((Models.Media)child).ChangeTrashedState(parentTrashed, child.ParentId);
- }
-
- eventInfo.Add(new MoveEventInfo(child, originalPath, child.ParentId));
- list.Add(child);
-
- var grandkids = GetChildren(child.Id).ToArray();
- if (grandkids.Any())
- {
- list.AddRange(UpdatePropertiesOnChildren(grandkids, child.Path, child.Level, child.Trashed, eventInfo));
- }
- }
- return list;
- }
-
- //private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
- //{
- // var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToDataString() };
- // var exists = db.FirstOrDefault("WHERE nodeId = @Id", new { Id = id }) != null;
- // int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
- //}
-
- private IMediaType FindMediaTypeByAlias(string mediaTypeAlias)
- {
- Mandate.ParameterNotNullOrEmpty(mediaTypeAlias, "mediaTypeAlias");
-
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.QueryFactory.Create().Where(x => x.Alias == mediaTypeAlias);
- var mediaTypes = repository.GetByQuery(query);
-
- if (mediaTypes.Any() == false)
- throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
- mediaTypeAlias)); // causes rollback
-
- var mediaType = mediaTypes.First();
-
- if (mediaType == null)
- throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
- mediaTypeAlias)); // causes rollback
-
- uow.Complete();
- return mediaType;
- }
- }
+ #region Private Methods
private void Audit(AuditType type, string message, int userId, int objectId)
{
@@ -1256,18 +1224,10 @@ namespace Umbraco.Core.Services
}
}
+ #endregion
+
#region Event Handlers
- ///
- /// Occurs before Delete
- ///
- public static event TypedEventHandler DeletingVersions;
-
- ///
- /// Occurs after Delete
- ///
- public static event TypedEventHandler DeletedVersions;
-
///
/// Occurs before Delete
///
@@ -1278,6 +1238,16 @@ namespace Umbraco.Core.Services
///
public static event TypedEventHandler> Deleted;
+ ///
+ /// Occurs before Delete Versions
+ ///
+ public static event TypedEventHandler DeletingVersions;
+
+ ///
+ /// Occurs after Delete Versions
+ ///
+ public static event TypedEventHandler DeletedVersions;
+
///
/// Occurs before Save
///
@@ -1298,18 +1268,18 @@ namespace Umbraco.Core.Services
/// Occurs after Create
///
///
- /// Please note that the Media object has been created, but not saved
+ /// Please note that the Media object has been created, but might not have been saved
/// so it does not have an identity yet (meaning no Id has been set).
///
public static event TypedEventHandler> Created;
///
- /// Occurs before Content is moved to Recycle Bin
+ /// Occurs before Media is moved to Recycle Bin
///
public static event TypedEventHandler> Trashing;
///
- /// Occurs after Content is moved to Recycle Bin
+ /// Occurs after Media is moved to Recycle Bin
///
public static event TypedEventHandler> Trashed;
@@ -1332,6 +1302,117 @@ namespace Umbraco.Core.Services
/// Occurs after the Recycle Bin has been Emptied
///
public static event TypedEventHandler EmptiedRecycleBin;
+
+ #endregion
+
+ #region Content Types
+
+ ///
+ /// Deletes all media of specified type. All children of deleted media is moved to Recycle Bin.
+ ///
+ /// This needs extra care and attention as its potentially a dangerous and extensive operation
+ /// Id of the
+ /// Optional id of the user deleting the media
+ public void DeleteMediaOfType(int mediaTypeId, int userId = 0)
+ {
+ //TODO: This currently this is called from the ContentTypeService but that needs to change,
+ // if we are deleting a content type, we should just delete the data and do this operation slightly differently.
+ // This method will recursively go lookup every content item, check if any of it's descendants are
+ // of a different type, move them to the recycle bin, then permanently delete the content items.
+ // The main problem with this is that for every content item being deleted, events are raised...
+ // which we need for many things like keeping caches in sync, but we can surely do this MUCH better.
+
+ var moves = new List>();
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+
+ // fixme what about media that has the contenttype as part of its composition?
+ var query = repository.Query.Where(x => x.ContentTypeId == mediaTypeId);
+ var medias = repository.GetByQuery(query).ToArray();
+
+ if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(medias), this))
+ return; // causes rollback
+
+ // order by level, descending, so deepest first - that way, we cannot move
+ // a media of the deleted type, to the recycle bin (and then delete it...)
+ foreach (var media in medias.OrderByDescending(x => x.ParentId))
+ {
+ // if current media has children, move them to trash
+ var m = media;
+ var childQuery = repository.Query.Where(x => x.Path.StartsWith(m.Path));
+ var children = repository.GetByQuery(childQuery);
+ foreach (var child in children.Where(x => x.ContentTypeId != mediaTypeId))
+ {
+ // see MoveToRecycleBin
+ PerformMoveLocked(repository, child, Constants.System.RecycleBinMedia, null, userId, moves, true);
+ }
+
+ // delete media
+ // triggers the deleted event (and handles the files)
+ DeleteLocked(repository, media);
+ }
+
+ uow.Complete();
+ }
+
+ var moveInfos = moves
+ .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId))
+ .ToArray();
+ if (moveInfos.Length > 0)
+ Trashed.RaiseEvent(new MoveEventArgs(false, moveInfos), this);
+
+ Audit(AuditType.Delete, $"Delete Media of Type {mediaTypeId} performed by user", userId, Constants.System.Root);
+ }
+
+ private IMediaType GetMediaType(string mediaTypeAlias)
+ {
+ Mandate.ParameterNotNullOrEmpty(mediaTypeAlias, nameof(mediaTypeAlias));
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MediaTree);
+
+ var repository = uow.CreateRepository();
+ var query = repository.Query.Where(x => x.Alias == mediaTypeAlias);
+ var mediaType = repository.GetByQuery(query).FirstOrDefault();
+
+ if (mediaType == null)
+ throw new Exception($"No MediaType matching the passed in Alias: '{mediaTypeAlias}' was found"); // causes rollback
+
+ uow.Complete();
+ return mediaType;
+ }
+ }
+
+ #endregion
+
+ #region Xml - Should Move!
+
+ ///
+ /// Rebuilds all xml content in the cmsContentXml table for all media
+ ///
+ ///
+ /// Only rebuild the xml structures for the content type ids passed in, if none then rebuilds the structures
+ /// for all media
+ ///
+ public void RebuildXmlStructures(params int[] contentTypeIds)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+ var repository = uow.CreateRepository();
+ repository.RebuildXmlStructures(
+ media => _entitySerializer.Serialize(this, _dataTypeService, _userService, _urlSegmentProviders, media),
+ contentTypeIds: contentTypeIds.Length == 0 ? null : contentTypeIds);
+ uow.Complete();
+ }
+
+ Audit(AuditType.Publish, "MediaService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
+ }
+
#endregion
}
}
diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs
index b89e7bffef..46aea609da 100644
--- a/src/Umbraco.Core/Services/MemberService.cs
+++ b/src/Umbraco.Core/Services/MemberService.cs
@@ -1,21 +1,16 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
-using System.Threading;
using System.Web.Security;
-using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Models.Rdbms;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
-using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using System.Linq;
+using Umbraco.Core.IO;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Security;
@@ -26,634 +21,44 @@ namespace Umbraco.Core.Services
///
public class MemberService : RepositoryService, IMemberService
{
- private readonly IMemberGroupService _memberGroupService;
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
- private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
+ private readonly IMemberGroupService _memberGroupService;
+ private IMemberTypeService _memberTypeService;
- public MemberService(IDatabaseUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, IDataTypeService dataTypeService)
+ #region Constructor
+
+ public MemberService(
+ IDatabaseUnitOfWorkProvider provider,
+ ILogger logger,
+ IEventMessagesFactory eventMessagesFactory,
+ IMemberGroupService memberGroupService,
+ IDataTypeService dataTypeService)
: base(provider, logger, eventMessagesFactory)
{
- if (memberGroupService == null) throw new ArgumentNullException("memberGroupService");
- if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
+ if (memberGroupService == null) throw new ArgumentNullException(nameof(memberGroupService));
+ if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService));
_memberGroupService = memberGroupService;
_dataTypeService = dataTypeService;
}
- #region IMemberService Implementation
-
- ///
- /// Gets the default MemberType alias
- ///
- /// By default we'll return the 'writer', but we need to check it exists. If it doesn't we'll
- /// return the first type that is not an admin, otherwise if there's only one we will return that one.
- /// Alias of the default MemberType
- public string GetDefaultMemberType()
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var types = repository.GetAll(new int[] { }).Select(x => x.Alias).ToArray();
-
- if (types.Any() == false)
- {
- throw new InvalidOperationException("No member types could be resolved"); // causes rollback
- }
- uow.Complete();
- if (types.InvariantContains("Member"))
- {
- return types.First(x => x.InvariantEquals("Member"));
- }
-
- return types.First();
- }
- }
-
- ///
- /// Checks if a Member with the username exists
- ///
- /// Username to check
- /// True if the Member exists otherwise False
- public bool Exists(string username)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var exists = repository.Exists(username);
- uow.Complete();
- return exists;
- }
- }
-
- ///
- /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
- ///
- /// This method exists so that Umbraco developers can use one entry point to create/update
- /// Members if they choose to.
- /// The Member to save the password for
- /// The password to encrypt and save
- public void SavePassword(IMember member, string password)
- {
- if (member == null) throw new ArgumentNullException("member");
-
- var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
- if (provider.IsUmbracoMembershipProvider())
- {
- provider.ChangePassword(member.Username, "", password);
- }
- else
- {
- throw new NotSupportedException("When using a non-Umbraco membership provider you must change the member password by using the MembershipProvider.ChangePassword method");
- }
-
- //go re-fetch the member and update the properties that may have changed
- var result = GetByUsername(member.Username);
-
- //should never be null but it could have been deleted by another thread.
- if (result == null)
- return;
-
- member.RawPasswordValue = result.RawPasswordValue;
- member.LastPasswordChangeDate = result.LastPasswordChangeDate;
- member.UpdateDate = result.UpdateDate;
- }
-
- ///
- /// Checks if a Member with the id exists
- ///
- /// Id of the Member
- /// True if the Member exists otherwise False
- public bool Exists(int id)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var exists = repository.Exists(id);
- uow.Complete();
- return exists;
- }
- }
-
- ///
- /// Gets a Member by its integer id
- ///
- /// Id
- ///
- public IMember GetById(int id)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var member = repository.Get(id);
- uow.Complete();
- return member;
- }
- }
-
- ///
- /// Gets a Member by the unique key
- ///
- /// The guid key corresponds to the unique id in the database
- /// and the user id in the membership provider.
- /// Id
- ///
- public IMember GetByKey(Guid id)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.Key == id);
- var member = repository.GetByQuery(query).FirstOrDefault();
- uow.Complete();
- return member;
- }
- }
-
- ///
- /// Gets all Members for the specified MemberType alias
- ///
- /// Alias of the MemberType
- ///
- public IEnumerable GetMembersByMemberType(string memberTypeAlias)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query.Where(x => x.ContentTypeAlias == memberTypeAlias);
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets all Members for the MemberType id
- ///
- /// Id of the MemberType
- ///
- public IEnumerable GetMembersByMemberType(int memberTypeId)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- repository.Get(memberTypeId);
- var query = repository.Query.Where(x => x.ContentTypeId == memberTypeId);
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets all Members within the specified MemberGroup name
- ///
- /// Name of the MemberGroup
- ///
- public IEnumerable GetMembersByGroup(string memberGroupName)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var members = repository.GetByMemberGroup(memberGroupName);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets all Members with the ids specified
- ///
- /// If no Ids are specified all Members will be retrieved
- /// Optional list of Member Ids
- ///
- public IEnumerable GetAllMembers(params int[] ids)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var members = repository.GetAll(ids);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Delete Members of the specified MemberType id
- ///
- /// Id of the MemberType
- public void DeleteMembersOfType(int memberTypeId)
- {
- using (new WriteLock(Locker))
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- //TODO: What about content that has the contenttype as part of its composition?
- var query = repository.Query.Where(x => x.ContentTypeId == memberTypeId);
- var members = repository.GetByQuery(query).ToArray();
-
- if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(members), this))
- return; // causes rollback
-
- foreach (var member in members)
- {
- //Permantly delete the member
- Delete(member);
- }
-
- uow.Complete();
- }
- }
- }
-
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public IEnumerable FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- long total;
- var result = FindMembersByDisplayName(displayNameToMatch, Convert.ToInt64(pageIndex), pageSize, out total, matchType);
- totalRecords = Convert.ToInt32(total);
- return result;
- }
-
- ///
- /// Finds Members based on their display name
- ///
- /// Display name to match
- /// Current page index
- /// Size of the page
- /// Total number of records found (out)
- /// The type of match to make as . Default is
- ///
- public IEnumerable FindMembersByDisplayName(string displayNameToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query;
-
- switch (matchType)
- {
- case StringPropertyMatchType.Exact:
- query.Where(member => member.Name.Equals(displayNameToMatch));
- break;
- case StringPropertyMatchType.Contains:
- query.Where(member => member.Name.Contains(displayNameToMatch));
- break;
- case StringPropertyMatchType.StartsWith:
- query.Where(member => member.Name.StartsWith(displayNameToMatch));
- break;
- case StringPropertyMatchType.EndsWith:
- query.Where(member => member.Name.EndsWith(displayNameToMatch));
- break;
- case StringPropertyMatchType.Wildcard:
- query.Where(member => member.Name.SqlWildcard(displayNameToMatch, TextColumnType.NVarchar));
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType"); // causes rollback
- }
-
- var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending, true);
- uow.Complete();
- return members;
- }
- }
-
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public IEnumerable FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- long total;
- var result = FindByEmail(emailStringToMatch, Convert.ToInt64(pageIndex), pageSize, out total, matchType);
- totalRecords = Convert.ToInt32(total);
- return result;
- }
-
- ///
- /// Finds a list of objects by a partial email string
- ///
- /// Partial email string to match
- /// Current page index
- /// Size of the page
- /// Total number of records found (out)
- /// The type of match to make as . Default is
- ///
- public IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query;
-
- switch (matchType)
- {
- case StringPropertyMatchType.Exact:
- query.Where(member => member.Email.Equals(emailStringToMatch));
- break;
- case StringPropertyMatchType.Contains:
- query.Where(member => member.Email.Contains(emailStringToMatch));
- break;
- case StringPropertyMatchType.StartsWith:
- query.Where(member => member.Email.StartsWith(emailStringToMatch));
- break;
- case StringPropertyMatchType.EndsWith:
- query.Where(member => member.Email.EndsWith(emailStringToMatch));
- break;
- case StringPropertyMatchType.Wildcard:
- query.Where(member => member.Email.SqlWildcard(emailStringToMatch, TextColumnType.NVarchar));
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType");
- }
-
- var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending, true);
- uow.Complete();
- return members;
- }
- }
-
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public IEnumerable FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- long total;
- var result = FindByUsername(login, Convert.ToInt64(pageIndex), pageSize, out total, matchType);
- totalRecords = Convert.ToInt32(total);
- return result;
- }
-
- ///
- /// Finds a list of objects by a partial username
- ///
- /// Partial username to match
- /// Current page index
- /// Size of the page
- /// Total number of records found (out)
- /// The type of match to make as . Default is
- ///
- public IEnumerable FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.Query;
-
- switch (matchType)
- {
- case StringPropertyMatchType.Exact:
- query.Where(member => member.Username.Equals(login));
- break;
- case StringPropertyMatchType.Contains:
- query.Where(member => member.Username.Contains(login));
- break;
- case StringPropertyMatchType.StartsWith:
- query.Where(member => member.Username.StartsWith(login));
- break;
- case StringPropertyMatchType.EndsWith:
- query.Where(member => member.Username.EndsWith(login));
- break;
- case StringPropertyMatchType.Wildcard:
- query.Where(member => member.Email.SqlWildcard(login, TextColumnType.NVarchar));
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType");
- }
-
- var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets a list of Members based on a property search
- ///
- /// Alias of the PropertyType to search for
- /// Value to match
- /// The type of match to make as . Default is
- ///
- public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, string value, StringPropertyMatchType matchType = StringPropertyMatchType.Exact)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- IQuery query;
-
- switch (matchType)
- {
- case StringPropertyMatchType.Exact:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- (((Member)x).LongStringPropertyValue.SqlEquals(value, TextColumnType.NText) ||
- ((Member)x).ShortStringPropertyValue.SqlEquals(value, TextColumnType.NVarchar)));
- break;
- case StringPropertyMatchType.Contains:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- (((Member)x).LongStringPropertyValue.SqlContains(value, TextColumnType.NText) ||
- ((Member)x).ShortStringPropertyValue.SqlContains(value, TextColumnType.NVarchar)));
- break;
- case StringPropertyMatchType.StartsWith:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- (((Member)x).LongStringPropertyValue.SqlStartsWith(value, TextColumnType.NText) ||
- ((Member)x).ShortStringPropertyValue.SqlStartsWith(value, TextColumnType.NVarchar)));
- break;
- case StringPropertyMatchType.EndsWith:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- (((Member)x).LongStringPropertyValue.SqlEndsWith(value, TextColumnType.NText) ||
- ((Member)x).ShortStringPropertyValue.SqlEndsWith(value, TextColumnType.NVarchar)));
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType"); // causes rollback
- }
-
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets a list of Members based on a property search
- ///
- /// Alias of the PropertyType to search for
- /// Value to match
- /// The type of match to make as . Default is
- ///
- public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, int value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- IQuery query;
-
- switch (matchType)
- {
- case ValuePropertyMatchType.Exact:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).IntegerPropertyValue == value);
- break;
- case ValuePropertyMatchType.GreaterThan:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).IntegerPropertyValue > value);
- break;
- case ValuePropertyMatchType.LessThan:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).IntegerPropertyValue < value);
- break;
- case ValuePropertyMatchType.GreaterThanOrEqualTo:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).IntegerPropertyValue >= value);
- break;
- case ValuePropertyMatchType.LessThanOrEqualTo:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).IntegerPropertyValue <= value);
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType"); // causes rollback
- }
-
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets a list of Members based on a property search
- ///
- /// Alias of the PropertyType to search for
- /// Value to match
- ///
- public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, bool value)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).BoolPropertyValue == value);
-
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Gets a list of Members based on a property search
- ///
- /// Alias of the PropertyType to search for
- /// Value to match
- /// The type of match to make as . Default is
- ///
- public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, DateTime value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- IQuery query;
-
- switch (matchType)
- {
- case ValuePropertyMatchType.Exact:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).DateTimePropertyValue == value);
- break;
- case ValuePropertyMatchType.GreaterThan:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).DateTimePropertyValue > value);
- break;
- case ValuePropertyMatchType.LessThan:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).DateTimePropertyValue < value);
- break;
- case ValuePropertyMatchType.GreaterThanOrEqualTo:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).DateTimePropertyValue >= value);
- break;
- case ValuePropertyMatchType.LessThanOrEqualTo:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
- ((Member)x).DateTimePropertyValue <= value);
- break;
- default:
- throw new ArgumentOutOfRangeException("matchType"); // causes rollback
- }
-
- //TODO: Since this is by property value, we need a GetByPropertyQuery on the repo!
- var members = repository.GetByQuery(query);
- uow.Complete();
- return members;
- }
- }
-
- ///
- /// Rebuilds all xml content in the cmsContentXml table for all members
- ///
- ///
- /// Only rebuild the xml structures for the content type ids passed in, if none then rebuilds the structures
- /// for all members = USE WITH CARE!
- ///
- /// True if publishing succeeded, otherwise False
- public void RebuildXmlStructures(params int[] memberTypeIds)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- repository.RebuildXmlStructures(
- member => _entitySerializer.Serialize(_dataTypeService, member),
- contentTypeIds: memberTypeIds.Length == 0 ? null : memberTypeIds);
- uow.Complete();
- }
-
- Audit(AuditType.Publish, "MemberService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
- }
+ // don't change or remove this, will need it later
+ private IMemberTypeService MemberTypeService => _memberTypeService;
+ //// handle circular dependencies
+ //internal IMemberTypeService MemberTypeService
+ //{
+ // get
+ // {
+ // if (_memberTypeService == null)
+ // throw new InvalidOperationException("MemberService.MemberTypeService has not been initialized.");
+ // return _memberTypeService;
+ // }
+ // set { _memberTypeService = value; }
+ //}
#endregion
- #region IMembershipMemberService Implementation
+ #region Count
///
/// Gets the total number of Members based on the count type
@@ -669,6 +74,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
IQuery query;
@@ -679,101 +85,28 @@ namespace Umbraco.Core.Services
break;
case MemberCountType.Online:
var fromDate = DateTime.Now.AddMinutes(-Membership.UserIsOnlineTimeWindow);
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.LastLoginDate &&
- ((Member)x).DateTimePropertyValue > fromDate);
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.LastLoginDate &&
+ ((Member)x).DateTimePropertyValue > fromDate);
break;
case MemberCountType.LockedOut:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsLockedOut &&
- ((Member)x).BoolPropertyValue);
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsLockedOut &&
+ ((Member)x).BoolPropertyValue);
break;
case MemberCountType.Approved:
- query =
- repository.Query.Where(
- x =>
- ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsApproved &&
- ((Member)x).BoolPropertyValue);
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsApproved &&
+ ((Member)x).BoolPropertyValue);
break;
default:
- throw new ArgumentOutOfRangeException("countType"); // causes rollback;
+ throw new ArgumentOutOfRangeException(nameof(countType)); // causes rollback;
}
var count = repository.GetCountByQuery(query);
uow.Complete();
return count;
}
-
- }
-
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords)
- {
- long total;
- var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total);
- totalRecords = Convert.ToInt32(total);
- return result;
- }
-
- ///
- /// Gets a list of paged objects
- ///
- /// Current page index
- /// Size of the page
- /// Total number of records found (out)
- ///
- public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var members = repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true);
- uow.Complete();
- return members;
- }
- }
-
- [Obsolete("Use the overload with 'long' parameter types instead")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords,
- string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "")
- {
- long total;
- var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total, orderBy, orderDirection, true, memberTypeAlias, filter);
- totalRecords = Convert.ToInt32(total);
- return result;
- }
-
- public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords,
- string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "")
- {
- return GetAll(pageIndex, pageSize, out totalRecords, orderBy, orderDirection, true, memberTypeAlias, filter);
- }
-
- public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords,
- string orderBy, Direction orderDirection, bool orderBySystemField, string memberTypeAlias, string filter)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- IEnumerable members;
- if (memberTypeAlias == null)
- {
- members = repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter);
- }
- else
- {
- var query = repository.Query.Where(x => x.ContentTypeAlias == memberTypeAlias);
- members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter);
- }
- uow.Complete();
- return members;
- }
}
///
@@ -786,6 +119,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var count = repository.Count(memberTypeAlias);
uow.Complete();
@@ -793,6 +127,10 @@ namespace Umbraco.Core.Services
}
}
+ #endregion
+
+ #region Create
+
///
/// Creates an object without persisting it
///
@@ -806,8 +144,14 @@ namespace Umbraco.Core.Services
///
public IMember CreateMember(string username, string email, string name, string memberTypeAlias)
{
- var memberType = FindMemberTypeByAlias(memberTypeAlias);
- return CreateMember(username, email, name, memberType);
+ var memberType = GetMemberType(memberTypeAlias);
+ if (memberType == null)
+ throw new ArgumentException("No member type with that alias.", nameof(memberTypeAlias));
+
+ var member = new Member(name, email.ToLower().Trim(), username, memberType);
+ CreateMember(null, member, 0, false);
+
+ return member;
}
///
@@ -823,9 +167,10 @@ namespace Umbraco.Core.Services
///
public IMember CreateMember(string username, string email, string name, IMemberType memberType)
{
- var member = new Member(name, email.ToLower().Trim(), username, memberType);
+ if (memberType == null) throw new ArgumentNullException(nameof(memberType));
- Created.RaiseEvent(new NewEventArgs(member, false, memberType.Alias, -1), this);
+ var member = new Member(name, email.ToLower().Trim(), username, memberType);
+ CreateMember(null, member, 0, false);
return member;
}
@@ -833,7 +178,7 @@ namespace Umbraco.Core.Services
///
/// Creates and persists a Member
///
- /// Using this method will persist the Member object before its returned
+ /// Using this method will persist the Member object before its returned
/// meaning that it will have an Id available (unlike the CreateMember method)
/// Username of the Member to create
/// Email of the Member to create
@@ -842,14 +187,27 @@ namespace Umbraco.Core.Services
///
public IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias)
{
- var memberType = FindMemberTypeByAlias(memberTypeAlias);
- return CreateMemberWithIdentity(username, email, name, memberType);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ // locking the media tree secures media types too
+ uow.WriteLock(Constants.Locks.MediaTree);
+
+ var memberType = GetMemberType(memberTypeAlias); // + locks
+ if (memberType == null)
+ throw new ArgumentException("No member type with that alias.", nameof(memberTypeAlias)); // causes rollback
+
+ var member = new Member(name, email.ToLower().Trim(), username, memberType);
+ CreateMember(uow, member, 0, true);
+
+ uow.Complete();
+ return member;
+ }
}
///
/// Creates and persists a Member
///
- /// Using this method will persist the Member object before its returned
+ /// Using this method will persist the Member object before its returned
/// meaning that it will have an Id available (unlike the CreateMember method)
/// Username of the Member to create
/// Email of the Member to create
@@ -857,13 +215,13 @@ namespace Umbraco.Core.Services
///
public IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType)
{
- return CreateMemberWithIdentity(username, email, username, memberType);
+ return CreateMemberWithIdentity(username, email, username, "", memberType);
}
///
/// Creates and persists a Member
///
- /// Using this method will persist the Member object before its returned
+ /// Using this method will persist the Member object before its returned
/// meaning that it will have an Id available (unlike the CreateMember method)
/// Username of the Member to create
/// Email of the Member to create
@@ -886,14 +244,27 @@ namespace Umbraco.Core.Services
///
IMember IMembershipMemberService.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias)
{
- var memberType = FindMemberTypeByAlias(memberTypeAlias);
- return CreateMemberWithIdentity(username, email, username, passwordValue, memberType);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+
+ // ensure it all still make sense
+ var memberType = GetMemberType(memberTypeAlias); // + locks
+ if (memberType == null)
+ throw new ArgumentException("No member type with that alias.", nameof(memberTypeAlias)); // causes rollback
+
+ var member = new Member(username, email.ToLower().Trim(), username, passwordValue, memberType);
+ CreateMember(uow, member, -1, true);
+
+ uow.Complete();
+ return member;
+ }
}
///
/// Creates and persists a Member
///
- /// Using this method will persist the Member object before its returned
+ /// Using this method will persist the Member object before its returned
/// meaning that it will have an Id available (unlike the CreateMember method)
/// Username of the Member to create
/// Email of the Member to create
@@ -903,35 +274,143 @@ namespace Umbraco.Core.Services
///
private IMember CreateMemberWithIdentity(string username, string email, string name, string passwordValue, IMemberType memberType)
{
- if (memberType == null) throw new ArgumentNullException("memberType");
+ if (memberType == null) throw new ArgumentNullException(nameof(memberType));
- var member = new Member(name, email.ToLower().Trim(), username, passwordValue, memberType);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MediaTree);
+
+ // ensure it all still make sense
+ var vrfy = GetMemberType(memberType.Alias); // + locks
+ if (vrfy == null || vrfy.Id != memberType.Id)
+ throw new ArgumentException($"Member type with alias {memberType.Alias} does not exist or is a different member type."); // causes rollback
+
+ var member = new Member(name, email.ToLower().Trim(), username, passwordValue, memberType);
+ CreateMember(uow, member, -1, true);
+
+ uow.Complete();
+ return member;
+ }
+ }
+
+ private void CreateMember(IDatabaseUnitOfWork uow, Member member, int userId, bool withIdentity)
+ {
+ // there's no Creating event for members
if (Saving.IsRaisedEventCancelled(new SaveEventArgs(member), this))
{
member.WasCancelled = true;
- return member;
+ return;
}
- using (var uow = UowProvider.CreateUnitOfWork())
+ member.CreatorId = userId;
+
+ if (withIdentity)
{
+ if (Saving.IsRaisedEventCancelled(new SaveEventArgs(member), this))
+ {
+ member.WasCancelled = true;
+ return;
+ }
+
var repository = uow.CreateRepository();
repository.AddOrUpdate(member);
- //insert the xml
+
+ // fixme kill
repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
// generate preview for blame history?
if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
- }
- uow.Complete();
+ Saved.RaiseEvent(new SaveEventArgs(member, false), this);
}
- Saved.RaiseEvent(new SaveEventArgs(member, false), this);
- Created.RaiseEvent(new NewEventArgs(member, false, memberType.Alias, -1), this);
+ Created.RaiseEvent(new NewEventArgs(member, false, member.ContentType.Alias, -1), this);
- return member;
+ var msg = withIdentity
+ ? "Member '{0}' was created with Id {1}"
+ : "Member '{0}' was created";
+ Audit(AuditType.New, string.Format(msg, member.Name, member.Id), member.CreatorId, member.Id);
+ }
+
+ #endregion
+
+ #region Get, Has, Is, Exists...
+
+ ///
+ /// Gets a Member by its integer id
+ ///
+ /// Id
+ ///
+ public IMember GetById(int id)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var member = repository.Get(id);
+ uow.Complete();
+ return member;
+ }
+ }
+
+ ///
+ /// Gets a Member by the unique key
+ ///
+ /// The guid key corresponds to the unique id in the database
+ /// and the user id in the membership provider.
+ /// Id
+ ///
+ public IMember GetByKey(Guid id)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query.Where(x => x.Key == id);
+ var member = repository.GetByQuery(query).FirstOrDefault();
+ uow.Complete();
+ return member;
+ }
+ }
+
+ ///
+ /// Gets a list of paged objects
+ ///
+ /// Current page index
+ /// Size of the page
+ /// Total number of records found (out)
+ ///
+ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var members = repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords,
+ string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "")
+ {
+ return GetAll(pageIndex, pageSize, out totalRecords, orderBy, orderDirection, true, memberTypeAlias, filter);
+ }
+
+ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords,
+ string orderBy, Direction orderDirection, bool orderBySystemField, string memberTypeAlias, string filter)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = memberTypeAlias == null ? null : repository.Query.Where(x => x.ContentTypeAlias == memberTypeAlias);
+ var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter);
+ uow.Complete();
+ return members;
+ }
}
///
@@ -943,14 +422,11 @@ namespace Umbraco.Core.Services
{
var asGuid = id.TryConvertTo();
if (asGuid.Success)
- {
- return GetByKey((Guid)id);
- }
+ return GetByKey(asGuid.Result);
+
var asInt = id.TryConvertTo();
if (asInt.Success)
- {
- return GetById((int)id);
- }
+ return GetById(asInt.Result);
return null;
}
@@ -964,6 +440,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.Email.Equals(email));
var member = repository.GetByQuery(query).FirstOrDefault();
@@ -979,12 +456,13 @@ namespace Umbraco.Core.Services
///
public IMember GetByUsername(string username)
{
- //TODO: Somewhere in here, whether at this level or the repository level, we need to add
+ //TODO: Somewhere in here, whether at this level or the repository level, we need to add
// a caching mechanism since this method is used by all the membership providers and could be
// called quite a bit when dealing with members.
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var query = repository.Query.Where(x => x.Username.Equals(username));
var member = repository.GetByQuery(query).FirstOrDefault();
@@ -993,6 +471,500 @@ namespace Umbraco.Core.Services
}
}
+ ///
+ /// Gets all Members for the specified MemberType alias
+ ///
+ /// Alias of the MemberType
+ ///
+ public IEnumerable GetMembersByMemberType(string memberTypeAlias)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query.Where(x => x.ContentTypeAlias == memberTypeAlias);
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets all Members for the MemberType id
+ ///
+ /// Id of the MemberType
+ ///
+ public IEnumerable GetMembersByMemberType(int memberTypeId)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ repository.Get(memberTypeId);
+ var query = repository.Query.Where(x => x.ContentTypeId == memberTypeId);
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets all Members within the specified MemberGroup name
+ ///
+ /// Name of the MemberGroup
+ ///
+ public IEnumerable GetMembersByGroup(string memberGroupName)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var members = repository.GetByMemberGroup(memberGroupName);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets all Members with the ids specified
+ ///
+ /// If no Ids are specified all Members will be retrieved
+ /// Optional list of Member Ids
+ ///
+ public IEnumerable GetAllMembers(params int[] ids)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var members = repository.GetAll(ids);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Finds Members based on their display name
+ ///
+ /// Display name to match
+ /// Current page index
+ /// Size of the page
+ /// Total number of records found (out)
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable FindMembersByDisplayName(string displayNameToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query;
+
+ switch (matchType)
+ {
+ case StringPropertyMatchType.Exact:
+ query.Where(member => member.Name.Equals(displayNameToMatch));
+ break;
+ case StringPropertyMatchType.Contains:
+ query.Where(member => member.Name.Contains(displayNameToMatch));
+ break;
+ case StringPropertyMatchType.StartsWith:
+ query.Where(member => member.Name.StartsWith(displayNameToMatch));
+ break;
+ case StringPropertyMatchType.EndsWith:
+ query.Where(member => member.Name.EndsWith(displayNameToMatch));
+ break;
+ case StringPropertyMatchType.Wildcard:
+ query.Where(member => member.Name.SqlWildcard(displayNameToMatch, TextColumnType.NVarchar));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType)); // causes rollback
+ }
+
+ var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending, true);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Finds a list of objects by a partial email string
+ ///
+ /// Partial email string to match
+ /// Current page index
+ /// Size of the page
+ /// Total number of records found (out)
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query;
+
+ switch (matchType)
+ {
+ case StringPropertyMatchType.Exact:
+ query.Where(member => member.Email.Equals(emailStringToMatch));
+ break;
+ case StringPropertyMatchType.Contains:
+ query.Where(member => member.Email.Contains(emailStringToMatch));
+ break;
+ case StringPropertyMatchType.StartsWith:
+ query.Where(member => member.Email.StartsWith(emailStringToMatch));
+ break;
+ case StringPropertyMatchType.EndsWith:
+ query.Where(member => member.Email.EndsWith(emailStringToMatch));
+ break;
+ case StringPropertyMatchType.Wildcard:
+ query.Where(member => member.Email.SqlWildcard(emailStringToMatch, TextColumnType.NVarchar));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType));
+ }
+
+ var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending, true);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Finds a list of objects by a partial username
+ ///
+ /// Partial username to match
+ /// Current page index
+ /// Size of the page
+ /// Total number of records found (out)
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query;
+
+ switch (matchType)
+ {
+ case StringPropertyMatchType.Exact:
+ query.Where(member => member.Username.Equals(login));
+ break;
+ case StringPropertyMatchType.Contains:
+ query.Where(member => member.Username.Contains(login));
+ break;
+ case StringPropertyMatchType.StartsWith:
+ query.Where(member => member.Username.StartsWith(login));
+ break;
+ case StringPropertyMatchType.EndsWith:
+ query.Where(member => member.Username.EndsWith(login));
+ break;
+ case StringPropertyMatchType.Wildcard:
+ query.Where(member => member.Email.SqlWildcard(login, TextColumnType.NVarchar));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType));
+ }
+
+ var members = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets a list of Members based on a property search
+ ///
+ /// Alias of the PropertyType to search for
+ /// Value to match
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, string value, StringPropertyMatchType matchType = StringPropertyMatchType.Exact)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ IQuery query;
+
+ switch (matchType)
+ {
+ case StringPropertyMatchType.Exact:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ (((Member)x).LongStringPropertyValue.SqlEquals(value, TextColumnType.NText) ||
+ ((Member)x).ShortStringPropertyValue.SqlEquals(value, TextColumnType.NVarchar)));
+ break;
+ case StringPropertyMatchType.Contains:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ (((Member)x).LongStringPropertyValue.SqlContains(value, TextColumnType.NText) ||
+ ((Member)x).ShortStringPropertyValue.SqlContains(value, TextColumnType.NVarchar)));
+ break;
+ case StringPropertyMatchType.StartsWith:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ (((Member)x).LongStringPropertyValue.SqlStartsWith(value, TextColumnType.NText) ||
+ ((Member)x).ShortStringPropertyValue.SqlStartsWith(value, TextColumnType.NVarchar)));
+ break;
+ case StringPropertyMatchType.EndsWith:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ (((Member)x).LongStringPropertyValue.SqlEndsWith(value, TextColumnType.NText) ||
+ ((Member)x).ShortStringPropertyValue.SqlEndsWith(value, TextColumnType.NVarchar)));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType)); // causes rollback
+ }
+
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets a list of Members based on a property search
+ ///
+ /// Alias of the PropertyType to search for
+ /// Value to match
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, int value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ IQuery query;
+
+ switch (matchType)
+ {
+ case ValuePropertyMatchType.Exact:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).IntegerPropertyValue == value);
+ break;
+ case ValuePropertyMatchType.GreaterThan:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).IntegerPropertyValue > value);
+ break;
+ case ValuePropertyMatchType.LessThan:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).IntegerPropertyValue < value);
+ break;
+ case ValuePropertyMatchType.GreaterThanOrEqualTo:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).IntegerPropertyValue >= value);
+ break;
+ case ValuePropertyMatchType.LessThanOrEqualTo:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).IntegerPropertyValue <= value);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType)); // causes rollback
+ }
+
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets a list of Members based on a property search
+ ///
+ /// Alias of the PropertyType to search for
+ /// Value to match
+ ///
+ public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, bool value)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).BoolPropertyValue == value);
+
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Gets a list of Members based on a property search
+ ///
+ /// Alias of the PropertyType to search for
+ /// Value to match
+ /// The type of match to make as . Default is
+ ///
+ public IEnumerable GetMembersByPropertyValue(string propertyTypeAlias, DateTime value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ IQuery query;
+
+ switch (matchType)
+ {
+ case ValuePropertyMatchType.Exact:
+ query = repository.Query.Where( x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).DateTimePropertyValue == value);
+ break;
+ case ValuePropertyMatchType.GreaterThan:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).DateTimePropertyValue > value);
+ break;
+ case ValuePropertyMatchType.LessThan:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).DateTimePropertyValue < value);
+ break;
+ case ValuePropertyMatchType.GreaterThanOrEqualTo:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).DateTimePropertyValue >= value);
+ break;
+ case ValuePropertyMatchType.LessThanOrEqualTo:
+ query = repository.Query.Where(x =>
+ ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
+ ((Member)x).DateTimePropertyValue <= value);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(matchType)); // causes rollback
+ }
+
+ //TODO: Since this is by property value, we need a GetByPropertyQuery on the repo!
+ var members = repository.GetByQuery(query);
+ uow.Complete();
+ return members;
+ }
+ }
+
+ ///
+ /// Checks if a Member with the id exists
+ ///
+ /// Id of the Member
+ /// True if the Member exists otherwise False
+ public bool Exists(int id)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var exists = repository.Exists(id);
+ uow.Complete();
+ return exists;
+ }
+ }
+
+ ///
+ /// Checks if a Member with the username exists
+ ///
+ /// Username to check
+ /// True if the Member exists otherwise False
+ public bool Exists(string username)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ var exists = repository.Exists(username);
+ uow.Complete();
+ return exists;
+ }
+ }
+
+ #endregion
+
+ #region Save
+
+ ///
+ /// Saves an
+ ///
+ /// to Save
+ /// Optional parameter to raise events.
+ /// Default is True otherwise set to False to not raise events
+ public void Save(IMember member, bool raiseEvents = true)
+ {
+ if (raiseEvents && Saving.IsRaisedEventCancelled(new SaveEventArgs(member), this))
+ return;
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+
+ repository.AddOrUpdate(member);
+
+ // fixme get rid of xml
+ repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
+
+ // generate preview for blame history?
+ if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
+ repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
+
+ uow.Complete();
+ }
+
+ if (raiseEvents)
+ Saved.RaiseEvent(new SaveEventArgs(member, false), this);
+ Audit(AuditType.Save, "Save Member performed by user", 0, member.Id);
+ }
+
+ ///
+ /// Saves a list of objects
+ ///
+ /// to save
+ /// Optional parameter to raise events.
+ /// Default is True otherwise set to False to not raise events
+ public void Save(IEnumerable members, bool raiseEvents = true)
+ {
+ var membersA = members.ToArray();
+
+ if (raiseEvents && Saving.IsRaisedEventCancelled(new SaveEventArgs(membersA), this))
+ return;
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+ foreach (var member in membersA)
+ {
+ repository.AddOrUpdate(member);
+
+ // fixme get rid of xml stuff
+ repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
+
+ // generate preview for blame history?
+ if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
+ repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
+ }
+
+ uow.Complete();
+ }
+
+ if (raiseEvents)
+ Saved.RaiseEvent(new SaveEventArgs(membersA, false), this);
+ Audit(AuditType.Save, "Save Member items performed by user", 0, -1);
+ }
+
+ #endregion
+
+ #region Delete
+
///
/// Deletes an
///
@@ -1004,100 +976,35 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
- repository.Delete(member);
+ DeleteLocked(repository, member);
uow.Complete();
- var args = new DeleteEventArgs(member, false);
- Deleted.RaiseEvent(args, this);
-
- //remove any flagged media files
- repository.DeleteMediaFiles(args.MediaFilesToDelete);
}
+
+ Audit(AuditType.Delete, "Delete Member performed by user", 0, member.Id);
}
- ///
- /// Saves an
- ///
- /// to Save
- /// Optional parameter to raise events.
- /// Default is True otherwise set to False to not raise events
- public void Save(IMember entity, bool raiseEvents = true)
+ private void DeleteLocked(IMemberRepository repository, IMember member)
{
- if (raiseEvents)
- {
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(entity), this))
- {
- return;
- }
- }
-
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- repository.AddOrUpdate(entity);
- repository.AddOrUpdateContentXml(entity, m => _entitySerializer.Serialize(_dataTypeService, m));
- // generate preview for blame history?
- if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
- repository.AddOrUpdatePreviewXml(entity, m => _entitySerializer.Serialize(_dataTypeService, m));
- }
-
- uow.Complete();
- }
-
- if (raiseEvents)
- Saved.RaiseEvent(new SaveEventArgs(entity, false), this);
- }
-
- ///
- /// Saves a list of objects
- ///
- /// to save
- /// Optional parameter to raise events.
- /// Default is True otherwise set to False to not raise events
- public void Save(IEnumerable entities, bool raiseEvents = true)
- {
- var asArray = entities.ToArray();
-
- if (raiseEvents)
- {
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(asArray), this))
- return;
- }
- using (new WriteLock(Locker))
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- foreach (var member in asArray)
- {
- repository.AddOrUpdate(member);
- repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
- // generate preview for blame history?
- if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
- {
- repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
- }
- }
-
- //commit the whole lot in one go
- uow.Complete();
- }
-
- if (raiseEvents)
- Saved.RaiseEvent(new SaveEventArgs(asArray, false), this);
- }
+ // a member has no descendants
+ repository.Delete(member);
+ var args = new DeleteEventArgs(member, false); // raise event & get flagged files
+ Deleted.RaiseEvent(args, this);
+ IOHelper.DeleteFiles(args.MediaFilesToDelete, // remove flagged files
+ (file, e) => Logger.Error("An error occurred while deleting file attached to nodes: " + file, e));
}
#endregion
- #region IMembershipRoleService Implementation
+ #region Roles
public void AddRole(string roleName)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
repository.CreateIfNotExists(roleName);
uow.Complete();
@@ -1108,6 +1015,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var result = repository.GetAll().Select(x => x.Name).Distinct();
uow.Complete();
@@ -1119,6 +1027,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var result = repository.GetMemberGroupsForMember(memberId);
var roles = result.Select(x => x.Name).Distinct();
@@ -1131,6 +1040,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var result = repository.GetMemberGroupsForMember(username);
var roles = result.Select(x => x.Name).Distinct();
@@ -1143,6 +1053,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var members = repository.GetByMemberGroup(roleName);
uow.Complete();
@@ -1154,6 +1065,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.ReadLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
var members = repository.FindMembersInRole(roleName, usernameToMatch, matchType);
uow.Complete();
@@ -1161,33 +1073,32 @@ namespace Umbraco.Core.Services
}
}
+ // FIXME CURRENT WIP
+
public bool DeleteRole(string roleName, bool throwIfBeingUsed)
{
- using (new WriteLock(Locker))
+ using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+
if (throwIfBeingUsed)
{
- var inRole = GetMembersInRole(roleName);
- if (inRole.Any())
- {
+ // get members in role
+ var memberRepository = uow.CreateRepository();
+ var membersInRole = memberRepository.GetByMemberGroup(roleName);
+ if (membersInRole.Any())
throw new InvalidOperationException("The role " + roleName + " is currently assigned to members");
- }
}
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var qry = repository.QueryFactory.Create().Where(g => g.Name == roleName);
- var found = repository.GetByQuery(qry).ToArray();
+ var query = repository.QueryFactory.Create().Where(g => g.Name == roleName);
+ var found = repository.GetByQuery(query).ToArray();
- foreach (var memberGroup in found)
- {
- _memberGroupService.Delete(memberGroup);
- }
- var deleted = found.Any();
- uow.Complete();
- return deleted;
- }
+ foreach (var memberGroup in found)
+ _memberGroupService.Delete(memberGroup); // FIXME BAD BAD BAD!
+
+ uow.Complete();
+ return found.Length > 0;
}
}
public void AssignRole(string username, string roleName)
@@ -1199,6 +1110,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
repository.AssignRoles(usernames, roleNames);
uow.Complete();
@@ -1214,6 +1126,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
repository.DissociateRoles(usernames, roleNames);
uow.Complete();
@@ -1229,6 +1142,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
repository.AssignRoles(memberIds, roleNames);
uow.Complete();
@@ -1244,39 +1158,16 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.CreateUnitOfWork())
{
+ uow.WriteLock(Constants.Locks.MemberTree);
var repository = uow.CreateRepository();
repository.DissociateRoles(memberIds, roleNames);
uow.Complete();
}
}
-
-
#endregion
- private IMemberType FindMemberTypeByAlias(string memberTypeAlias)
- {
- using (var uow = UowProvider.CreateUnitOfWork())
- {
- var repository = uow.CreateRepository();
- var query = repository.QueryFactory.Create().Where(x => x.Alias == memberTypeAlias);
- var types = repository.GetByQuery(query);
-
- if (types.Any() == false)
- throw new Exception(
- string.Format("No MemberType matching the passed in Alias: '{0}' was found",
- memberTypeAlias)); // causes rollback
-
- var contentType = types.First();
-
- if (contentType == null)
- throw new Exception(string.Format("MemberType matching the passed in Alias: '{0}' was null",
- memberTypeAlias)); // causes rollback
-
- uow.Complete();
- return contentType;
- }
- }
+ #region Private Methods
private void Audit(AuditType type, string message, int userId, int objectId)
{
@@ -1288,6 +1179,8 @@ namespace Umbraco.Core.Services
}
}
+ #endregion
+
#region Event Handlers
///
@@ -1321,6 +1214,40 @@ namespace Umbraco.Core.Services
#endregion
+ #region Membership
+
+ ///
+ /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
+ ///
+ /// This method exists so that Umbraco developers can use one entry point to create/update
+ /// Members if they choose to.
+ /// The Member to save the password for
+ /// The password to encrypt and save
+ public void SavePassword(IMember member, string password)
+ {
+ if (member == null) throw new ArgumentNullException("member");
+
+ var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
+ if (provider.IsUmbracoMembershipProvider())
+ provider.ChangePassword(member.Username, "", password);
+ else
+ throw new NotSupportedException("When using a non-Umbraco membership provider you must change the member password by using the MembershipProvider.ChangePassword method");
+
+ //go re-fetch the member and update the properties that may have changed
+ var result = GetByUsername(member.Username);
+
+ //should never be null but it could have been deleted by another thread.
+ // fixme - should LOCK! instead
+ if (result == null)
+ return;
+
+ member.RawPasswordValue = result.RawPasswordValue;
+ member.LastPasswordChangeDate = result.LastPasswordChangeDate;
+ member.UpdateDate = result.UpdateDate;
+
+ // fixme - not saving?
+ }
+
///
/// A helper method that will create a basic/generic member for use with a generic membership provider
///
@@ -1380,6 +1307,7 @@ namespace Umbraco.Core.Services
memType.PropertyGroups.Add(propGroup);
+ // should we "create member"?
var member = new Member(name, email, username, password, memType);
//we've assigned ids to the property types and groups but we also need to assign fake ids to the properties themselves.
@@ -1390,5 +1318,82 @@ namespace Umbraco.Core.Services
return member;
}
+
+ #endregion
+
+ #region Content Types
+
+ ///
+ /// Delete Members of the specified MemberType id
+ ///
+ /// Id of the MemberType
+ public void DeleteMembersOfType(int memberTypeId)
+ {
+ // note: no tree to manage here
+
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.WriteLock(Constants.Locks.MemberTree);
+ var repository = uow.CreateRepository();
+
+ //TODO: What about content that has the contenttype as part of its composition?
+ var query = repository.Query.Where(x => x.ContentTypeId == memberTypeId);
+ var members = repository.GetByQuery(query).ToArray();
+
+ if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(members), this))
+ return; // causes rollback
+
+ foreach (var member in members)
+ {
+ // delete media
+ // triggers the deleted event (and handles the files)
+ DeleteLocked(repository, member);
+ }
+
+ uow.Complete();
+ }
+ }
+
+ private IMemberType GetMemberType(string memberTypeAlias)
+ {
+ var memberType = MemberTypeService.Get(memberTypeAlias);
+ if (memberType == null)
+ throw new Exception(string.Format("No MemberType matching alias: \"{0}\".", memberTypeAlias));
+ return memberType;
+ }
+
+ [Obsolete("use MemberTypeService.GetDefault()")] // fixme kill!
+ public string GetDefaultMemberType()
+ {
+ return MemberTypeService.GetDefault();
+ }
+
+ #endregion
+
+ #region Xml - Should Move!
+
+ ///
+ /// Rebuilds all xml content in the cmsContentXml table for all members
+ ///
+ ///
+ /// Only rebuild the xml structures for the content type ids passed in, if none then rebuilds the structures
+ /// for all members = USE WITH CARE!
+ ///
+ /// True if publishing succeeded, otherwise False
+ public void RebuildXmlStructures(params int[] memberTypeIds)
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ var repository = uow.CreateRepository();
+ repository.RebuildXmlStructures(
+ member => _entitySerializer.Serialize(_dataTypeService, member),
+ contentTypeIds: memberTypeIds.Length == 0 ? null : memberTypeIds);
+ uow.Complete();
+ }
+
+ Audit(AuditType.Publish, "MemberService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/MemberTypeService.cs b/src/Umbraco.Core/Services/MemberTypeService.cs
index 03b864e852..df78b59bd1 100644
--- a/src/Umbraco.Core/Services/MemberTypeService.cs
+++ b/src/Umbraco.Core/Services/MemberTypeService.cs
@@ -54,5 +54,23 @@ namespace Umbraco.Core.Services
var memberService = _memberService as MemberService;
memberService?.RebuildXmlStructures(toUpdate.Select(x => x.Id).ToArray());
}
+
+ public string GetDefault()
+ {
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ uow.ReadLock(ReadLockIds);
+ var repo = uow.CreateRepository();
+ var e = repo.GetAll(new int[0]).GetEnumerator();
+ if (e.MoveNext() == false)
+ throw new InvalidOperationException("No member types could be resolved");
+ var first = e.Current.Alias;
+ var current = true;
+ while (e.Current.Alias.InvariantEquals("Member") == false && (current = e.MoveNext()))
+ { }
+ uow.Complete();
+ return current ? e.Current.Alias : first;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/NotificationService.cs b/src/Umbraco.Core/Services/NotificationService.cs
index 8744409521..c772eb95f1 100644
--- a/src/Umbraco.Core/Services/NotificationService.cs
+++ b/src/Umbraco.Core/Services/NotificationService.cs
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Services
//we'll lazily get these if we need to send notifications
IEnumerable allVersions = null;
- int totalUsers;
+ long totalUsers;
var allUsers = _userService.GetAll(0, int.MaxValue, out totalUsers);
foreach (var u in allUsers)
{
diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs
index 0cad058ceb..4498e64347 100644
--- a/src/Umbraco.Core/Services/UserService.cs
+++ b/src/Umbraco.Core/Services/UserService.cs
@@ -384,7 +384,7 @@ namespace Umbraco.Core.Services
/// Total number of records found (out)
/// The type of match to make as . Default is
///
- public IEnumerable FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
+ public IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
@@ -427,7 +427,7 @@ namespace Umbraco.Core.Services
/// Total number of records found (out)
/// The type of match to make as . Default is
///
- public IEnumerable FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
+ public IEnumerable FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
@@ -515,7 +515,7 @@ namespace Umbraco.Core.Services
/// Size of the page
/// Total number of records found (out)
///
- public IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords)
+ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords)
{
using (var uow = UowProvider.CreateUnitOfWork())
{
diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs
index 1407240fdf..000817cd5c 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs
@@ -59,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories
}
unitOfWork.Flush();
- //delete all xml
+ //delete all xml
unitOfWork.Database.Execute("DELETE FROM cmsContentXml");
Assert.AreEqual(0, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml"));
@@ -99,7 +99,7 @@ namespace Umbraco.Tests.Persistence.Repositories
}
unitOfWork.Flush();
- //delete all xml
+ //delete all xml
unitOfWork.Database.Execute("DELETE FROM cmsContentXml");
Assert.AreEqual(0, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml"));
diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs
index 14233283d7..1a2ec8e516 100644
--- a/src/Umbraco.Tests/Services/MemberServiceTests.cs
+++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs
@@ -446,7 +446,7 @@ namespace Umbraco.Tests.Services
var members = MockedMember.CreateSimpleMember(memberType, 10);
ServiceContext.MemberService.Save(members);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.GetAll(0, 2, out totalRecs);
Assert.AreEqual(2, found.Count());
@@ -466,7 +466,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "Bob", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindMembersByDisplayName("B", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(1, found.Count());
@@ -483,7 +483,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello","hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByEmail("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(10, found.Count());
@@ -500,7 +500,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByEmail("test.com", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith);
Assert.AreEqual(11, found.Count());
@@ -517,7 +517,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByEmail("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains);
Assert.AreEqual(11, found.Count());
@@ -534,7 +534,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByEmail("hello@test.com", 0, 100, out totalRecs, StringPropertyMatchType.Exact);
Assert.AreEqual(1, found.Count());
@@ -551,7 +551,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByUsername("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(10, found.Count());
@@ -568,7 +568,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByUsername("llo", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith);
Assert.AreEqual(1, found.Count());
@@ -585,7 +585,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hellotest");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByUsername("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains);
Assert.AreEqual(11, found.Count());
@@ -602,7 +602,7 @@ namespace Umbraco.Tests.Services
var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello");
ServiceContext.MemberService.Save(customMember);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.MemberService.FindByUsername("hello", 0, 100, out totalRecs, StringPropertyMatchType.Exact);
Assert.AreEqual(1, found.Count());
diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs
index 6b522efddd..0ca0f11ebf 100644
--- a/src/Umbraco.Tests/Services/UserServiceTests.cs
+++ b/src/Umbraco.Tests/Services/UserServiceTests.cs
@@ -188,7 +188,7 @@ namespace Umbraco.Tests.Services
customUser.Email = "hello@hello.com";
ServiceContext.UserService.Save(customUser);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.UserService.FindByEmail("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith);
Assert.AreEqual(10, found.Count());
@@ -206,7 +206,7 @@ namespace Umbraco.Tests.Services
customUser.Email = "hello@test.com";
ServiceContext.UserService.Save(customUser);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.UserService.FindByEmail("test.com", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith);
Assert.AreEqual(11, found.Count());
@@ -224,7 +224,7 @@ namespace Umbraco.Tests.Services
customUser.Email = "hello@test.com";
ServiceContext.UserService.Save(customUser);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.UserService.FindByEmail("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains);
Assert.AreEqual(11, found.Count());
@@ -242,7 +242,7 @@ namespace Umbraco.Tests.Services
customUser.Email = "hello@test.com";
ServiceContext.UserService.Save(customUser);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.UserService.FindByEmail("hello@test.com", 0, 100, out totalRecs, StringPropertyMatchType.Exact);
Assert.AreEqual(1, found.Count());
@@ -256,7 +256,7 @@ namespace Umbraco.Tests.Services
var users = MockedUser.CreateUser(userType, 10);
ServiceContext.UserService.Save(users);
- int totalRecs;
+ long totalRecs;
var found = ServiceContext.UserService.GetAll(0, 2, out totalRecs);
Assert.AreEqual(2, found.Count());
diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index 9f3203d4ed..8649962cd7 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -588,7 +588,7 @@ namespace Umbraco.Web.Editors
case UmbracoEntityTypes.User:
- int total;
+ long total;
var users = Services.UserService.GetAll(0, int.MaxValue, out total);
var filteredUsers = ExecutePostFilter(users, postFilter, postFilterParams);
return Mapper.Map, IEnumerable>(filteredUsers);
diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
index 8482eb72a2..ce7e9e14ec 100644
--- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
+++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
@@ -211,7 +211,9 @@ namespace Umbraco.Web.Security.Providers
///
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
- var byEmail = MemberService.FindByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
+ long totalRecords2;
+ var byEmail = MemberService.FindByEmail(emailToMatch, pageIndex, pageSize, out totalRecords2, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = Convert.ToInt32(totalRecords2);
var collection = new MembershipUserCollection();
foreach (var m in byEmail)
@@ -233,7 +235,9 @@ namespace Umbraco.Web.Security.Providers
///
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
- var byEmail = MemberService.FindByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
+ long totalRecords2;
+ var byEmail = MemberService.FindByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords2, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = Convert.ToInt32(totalRecords2);
var collection = new MembershipUserCollection();
foreach (var m in byEmail)
@@ -256,7 +260,9 @@ namespace Umbraco.Web.Security.Providers
{
var membersList = new MembershipUserCollection();
- var pagedMembers = MemberService.GetAll(pageIndex, pageSize, out totalRecords);
+ long totalRecords2;
+ var pagedMembers = MemberService.GetAll(pageIndex, pageSize, out totalRecords2);
+ totalRecords = Convert.ToInt32(totalRecords2);
foreach (var m in pagedMembers)
{
@@ -483,7 +489,7 @@ namespace Umbraco.Web.Security.Providers
if (RequiresUniqueEmail && user.Email.Trim().IsNullOrWhiteSpace() == false)
{
- int totalRecs;
+ long totalRecs;
var byEmail = MemberService.FindByEmail(user.Email.Trim(), 0, int.MaxValue, out totalRecs, StringPropertyMatchType.Exact);
if (byEmail.Count(x => x.Id != m.Id) > 0)
{
diff --git a/src/Umbraco.Web/Trees/UsersTreeController.cs b/src/Umbraco.Web/Trees/UsersTreeController.cs
index 1ac0f25e27..cd3bf66649 100644
--- a/src/Umbraco.Web/Trees/UsersTreeController.cs
+++ b/src/Umbraco.Web/Trees/UsersTreeController.cs
@@ -26,7 +26,7 @@ namespace Umbraco.Web.Trees
{
var nodes = new TreeNodeCollection();
- int totalusers;
+ long totalusers;
var users = new List(Services.UserService.GetAll(0, int.MaxValue, out totalusers));
var currentUser = UmbracoContext.Current.Security.CurrentUser;
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/UserPermissions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/UserPermissions.cs
index f6b0a0e145..c52326e80d 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/UserPermissions.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/UserPermissions.cs
@@ -35,7 +35,7 @@ namespace umbraco.cms.presentation.Trees
public override void Render(ref XmlTree tree)
{
- int totalusers;
+ long totalusers;
foreach (var user in Services.UserService.GetAll(0, int.MaxValue, out totalusers))
{
if (user.Id > 0 && user.IsApproved)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
index 0602882ff1..fc6149808d 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
@@ -63,7 +63,7 @@ namespace umbraco.dialogs
ht.Rows.Add(names);
- int totalUsers;
+ long totalUsers;
foreach (var u in Services.UserService.GetAll(0, int.MaxValue, out totalUsers))
{
// Not disabled users and not system account
@@ -117,7 +117,7 @@ namespace umbraco.dialogs
{
//get non disabled, non admin users and project to a dictionary,
// the string (value) portion will store the array of chars = their permissions
- int totalUsers;
+ long totalUsers;
var usersPermissions = Services.UserService.GetAll(0, int.MaxValue, out totalUsers)
.Where(user => user.IsApproved && user.Id > 0)
.ToDictionary(user => user, user => "");
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs
index 92b138cbfd..dcc8bc9301 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs
@@ -70,7 +70,7 @@ namespace umbraco.presentation.dialogs
includeSubpages.Enabled = false;
// Translators
- int totalUsers;
+ long totalUsers;
foreach (var u in Services.UserService.GetAll(0, int.MaxValue, out totalUsers))
if (u.UserType.Alias.ToLower() == "translator" || UserHasTranslatePermission(u, _currentPage))
translator.Items.Add(new ListItem(u.Name, u.Id.ToString()));
diff --git a/src/UmbracoExamine/UmbracoMemberIndexer.cs b/src/UmbracoExamine/UmbracoMemberIndexer.cs
index a2879bd283..700cf05c2e 100644
--- a/src/UmbracoExamine/UmbracoMemberIndexer.cs
+++ b/src/UmbracoExamine/UmbracoMemberIndexer.cs
@@ -152,7 +152,7 @@ namespace UmbracoExamine
//no node types specified, do all members
do
{
- int total;
+ long total;
members = _memberService.GetAll(pageIndex, pageSize, out total).ToArray();
IndexItems(GetValueSets(members));
diff --git a/src/umbraco.cms/businesslogic/member/Member.cs b/src/umbraco.cms/businesslogic/member/Member.cs
index 5ce35f0050..2fd03ea8d3 100644
--- a/src/umbraco.cms/businesslogic/member/Member.cs
+++ b/src/umbraco.cms/businesslogic/member/Member.cs
@@ -109,7 +109,7 @@ namespace umbraco.cms.businesslogic.member
public static IEnumerable GetAllAsList()
{
- int totalRecs;
+ long totalRecs;
return ApplicationContext.Current.Services.MemberService.GetAll(0, int.MaxValue, out totalRecs)
.Select(x => new Member(x))
.ToArray();
@@ -154,7 +154,7 @@ namespace umbraco.cms.businesslogic.member
///
public static Member[] getMemberFromFirstLetter(char letter)
{
- int totalRecs;
+ long totalRecs;
return ApplicationContext.Current.Services.MemberService.FindMembersByDisplayName(
letter.ToString(CultureInfo.InvariantCulture), 0, int.MaxValue, out totalRecs, StringPropertyMatchType.StartsWith)
@@ -164,7 +164,7 @@ namespace umbraco.cms.businesslogic.member
public static Member[] GetMemberByName(string usernameToMatch, bool matchByNameInsteadOfLogin)
{
- int totalRecs;
+ long totalRecs;
if (matchByNameInsteadOfLogin)
{
var found = ApplicationContext.Current.Services.MemberService.FindMembersByDisplayName(
@@ -289,7 +289,7 @@ namespace umbraco.cms.businesslogic.member
if (string.IsNullOrEmpty(email))
return null;
- int totalRecs;
+ long totalRecs;
var found = ApplicationContext.Current.Services.MemberService.FindByEmail(
email, 0, int.MaxValue, out totalRecs, StringPropertyMatchType.Exact);