2016-06-07 39 views
1

我有一个内容部分提供了一个开始时间戳和结束时间戳选项。这两个字段用于定义内容项目应该显示的时间段。如何跳过在Orchard CMS中显示内容项目?

我现在很难实现跳过方法,而内容项目在时间段不跨越当前时间时不应显示/跳过。

挖的源代码,并试图找到我的方法的切入点取得了以下内容处理器

public class SkipContentHandler : Orchard.ContentManagement.Handlers.ContentHandler 
{ 
    protected override void BuildDisplayShape(Orchard.ContentManagement.Handlers.BuildDisplayContext aContext) 
    { 
    if (...) // my condition to process only content shapes which need to be skipped 
    { 
     aContext.Shape = null; // return null shape to skip it 
    } 
    } 
} 

这工作,但也有一些副作用

  • 我不得不改变BuildDisplayContext的源代码作为Shape通常只读
  • 如果列表形状包含带有我的内容部分的内容项时可能显示错误的寻呼机,因为Count()呼叫ContainerPartDriver.Display()之前BuildDisplay()
  • 调用是一个异常跳过结果的内容项的URL,因为View(null)是abigious

那么执行的,你会在这里是正确的做法或有任何模块存在这样的工作吗?我找不到一个。

+1

您可能想考虑只是在时间跨度到期时注册'unpublish'事件 – devqon

+0

@devqon是的,我也考虑过这个问题。但是这需要一些定期运行的后台任务,并且此任务需要查询所有内容项以搜索正确的内容以取消发布。另外,我不喜欢取消发布,因为它可能会混淆以前点击发布按钮的用户。我仍然希望有办法以某种方式安全地中止渲染形状...... – ViRuSTriNiTy

+0

您可能会成功阻止渲染,但是如上所述,您仍然会遇到'Count'问题。因此,分页可能会失败,并可能更多 – devqon

回答

1

