From 8a328902fd41f89ed8bd8d84da1ad6b9e3574742 Mon Sep 17 00:00:00 2001 From: Hermes Sbicego Date: Thu, 1 Dec 2016 22:00:13 +0100 Subject: [PATCH] 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 --- .../Drivers/ProjectionPartDriver.cs | 8 +-- .../Orchard.Projections.csproj | 1 + .../Services/IProjectionManagerExtension.cs | 16 +++++ .../Services/ProjectionManager.cs | 66 ++++++++++++------- 4 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Projections/Services/IProjectionManagerExtension.cs diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs index 42d618f60..0283d3bda 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs @@ -24,7 +24,7 @@ using Orchard.Utility.Extensions; namespace Orchard.Projections.Drivers { public class ProjectionPartDriver : ContentPartDriver { private readonly IRepository _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 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()).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); } diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Orchard.Projections.csproj b/src/Orchard.Web/Modules/Orchard.Projections/Orchard.Projections.csproj index 8eaa2ccfc..003e87bd9 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Orchard.Projections.csproj +++ b/src/Orchard.Web/Modules/Orchard.Projections/Orchard.Projections.csproj @@ -175,6 +175,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Services/IProjectionManagerExtension.cs b/src/Orchard.Web/Modules/Orchard.Projections/Services/IProjectionManagerExtension.cs new file mode 100644 index 000000000..cad06b62e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Projections/Services/IProjectionManagerExtension.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 GetContentItems(int queryId, ContentPart part, int skip = 0, int count = 0); + int GetCount(int queryId, ContentPart part); + } + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Services/ProjectionManager.cs b/src/Orchard.Web/Modules/Orchard.Projections/Services/ProjectionManager.cs index 665197b45..69e343132 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Services/ProjectionManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Services/ProjectionManager.cs @@ -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 _filterProviders; private readonly IEnumerable _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 tokens = new Dictionary(); + if (part != null) { + tokens.Add("Content", part.ContentItem); + } + + // aggregate the result for each group query + return GetContentQueries(queryRecord, Enumerable.Empty(), tokens) + .Sum(contentQuery => contentQuery.Count()); + } + + public IEnumerable GetContentItems(int queryId, int skip = 0, int count = 0) { + return GetContentItems(queryId, null, skip, count); + } + + public IEnumerable 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()) - .Sum(contentQuery => contentQuery.Count()); - } - - public IEnumerable 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(); + // prepares tokens + Dictionary tokens = new Dictionary(); + 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(); } @@ -173,9 +191,13 @@ namespace Orchard.Projections.Services { return groupQuery.Slice(skip, count); } - public IEnumerable GetContentQueries(QueryPartRecord queryRecord, IEnumerable sortCriteria) { + public IEnumerable GetContentQueries(QueryPartRecord queryRecord, IEnumerable sortCriteria, Dictionary tokens) { + var availableFilters = DescribeFilters().ToList(); var availableSortCriteria = DescribeSortCriteria().ToList(); + if (tokens == null) { + tokens = new Dictionary(); + } // 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()); + 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; - } + } } } }