mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Adding Query Hints and GetMany in Content Manager
--HG-- branch : 1.x
This commit is contained in:
@@ -5,12 +5,17 @@ using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml.Linq;
|
||||
using Autofac;
|
||||
using NHibernate;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.Metadata;
|
||||
using NHibernate.SqlCommand;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Logging;
|
||||
using Orchard.UI;
|
||||
@@ -24,6 +29,7 @@ namespace Orchard.ContentManagement {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly Func<IContentManagerSession> _contentManagerSession;
|
||||
private readonly Lazy<IContentDisplay> _contentDisplay;
|
||||
private readonly Work<ISessionLocator> _sessionLocator;
|
||||
private const string Published = "Published";
|
||||
private const string Draft = "Draft";
|
||||
|
||||
@@ -34,7 +40,8 @@ namespace Orchard.ContentManagement {
|
||||
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
Func<IContentManagerSession> contentManagerSession,
|
||||
Lazy<IContentDisplay> contentDisplay) {
|
||||
Lazy<IContentDisplay> contentDisplay,
|
||||
Work<ISessionLocator> sessionLocator) {
|
||||
_context = context;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_contentItemRepository = contentItemRepository;
|
||||
@@ -42,6 +49,7 @@ namespace Orchard.ContentManagement {
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
_contentManagerSession = contentManagerSession;
|
||||
_contentDisplay = contentDisplay;
|
||||
_sessionLocator = sessionLocator;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -50,8 +58,10 @@ namespace Orchard.ContentManagement {
|
||||
private IEnumerable<IContentHandler> _handlers;
|
||||
public IEnumerable<IContentHandler> Handlers {
|
||||
get {
|
||||
if (_handlers == null)
|
||||
if (_handlers == null) {
|
||||
_handlers = _context.Resolve<IEnumerable<IContentHandler>>();
|
||||
}
|
||||
|
||||
return _handlers;
|
||||
}
|
||||
}
|
||||
@@ -110,8 +120,9 @@ namespace Orchard.ContentManagement {
|
||||
// obtain the root records based on version options
|
||||
if (options.VersionRecordId != 0) {
|
||||
// short-circuit if item held in session
|
||||
if (session.RecallVersionRecordId(options.VersionRecordId, out contentItem))
|
||||
if (session.RecallVersionRecordId(options.VersionRecordId, out contentItem)) {
|
||||
return contentItem;
|
||||
}
|
||||
|
||||
// locate explicit version record
|
||||
versionRecord = _contentItemVersionRepository.Get(options.VersionRecordId);
|
||||
@@ -160,25 +171,25 @@ namespace Orchard.ContentManagement {
|
||||
private ContentItemVersionRecord GetVersionRecord(VersionOptions options, ContentItemRecord itemRecord) {
|
||||
if (options.IsPublished) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Published) ??
|
||||
x => x.Published) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Published);
|
||||
}
|
||||
if (options.IsLatest || options.IsDraftRequired) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Latest) ??
|
||||
x => x.Latest) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Latest);
|
||||
}
|
||||
if (options.IsDraft) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Latest && !x.Published) ??
|
||||
x => x.Latest && !x.Published) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Latest && !x.Published);
|
||||
}
|
||||
if (options.VersionNumber != 0) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Number == options.VersionNumber) ??
|
||||
x => x.Number == options.VersionNumber) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Number == options.VersionNumber);
|
||||
}
|
||||
@@ -192,6 +203,71 @@ namespace Orchard.ContentManagement {
|
||||
.Select(x => Get(x.ContentItemRecord.Id, VersionOptions.VersionRecord(x.Id)));
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetMany<T>(IEnumerable<int> ids, VersionOptions options, QueryHints hints) where T : class, IContent {
|
||||
var contentItemVersionRecords = GetManyImplementation(hints, (contentItemCriteria, contentItemVersionCriteria) => {
|
||||
contentItemCriteria.Add(Restrictions.In("Id", ids.ToArray()));
|
||||
if (options.IsPublished) {
|
||||
contentItemVersionCriteria.Add(Restrictions.Eq("Published", true));
|
||||
}
|
||||
else if (options.IsLatest) {
|
||||
contentItemVersionCriteria.Add(Restrictions.Eq("Latest", true));
|
||||
}
|
||||
else if (options.IsDraft) {
|
||||
contentItemVersionCriteria.Add(
|
||||
Restrictions.And(Restrictions.Eq("Published", false),
|
||||
Restrictions.Eq("Latest", true)));
|
||||
}
|
||||
});
|
||||
var itemsById = contentItemVersionRecords
|
||||
.Select(r => Get(r.ContentItemRecord.Id, VersionOptions.VersionRecord(r.Id)))
|
||||
.GroupBy(ci => ci.Id)
|
||||
.ToDictionary(g => g.Key);
|
||||
|
||||
return ids.SelectMany(id => {
|
||||
IGrouping<int, ContentItem> values;
|
||||
return itemsById.TryGetValue(id, out values) ? values : Enumerable.Empty<ContentItem>();
|
||||
}).AsPart<T>().ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetManyByVersionId<T>(IEnumerable<int> versionRecordIds, QueryHints hints) where T : class, IContent {
|
||||
var contentItemVersionRecords = GetManyImplementation(hints, (contentItemCriteria, contentItemVersionCriteria) =>
|
||||
contentItemVersionCriteria.Add(Restrictions.In("Id", versionRecordIds.ToArray())));
|
||||
|
||||
var itemsById = contentItemVersionRecords
|
||||
.Select(r => Get(r.ContentItemRecord.Id, VersionOptions.VersionRecord(r.Id)))
|
||||
.GroupBy(ci => ci.VersionRecord.Id)
|
||||
.ToDictionary(g => g.Key);
|
||||
|
||||
return versionRecordIds.SelectMany(id => {
|
||||
IGrouping<int, ContentItem> values;
|
||||
return itemsById.TryGetValue(id, out values) ? values : Enumerable.Empty<ContentItem>();
|
||||
}).AsPart<T>().ToArray();
|
||||
}
|
||||
|
||||
private IEnumerable<ContentItemVersionRecord> GetManyImplementation(QueryHints hints, Action<ICriteria, ICriteria> predicate) {
|
||||
var session = _sessionLocator.Value.For(typeof (ContentItemRecord));
|
||||
var contentItemVersionCriteria = session.CreateCriteria(typeof (ContentItemVersionRecord));
|
||||
var contentItemCriteria = contentItemVersionCriteria.CreateCriteria("ContentItemRecord");
|
||||
predicate(contentItemCriteria, contentItemVersionCriteria);
|
||||
|
||||
var hintDictionary = hints.Records.Distinct().ToDictionary(value => value);
|
||||
var contentItemMetadata = session.SessionFactory.GetClassMetadata(typeof (ContentItemRecord));
|
||||
var contentItemVersionMetadata = session.SessionFactory.GetClassMetadata(typeof (ContentItemVersionRecord));
|
||||
|
||||
ExpandHints(hintDictionary, contentItemMetadata, contentItemCriteria);
|
||||
ExpandHints(hintDictionary, contentItemVersionMetadata, contentItemVersionCriteria);
|
||||
|
||||
return contentItemVersionCriteria.List<ContentItemVersionRecord>();
|
||||
}
|
||||
|
||||
private static void ExpandHints(Dictionary<string, string> hintDictionary, IClassMetadata recordMetadata, ICriteria recordCriteria) {
|
||||
foreach (var associationPath in recordMetadata.PropertyNames.Where(hintDictionary.ContainsKey)) {
|
||||
if (recordCriteria.GetCriteriaByPath(associationPath) == null) {
|
||||
recordCriteria.CreateCriteria(associationPath, JoinType.LeftOuterJoin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Publish(ContentItem contentItem) {
|
||||
if (contentItem.VersionRecord.Published) {
|
||||
return;
|
||||
@@ -407,8 +483,9 @@ namespace Orchard.ContentManagement {
|
||||
// Call content item handlers.
|
||||
public void Import(XElement element, ImportContentSession importContentSession) {
|
||||
var elementId = element.Attribute("Id");
|
||||
if (elementId == null)
|
||||
if (elementId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var identity = elementId.Value;
|
||||
var status = element.Attribute("Status");
|
||||
@@ -487,8 +564,8 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
}
|
||||
|
||||
class CallSiteCollection : ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> {
|
||||
readonly Func<string, CallSite<Func<CallSite, object, object>>> _valueFactory;
|
||||
internal class CallSiteCollection : ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> {
|
||||
private readonly Func<string, CallSite<Func<CallSite, object, object>>> _valueFactory;
|
||||
|
||||
public CallSiteCollection(Func<string, CallSite<Func<CallSite, object, object>>> callSiteFactory) {
|
||||
_valueFactory = callSiteFactory;
|
||||
|
@@ -16,6 +16,9 @@ namespace Orchard.ContentManagement {
|
||||
ContentItem Get(int id, VersionOptions options);
|
||||
IEnumerable<ContentItem> GetAllVersions(int id);
|
||||
|
||||
IEnumerable<T> GetMany<T>(IEnumerable<int> ids, VersionOptions options, QueryHints hints) where T : class, IContent;
|
||||
IEnumerable<T> GetManyByVersionId<T>(IEnumerable<int> versionRecordIds, QueryHints hints) where T : class, IContent;
|
||||
|
||||
void Publish(ContentItem contentItem);
|
||||
void Unpublish(ContentItem contentItem);
|
||||
void Remove(ContentItem contentItem);
|
||||
|
202
src/Orchard/ContentManagement/QueryHints.cs
Normal file
202
src/Orchard/ContentManagement/QueryHints.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.ContentManagement
|
||||
{
|
||||
public class QueryHints
|
||||
{
|
||||
private readonly List<string> _records = new List<string>();
|
||||
private static readonly QueryHints _empty = new QueryHints();
|
||||
|
||||
public IEnumerable<string> Records
|
||||
{
|
||||
get { return _records; }
|
||||
}
|
||||
|
||||
public static QueryHints Empty
|
||||
{
|
||||
get { return _empty; }
|
||||
}
|
||||
|
||||
public QueryHints ExpandRecords(IEnumerable<string> records)
|
||||
{
|
||||
_records.AddRange(records);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryHints ExpandRecords(params string[] records)
|
||||
{
|
||||
_records.AddRange(records);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryHints ExpandRecords<TRecord1>() where TRecord1 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3, TRecord4>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
where TRecord4 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name, typeof(TRecord4).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3, TRecord4, TRecord5>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
where TRecord4 : ContentPartRecord
|
||||
where TRecord5 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name, typeof(TRecord4).Name, typeof(TRecord5).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3, TRecord4, TRecord5, TRecord6>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
where TRecord4 : ContentPartRecord
|
||||
where TRecord5 : ContentPartRecord
|
||||
where TRecord6 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name, typeof(TRecord4).Name, typeof(TRecord5).Name, typeof(TRecord6).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3, TRecord4, TRecord5, TRecord6, TRecord7>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
where TRecord4 : ContentPartRecord
|
||||
where TRecord5 : ContentPartRecord
|
||||
where TRecord6 : ContentPartRecord
|
||||
where TRecord7 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name, typeof(TRecord4).Name, typeof(TRecord5).Name, typeof(TRecord6).Name, typeof(TRecord7).Name });
|
||||
return this;
|
||||
}
|
||||
public QueryHints ExpandRecords<TRecord1, TRecord2, TRecord3, TRecord4, TRecord5, TRecord6, TRecord7, TRecord8>()
|
||||
where TRecord1 : ContentPartRecord
|
||||
where TRecord2 : ContentPartRecord
|
||||
where TRecord3 : ContentPartRecord
|
||||
where TRecord4 : ContentPartRecord
|
||||
where TRecord5 : ContentPartRecord
|
||||
where TRecord6 : ContentPartRecord
|
||||
where TRecord7 : ContentPartRecord
|
||||
where TRecord8 : ContentPartRecord
|
||||
{
|
||||
_records.AddRange(new[] { typeof(TRecord1).Name, typeof(TRecord2).Name, typeof(TRecord3).Name, typeof(TRecord4).Name, typeof(TRecord5).Name, typeof(TRecord6).Name, typeof(TRecord7).Name, typeof(TRecord8).Name });
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1>() where TPart1 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3, TPart4>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
where TPart4 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3), typeof(TPart4));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3, TPart4, TPart5>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
where TPart4 : ContentPart
|
||||
where TPart5 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3), typeof(TPart4), typeof(TPart5));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3, TPart4, TPart5, TPart6>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
where TPart4 : ContentPart
|
||||
where TPart5 : ContentPart
|
||||
where TPart6 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3), typeof(TPart4), typeof(TPart5), typeof(TPart6));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3, TPart4, TPart5, TPart6, TPart7>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
where TPart4 : ContentPart
|
||||
where TPart5 : ContentPart
|
||||
where TPart6 : ContentPart
|
||||
where TPart7 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3), typeof(TPart4), typeof(TPart5), typeof(TPart6), typeof(TPart7));
|
||||
}
|
||||
|
||||
public QueryHints ExpandParts<TPart1, TPart2, TPart3, TPart4, TPart5, TPart6, TPart7, TPart8>()
|
||||
where TPart1 : ContentPart
|
||||
where TPart2 : ContentPart
|
||||
where TPart3 : ContentPart
|
||||
where TPart4 : ContentPart
|
||||
where TPart5 : ContentPart
|
||||
where TPart6 : ContentPart
|
||||
where TPart7 : ContentPart
|
||||
where TPart8 : ContentPart
|
||||
{
|
||||
return ExpandPartsImpl(typeof(TPart1), typeof(TPart2), typeof(TPart3), typeof(TPart4), typeof(TPart5), typeof(TPart6), typeof(TPart7), typeof(TPart8));
|
||||
}
|
||||
|
||||
private QueryHints ExpandPartsImpl(params Type[] parts)
|
||||
{
|
||||
foreach (var part in parts)
|
||||
{
|
||||
for (var scan = part; scan != typeof(Object); scan = scan.BaseType)
|
||||
{
|
||||
if (scan.IsGenericType && scan.GetGenericTypeDefinition() == typeof(ContentPart<>))
|
||||
{
|
||||
_records.Add(scan.GetGenericArguments().Single().Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@@ -175,6 +175,7 @@
|
||||
<Compile Include="ContentManagement\Handlers\ImportContentContext.cs" />
|
||||
<Compile Include="ContentManagement\IContentBehavior.cs" />
|
||||
<Compile Include="ContentManagement\ImportContentSession.cs" />
|
||||
<Compile Include="ContentManagement\QueryHints.cs" />
|
||||
<Compile Include="ContentManagement\Utilities\ComputedField.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\PlacementInfo.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ResourceBindingStrategy\StylesheetBindingStrategy.cs" />
|
||||
@@ -186,6 +187,7 @@
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapePlacementStrategy\ShapePlacementParsingStrategy.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeTable.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeTableBuilder.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeTableLocator.cs" />
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeDisplayEvents.cs" />
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeFactoryEvents.cs" />
|
||||
<Compile Include="DisplayManagement\Shapes\ShapeDebugView.cs" />
|
||||
@@ -252,6 +254,7 @@
|
||||
<Compile Include="Security\Providers\DefaultEncryptionService.cs" />
|
||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||
<Compile Include="Themes\CurrentThemeWorkContext.cs" />
|
||||
<Compile Include="Themes\ThemeManager.cs" />
|
||||
<Compile Include="UI\FlatPositionComparer.cs" />
|
||||
<Compile Include="UI\Navigation\Pager.cs" />
|
||||
|
Reference in New Issue
Block a user