这是一个相当复杂的任务。有达到适当跳跃的显示项目需要以下几个步骤:

  1. 创建部分正确

    这里还有一些缺陷如来增加局部视图的任务时可能会利用Orchards日期时间编辑器与DateTime属性相关联。但是这给桌面带来了很多额外的问题,但这些并不涉及这个问题。

    如果有人对如何使用Orchards日期时间编辑器感兴趣,那么我也可以发布此代码,但现在它只会不必要地炸毁代码。

    所以在这里我们去,部分类...

    public class ValidityPart : Orchard.ContentManagement.ContentPart<ValidityPartRecord> 
    { 
        // public 
        public System.DateTime? ValidFromUtc 
        { 
         get { return Retrieve(r => r.ValidFromUtc); } 
         set { Store(r => r.ValidFromUtc, value); } 
        } 
    
        ... 
    
        public System.DateTime? ValidTillUtc 
        { 
         get { return Retrieve(r => r.ValidTillUtc); } 
         set { Store(r => r.ValidTillUtc, value); } 
        } 
    
        ... 
    
        public bool IsContentItemValid() 
        { 
         var lUtcNow = System.DateTime.UtcNow; 
    
         return (ValidFromUtc == null || ValidFromUtc.Value <= lUtcNow) && (ValidTillUtc == null || ValidTillUtc.Value >= lUtcNow); 
        } 
    
        ... 
    } 
    

    ...和记录类...

    public class ValidityPartRecord : Orchard.ContentManagement.Records.ContentPartRecord 
    { 
        // valid from value as UTC to use Orchard convention (see CommonPart table) and to be compatible with projections 
        // (date/time tokens work with UTC values, see https://github.com/OrchardCMS/Orchard/issues/6963 for a related issue) 
        public virtual System.DateTime? ValidFromUtc { get; set; } 
    
        // valid from value as UTC to use Orchard convention (see CommonPart table) and to be compatible with projections 
        // (date/time tokens work with UTC values, see https://github.com/OrchardCMS/Orchard/issues/6963 for a related issue) 
        public virtual System.DateTime? ValidTillUtc { get; set; } 
    } 
    
  2. 创建自定义内容查询类

    public class MyContentQuery : Orchard.ContentManagement.DefaultContentQuery 
    { 
        // public 
        public ContentQuery(Orchard.ContentManagement.IContentManager aContentManager, 
         Orchard.Data.ITransactionManager aTransactionManager, 
         Orchard.Caching.ICacheManager aCacheManager, 
         Orchard.Caching.ISignals aSignals, 
         Orchard.Data.IRepository<Orchard.ContentManagement.Records.ContentTypeRecord> aContentTypeRepository, 
         Orchard.IWorkContextAccessor aWorkContextAccessor) 
         : base(aContentManager, aTransactionManager, aCacheManager, aSignals, aContentTypeRepository) 
        { 
         mWorkContextAccessor = aWorkContextAccessor; 
        } 
    
        protected override void BeforeExecuteQuery(NHibernate.ICriteria aContentItemVersionCriteria) 
        { 
         base.BeforeExecuteQuery(aContentItemVersionCriteria); 
    
         // note: 
         // this method will be called each time a query for multiple items is going to be executed (e.g. content items of a container, layers, menus), 
         // this gives us the chance to add a validity criteria 
    
         var lWorkContext = mWorkContextAccessor.GetContext(); 
    
         // exclude admin as content items should still be displayed/accessible when invalid as validity needs to be editable 
         if (lWorkContext == null || !Orchard.UI.Admin.AdminFilter.IsApplied(lWorkContext.HttpContext.Request.RequestContext)) 
         { 
         var lUtcNow = System.DateTime.UtcNow; 
    
         // left outer join of ValidityPartRecord table as part is optional (not present on all content types) 
         var ValidityPartRecordCriteria = aContentItemVersionCriteria.CreateCriteria(
          "ContentItemRecord.ValidityPartRecord", // string adopted from foreach loops in Orchard.ContentManagement.DefaultContentQuery.WithQueryHints() 
          NHibernate.SqlCommand.JoinType.LeftOuterJoin 
         ); 
    
         // add validity criterion 
         ValidityPartRecordCriteria.Add( 
          NHibernate.Criterion.Restrictions.And(
          NHibernate.Criterion.Restrictions.Or(
           NHibernate.Criterion.Restrictions.IsNull("ValidFromUtc"), 
           NHibernate.Criterion.Restrictions.Le("ValidFromUtc", lUtcNow) 
          ), 
          NHibernate.Criterion.Restrictions.Or(
           NHibernate.Criterion.Restrictions.IsNull("ValidTillUtc"), 
           NHibernate.Criterion.Restrictions.Ge("ValidTillUtc", lUtcNow) 
          ) 
         ) 
         ); 
         } 
        } 
    
        // private 
        Orchard.IWorkContextAccessor mWorkContextAccessor; 
    } 
    

    这实质上增加了有效部分字段的左连接到SQL查询(内容查询)并使用有效性条件扩展WHERE语句。

    请注意,这一步是唯一可能的解决方案描述了以下问题:https://github.com/OrchardCMS/Orchard/issues/6978

  3. 注册内容查询类

    public class ContentModule : Autofac.Module 
    { 
        protected override void Load(Autofac.ContainerBuilder aBuilder) 
        { 
        aBuilder.RegisterType<MyContentQuery>().As<Orchard.ContentManagement.IContentQuery>().InstancePerDependency(); 
        } 
    } 
    
  4. 创建一个定制的内容管理

    public class ContentManager : Orchard.ContentManagement.DefaultContentManager 
    { 
        // public 
        public ContentManager(
         Autofac.IComponentContext aContext, 
         Orchard.Data.IRepository<Orchard.ContentManagement.Records.ContentTypeRecord> aContentTypeRepository, 
         Orchard.Data.IRepository<Orchard.ContentManagement.Records.ContentItemRecord> aContentItemRepository, 
         Orchard.Data.IRepository<Orchard.ContentManagement.Records.ContentItemVersionRecord> aContentItemVersionRepository, 
         Orchard.ContentManagement.MetaData.IContentDefinitionManager aContentDefinitionManager, 
         Orchard.Caching.ICacheManager aCacheManager, 
         System.Func<Orchard.ContentManagement.IContentManagerSession> aContentManagerSession, 
         System.Lazy<Orchard.ContentManagement.IContentDisplay> aContentDisplay, 
         System.Lazy<Orchard.Data.ITransactionManager> aTransactionManager, 
         System.Lazy<System.Collections.Generic.IEnumerable<Orchard.ContentManagement.Handlers.IContentHandler>> aHandlers, 
         System.Lazy<System.Collections.Generic.IEnumerable<Orchard.ContentManagement.IIdentityResolverSelector>> aIdentityResolverSelectors, 
         System.Lazy<System.Collections.Generic.IEnumerable<Orchard.Data.Providers.ISqlStatementProvider>> aSqlStatementProviders, 
         Orchard.Environment.Configuration.ShellSettings aShellSettings, 
         Orchard.Caching.ISignals aSignals, 
         Orchard.IWorkContextAccessor aWorkContextAccessor) 
         : base(aContext, aContentTypeRepository, aContentItemRepository, aContentItemVersionRepository, aContentDefinitionManager, aCacheManager, aContentManagerSession, 
          aContentDisplay, aTransactionManager, aHandlers, aIdentityResolverSelectors, aSqlStatementProviders, aShellSettings, aSignals) 
        { 
         mWorkContextAccessor = aWorkContextAccessor; 
        } 
    
        public override ContentItem Get(int aId, Orchard.ContentManagement.VersionOptions aOptions, Orchard.ContentManagement.QueryHints aHints) 
        { 
         var lResult = base.Get(aId, aOptions, aHints); 
    
         if (lResult != null) 
         { 
         // note: 
         // the validity check is done here (after the query has been executed!) as changing base.GetManyImplementation() to 
         // apply the validity critera directly to the query (like in ContentQuery) will not work due to a second attempt to retrieve the 
         // content item from IRepository<> (see base.GetManyImplementation(), comment "check in memory") when the query 
         // returns no data (and the query should not return data when the validity critera is false) 
         // 
         // http://stackoverflow.com/q/37841249/3936440 
    
         var lWorkContext = mWorkContextAccessor.GetContext(); 
    
         // exclude admin as content items should still be displayed/accessible when invalid as validity needs to be editable 
         if (lWorkContext == null || !Orchard.UI.Admin.AdminFilter.IsApplied(lWorkContext.HttpContext.Request.RequestContext)) 
         { 
          var lValidityPart = lResult.As<ValidityPart>(); 
          if (lValidityPart != null) 
          { 
          if (lValidityPart.IsContentItemValid()) 
          { 
           // content item is valid 
          } 
          else 
          { 
           // content item is not valid, return null (adopted from base.Get()) 
    
           lResult = null; 
          } 
          } 
         } 
         } 
    
         return lResult; 
        } 
    
        // private 
        Orchard.IWorkContextAccessor mWorkContextAccessor; 
    } 
    

当有内容项目时需要步骤2-4,而内容类型有ContainerContainable部分,或者甚至分开处理/显示的内容项目。在这里,您通常无法自定义在幕后执行的内容查询。

如果您使用投影模块,则步骤2-4是而不是。但是,这又带来了一些其他问题,如本期报告中所示:https://github.com/OrchardCMS/Orchard/issues/6979

相关问题