Datetime 如何跳过在Orchard CMS中显示内容项?

Datetime 如何跳过在Orchard CMS中显示内容项?,datetime,orchardcms,Datetime,Orchardcms,我有一个提供开始时间戳和结束时间戳选项的内容部分。这两个字段用于定义显示内容项的时间段 我现在很难实现跳过方法,而当时间段不跨越当前时间时,不应显示/跳过内容项 在源代码中挖掘并试图为我的方法找到一个入口点导致了以下内容处理程序 public class SkipContentHandler : Orchard.ContentManagement.Handlers.ContentHandler { protected override void BuildDisplayShape(Orcha

我有一个提供开始时间戳和结束时间戳选项的内容部分。这两个字段用于定义显示内容项的时间段

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

在源代码中挖掘并试图为我的方法找到一个入口点导致了以下内容处理程序

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
    的源代码,因为
    形状通常是只读的
  • 当列表形状包含带有“我的内容”部分的内容项时,可能会显示错误的寻呼机,因为在
    BuildDisplay()之前执行了
    Count()
    调用
    ContainerPartDriver.Display()
  • 调用被跳过的内容项的URL会导致异常,因为
    View(null)
    是无效的

那么,这里的正确方法是什么,或者是否存在任何模块来完成这项工作?我找不到。这是一项相当复杂的任务。要正确跳过显示项目,需要执行以下几个步骤:

  • 正确创建零件

    这里有一些陷阱,因为在添加零件视图时,可能会将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 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;
    }
    
    public class ContentModule : Autofac.Module
    {
      protected override void Load(Autofac.ContainerBuilder aBuilder)
      {
        aBuilder.RegisterType<MyContentQuery>().As<Orchard.ContentManagement.IContentQuery>().InstancePerDependency();
      }
    }
    
  • 创建自定义内容管理器

    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;
    }
    
    公共类ContentManager:Orchard.ContentManagement.DefaultContentManager
    {
    //公开的
    公共内容管理器(
    Autofac.IComponentContext文本,
    Orchard.Data.i存储类型存储库,
    Orchard.Data.IRepository aContentItemRepository,
    Orchard.Data.i存储库aContentItemVersionRepository,
    Orchard.ContentManagement.MetaData.IContentDefinitionManager一个ContentDefinitionManager,
    Orchard.Caching.ICacheManager aCacheManager,
    System.Func aContentManagerSession,
    系统。延迟显示,
    系统。懒惰的aTransactionManager,
    系统。懒惰的安德勒,
    系统。惰性辅助解决方案选择器,
    System.Lazy aSqlStatementProviders,
    Orchard.Environment.Configuration.ShellSettings aShellSettings,
    Orchard.Caching.ISignals aSignals,
    Orchard.IWorkContextAccessor(工作上下文访问器)
    :base(aContext、aconttyperepository、acontItemRepository、acontItemVersionRepository、acontDefinitionManager、aCacheManager、acontManagerSession、,
    A触控显示器、aTransactionManager、处理程序、辅助解决方案选择器、aSqlStatementProviders、aShellSettings、aSignals)
    {
    mWorkContextAccessor=一个WorkContextAccessor;
    }
    public override ContentItem Get(int-aId,Orchard.ContentManagement.VersionOptions aooptions,Orchard.ContentManagement.QueryHints aHints)
    {
    var lResult=base.Get(aId、aooptions、ahint);
    如果(lResult!=null)
    {
    //注:
    //将base.GetManyImplementation()更改为时,有效性检查在此处完成(在执行查询之后!)
    //将有效性标准直接应用于查询(如ContentQuery)将无法工作,因为第二次尝试检索
    //查询时,来自IRepository的内容项(请参见base.GetManyImplementation(),注释“签入内存”)
    //不返回数据(当有效性标准为false时,查询不应返回数据)
    //
    // http://stackoverflow.com/q/37841249/3936440
    var lWorkContext=mWorkContextAccessor.GetContext();
    //“排除管理为内容”项目在无效时仍应显示/可访问,因为有效性需要可编辑
    if(lWorkContext==null | | |!Orchard.UI.Admin.AdminFilter.IsApplied(lWorkContext.HttpContext.Request.RequestContext))
    {
    var lValidityPart=lResult.As();
    if(lValidityPart!=null)
    {
    if(lValidityPart.IsContentItemValid())
    {
    //内容项是有效的
    }
    其他的
    {
    //内容项无效,返回null(从base.Get()采用)
    lResult=null;
    }
    }
    }
    }
    返回lResult;
    }
    //私人的
    Orchard.IWorkContextAccessor mWorkContextAccessor;
    }
    
  • 当有内容项时,需要执行步骤2-4,而内容类型有一个
    容器
    可包含
    部分,甚至是单独处理/显示的内容项。在这里,您通常无法自定义在后台执行的内容查询


    如果使用投影模块,则不需要执行步骤2-4。但是,在这个问题上,这又带来了一些其他问题:

    您可能想考虑在时间跨度内只登记一个“未发布”事件。expires@devqon是的,我也想过。但这需要某种定期运行的后台任务,此任务需要查询所有内容项,以搜索要取消发布的内容项。另外,我不喜欢取消发布,因为这可能会让之前单击发布按钮的用户感到困惑。我仍然希望有一种方法可以以某种方式安全地中止形状的渲染…您可能会成功地阻止它渲染,但是您仍然会遇到您提到的
    计数问题。所以寻呼
    
    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;
    }