mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00

I think the problem is that the TermsPartHandler triggers the TermCountProcessor as a Task async and the TermCountProcessor used the ContentTypeId as a parameter. If a ContentItem gets deleted, the TermCountProcessor cannot access it anymore and the Terms won't getting reprocessed which results in a wrong count. I altered the ITermCountProcessor interface to accept TermPartRecordId's instead of the ContentTypeId and use this id's directly. I also had to add a call for the ITermCountProcessor in the TermService UpdateTerm method. This is because when you re-publish a ContentItem only the new Terms are available in the PublishedEvent - but also terms from the previous version needed to be processed.
116 lines
5.6 KiB
C#
116 lines
5.6 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Orchard.ContentManagement.Utilities;
|
|
using Orchard.Taxonomies.Fields;
|
|
using Orchard.Taxonomies.Models;
|
|
using Orchard.Taxonomies.Services;
|
|
using Orchard.ContentManagement;
|
|
using Orchard.ContentManagement.Handlers;
|
|
using Orchard.ContentManagement.MetaData;
|
|
using Orchard.Core.Title.Models;
|
|
using Orchard.Data;
|
|
using Orchard.Environment.State;
|
|
using Orchard.Environment.Configuration;
|
|
using Orchard.Environment.Descriptor;
|
|
|
|
namespace Orchard.Taxonomies.Handlers {
|
|
public class TermsPartHandler : ContentHandler {
|
|
private readonly IContentDefinitionManager _contentDefinitionManager;
|
|
private readonly IContentManager _contentManager;
|
|
|
|
public TermsPartHandler(
|
|
IContentDefinitionManager contentDefinitionManager,
|
|
IRepository<TermsPartRecord> repository,
|
|
ITaxonomyService taxonomyService,
|
|
IContentManager contentManager,
|
|
IProcessingEngine processingEngine,
|
|
ShellSettings shellSettings,
|
|
IShellDescriptorManager shellDescriptorManager) {
|
|
_contentDefinitionManager = contentDefinitionManager;
|
|
_contentManager = contentManager;
|
|
|
|
Filters.Add(StorageFilter.For(repository));
|
|
OnPublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
|
|
OnUnpublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
|
|
OnRemoved<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
|
|
|
|
// Tells how to load the field terms on demand, when a content item it loaded or when it has been created
|
|
OnInitialized<TermsPart>((context, part) => InitializerTermsLoader(part));
|
|
OnLoading<TermsPart>((context, part) => InitializerTermsLoader(part));
|
|
OnUpdating<TermsPart>((context, part) => InitializerTermsLoader(part));
|
|
|
|
OnIndexing<TermsPart>(
|
|
(context, part) => {
|
|
|
|
foreach (var term in part.Terms) {
|
|
var termContentItem = context.ContentManager.Get(term.TermRecord.Id);
|
|
context.DocumentIndex.Add(term.Field, termContentItem.As<TitlePart>().Title).Analyze();
|
|
context.DocumentIndex.Add(term.Field + "-id", termContentItem.Id).Store();
|
|
// tag the current content item with all parent terms
|
|
foreach (var parent in taxonomyService.GetParents(termContentItem.As<TermPart>())) {
|
|
context.DocumentIndex.Add(term.Field + "-id", parent.Id).Store();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void InitializerTermsLoader(TermsPart part) {
|
|
if (part._termParts != null) {
|
|
return;
|
|
}
|
|
|
|
var queryHint = new QueryHints()
|
|
.ExpandRecords("ContentTypeRecord", "CommonPartRecord", "TermsPartRecord");
|
|
|
|
|
|
foreach (var field in part.ContentItem.Parts.SelectMany(p => p.Fields).OfType<TaxonomyField>()) {
|
|
var tempField = field.Name;
|
|
field.TermsField.Loader(value => {
|
|
var fieldTermRecordIds = part.Record.Terms.Where(t => t.Field == tempField).Select(tci => tci.TermRecord.Id);
|
|
var terms = _contentManager.GetMany<TermPart>(fieldTermRecordIds, VersionOptions.Published, queryHint);
|
|
return terms.ToList();
|
|
});
|
|
}
|
|
|
|
part._termParts = new LazyField<IEnumerable<TermContentItemPart>>();
|
|
part._termParts.Loader(value => {
|
|
var ids = part.Terms.Select(t => t.TermRecord.Id).Distinct();
|
|
var terms = _contentManager.GetMany<TermPart>(ids, VersionOptions.Published, queryHint)
|
|
.ToDictionary(t => t.Id, t => t);
|
|
return
|
|
part.Terms.Select(
|
|
x =>
|
|
new TermContentItemPart {
|
|
Field = x.Field,
|
|
TermPart = terms[x.TermRecord.Id]
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
|
|
// Fires off a processing engine task to run the count processing after the request so it's non-blocking.
|
|
private void RecalculateCount(IProcessingEngine processingEngine, ShellSettings shellSettings, IShellDescriptorManager shellDescriptorManager, TermsPart part) {
|
|
var termPartRecordIds = part.Terms.Select(t => t.TermRecord.Id).ToArray();
|
|
processingEngine.AddTask(shellSettings, shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termPartRecordIds", termPartRecordIds } });
|
|
|
|
}
|
|
|
|
protected override void Activating(ActivatingContentContext context) {
|
|
base.Activating(context);
|
|
|
|
// weld the TermsPart dynamically, if a field has been assigned to one of its parts
|
|
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(context.ContentType);
|
|
if (contentTypeDefinition == null) {
|
|
return;
|
|
}
|
|
|
|
if (contentTypeDefinition.Parts.Any(
|
|
part => part.PartDefinition.Fields.Any(
|
|
field => field.FieldDefinition.Name == typeof(TaxonomyField).Name))) {
|
|
|
|
context.Builder.Weld<TermsPart>();
|
|
}
|
|
}
|
|
}
|
|
} |