2015-01-05 4 views
3

Я создал пользовательский модуль в Orchard, который создает новую часть, тип и пользовательскую активность, но я борюсь с последней частью того, что мне нужно сделать, чтобы создать копию всех элементы контента, связанные с определенным родительским элементом.Orchard Custom Workflow Activity

Например, когда кто-то создает «торговую выставку» (новый тип из моего модуля), из него могут быть созданы различные подстраницы (направления, карты поставщиков и т. Д.), Поскольку клиент запускает одно шоу за раз , Что мне нужно сделать, когда они создают новую выставку, я хочу получить последнее предыдущее шоу (которое я делаю через _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"))); 

Тогда мои детские страницы (только один на данный момент, но еще много Coming) созданы как это:

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

Так у вас есть Trade Show элемент контента, следующий шаг будет найти все части с ContentPickerField, затем отфильтровать этот список до тех, где поле содержит идентификатор вашего шоу.

 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 

Это может стоить дорого в зависимости от количества элементов контента в вашей базе данных.

Смежные вопросы