AB3649 - Moved IContent and ContentSchedule

This commit is contained in:
Bjarke Berg
2019-11-11 15:42:14 +01:00
parent 16ff38a456
commit f90fc48ca8
7 changed files with 10 additions and 9 deletions

View File

@@ -1,77 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a scheduled action for a document.
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class ContentSchedule : IDeepCloneable
{
/// <summary>
/// Initializes a new instance of the <see cref="ContentSchedule"/> class.
/// </summary>
public ContentSchedule(string culture, DateTime date, ContentScheduleAction action)
{
Id = Guid.Empty; // will be assigned by document repository
Culture = culture;
Date = date;
Action = action;
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentSchedule"/> class.
/// </summary>
public ContentSchedule(Guid id, string culture, DateTime date, ContentScheduleAction action)
{
Id = id;
Culture = culture;
Date = date;
Action = action;
}
/// <summary>
/// Gets the unique identifier of the document targeted by the scheduled action.
/// </summary>
[DataMember]
public Guid Id { get; internal set; }
/// <summary>
/// Gets the culture of the scheduled action.
/// </summary>
/// <remarks>
/// string.Empty represents the invariant culture.
/// </remarks>
[DataMember]
public string Culture { get; }
/// <summary>
/// Gets the date of the scheduled action.
/// </summary>
[DataMember]
public DateTime Date { get; }
/// <summary>
/// Gets the action to take.
/// </summary>
[DataMember]
public ContentScheduleAction Action { get; }
public override bool Equals(object obj)
=> obj is ContentSchedule other && Equals(other);
public bool Equals(ContentSchedule other)
{
// don't compare Ids, two ContentSchedule are equal if they are for the same change
// for the same culture, on the same date - and the collection deals w/duplicates
return Culture.InvariantEquals(other.Culture) && Date == other.Date && Action == other.Action;
}
public object DeepClone()
{
return new ContentSchedule(Id, Culture, Date, Action);
}
}
}

View File

@@ -1,18 +0,0 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Defines scheduled actions for documents.
/// </summary>
public enum ContentScheduleAction
{
/// <summary>
/// Release the document.
/// </summary>
Release,
/// <summary>
/// Expire the document.
/// </summary>
Expire
}
}

View File

@@ -1,223 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Umbraco.Core.Models
{
public class ContentScheduleCollection : INotifyCollectionChanged, IDeepCloneable, IEquatable<ContentScheduleCollection>
{
//underlying storage for the collection backed by a sorted list so that the schedule is always in order of date and that duplicate dates per culture are not allowed
private readonly Dictionary<string, SortedList<DateTime, ContentSchedule>> _schedule
= new Dictionary<string, SortedList<DateTime, ContentSchedule>>(StringComparer.InvariantCultureIgnoreCase);
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
CollectionChanged?.Invoke(this, args);
}
/// <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);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, schedule));
}
/// <summary>
/// Adds a new schedule for invariant content
/// </summary>
/// <param name="releaseDate"></param>
/// <param name="expireDate"></param>
public bool Add(DateTime? releaseDate, DateTime? expireDate)
{
return 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>
/// <returns>true if successfully added, false if validation fails</returns>
public bool Add(string culture, DateTime? releaseDate, DateTime? expireDate)
{
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (releaseDate.HasValue && expireDate.HasValue && releaseDate >= expireDate)
return false;
if (!releaseDate.HasValue && !expireDate.HasValue) return false;
// 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)
{
var entry = new ContentSchedule(culture, releaseDate.Value, ContentScheduleAction.Release);
changes.Add(releaseDate.Value, entry);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, entry));
}
if (expireDate.HasValue)
{
var entry = new ContentSchedule(culture, expireDate.Value, ContentScheduleAction.Expire);
changes.Add(expireDate.Value, entry);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, entry));
}
return true;
}
/// <summary>
/// Remove a scheduled change
/// </summary>
/// <param name="change"></param>
public void Remove(ContentSchedule change)
{
if (_schedule.TryGetValue(change.Culture, out var s))
{
var removed = s.Remove(change.Date);
if (removed)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, change));
if (s.Count == 0)
_schedule.Remove(change.Culture);
}
}
}
/// <summary>
/// Clear all of the scheduled change type for invariant content
/// </summary>
/// <param name="action"></param>
/// <param name="changeDate">If specified, will clear all entries with dates less than or equal to the value</param>
public void Clear(ContentScheduleAction action, DateTime? changeDate = null)
{
Clear(string.Empty, action, changeDate);
}
/// <summary>
/// Clear all of the scheduled change type for the culture
/// </summary>
/// <param name="culture"></param>
/// <param name="action"></param>
/// <param name="date">If specified, will clear all entries with dates less than or equal to the value</param>
public void Clear(string culture, ContentScheduleAction action, DateTime? date = null)
{
if (!_schedule.TryGetValue(culture, out var schedules))
return;
var removes = schedules.Where(x => x.Value.Action == action && (!date.HasValue || x.Value.Date <= date.Value)).ToList();
foreach (var remove in removes)
{
var removed = schedules.Remove(remove.Value.Date);
if (!removed)
continue;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, remove.Value));
}
if (schedules.Count == 0)
_schedule.Remove(culture);
}
/// <summary>
/// Returns all pending schedules based on the date and type provided
/// </summary>
/// <param name="action"></param>
/// <param name="date"></param>
/// <returns></returns>
public IReadOnlyList<ContentSchedule> GetPending(ContentScheduleAction action, DateTime date)
{
return _schedule.Values.SelectMany(x => x.Values).Where(x => x.Date <= date).ToList();
}
/// <summary>
/// Gets the schedule for invariant content
/// </summary>
/// <returns></returns>
public IEnumerable<ContentSchedule> GetSchedule(ContentScheduleAction? action = null)
{
return GetSchedule(string.Empty, action);
}
/// <summary>
/// Gets the schedule for a culture
/// </summary>
/// <param name="culture"></param>
/// <param name="action"></param>
/// <returns></returns>
public IEnumerable<ContentSchedule> GetSchedule(string culture, ContentScheduleAction? action = null)
{
if (_schedule.TryGetValue(culture, out var changes))
return action == null ? changes.Values : changes.Values.Where(x => x.Action == action.Value);
return Enumerable.Empty<ContentSchedule>();
}
/// <summary>
/// Returns all schedules registered
/// </summary>
/// <returns></returns>
public IReadOnlyList<ContentSchedule> FullSchedule => _schedule.SelectMany(x => x.Value.Values).ToList();
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;
}
public override bool Equals(object obj)
=> obj is ContentScheduleCollection other && Equals(other);
public bool Equals(ContentScheduleCollection other)
{
if (other == null) return false;
var thisSched = _schedule;
var thatSched = other._schedule;
if (thisSched.Count != thatSched.Count)
return false;
foreach (var (culture, thisList) in thisSched)
{
// if culture is missing, or actions differ, false
if (!thatSched.TryGetValue(culture, out var thatList) || !thatList.SequenceEqual(thisList))
return false;
}
return true;
}
}
}

