diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs index c37997769e..1045182cf5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs @@ -1,5 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.Repositories @@ -27,5 +30,16 @@ namespace Umbraco.Core.Persistence.Repositories /// int GetCountByQuery(IQuery query); + /// + /// Gets paged member results + /// + /// + /// + /// + /// + /// + /// + IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy); + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 6fb99d0d13..58996209fa 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Linq.Expressions; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models.EntityBase; @@ -9,6 +10,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; +using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.UnitOfWork; @@ -460,6 +462,51 @@ namespace Umbraco.Core.Persistence.Repositories return Database.ExecuteScalar(sql); } + /// + /// Gets paged member results + /// + /// + /// + /// + /// + /// + /// + /// + /// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging) + /// + public IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy) + { + if (orderBy == null) throw new ArgumentNullException("orderBy"); + + var sql = new Sql(); + sql.Select("*").From(); + + var translator = new SqlTranslator(sql, query); + var resultQuery = translator.Translate(); + + //get the referenced column name + var expressionMember = ExpressionHelper.GetMemberInfo(orderBy); + //now find the mapped column name + var mapper = MappingResolver.Current.ResolveMapperByType(typeof(IMember)); + var mappedField = mapper.Map(expressionMember.Name); + if (mappedField.IsNullOrWhiteSpace()) + { + throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause"); + } + //need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177 + resultQuery.OrderBy(string.Format("({0})", mappedField)); + + var pagedResult = Database.Page(pageIndex + 1, pageSize, resultQuery); + + totalRecords = Convert.ToInt32(pagedResult.TotalItems); + + //now that we have the member dto's we need to construct true members from the list. + var result = GetAll(pagedResult.Items.Select(x => x.NodeId).ToArray()); + + //now we need to ensure this result is also ordered by the same order by clause + return result.OrderBy(orderBy.Compile()); + } + private IMember BuildFromDto(List dtos) { if (dtos == null || dtos.Any() == false) diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs index 715f85f3fb..6c3027d21c 100644 --- a/src/Umbraco.Core/Services/IMembershipMemberService.cs +++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs @@ -46,9 +46,9 @@ namespace Umbraco.Core.Services void Save(IEnumerable members, bool raiseEvents = true); - IEnumerable FindMembersByEmail(string emailStringToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith); + IEnumerable FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith); - IEnumerable FindMembersByUsername(string login, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith); + IEnumerable FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith); /// /// Gets the total number of members based on the count type diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index f5474288ff..d180d13e82 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -184,9 +184,12 @@ namespace Umbraco.Core.Services /// Does a search for members that contain the specified string in their email address /// /// + /// /// + /// + /// /// - public IEnumerable FindMembersByEmail(string emailStringToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) + public IEnumerable FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateMemberRepository(uow)) @@ -214,11 +217,13 @@ namespace Umbraco.Core.Services throw new ArgumentOutOfRangeException("matchType"); } - return repository.GetByQuery(query); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Email); + + //return repository.GetByQuery(query); } } - public IEnumerable FindMembersByUsername(string login, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) + public IEnumerable FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateMemberRepository(uow)) @@ -246,7 +251,9 @@ namespace Umbraco.Core.Services throw new ArgumentOutOfRangeException("matchType"); } - return repository.GetByQuery(query); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Username); + + //return repository.GetByQuery(query); } } diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 873e5c189d..76f565223e 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -123,7 +123,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello","hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByEmail("tes", StringPropertyMatchType.StartsWith); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByEmail("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith); Assert.AreEqual(10, found.Count()); } @@ -139,7 +140,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByEmail("test.com", StringPropertyMatchType.EndsWith); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByEmail("test.com", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith); Assert.AreEqual(11, found.Count()); } @@ -155,7 +157,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByEmail("test", StringPropertyMatchType.Contains); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByEmail("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains); Assert.AreEqual(11, found.Count()); } @@ -171,7 +174,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByEmail("hello@test.com", StringPropertyMatchType.Exact); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByEmail("hello@test.com", 0, 100, out totalRecs, StringPropertyMatchType.Exact); Assert.AreEqual(1, found.Count()); } @@ -187,7 +191,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByUsername("tes", StringPropertyMatchType.StartsWith); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByUsername("tes", 0, 100, out totalRecs, StringPropertyMatchType.StartsWith); Assert.AreEqual(10, found.Count()); } @@ -203,7 +208,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByUsername("llo", StringPropertyMatchType.EndsWith); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByUsername("llo", 0, 100, out totalRecs, StringPropertyMatchType.EndsWith); Assert.AreEqual(1, found.Count()); } @@ -219,7 +225,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hellotest"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByUsername("test", StringPropertyMatchType.Contains); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByUsername("test", 0, 100, out totalRecs, StringPropertyMatchType.Contains); Assert.AreEqual(11, found.Count()); } @@ -235,7 +242,8 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var found = ServiceContext.MemberService.FindMembersByUsername("hello", StringPropertyMatchType.Exact); + int totalRecs; + var found = ServiceContext.MemberService.FindMembersByUsername("hello", 0, 100, out totalRecs, StringPropertyMatchType.Exact); Assert.AreEqual(1, found.Count()); } diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index 133314d31a..d1b9c9a14e 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -203,12 +203,13 @@ namespace Umbraco.Web.Security.Providers /// public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { - var byEmail = MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray(); - totalRecords = byEmail.Length; - var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + var byEmail = MemberService.FindMembersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray(); + //totalRecords = byEmail.Length; + //var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); var collection = new MembershipUserCollection(); - foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + //foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + foreach (var m in byEmail) { collection.Add(m.AsConcreteMembershipUser()); } @@ -227,12 +228,13 @@ namespace Umbraco.Web.Security.Providers /// public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { - var byEmail = MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray(); - totalRecords = byEmail.Length; - var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + var byEmail = MemberService.FindMembersByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray(); + //totalRecords = byEmail.Length; + //var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); var collection = new MembershipUserCollection(); - foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + //foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + foreach (var m in byEmail) { collection.Add(m.AsConcreteMembershipUser()); } diff --git a/src/umbraco.providers/members/UmbracoMembershipProvider.cs b/src/umbraco.providers/members/UmbracoMembershipProvider.cs index 500444b3fd..6bac76be81 100644 --- a/src/umbraco.providers/members/UmbracoMembershipProvider.cs +++ b/src/umbraco.providers/members/UmbracoMembershipProvider.cs @@ -343,12 +343,13 @@ namespace umbraco.providers.members /// public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { - var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray(); - totalRecords = byEmail.Length; - var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray(); + //totalRecords = byEmail.Length; + //var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); var collection = new MembershipUserCollection(); - foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + //foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + foreach (var m in byEmail) { collection.Add(ConvertToMembershipUser(m)); } @@ -367,12 +368,13 @@ namespace umbraco.providers.members /// public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { - var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray(); - totalRecords = byEmail.Length; - var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByUsername(usernameToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray(); + //totalRecords = byEmail.Length; + //var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); var collection = new MembershipUserCollection(); - foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + //foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + foreach (var m in byEmail) { collection.Add(ConvertToMembershipUser(m)); }