ProjectionManager Extension (#7417)

- Defined a new interface IProjectionManagerExtension that inherits from IProjectionManager
- ProjectionManager now implements IProjectionManagerExtension, so we can pass a part to GetCount and GetContentItems
- GetCount and GetContentItems transform the part into a Content token, so you can filter data with informations contained in the Projection itself
This commit is contained in:
Hermes Sbicego
2016-12-01 22:00:13 +01:00
committed by Sébastien Ros
parent 83f47ac148
commit 8a328902fd
4 changed files with 65 additions and 26 deletions

View File

@@ -24,7 +24,7 @@ using Orchard.Utility.Extensions;
namespace Orchard.Projections.Drivers {
public class ProjectionPartDriver : ContentPartDriver<ProjectionPart> {
private readonly IRepository<QueryPartRecord> _queryRepository;
private readonly IProjectionManager _projectionManager;
private readonly IProjectionManagerExtension _projectionManager;
private readonly IFeedManager _feedManager;
private readonly ITokenizer _tokenizer;
private readonly IDisplayHelperFactory _displayHelperFactory;
@@ -34,7 +34,7 @@ namespace Orchard.Projections.Drivers {
public ProjectionPartDriver(
IOrchardServices services,
IRepository<QueryPartRecord> queryRepository,
IProjectionManager projectionManager,
IProjectionManagerExtension projectionManager,
IFeedManager feedManager,
ITokenizer tokenizer,
IDisplayHelperFactory displayHelperFactory,
@@ -110,7 +110,7 @@ namespace Orchard.Projections.Drivers {
_feedManager.Register(metaData.DisplayText, "rss", new RouteValueDictionary { { "projection", part.Id } });
// execute the query
var contentItems = _projectionManager.GetContentItems(query.Id, pager.GetStartIndex() + part.Record.Skip, pager.PageSize).ToList();
var contentItems = _projectionManager.GetContentItems(query.Id, part, pager.GetStartIndex() + part.Record.Skip, pager.PageSize).ToList();
// sanity check so that content items with ProjectionPart can't be added here, or it will result in an infinite loop
contentItems = contentItems.Where(x => !x.Has<ProjectionPart>()).ToList();
@@ -122,7 +122,7 @@ namespace Orchard.Projections.Drivers {
// create pager shape
if (part.Record.DisplayPager) {
var contentItemsCount = _projectionManager.GetCount(query.Id) - part.Record.Skip;
var contentItemsCount = _projectionManager.GetCount(query.Id, part) - part.Record.Skip;
contentItemsCount = Math.Max(0, contentItemsCount);
pagerShape.TotalItemCount(contentItemsCount);
}

View File

@@ -175,6 +175,7 @@
<Compile Include="Providers\Layouts\ShapeLayoutForms.cs" />
<Compile Include="Providers\Properties\CustomValueProperties.cs" />
<Compile Include="Navigation\NavigationQueryProvider.cs" />
<Compile Include="Services\IProjectionManagerExtension.cs" />
<Compile Include="Shapes.cs" />
<Compile Include="Descriptors\Layout\LayoutComponentResult.cs" />
<Compile Include="Descriptors\Layout\LayoutContext.cs" />

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Projections.Descriptors;
using Orchard.Projections.Descriptors.Property;
using Orchard.Projections.Descriptors.Filter;
using Orchard.Projections.Descriptors.Layout;
using Orchard.Projections.Descriptors.SortCriterion;
namespace Orchard.Projections.Services {
public interface IProjectionManagerExtension : IProjectionManager {
IEnumerable<ContentItem> GetContentItems(int queryId, ContentPart part, int skip = 0, int count = 0);
int GetCount(int queryId, ContentPart part);
}
}

View File

@@ -14,7 +14,7 @@ using Orchard.Projections.Models;
using Orchard.Tokens;
namespace Orchard.Projections.Services {
public class ProjectionManager : IProjectionManager{
public class ProjectionManager : IProjectionManagerExtension {
private readonly ITokenizer _tokenizer;
private readonly IEnumerable<IFilterProvider> _filterProviders;
private readonly IEnumerable<ISortCriterionProvider> _sortCriterionProviders;
@@ -104,6 +104,33 @@ namespace Orchard.Projections.Services {
}
public int GetCount(int queryId) {
return GetCount(queryId, null);
}
public int GetCount(int queryId, ContentPart part) {
var queryRecord = _queryRepository.Get(queryId);
if (queryRecord == null) {
throw new ArgumentException("queryId");
}
// prepares tokens
Dictionary<string, object> tokens = new Dictionary<string, object>();
if (part != null) {
tokens.Add("Content", part.ContentItem);
}
// aggregate the result for each group query
return GetContentQueries(queryRecord, Enumerable.Empty<SortCriterionRecord>(), tokens)
.Sum(contentQuery => contentQuery.Count());
}
public IEnumerable<ContentItem> GetContentItems(int queryId, int skip = 0, int count = 0) {
return GetContentItems(queryId, null, skip, count);
}
public IEnumerable<ContentItem> GetContentItems(int queryId, ContentPart part, int skip = 0, int count = 0) {
var availableSortCriteria = DescribeSortCriteria().ToList();
var queryRecord = _queryRepository.Get(queryId);
@@ -111,36 +138,27 @@ namespace Orchard.Projections.Services {
throw new ArgumentException("queryId");
}
// aggregate the result for each group query
return GetContentQueries(queryRecord, Enumerable.Empty<SortCriterionRecord>())
.Sum(contentQuery => contentQuery.Count());
}
public IEnumerable<ContentItem> GetContentItems(int queryId, int skip = 0, int count = 0) {
var availableSortCriteria = DescribeSortCriteria().ToList();
var queryRecord = _queryRepository.Get(queryId);
if(queryRecord == null) {
throw new ArgumentException("queryId");
}
var contentItems = new List<ContentItem>();
// prepares tokens
Dictionary<string, object> tokens = new Dictionary<string, object>();
if (part != null) {
tokens.Add("Content", part.ContentItem);
}
// aggregate the result for each group query
foreach(var contentQuery in GetContentQueries(queryRecord, queryRecord.SortCriteria.OrderBy(sc => sc.Position))) {
foreach (var contentQuery in GetContentQueries(queryRecord, queryRecord.SortCriteria.OrderBy(sc => sc.Position), tokens)) {
contentItems.AddRange(contentQuery.Slice(skip, count));
}
if(queryRecord.FilterGroups.Count <= 1) {
if (queryRecord.FilterGroups.Count <= 1) {
return contentItems;
}
// re-executing the sorting with the cumulated groups
var ids = contentItems.Select(c => c.Id).ToArray();
if(ids.Length == 0) {
if (ids.Length == 0) {
return Enumerable.Empty<ContentItem>();
}
@@ -173,9 +191,13 @@ namespace Orchard.Projections.Services {
return groupQuery.Slice(skip, count);
}
public IEnumerable<IHqlQuery> GetContentQueries(QueryPartRecord queryRecord, IEnumerable<SortCriterionRecord> sortCriteria) {
public IEnumerable<IHqlQuery> GetContentQueries(QueryPartRecord queryRecord, IEnumerable<SortCriterionRecord> sortCriteria, Dictionary<string, object> tokens) {
var availableFilters = DescribeFilters().ToList();
var availableSortCriteria = DescribeSortCriteria().ToList();
if (tokens == null) {
tokens = new Dictionary<string, object>();
}
// pre-executing all groups
foreach (var group in queryRecord.FilterGroups) {
@@ -184,7 +206,7 @@ namespace Orchard.Projections.Services {
// iterate over each filter to apply the alterations to the query object
foreach (var filter in group.Filters) {
var tokenizedState = _tokenizer.Replace(filter.State, new Dictionary<string, object>());
var tokenizedState = _tokenizer.Replace(filter.State, tokens);
var filterContext = new FilterContext {
Query = contentQuery,
State = FormParametersHelper.ToDynamic(tokenizedState)
@@ -237,7 +259,7 @@ namespace Orchard.Projections.Services {
yield return contentQuery;
}
}
}
}
}