我在Orchard中构建了一个自定义模块,用于创建新的部件,类型和自定义活动,但我正在努力完成我需要做的最后一部分,即创建所有内容项的副本与特定父项关联。
例如,有人创建了一个"贸易展览会" (我的模块中的新类型),可以创建各种子页面(方向,供应商地图等),因为客户端一次只运行一个节目。我需要做的是,当他们创建一个新的贸易展时,我希望得到最新的展览(我通过_contentManager.HqlQuery().ForType("TradeShow").ForVersion(VersionOptions.Latest).ForVersion(VersionOptions.Published).List().Last()
做的(积极的,这不是最有效的方式) ,但它起作用,并且记录计数在五年后将为~10,然后找到所有那些与旧节目相关的子页面并将它们复制到新的内容项目中。它们必须是副本,因为有时他们可能有用旧的节目参考部分,或者它可以改变等等。所有通常的原因。
如何查找引用活动中之前节目的所有内容项?这是我的活动全班:
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Autoroute.Services;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Projections.Models;
using Orchard.Projections.Services;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
using Orchard.Workflows.Activities;
namespace Orchard.Web.Modules.TradeShows.Activities
{
public class TradeShowPublishedActivity : Task
{
private readonly IContentManager _contentManager;
private readonly IAutorouteService _autorouteService;
private readonly IProjectionManager _projectionManager;
public TradeShowPublishedActivity(IContentManager contentManager, IAutorouteService autorouteService, IProjectionManager projectionManager)
{
_contentManager = contentManager;
_autorouteService = autorouteService;
_projectionManager = projectionManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public override LocalizedString Category
{
get { return T("Flow"); }
}
public override LocalizedString Description
{
get { return T("Handles the automatic creation of content pages for the new show."); }
}
public override string Name
{
get { return "TradeShowPublished"; }
}
public override string Form
{
get { return null; }
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext)
{
yield return T("Done");
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext)
{
var priorShow = _contentManager.HqlQuery().ForType("TradeShow").ForVersion(VersionOptions.Latest).ForVersion(VersionOptions.Published).List().Last();
var tradeShowPart = priorShow.Parts.Where(p => p.PartDefinition.Name == "TradeShowContentPart").Single();
//new show alias
//workflowContext.Content.ContentItem.As<Orchard.Autoroute.Models.AutoroutePart>().DisplayAlias
yield return T("Done");
}
}
}
我的Migrations.cs
文件设置用于子页面的部分以引用父节目,如下所示:
ContentDefinitionManager.AlterPartDefinition("AssociatedTradeShowPart", builder => builder.WithField("Trade Show", cfg => cfg.OfType("ContentPickerField")
.WithDisplayName("Trade Show")
.WithSetting("ContentPickerFieldSettings.Attachable", "true")
.WithSetting("ContentPickerFieldSettings.Description", "Select the trade show this item is for.")
.WithSetting("ContentPickerFieldSettings.Required", "true")
.WithSetting("ContentPickerFieldSettings.DisplayedContentTypes", "TradeShow")
.WithSetting("ContentPickerFieldSettings.Multiple", "false")
.WithSetting("ContentPickerFieldSettings.ShowContentTab", "true")));
然后,我的子页面(现在只有一个,但还有更多)会像这样创建:
ContentDefinitionManager.AlterTypeDefinition("ShowDirections", cfg => cfg.DisplayedAs("Show Directions")
.WithPart("AutoroutePart", builder => builder.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: '{Content.Slug}', Description: 'international-trade-show'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("CommonPart", builder => builder.WithSetting("DateEditorSettings.ShowDateEditor", "false"))
.WithPart("PublishLaterPart")
.WithPart("TitlePart")
.WithPart("AssociatedTradeShowPart") /* allows linking to parent show */
.WithPart("ContainablePart", builder => builder.WithSetting("ContainablePartSettings.ShowContainerPicker", "true"))
.WithPart("BodyPart"));
答案 0 :(得分:0)
因此,您拥有了Trade Show内容项,下一步将是使用ContentPickerField查找所有部分,然后将该列表过滤到该字段包含您的节目ID的那些部分。
var items = _contentManager.Query().List().ToList() // Select all content items
.Select(p => (p.Parts
// Select all parts on content items
.Where(f => f.Fields.Where(d =>
d.FieldDefinition.Name == typeof(ContentPickerField).Name &&
// See if any of the fields are ContentPickerFields
(d as ContentPickerField).Ids.ToList().Contains(priorShow.Id)).Any())));
// That field contains the Id of the show
这可能会变得很昂贵,具体取决于数据库中有多少内容项。