mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-26 12:03:16 +08:00
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:
committed by
Sébastien Ros
parent
83f47ac148
commit
8a328902fd
@@ -24,7 +24,7 @@ using Orchard.Utility.Extensions;
|
|||||||
namespace Orchard.Projections.Drivers {
|
namespace Orchard.Projections.Drivers {
|
||||||
public class ProjectionPartDriver : ContentPartDriver<ProjectionPart> {
|
public class ProjectionPartDriver : ContentPartDriver<ProjectionPart> {
|
||||||
private readonly IRepository<QueryPartRecord> _queryRepository;
|
private readonly IRepository<QueryPartRecord> _queryRepository;
|
||||||
private readonly IProjectionManager _projectionManager;
|
private readonly IProjectionManagerExtension _projectionManager;
|
||||||
private readonly IFeedManager _feedManager;
|
private readonly IFeedManager _feedManager;
|
||||||
private readonly ITokenizer _tokenizer;
|
private readonly ITokenizer _tokenizer;
|
||||||
private readonly IDisplayHelperFactory _displayHelperFactory;
|
private readonly IDisplayHelperFactory _displayHelperFactory;
|
||||||
@@ -34,7 +34,7 @@ namespace Orchard.Projections.Drivers {
|
|||||||
public ProjectionPartDriver(
|
public ProjectionPartDriver(
|
||||||
IOrchardServices services,
|
IOrchardServices services,
|
||||||
IRepository<QueryPartRecord> queryRepository,
|
IRepository<QueryPartRecord> queryRepository,
|
||||||
IProjectionManager projectionManager,
|
IProjectionManagerExtension projectionManager,
|
||||||
IFeedManager feedManager,
|
IFeedManager feedManager,
|
||||||
ITokenizer tokenizer,
|
ITokenizer tokenizer,
|
||||||
IDisplayHelperFactory displayHelperFactory,
|
IDisplayHelperFactory displayHelperFactory,
|
||||||
@@ -110,7 +110,7 @@ namespace Orchard.Projections.Drivers {
|
|||||||
_feedManager.Register(metaData.DisplayText, "rss", new RouteValueDictionary { { "projection", part.Id } });
|
_feedManager.Register(metaData.DisplayText, "rss", new RouteValueDictionary { { "projection", part.Id } });
|
||||||
|
|
||||||
// execute the query
|
// 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
|
// 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();
|
contentItems = contentItems.Where(x => !x.Has<ProjectionPart>()).ToList();
|
||||||
@@ -122,7 +122,7 @@ namespace Orchard.Projections.Drivers {
|
|||||||
|
|
||||||
// create pager shape
|
// create pager shape
|
||||||
if (part.Record.DisplayPager) {
|
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);
|
contentItemsCount = Math.Max(0, contentItemsCount);
|
||||||
pagerShape.TotalItemCount(contentItemsCount);
|
pagerShape.TotalItemCount(contentItemsCount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,7 @@
|
|||||||
<Compile Include="Providers\Layouts\ShapeLayoutForms.cs" />
|
<Compile Include="Providers\Layouts\ShapeLayoutForms.cs" />
|
||||||
<Compile Include="Providers\Properties\CustomValueProperties.cs" />
|
<Compile Include="Providers\Properties\CustomValueProperties.cs" />
|
||||||
<Compile Include="Navigation\NavigationQueryProvider.cs" />
|
<Compile Include="Navigation\NavigationQueryProvider.cs" />
|
||||||
|
<Compile Include="Services\IProjectionManagerExtension.cs" />
|
||||||
<Compile Include="Shapes.cs" />
|
<Compile Include="Shapes.cs" />
|
||||||
<Compile Include="Descriptors\Layout\LayoutComponentResult.cs" />
|
<Compile Include="Descriptors\Layout\LayoutComponentResult.cs" />
|
||||||
<Compile Include="Descriptors\Layout\LayoutContext.cs" />
|
<Compile Include="Descriptors\Layout\LayoutContext.cs" />
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ using Orchard.Projections.Models;
|
|||||||
using Orchard.Tokens;
|
using Orchard.Tokens;
|
||||||
|
|
||||||
namespace Orchard.Projections.Services {
|
namespace Orchard.Projections.Services {
|
||||||
public class ProjectionManager : IProjectionManager{
|
public class ProjectionManager : IProjectionManagerExtension {
|
||||||
private readonly ITokenizer _tokenizer;
|
private readonly ITokenizer _tokenizer;
|
||||||
private readonly IEnumerable<IFilterProvider> _filterProviders;
|
private readonly IEnumerable<IFilterProvider> _filterProviders;
|
||||||
private readonly IEnumerable<ISortCriterionProvider> _sortCriterionProviders;
|
private readonly IEnumerable<ISortCriterionProvider> _sortCriterionProviders;
|
||||||
@@ -104,6 +104,33 @@ namespace Orchard.Projections.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int GetCount(int queryId) {
|
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);
|
var queryRecord = _queryRepository.Get(queryId);
|
||||||
|
|
||||||
@@ -111,36 +138,27 @@ namespace Orchard.Projections.Services {
|
|||||||
throw new ArgumentException("queryId");
|
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>();
|
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
|
// 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));
|
contentItems.AddRange(contentQuery.Slice(skip, count));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(queryRecord.FilterGroups.Count <= 1) {
|
if (queryRecord.FilterGroups.Count <= 1) {
|
||||||
return contentItems;
|
return contentItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-executing the sorting with the cumulated groups
|
// re-executing the sorting with the cumulated groups
|
||||||
var ids = contentItems.Select(c => c.Id).ToArray();
|
var ids = contentItems.Select(c => c.Id).ToArray();
|
||||||
|
|
||||||
if(ids.Length == 0) {
|
if (ids.Length == 0) {
|
||||||
return Enumerable.Empty<ContentItem>();
|
return Enumerable.Empty<ContentItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,9 +191,13 @@ namespace Orchard.Projections.Services {
|
|||||||
return groupQuery.Slice(skip, count);
|
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 availableFilters = DescribeFilters().ToList();
|
||||||
var availableSortCriteria = DescribeSortCriteria().ToList();
|
var availableSortCriteria = DescribeSortCriteria().ToList();
|
||||||
|
if (tokens == null) {
|
||||||
|
tokens = new Dictionary<string, object>();
|
||||||
|
}
|
||||||
|
|
||||||
// pre-executing all groups
|
// pre-executing all groups
|
||||||
foreach (var group in queryRecord.FilterGroups) {
|
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
|
// iterate over each filter to apply the alterations to the query object
|
||||||
foreach (var filter in group.Filters) {
|
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 {
|
var filterContext = new FilterContext {
|
||||||
Query = contentQuery,
|
Query = contentQuery,
|
||||||
State = FormParametersHelper.ToDynamic(tokenizedState)
|
State = FormParametersHelper.ToDynamic(tokenizedState)
|
||||||
@@ -237,7 +259,7 @@ namespace Orchard.Projections.Services {
|
|||||||
|
|
||||||
|
|
||||||
yield return contentQuery;
|
yield return contentQuery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user