Got database and persistence models in place for scheduled publishing, now need to start writing tests, fixing tests and cleaning up fixme statements
This commit is contained in:
@@ -17,6 +17,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
private IContentType _contentType;
|
||||
private ITemplate _template;
|
||||
private ContentScheduleCollection _schedule;
|
||||
private bool _published;
|
||||
private PublishedState _publishedState;
|
||||
private DateTime? _releaseDate;
|
||||
@@ -86,11 +87,17 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo<Content, ITemplate>(x => x.Template);
|
||||
public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Published);
|
||||
public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ReleaseDate);
|
||||
public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
|
||||
public readonly PropertyInfo ContentScheduleSelector = ExpressionHelper.GetPropertyInfo<Content, ContentScheduleCollection>(x => x.ContentSchedule);
|
||||
public readonly PropertyInfo PublishCultureInfosSelector = ExpressionHelper.GetPropertyInfo<Content, IReadOnlyDictionary<string, ContentCultureInfos>>(x => x.PublishCultureInfos);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ContentScheduleCollection ContentSchedule
|
||||
{
|
||||
get => _schedule ?? (_schedule = new ContentScheduleCollection());
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _schedule, Ps.Value.ContentScheduleSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template used by the Content.
|
||||
/// This is used to override the default one from the ContentType.
|
||||
@@ -100,7 +107,7 @@ namespace Umbraco.Core.Models
|
||||
/// the Default template from the ContentType will be returned.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public virtual ITemplate Template
|
||||
public ITemplate Template
|
||||
{
|
||||
get => _template ?? _contentType.DefaultTemplate;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _template, Ps.Value.TemplateSelector);
|
||||
@@ -117,10 +124,14 @@ namespace Umbraco.Core.Models
|
||||
if(Trashed)
|
||||
return ContentStatus.Trashed;
|
||||
|
||||
if(ExpireDate.HasValue && ExpireDate.Value > DateTime.MinValue && DateTime.Now > ExpireDate.Value)
|
||||
//fixme - deal with variants
|
||||
var expires = ContentSchedule.GetSchedule(ContentScheduleChange.End).FirstOrDefault();
|
||||
if (expires != null && expires.Date > DateTime.MinValue && DateTime.Now > expires.Date)
|
||||
return ContentStatus.Expired;
|
||||
|
||||
if(ReleaseDate.HasValue && ReleaseDate.Value > DateTime.MinValue && ReleaseDate.Value > DateTime.Now)
|
||||
//fixme - deal with variants
|
||||
var release = ContentSchedule.GetSchedule(ContentScheduleChange.Start).FirstOrDefault();
|
||||
if (release != null && release.Date > DateTime.MinValue && release.Date > DateTime.Now)
|
||||
return ContentStatus.AwaitingRelease;
|
||||
|
||||
if(Published)
|
||||
@@ -169,26 +180,6 @@ namespace Umbraco.Core.Models
|
||||
[IgnoreDataMember]
|
||||
public bool Edited { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date this Content should be released and thus be published
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public DateTime? ReleaseDate
|
||||
{
|
||||
get => _releaseDate;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _releaseDate, Ps.Value.ReleaseDateSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The date this Content should expire and thus be unpublished
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public DateTime? ExpireDate
|
||||
{
|
||||
get => _expireDate;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _expireDate, Ps.Value.ExpireDateSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ContentType used by this content object
|
||||
/// </summary>
|
||||
|
||||
49
src/Umbraco.Core/Models/ContentSchedule.cs
Normal file
49
src/Umbraco.Core/Models/ContentSchedule.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Model for scheduled content
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class ContentSchedule
|
||||
{
|
||||
public ContentSchedule(int id, string culture, DateTime date, ContentScheduleChange change)
|
||||
{
|
||||
Id = id;
|
||||
Culture = culture;
|
||||
Date = date;
|
||||
Change = change;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The unique Id of the schedule item
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The culture for the schedule item
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// string.Empty represents invariant culture
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public string Culture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The date for the schedule
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public DateTime Date { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The action to take for the schedule
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public ContentScheduleChange Change { get; }
|
||||
}
|
||||
}
|
||||
11
src/Umbraco.Core/Models/ContentScheduleChange.cs
Normal file
11
src/Umbraco.Core/Models/ContentScheduleChange.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The scheduled change types of scheduled content
|
||||
/// </summary>
|
||||
public enum ContentScheduleChange
|
||||
{
|
||||
Start,
|
||||
End
|
||||
}
|
||||
}
|
||||
136
src/Umbraco.Core/Models/ContentScheduleCollection.cs
Normal file
136
src/Umbraco.Core/Models/ContentScheduleCollection.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class ContentScheduleCollection
|
||||
{
|
||||
//underlying storage for the collection backed by a sorted list so that the schedule is always in order of date
|
||||
private readonly Dictionary<string, SortedList<DateTime, ContentSchedule>> _schedule = new Dictionary<string, SortedList<DateTime, ContentSchedule>>();
|
||||
|
||||
/// <summary>
|
||||
/// Add an existing schedule
|
||||
/// </summary>
|
||||
/// <param name="schedule"></param>
|
||||
public void Add(ContentSchedule schedule)
|
||||
{
|
||||
if (!_schedule.TryGetValue(schedule.Culture, out var changes))
|
||||
{
|
||||
changes = new SortedList<DateTime, ContentSchedule>();
|
||||
_schedule[schedule.Culture] = changes;
|
||||
}
|
||||
|
||||
//TODO: Below will throw if there are duplicate dates added, validate/return bool?
|
||||
changes.Add(schedule.Date, schedule);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new schedule for invariant content
|
||||
/// </summary>
|
||||
/// <param name="releaseDate"></param>
|
||||
/// <param name="expireDate"></param>
|
||||
public void Add(DateTime? releaseDate, DateTime? expireDate)
|
||||
{
|
||||
Add(string.Empty, releaseDate, expireDate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new schedule for a culture
|
||||
/// </summary>
|
||||
/// <param name="culture"></param>
|
||||
/// <param name="releaseDate"></param>
|
||||
/// <param name="expireDate"></param>
|
||||
public void Add(string culture, DateTime? releaseDate, DateTime? expireDate)
|
||||
{
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (releaseDate.HasValue && expireDate.HasValue && releaseDate >= expireDate)
|
||||
throw new InvalidOperationException($"The {nameof(releaseDate)} must be less than {nameof(expireDate)}");
|
||||
|
||||
if (!releaseDate.HasValue && !expireDate.HasValue) return;
|
||||
|
||||
//TODO: Do we allow passing in a release or expiry date that is before now?
|
||||
|
||||
if (!_schedule.TryGetValue(culture, out var changes))
|
||||
{
|
||||
changes = new SortedList<DateTime, ContentSchedule>();
|
||||
_schedule[culture] = changes;
|
||||
}
|
||||
|
||||
//TODO: Below will throw if there are duplicate dates added, should validate/return bool?
|
||||
// but the bool won't indicate which date was in error, maybe have 2 diff methods to schedule start/end?
|
||||
|
||||
if (releaseDate.HasValue)
|
||||
changes.Add(releaseDate.Value, new ContentSchedule(0, culture, releaseDate.Value, ContentScheduleChange.Start));
|
||||
if (expireDate.HasValue)
|
||||
changes.Add(expireDate.Value, new ContentSchedule(0, culture, expireDate.Value, ContentScheduleChange.End));
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a scheduled change
|
||||
/// </summary>
|
||||
/// <param name="change"></param>
|
||||
public void Remove(ContentSchedule change)
|
||||
{
|
||||
if (_schedule.TryGetValue(change.Culture, out var s))
|
||||
{
|
||||
s.Remove(change.Date);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all of the scheduled change type for invariant content
|
||||
/// </summary>
|
||||
/// <param name="changeType"></param>
|
||||
public void Clear(ContentScheduleChange changeType)
|
||||
{
|
||||
Clear(string.Empty, changeType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all of the scheduled change type for the culture
|
||||
/// </summary>
|
||||
/// <param name="culture"></param>
|
||||
/// <param name="changeType"></param>
|
||||
public void Clear(string culture, ContentScheduleChange changeType)
|
||||
{
|
||||
if (_schedule.TryGetValue(culture, out var s))
|
||||
{
|
||||
foreach (var ofChange in s.Where(x => x.Value.Change == changeType).ToList())
|
||||
s.Remove(ofChange.Value.Date);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the schedule for invariant content
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ContentSchedule> GetSchedule(ContentScheduleChange? changeType = null)
|
||||
{
|
||||
return GetSchedule(string.Empty, changeType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the schedule for a culture
|
||||
/// </summary>
|
||||
/// <param name="culture"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ContentSchedule> GetSchedule(string culture, ContentScheduleChange? changeType = null)
|
||||
{
|
||||
if (_schedule.TryGetValue(culture, out var changes))
|
||||
return changeType == null ? changes.Values : changes.Values.Where(x => x.Change == changeType.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all schedules for both invariant and variant cultures
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IReadOnlyDictionary<string, IEnumerable<ContentSchedule>> GetFullSchedule()
|
||||
{
|
||||
return _schedule.ToDictionary(x => x.Key, x => (IEnumerable<ContentSchedule>)x.Value.Values);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents a document.
|
||||
/// </summary>
|
||||
@@ -11,6 +12,11 @@ namespace Umbraco.Core.Models
|
||||
/// </remarks>
|
||||
public interface IContent : IContentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the content schedule
|
||||
/// </summary>
|
||||
ContentScheduleCollection ContentSchedule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template used to render the content.
|
||||
/// </summary>
|
||||
@@ -60,16 +66,6 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
DateTime? PublishDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date and time the content item should be published.
|
||||
/// </summary>
|
||||
DateTime? ReleaseDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date and time the content should be unpublished.
|
||||
/// </summary>
|
||||
DateTime? ExpireDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of this content.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user