View File

@@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a document.
/// </summary>
/// <remarks>
/// <para>A document can be published, rendered by a template.</para>
/// </remarks>
public interface IContent : IContentBase
{
/// <summary>
/// Gets or sets the content schedule
/// </summary>
ContentScheduleCollection ContentSchedule { get; set; }
/// <summary>
/// Gets or sets the template id used to render the content.
/// </summary>
int? TemplateId { get; set; }
/// <summary>
/// Gets a value indicating whether the content is published.
/// </summary>
bool Published { get; set; }
PublishedState PublishedState { get; set; }
/// <summary>
/// Gets a value indicating whether the content has been edited.
/// </summary>
bool Edited { get; set; }
/// <summary>
/// Gets the published version identifier.
/// </summary>
int PublishedVersionId { get; set; }
/// <summary>
/// Gets a value indicating whether the content item is a blueprint.
/// </summary>
bool Blueprint { get; set; }
/// <summary>
/// Gets the template id used to render the published version of the content.
/// </summary>
/// <remarks>When editing the content, the template can change, but this will not until the content is published.</remarks>
int? PublishTemplateId { get; set; }
/// <summary>
/// Gets the name of the published version of the content.
/// </summary>
/// <remarks>When editing the content, the name can change, but this will not until the content is published.</remarks>
string PublishName { get; set; }
/// <summary>
/// Gets the identifier of the user who published the content.
/// </summary>
int? PublisherId { get; set; }
/// <summary>
/// Gets the date and time the content was published.
/// </summary>
DateTime? PublishDate { get; set; }
/// <summary>
/// Gets a value indicating whether a culture is published.
/// </summary>
/// <remarks>
/// <para>A culture becomes published whenever values for this culture are published,
/// and the content published name for this culture is non-null. It becomes non-published
/// whenever values for this culture are unpublished.</para>
/// <para>A culture becomes published as soon as PublishCulture has been invoked,
/// even though the document might not have been saved yet (and can have no identity).</para>
/// <para>Does not support the '*' wildcard (returns false).</para>
/// </remarks>
bool IsCulturePublished(string culture);
/// <summary>
/// Gets the date a culture was published.
/// </summary>
DateTime? GetPublishDate(string culture);
/// <summary>
/// Gets a value indicated whether a given culture is edited.
/// </summary>
/// <remarks>
/// <para>A culture is edited when it is available, and not published or published but
/// with changes.</para>
/// <para>A culture can be edited even though the document might now have been saved yet (and can have no identity).</para>
/// <para>Does not support the '*' wildcard (returns false).</para>
/// </remarks>
bool IsCultureEdited(string culture);
/// <summary>
/// Gets the name of the published version of the content for a given culture.
/// </summary>
/// <remarks>
/// <para>When editing the content, the name can change, but this will not until the content is published.</para>
/// <para>When <paramref name="culture"/> is <c>null</c>, gets the invariant
/// language, which is the value of the <see cref="PublishName"/> property.</para>
/// </remarks>
string GetPublishName(string culture);
/// <summary>
/// Gets the published culture infos of the content.
/// </summary>
/// <remarks>
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get the invariant
/// name, which must be get via the <see cref="PublishName"/> property.</para>
/// </remarks>
ContentCultureInfosCollection PublishCultureInfos { get; set; }
/// <summary>
/// Gets the published cultures.
/// </summary>
IEnumerable<string> PublishedCultures { get; }
/// <summary>
/// Gets the edited cultures.
/// </summary>
IEnumerable<string> EditedCultures { get; set; }
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
IContent DeepCloneWithResetIdentities();
}
}