3

我在 Orchard 中构建了一个自定义模块,该模块创建了一个新部件、类型和自定义活动,但我正在努力完成我需要做的最后一部分,即创建与特定父级关联的所有内容项的副本物品。

例如,当有人创建“贸易展”(我的模块中的新类型)时,可以从中创建各种子页面(方向、供应商地图等),因为客户端一次运行一个节目。我需要做的是,当他们创建一个新的贸易展览时,我想获得最近的先前展览(我正在通过_contentManager.HqlQuery().ForType("TradeShow").ForVersion(VersionOptions.Latest).ForVersion(VersionOptions.Published).List().Last()(肯定这不是最有效的方式,但它有效并且记录数将是〜 5 年后 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"));
4

1 回答 1

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

这可能会变得昂贵,具体取决于您的数据库中有多少内容项。

于 2017-06-07T17:46:58.033 回答