Adds change tracking to the schedule collection, updates the DocumentRepository to add logic to fetch the schedule, adds/updates tests, all green
This commit is contained in:
@@ -92,10 +92,36 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DoNotClone]
|
||||
public ContentScheduleCollection ContentSchedule
|
||||
{
|
||||
get => _schedule ?? (_schedule = new ContentScheduleCollection());
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _schedule, Ps.Value.ContentScheduleSelector);
|
||||
get
|
||||
{
|
||||
if (_schedule == null)
|
||||
{
|
||||
_schedule = new ContentScheduleCollection();
|
||||
_schedule.CollectionChanged += ScheduleCollectionChanged;
|
||||
}
|
||||
return _schedule ?? (_schedule = new ContentScheduleCollection());
|
||||
}
|
||||
set
|
||||
{
|
||||
if(_schedule != null)
|
||||
_schedule.CollectionChanged -= ScheduleCollectionChanged;
|
||||
SetPropertyValueAndDetectChanges(value, ref _schedule, Ps.Value.ContentScheduleSelector);
|
||||
if (_schedule != null)
|
||||
_schedule.CollectionChanged += ScheduleCollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection changed event handler to ensure the schedule field is set to dirty when the schedule changes
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void ScheduleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(Ps.Value.ContentScheduleSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,13 +151,13 @@ namespace Umbraco.Core.Models
|
||||
return ContentStatus.Trashed;
|
||||
|
||||
//fixme - deal with variants
|
||||
var expires = ContentSchedule.GetSchedule(ContentScheduleChange.End).FirstOrDefault();
|
||||
if (expires != null && expires.Date > DateTime.MinValue && DateTime.Now > expires.Date)
|
||||
var expires = ContentSchedule.GetSchedule(ContentScheduleChange.End);
|
||||
if (expires != null && expires.Any(x => x.Date > DateTime.MinValue && DateTime.Now > x.Date))
|
||||
return ContentStatus.Expired;
|
||||
|
||||
//fixme - deal with variants
|
||||
var release = ContentSchedule.GetSchedule(ContentScheduleChange.Start).FirstOrDefault();
|
||||
if (release != null && release.Date > DateTime.MinValue && release.Date > DateTime.Now)
|
||||
var release = ContentSchedule.GetSchedule(ContentScheduleChange.Start);
|
||||
if (release != null && release.Any(x => x.Date > DateTime.MinValue && x.Date > DateTime.Now))
|
||||
return ContentStatus.AwaitingRelease;
|
||||
|
||||
if(Published)
|
||||
@@ -508,6 +534,14 @@ namespace Umbraco.Core.Models
|
||||
clone._publishInfos.CollectionChanged += clone.PublishNamesCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
//if properties exist then deal with event bindings
|
||||
if (clone._schedule != null)
|
||||
{
|
||||
clone._schedule.CollectionChanged -= ScheduleCollectionChanged; //clear this event handler if any
|
||||
clone._schedule = (ContentScheduleCollection)_schedule.DeepClone(); //manually deep clone
|
||||
clone._schedule.CollectionChanged += clone.ScheduleCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class ContentSchedule
|
||||
public class ContentSchedule : IDeepCloneable
|
||||
{
|
||||
public ContentSchedule(int id, string culture, DateTime date, ContentScheduleChange change)
|
||||
{
|
||||
@@ -45,5 +45,10 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public ContentScheduleChange Change { get; }
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
return new ContentSchedule(Id, Culture, Date, Change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,22 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class ContentScheduleCollection
|
||||
public class ContentScheduleCollection : INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
//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>>();
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an existing schedule
|
||||
/// </summary>
|
||||
@@ -24,6 +32,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
//TODO: Below will throw if there are duplicate dates added, validate/return bool?
|
||||
changes.Add(schedule.Date, schedule);
|
||||
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, schedule));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,9 +72,20 @@ namespace Umbraco.Core.Models
|
||||
// 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));
|
||||
{
|
||||
var entry = new ContentSchedule(0, culture, releaseDate.Value, ContentScheduleChange.Start);
|
||||
changes.Add(releaseDate.Value, entry);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, entry));
|
||||
}
|
||||
|
||||
if (expireDate.HasValue)
|
||||
changes.Add(expireDate.Value, new ContentSchedule(0, culture, expireDate.Value, ContentScheduleChange.End));
|
||||
{
|
||||
var entry = new ContentSchedule(0, culture, expireDate.Value, ContentScheduleChange.End);
|
||||
changes.Add(expireDate.Value, entry);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, entry));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +97,14 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
if (_schedule.TryGetValue(change.Culture, out var s))
|
||||
{
|
||||
s.Remove(change.Date);
|
||||
var removed = s.Remove(change.Date);
|
||||
if (removed)
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, change));
|
||||
if (s.Count == 0)
|
||||
_schedule.Remove(change.Culture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +127,16 @@ namespace Umbraco.Core.Models
|
||||
if (_schedule.TryGetValue(culture, out var s))
|
||||
{
|
||||
foreach (var ofChange in s.Where(x => x.Value.Change == changeType).ToList())
|
||||
s.Remove(ofChange.Value.Date);
|
||||
{
|
||||
var removed = s.Remove(ofChange.Value.Date);
|
||||
if (removed)
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, ofChange.Value));
|
||||
if (s.Count == 0)
|
||||
_schedule.Remove(culture);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,5 +169,18 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
return _schedule.ToDictionary(x => x.Key, x => (IEnumerable<ContentSchedule>)x.Value.Values);
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = new ContentScheduleCollection();
|
||||
foreach(var cultureSched in _schedule)
|
||||
{
|
||||
var list = new SortedList<DateTime, ContentSchedule>();
|
||||
foreach (var schedEntry in cultureSched.Value)
|
||||
list.Add(schedEntry.Key, (ContentSchedule)schedEntry.Value.DeepClone());
|
||||
clone._schedule[cultureSched.Key] = list;
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user