diff --git a/src/Umbraco.Core/Constants-ObjectTypes.cs b/src/Umbraco.Core/Constants-ObjectTypes.cs
index d364c1379c..229bd1b7d7 100644
--- a/src/Umbraco.Core/Constants-ObjectTypes.cs
+++ b/src/Umbraco.Core/Constants-ObjectTypes.cs
@@ -109,6 +109,11 @@ namespace Umbraco.Core
///
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
+ ///
+ /// Guid for a Media Type object.
+ ///
+ public static readonly Guid MemberGuid = new Guid(Member);
+
///
/// Guid for a Member Group object.
///
diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs
index 58d4d453b7..d708dfbf82 100644
--- a/src/Umbraco.Core/EnumerableExtensions.cs
+++ b/src/Umbraco.Core/EnumerableExtensions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
@@ -67,22 +68,15 @@ namespace Umbraco.Core
}
}
- /// The for each.
- /// The items.
- /// The func.
- /// item type
- /// Result type
- /// the Results
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
public static TResult[] ForEach(this IEnumerable items, Func func)
{
return items.Select(func).ToArray();
}
- /// The for each.
- /// The items.
- /// The action.
- /// Item type
- /// list of TItem
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
public static IEnumerable ForEach(this IEnumerable items, Action action)
{
if (items != null)
@@ -101,6 +95,7 @@ namespace Umbraco.Core
/// The select child.
/// Item type
/// list of TItem
+ [EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
public static IEnumerable FlattenList(this IEnumerable e, Func> f)
{
diff --git a/src/Umbraco.Core/Models/ContentTypeExtensions.cs b/src/Umbraco.Core/Models/ContentTypeExtensions.cs
index f0d8b10898..90488219fc 100644
--- a/src/Umbraco.Core/Models/ContentTypeExtensions.cs
+++ b/src/Umbraco.Core/Models/ContentTypeExtensions.cs
@@ -30,7 +30,8 @@ namespace Umbraco.Core.Models
return descendants;
}
- throw new NotSupportedException("The content type must be " + typeof(IContentType) + " or " + typeof(IMediaType));
+ //No other content types have children (i.e. member types)
+ return Enumerable.Empty();
}
///
diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs
index e3bfb6dde9..08fd990036 100644
--- a/src/Umbraco.Core/Services/EntityService.cs
+++ b/src/Umbraco.Core/Services/EntityService.cs
@@ -375,6 +375,18 @@ namespace Umbraco.Core.Services
}
}
+ ///
+ /// Returns a apged collection of children
+ ///
+ /// The parent id to return children for
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public IEnumerable GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
{
diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs
index 339b0b7146..2239cb058b 100644
--- a/src/Umbraco.Core/Services/IEntityService.cs
+++ b/src/Umbraco.Core/Services/IEntityService.cs
@@ -138,6 +138,18 @@ namespace Umbraco.Core.Services
/// An enumerable list of objects
IEnumerable GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType);
+ ///
+ /// Returns a apged collection of children
+ ///
+ /// The parent id to return children for
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
IEnumerable GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index 989e3dbabe..5e23e1f0d2 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -409,18 +409,45 @@ namespace Umbraco.Web.Editors
string filter = "")
{
int intId;
- if (id == Constants.Conventions.MemberTypes.AllMembersListId)
- {
- intId = 0;
- return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
- }
-
- if(int.TryParse(id, out intId))
+
+ if (int.TryParse(id, out intId))
{
return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
}
- throw new HttpResponseException(HttpStatusCode.NotFound);
+ Guid guidId;
+ if (Guid.TryParse(id, out guidId))
+ {
+ //Not supported currently
+ throw new HttpResponseException(HttpStatusCode.NotFound);
+ }
+
+ Udi udiId;
+ if (Udi.TryParse(id, out udiId))
+ {
+ //Not supported currently
+ throw new HttpResponseException(HttpStatusCode.NotFound);
+ }
+
+ //so we don't have an INT, GUID or UDI, it's just a string, so now need to check if it's a special id or a member type
+ if (id == Constants.Conventions.MemberTypes.AllMembersListId)
+ {
+ //the EntityService can search paged members from the root
+
+ intId = -1;
+ return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
+ }
+
+ //the EntityService cannot search members of a certain type, this is currently not supported and would require
+ //quite a bit of plumbing to do in the Services/Repository, we'll revert to a paged search
+
+ int total;
+ var searchResult = ExamineSearch(filter ?? "", type, pageSize, pageNumber - 1, out total, id);
+
+ return new PagedResult(total, pageNumber, pageSize)
+ {
+ Items = searchResult
+ };
}
///
@@ -496,12 +523,30 @@ namespace Umbraco.Web.Editors
///
///
///
- ///
- /// A starting point for the search, generally a node id, but for members this is a member type alias
- ///
+ ///
///
private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null)
{
+ int total;
+ return ExamineSearch(query, entityType, 200, 0, out total, searchFrom);
+ }
+
+ ///
+ /// Searches for results based on the entity type
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A starting point for the search, generally a node id, but for members this is a member type alias
+ ///
+ ///
+ ///
+ ///
+ private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, int pageSize, int pageIndex, out int totalFound, string searchFrom = null)
+ {
+ //TODO: We need to update this to support paging
+
var sb = new StringBuilder();
string type;
@@ -577,91 +622,113 @@ namespace Umbraco.Web.Editors
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
- if (query.IsNullOrWhiteSpace())
+ //nothing to search
+ if (searchFrom.IsNullOrWhiteSpace() && query.IsNullOrWhiteSpace())
{
+ totalFound = 0;
return new List();
}
- //add back the surrounding quotes
- query = string.Format("{0}{1}{0}", "\"", query);
-
- //node name exactly boost x 10
- sb.Append("+(__nodeName: (");
- sb.Append(query.ToLower());
- sb.Append(")^10.0 ");
-
- foreach (var f in fields)
+ //update the query with the query term
+ if (query.IsNullOrWhiteSpace() == false)
{
- //additional fields normally
- sb.Append(f);
- sb.Append(": (");
- sb.Append(query);
+ //add back the surrounding quotes
+ query = string.Format("{0}{1}{0}", "\"", query);
+
+ //node name exactly boost x 10
+ sb.Append("+(__nodeName: (");
+ sb.Append(query.ToLower());
+ sb.Append(")^10.0 ");
+
+ foreach (var f in fields)
+ {
+ //additional fields normally
+ sb.Append(f);
+ sb.Append(": (");
+ sb.Append(query);
+ sb.Append(") ");
+ }
+
sb.Append(") ");
}
}
else
{
- if (query.Trim(new[] { '\"', '\'' }).IsNullOrWhiteSpace())
+ var trimmed = query.Trim(new[] {'\"', '\''});
+
+ //nothing to search
+ if (searchFrom.IsNullOrWhiteSpace() && trimmed.IsNullOrWhiteSpace())
{
+ totalFound = 0;
return new List();
}
-
- query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
- var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
-
- //node name exactly boost x 10
- sb.Append("+(__nodeName:");
- sb.Append("\"");
- sb.Append(query.ToLower());
- sb.Append("\"");
- sb.Append("^10.0 ");
-
- //node name normally with wildcards
- sb.Append(" __nodeName:");
- sb.Append("(");
- foreach (var w in querywords)
+ //update the query with the query term
+ if (trimmed.IsNullOrWhiteSpace() == false)
{
- sb.Append(w.ToLower());
- sb.Append("* ");
- }
- sb.Append(") ");
+ query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
+ var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (var f in fields)
- {
- //additional fields normally
- sb.Append(f);
- sb.Append(":");
+ //node name exactly boost x 10
+ sb.Append("+(__nodeName:");
+ sb.Append("\"");
+ sb.Append(query.ToLower());
+ sb.Append("\"");
+ sb.Append("^10.0 ");
+
+ //node name normally with wildcards
+ sb.Append(" __nodeName:");
sb.Append("(");
foreach (var w in querywords)
{
sb.Append(w.ToLower());
sb.Append("* ");
}
- sb.Append(")");
- sb.Append(" ");
+ sb.Append(") ");
+
+
+ foreach (var f in fields)
+ {
+ //additional fields normally
+ sb.Append(f);
+ sb.Append(":");
+ sb.Append("(");
+ foreach (var w in querywords)
+ {
+ sb.Append(w.ToLower());
+ sb.Append("* ");
+ }
+ sb.Append(")");
+ sb.Append(" ");
+ }
+
+ sb.Append(") ");
}
}
//must match index type
- sb.Append(") +__IndexType:");
+ sb.Append("+__IndexType:");
sb.Append(type);
-
var raw = internalSearcher.CreateSearchCriteria().RawQuery(sb.ToString());
- //limit results to 200 to avoid huge over processing (CPU)
- var result = internalSearcher.Search(raw, 200);
+ var result = internalSearcher
+ //only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested
+ .Search(raw, pageSize * (pageIndex + 1));
+ totalFound = result.TotalItemCount;
+
+ var pagedResult = result.Skip(pageIndex);
+
switch (entityType)
{
case UmbracoEntityTypes.Member:
- return MemberFromSearchResults(result);
+ return MemberFromSearchResults(pagedResult.ToArray());
case UmbracoEntityTypes.Media:
- return MediaFromSearchResults(result);
+ return MediaFromSearchResults(pagedResult);
case UmbracoEntityTypes.Document:
- return ContentFromSearchResults(result);
+ return ContentFromSearchResults(pagedResult);
default:
throw new NotSupportedException("The " + typeof(EntityController) + " currently does not support searching against object type " + entityType);
}
@@ -672,7 +739,7 @@ namespace Umbraco.Web.Editors
///
///
///
- private IEnumerable MemberFromSearchResults(ISearchResults results)
+ private IEnumerable MemberFromSearchResults(SearchResult[] results)
{
var mapped = Mapper.Map>(results).ToArray();
//add additional data
@@ -706,7 +773,7 @@ namespace Umbraco.Web.Editors
///
///
///
- private IEnumerable MediaFromSearchResults(ISearchResults results)
+ private IEnumerable MediaFromSearchResults(IEnumerable results)
{
var mapped = Mapper.Map>(results).ToArray();
//add additional data
@@ -726,9 +793,9 @@ namespace Umbraco.Web.Editors
///
///
///
- private IEnumerable ContentFromSearchResults(ISearchResults results)
+ private IEnumerable ContentFromSearchResults(IEnumerable results)
{
- var mapped = Mapper.Map>(results).ToArray();
+ var mapped = Mapper.Map>(results).ToArray();
//add additional data
foreach (var m in mapped)
{
diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
index cd6b9b9f83..5be9d550e5 100644
--- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
@@ -21,7 +21,14 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(x.NodeObjectTypeId), x.Key)))
.ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon))
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
- .ForMember(x => x.Alias, expression => expression.Ignore());
+ .ForMember(x => x.Alias, expression => expression.Ignore())
+ .AfterMap((entity, basic) =>
+ {
+ if (entity.NodeObjectTypeId == Constants.ObjectTypes.MemberGuid && basic.Icon.IsNullOrWhiteSpace())
+ {
+ basic.Icon = "icon-user";
+ }
+ });
config.CreateMap()
.ForMember(x => x.Udi, expression => expression.Ignore())
@@ -151,6 +158,9 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap>()
.ConvertUsing(results => results.Select(Mapper.Map).ToList());
+
+ config.CreateMap, IEnumerable>()
+ .ConvertUsing(results => results.Select(Mapper.Map).ToList());
}
}
}
\ No newline at end of file