Merge pull request #7120 from umbraco/netcore/feature/AB3649-move-manifest-stuff
Netcore: Move manifest code
This commit is contained in:
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
private int _contentTypeId;
|
||||
private int _writerId;
|
||||
private PropertyCollection _properties;
|
||||
private IPropertyCollection _properties;
|
||||
private ContentCultureInfosCollection _cultureInfos;
|
||||
internal IReadOnlyList<PropertyType> AllPropertyTypes { get; }
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Models
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
[DoNotClone]
|
||||
public PropertyCollection Properties
|
||||
public IPropertyCollection Properties
|
||||
{
|
||||
get => _properties;
|
||||
set
|
||||
@@ -490,7 +490,7 @@ namespace Umbraco.Core.Models
|
||||
if (clonedContent._properties != null)
|
||||
{
|
||||
clonedContent._properties.CollectionChanged -= PropertiesChanged; //clear this event handler if any
|
||||
clonedContent._properties = (PropertyCollection)_properties.DeepClone(); //manually deep clone
|
||||
clonedContent._properties = (IPropertyCollection)_properties.DeepClone(); //manually deep clone
|
||||
clonedContent._properties.CollectionChanged += clonedContent.PropertiesChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
// gets and validates the property
|
||||
private static Property GetTagProperty(this IContentBase content, string propertyTypeAlias)
|
||||
private static IProperty GetTagProperty(this IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for content items.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Content items are documents, medias and members.</para>
|
||||
/// <para>Content items have a content type, and properties.</para>
|
||||
/// </remarks>
|
||||
public interface IContentBase : IUmbracoEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// Integer Id of the default ContentType
|
||||
/// </summary>
|
||||
int ContentTypeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of this content.
|
||||
/// </summary>
|
||||
ISimpleContentType ContentType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifier of the writer.
|
||||
/// </summary>
|
||||
int WriterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version identifier.
|
||||
/// </summary>
|
||||
int VersionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the name of the content item for a specified culture.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When <paramref name="culture"/> is null, sets the invariant
|
||||
/// culture name, which sets the <see cref="TreeEntityBase.Name"/> property.</para>
|
||||
/// <para>When <paramref name="culture"/> is not null, throws if the content
|
||||
/// type does not vary by culture.</para>
|
||||
/// </remarks>
|
||||
void SetCultureName(string value, string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the content item for a specified language.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When <paramref name="culture"/> is null, gets the invariant
|
||||
/// culture name, which is the value of the <see cref="TreeEntityBase.Name"/> property.</para>
|
||||
/// <para>When <paramref name="culture"/> is not null, and the content type
|
||||
/// does not vary by culture, returns null.</para>
|
||||
/// </remarks>
|
||||
string GetCultureName(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets culture infos of the content item.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Because a dictionary key cannot be <c>null</c> this cannot contain the invariant
|
||||
/// culture name, which must be get or set via the <see cref="TreeEntityBase.Name"/> property.</para>
|
||||
/// </remarks>
|
||||
ContentCultureInfosCollection CultureInfos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available cultures.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Cannot contain the invariant culture, which is always available.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<string> AvailableCultures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a given culture is available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>A culture becomes available whenever the content name for this culture is
|
||||
/// non-null, and it becomes unavailable whenever the content name is null.</para>
|
||||
/// <para>Returns <c>false</c> for the invariant culture, in order to be consistent
|
||||
/// with <seealso cref="AvailableCultures"/>, even though the invariant culture is
|
||||
/// always available.</para>
|
||||
/// <para>Does not support the '*' wildcard (returns false).</para>
|
||||
/// </remarks>
|
||||
bool IsCultureAvailable(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date a culture was updated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When <paramref name="culture" /> is <c>null</c>, returns <c>null</c>.</para>
|
||||
/// <para>If the specified culture is not available, returns <c>null</c>.</para>
|
||||
/// </remarks>
|
||||
DateTime? GetUpdateDate(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// List of properties, which make up all the data available for this Content object
|
||||
/// </summary>
|
||||
/// <remarks>Properties are loaded as part of the Content object graph</remarks>
|
||||
PropertyCollection Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content entity has a property with the supplied alias.
|
||||
/// </summary>
|
||||
/// <remarks>Indicates that the content entity has a property with the supplied alias, but
|
||||
/// not necessarily that the content has a value for that property. Could be missing.</remarks>
|
||||
bool HasProperty(string propertyTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a Property
|
||||
/// </summary>
|
||||
/// <remarks>Values 'null' and 'empty' are equivalent for culture and segment.</remarks>
|
||||
object GetValue(string propertyTypeAlias, string culture = null, string segment = null, bool published = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the typed value of a Property
|
||||
/// </summary>
|
||||
/// <remarks>Values 'null' and 'empty' are equivalent for culture and segment.</remarks>
|
||||
TValue GetValue<TValue>(string propertyTypeAlias, string culture = null, string segment = null, bool published = false);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the (edited) value of a Property
|
||||
/// </summary>
|
||||
/// <remarks>Values 'null' and 'empty' are equivalent for culture and segment.</remarks>
|
||||
void SetValue(string propertyTypeAlias, object value, string culture = null, string segment = null);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an editor for editing data values.
|
||||
/// </summary>
|
||||
/// <remarks>This is the base interface for parameter and property value editors.</remarks>
|
||||
public interface IDataValueEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the editor view.
|
||||
/// </summary>
|
||||
string View { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the value.
|
||||
/// </summary>
|
||||
/// <remarks>The value has to be a valid <see cref="ValueTypes"/> value.</remarks>
|
||||
string ValueType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the edited value is read-only.
|
||||
/// </summary>
|
||||
bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to display the associated label.
|
||||
/// </summary>
|
||||
bool HideLabel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a property value.
|
||||
/// </summary>
|
||||
/// <param name="value">The property value.</param>
|
||||
/// <param name="required">A value indicating whether the property value is required.</param>
|
||||
/// <param name="format">A specific format (regex) that the property value must respect.</param>
|
||||
IEnumerable<ValidationResult> Validate(object value, bool required, string format);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the validators to use to validate the edited value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Use this property to add validators, not to validate. Use <see cref="Validate"/> instead.</para>
|
||||
/// TODO: replace with AddValidator? WithValidator?
|
||||
/// </remarks>
|
||||
List<IValueValidator> Validators { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value posted by the editor to a property value.
|
||||
/// </summary>
|
||||
object FromEditor(ContentPropertyData editorValue, object currentValue);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a property value to a value for the editor.
|
||||
/// </summary>
|
||||
object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null);
|
||||
|
||||
// TODO: / deal with this when unplugging the xml cache
|
||||
// why property vs propertyType? services should be injected! etc...
|
||||
IEnumerable<XElement> ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published);
|
||||
XNode ConvertDbToXml(PropertyType propertyType, object value, IDataTypeService dataTypeService);
|
||||
string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IMedia : IContentBase
|
||||
{ }
|
||||
}
|
||||
@@ -13,16 +13,16 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class Property : EntityBase
|
||||
public class Property : EntityBase, IProperty
|
||||
{
|
||||
// _values contains all property values, including the invariant-neutral value
|
||||
private List<PropertyValue> _values = new List<PropertyValue>();
|
||||
private List<IPropertyValue> _values = new List<IPropertyValue>();
|
||||
|
||||
// _pvalue contains the invariant-neutral property value
|
||||
private PropertyValue _pvalue;
|
||||
private IPropertyValue _pvalue;
|
||||
|
||||
// _vvalues contains the (indexed) variant property values
|
||||
private Dictionary<CompositeNStringNStringKey, PropertyValue> _vvalues;
|
||||
private Dictionary<CompositeNStringNStringKey, IPropertyValue> _vvalues;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Property"/> class.
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Property"/> class.
|
||||
/// </summary>
|
||||
public Property(PropertyType propertyType)
|
||||
public Property(IPropertyType propertyType)
|
||||
{
|
||||
PropertyType = propertyType;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Property"/> class.
|
||||
/// </summary>
|
||||
public Property(int id, PropertyType propertyType)
|
||||
public Property(int id, IPropertyType propertyType)
|
||||
{
|
||||
Id = id;
|
||||
PropertyType = propertyType;
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Represents a property value.
|
||||
/// </summary>
|
||||
public class PropertyValue
|
||||
public class PropertyValue : IPropertyValue
|
||||
{
|
||||
// TODO: Either we allow change tracking at this class level, or we add some special change tracking collections to the Property
|
||||
// class to deal with change tracking which variants have changed
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Core.Models
|
||||
public string Culture
|
||||
{
|
||||
get => _culture;
|
||||
internal set => _culture = value.IsNullOrWhiteSpace() ? null : value.ToLowerInvariant();
|
||||
set => _culture = value.IsNullOrWhiteSpace() ? null : value.ToLowerInvariant();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -77,23 +77,23 @@ namespace Umbraco.Core.Models
|
||||
public string Segment
|
||||
{
|
||||
get => _segment;
|
||||
internal set => _segment = value?.ToLowerInvariant();
|
||||
set => _segment = value?.ToLowerInvariant();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the edited value of the property.
|
||||
/// </summary>
|
||||
public object EditedValue { get; internal set; }
|
||||
public object EditedValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the published value of the property.
|
||||
/// </summary>
|
||||
public object PublishedValue { get; internal set; }
|
||||
public object PublishedValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Clones the property value.
|
||||
/// </summary>
|
||||
public PropertyValue Clone()
|
||||
public IPropertyValue Clone()
|
||||
=> new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
|
||||
}
|
||||
|
||||
@@ -121,13 +121,13 @@ namespace Umbraco.Core.Models
|
||||
/// Returns the PropertyType, which this Property is based on
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public PropertyType PropertyType { get; private set; }
|
||||
public IPropertyType PropertyType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of values.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public IReadOnlyCollection<PropertyValue> Values
|
||||
public IReadOnlyCollection<IPropertyValue> Values
|
||||
{
|
||||
get => _values;
|
||||
set
|
||||
@@ -152,7 +152,7 @@ namespace Umbraco.Core.Models
|
||||
/// Returns the Id of the PropertyType, which this Property is based on
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal int PropertyTypeId => PropertyType.Id;
|
||||
public int PropertyTypeId => PropertyType.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DatabaseType that the underlaying DataType is using to store its values
|
||||
@@ -161,7 +161,7 @@ namespace Umbraco.Core.Models
|
||||
/// Only used internally when saving the property value.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
internal ValueStorageType ValueStorageType => PropertyType.ValueStorageType;
|
||||
public ValueStorageType ValueStorageType => PropertyType.ValueStorageType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
@@ -180,7 +180,7 @@ namespace Umbraco.Core.Models
|
||||
: null;
|
||||
}
|
||||
|
||||
private object GetPropertyValue(PropertyValue pvalue, bool published)
|
||||
private object GetPropertyValue(IPropertyValue pvalue, bool published)
|
||||
{
|
||||
if (pvalue == null) return null;
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// internal - must be invoked by the content item
|
||||
// does *not* validate the value - content item must validate first
|
||||
internal void PublishValues(string culture = "*", string segment = "*")
|
||||
public void PublishValues(string culture = "*", string segment = "*")
|
||||
{
|
||||
culture = culture.NullOrWhiteSpaceAsNull();
|
||||
segment = segment.NullOrWhiteSpaceAsNull();
|
||||
@@ -216,7 +216,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
// internal - must be invoked by the content item
|
||||
internal void UnpublishValues(string culture = "*", string segment = "*")
|
||||
public void UnpublishValues(string culture = "*", string segment = "*")
|
||||
{
|
||||
culture = culture.NullOrWhiteSpaceAsNull();
|
||||
segment = segment.NullOrWhiteSpaceAsNull();
|
||||
@@ -240,7 +240,7 @@ namespace Umbraco.Core.Models
|
||||
UnpublishValue(pvalue);
|
||||
}
|
||||
|
||||
private void PublishValue(PropertyValue pvalue)
|
||||
private void PublishValue(IPropertyValue pvalue)
|
||||
{
|
||||
if (pvalue == null) return;
|
||||
|
||||
@@ -251,7 +251,7 @@ namespace Umbraco.Core.Models
|
||||
DetectChanges(pvalue.EditedValue, origValue, nameof(Values), PropertyValueComparer, false);
|
||||
}
|
||||
|
||||
private void UnpublishValue(PropertyValue pvalue)
|
||||
private void UnpublishValue(IPropertyValue pvalue)
|
||||
{
|
||||
if (pvalue == null) return;
|
||||
|
||||
@@ -294,7 +294,7 @@ namespace Umbraco.Core.Models
|
||||
pvalue.EditedValue = value;
|
||||
}
|
||||
|
||||
private (PropertyValue, bool) GetPValue(bool create)
|
||||
private (IPropertyValue, bool) GetPValue(bool create)
|
||||
{
|
||||
var change = false;
|
||||
if (_pvalue == null)
|
||||
@@ -307,7 +307,7 @@ namespace Umbraco.Core.Models
|
||||
return (_pvalue, change);
|
||||
}
|
||||
|
||||
private (PropertyValue, bool) GetPValue(string culture, string segment, bool create)
|
||||
private (IPropertyValue, bool) GetPValue(string culture, string segment, bool create)
|
||||
{
|
||||
if (culture == null && segment == null)
|
||||
return GetPValue(create);
|
||||
@@ -316,7 +316,7 @@ namespace Umbraco.Core.Models
|
||||
if (_vvalues == null)
|
||||
{
|
||||
if (!create) return (null, false);
|
||||
_vvalues = new Dictionary<CompositeNStringNStringKey, PropertyValue>();
|
||||
_vvalues = new Dictionary<CompositeNStringNStringKey, IPropertyValue>();
|
||||
change = true;
|
||||
}
|
||||
var k = new CompositeNStringNStringKey(culture, segment);
|
||||
|
||||
@@ -12,11 +12,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class PropertyCollection : KeyedCollection<string, Property>, INotifyCollectionChanged, IDeepCloneable
|
||||
public class PropertyCollection : KeyedCollection<string, IProperty>, IPropertyCollection
|
||||
{
|
||||
private readonly object _addLocker = new object();
|
||||
|
||||
internal Func<Property, bool> AdditionValidator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
|
||||
@@ -25,16 +23,6 @@ namespace Umbraco.Core.Models
|
||||
: base(StringComparer.InvariantCultureIgnoreCase)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
|
||||
/// </summary>
|
||||
/// <param name="additionValidator">A function validating added properties.</param>
|
||||
internal PropertyCollection(Func<Property, bool> additionValidator)
|
||||
: this()
|
||||
{
|
||||
AdditionValidator = additionValidator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
|
||||
/// </summary>
|
||||
@@ -47,7 +35,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Replaces all properties, whilst maintaining validation delegates.
|
||||
/// </summary>
|
||||
internal void Reset(IEnumerable<Property> properties)
|
||||
private void Reset(IEnumerable<Property> properties)
|
||||
{
|
||||
//collection events will be raised in each of these calls
|
||||
Clear();
|
||||
@@ -60,7 +48,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Replaces the property at the specified index with the specified property.
|
||||
/// </summary>
|
||||
protected override void SetItem(int index, Property property)
|
||||
protected override void SetItem(int index, IProperty property)
|
||||
{
|
||||
var oldItem = index >= 0 ? this[index] : property;
|
||||
base.SetItem(index, property);
|
||||
@@ -80,7 +68,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Inserts the specified property at the specified index.
|
||||
/// </summary>
|
||||
protected override void InsertItem(int index, Property property)
|
||||
protected override void InsertItem(int index, IProperty property)
|
||||
{
|
||||
base.InsertItem(index, property);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property));
|
||||
@@ -95,10 +83,8 @@ namespace Umbraco.Core.Models
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or updates a property.
|
||||
/// </summary>
|
||||
internal new void Add(Property property)
|
||||
/// <inheritdoc />
|
||||
public new void Add(IProperty property)
|
||||
{
|
||||
lock (_addLocker) // TODO: why are we locking here and not everywhere else?!
|
||||
{
|
||||
@@ -131,7 +117,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Gets the index for a specified property alias.
|
||||
/// </summary>
|
||||
public int IndexOfKey(string key)
|
||||
private int IndexOfKey(string key)
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
@@ -141,7 +127,7 @@ namespace Umbraco.Core.Models
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected override string GetKeyForItem(Property item)
|
||||
protected override string GetKeyForItem(IProperty item)
|
||||
{
|
||||
return item.Alias;
|
||||
}
|
||||
@@ -149,7 +135,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Gets the property with the specified PropertyType.
|
||||
/// </summary>
|
||||
internal Property this[PropertyType propertyType]
|
||||
internal IProperty this[IPropertyType propertyType]
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -157,7 +143,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(string propertyTypeAlias, out Property property)
|
||||
public bool TryGetValue(string propertyTypeAlias, out IProperty property)
|
||||
{
|
||||
property = this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
return property != null;
|
||||
@@ -173,10 +159,9 @@ namespace Umbraco.Core.Models
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the collection contains properties for the specified property types.
|
||||
/// </summary>
|
||||
protected internal void EnsurePropertyTypes(IEnumerable<PropertyType> propertyTypes)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void EnsurePropertyTypes(IEnumerable<IPropertyType> propertyTypes)
|
||||
{
|
||||
if (propertyTypes == null)
|
||||
return;
|
||||
@@ -185,10 +170,9 @@ namespace Umbraco.Core.Models
|
||||
Add(new Property(propertyType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the collection does not contain properties not in the specified property types.
|
||||
/// </summary>
|
||||
protected internal void EnsureCleanPropertyTypes(IEnumerable<PropertyType> propertyTypes)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void EnsureCleanPropertyTypes(IEnumerable<IPropertyType> propertyTypes)
|
||||
{
|
||||
if (propertyTypes == null)
|
||||
return;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// gets the tag configuration for a property
|
||||
// from the datatype configuration, and the editor tag configuration attribute
|
||||
internal static TagConfiguration GetTagConfiguration(this Property property)
|
||||
internal static TagConfiguration GetTagConfiguration(this IProperty property)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="tags">The tags.</param>
|
||||
/// <param name="merge">A value indicating whether to merge the tags with existing tags instead of replacing them.</param>
|
||||
/// <param name="culture">A culture, for multi-lingual properties.</param>
|
||||
public static void AssignTags(this Property property, IEnumerable<string> tags, bool merge = false, string culture = null)
|
||||
public static void AssignTags(this IProperty property, IEnumerable<string> tags, bool merge = false, string culture = null)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
// assumes that parameters are consistent with the datatype configuration
|
||||
private static void AssignTags(this Property property, IEnumerable<string> tags, bool merge, TagsStorageType storageType, char delimiter, string culture)
|
||||
private static void AssignTags(this IProperty property, IEnumerable<string> tags, bool merge, TagsStorageType storageType, char delimiter, string culture)
|
||||
{
|
||||
// set the property value
|
||||
var trimmedTags = tags.Select(x => x.Trim()).ToArray();
|
||||
@@ -97,7 +97,7 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="tags">The tags.</param>
|
||||
/// <param name="culture">A culture, for multi-lingual properties.</param>
|
||||
public static void RemoveTags(this Property property, IEnumerable<string> tags, string culture = null)
|
||||
public static void RemoveTags(this IProperty property, IEnumerable<string> tags, string culture = null)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
// assumes that parameters are consistent with the datatype configuration
|
||||
private static void RemoveTags(this Property property, IEnumerable<string> tags, TagsStorageType storageType, char delimiter, string culture)
|
||||
private static void RemoveTags(this IProperty property, IEnumerable<string> tags, TagsStorageType storageType, char delimiter, string culture)
|
||||
{
|
||||
// already empty = nothing to do
|
||||
var value = property.GetValue(culture)?.ToString();
|
||||
@@ -131,7 +131,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
// used by ContentRepositoryBase
|
||||
internal static IEnumerable<string> GetTagsValue(this Property property, string culture = null)
|
||||
internal static IEnumerable<string> GetTagsValue(this IProperty property, string culture = null)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Umbraco.Core.Models
|
||||
return property.GetTagsValue(configuration.StorageType, configuration.Delimiter, culture);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetTagsValue(this Property property, TagsStorageType storageType, char delimiter, string culture = null)
|
||||
private static IEnumerable<string> GetTagsValue(this IProperty property, TagsStorageType storageType, char delimiter, string culture = null)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Umbraco.Core.Models
|
||||
/// <para>This is used both by the content repositories to initialize a property with some tag values, and by the
|
||||
/// content controllers to update a property with values received from the property editor.</para>
|
||||
/// </remarks>
|
||||
internal static void SetTagsValue(this Property property, object value, TagConfiguration tagConfiguration, string culture)
|
||||
internal static void SetTagsValue(this IProperty property, object value, TagConfiguration tagConfiguration, string culture)
|
||||
{
|
||||
if (property == null) throw new ArgumentNullException(nameof(property));
|
||||
if (tagConfiguration == null) throw new ArgumentNullException(nameof(tagConfiguration));
|
||||
@@ -195,7 +195,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// assumes that parameters are consistent with the datatype configuration
|
||||
// value can be an enumeration of string, or a serialized value using storageType format
|
||||
private static void SetTagsValue(Property property, object value, TagsStorageType storageType, char delimiter, string culture)
|
||||
private static void SetTagsValue(IProperty property, object value, TagsStorageType storageType, char delimiter, string culture)
|
||||
{
|
||||
if (value == null) value = Enumerable.Empty<string>();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
|
||||
public class PropertyType : EntityBase, IEquatable<PropertyType>
|
||||
public class PropertyType : EntityBase, IPropertyType, IEquatable<PropertyType>
|
||||
{
|
||||
private readonly bool _forceValueStorageType;
|
||||
private string _name;
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
if (dataType == null) throw new ArgumentNullException(nameof(dataType));
|
||||
|
||||
if(dataType.HasIdentity)
|
||||
if (dataType.HasIdentity)
|
||||
_dataTypeId = dataType.Id;
|
||||
|
||||
_propertyEditorAlias = dataType.EditorAlias;
|
||||
@@ -58,14 +58,16 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType)
|
||||
: this(propertyEditorAlias, valueStorageType, false)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyType"/> class.
|
||||
/// </summary>
|
||||
public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType, string propertyTypeAlias)
|
||||
: this(propertyEditorAlias, valueStorageType, false, propertyTypeAlias)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyType"/> class.
|
||||
@@ -99,9 +101,7 @@ namespace Umbraco.Core.Models
|
||||
/// </remarks>
|
||||
public bool SupportsPublishing { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets the name of the property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
@@ -109,9 +109,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets the alias of the property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public virtual string Alias
|
||||
{
|
||||
@@ -119,9 +117,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(SanitizeAlias(value), ref _alias, nameof(Alias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets the description of the property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string Description
|
||||
{
|
||||
@@ -129,9 +125,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _description, nameof(Description));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the datatype for this property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public int DataTypeId
|
||||
{
|
||||
@@ -146,9 +140,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _dataTypeKey, nameof(DataTypeKey));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alias of the property editor for this property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string PropertyEditorAlias
|
||||
{
|
||||
@@ -156,11 +148,9 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, nameof(PropertyEditorAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the database type for storing value for this property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
internal ValueStorageType ValueStorageType
|
||||
public ValueStorageType ValueStorageType
|
||||
{
|
||||
get => _valueStorageType;
|
||||
set
|
||||
@@ -170,20 +160,16 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the property group this property type belongs to.
|
||||
/// </summary>
|
||||
/// <remarks>For generic properties, the value is <c>null</c>.</remarks>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
internal Lazy<int> PropertyGroupId
|
||||
public Lazy<int> PropertyGroupId
|
||||
{
|
||||
get => _propertyGroupId;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _propertyGroupId, nameof(PropertyGroupId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets a value indicating whether a value for this property type is required.
|
||||
/// </summary>
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public bool Mandatory
|
||||
{
|
||||
@@ -191,9 +177,8 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _mandatory, nameof(Mandatory));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets the sort order of the property type.
|
||||
/// </summary>
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public int SortOrder
|
||||
{
|
||||
@@ -201,9 +186,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, nameof(SortOrder));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the regular expression validating the property values.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string ValidationRegExp
|
||||
{
|
||||
@@ -211,21 +194,14 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExp, nameof(ValidationRegExp));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content variation of the property type.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public ContentVariation Variations
|
||||
{
|
||||
get => _variations;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _variations, nameof(Variations));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type supports a combination of culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture.</param>
|
||||
/// <param name="segment">The segment.</param>
|
||||
/// <param name="wildcards">A value indicating whether wildcards are valid.</param>
|
||||
/// <inheritdoc />
|
||||
public bool SupportsVariation(string culture, string segment, bool wildcards = false)
|
||||
{
|
||||
// exact validation: cannot accept a 'null' culture if the property type varies
|
||||
@@ -249,7 +225,7 @@ namespace Umbraco.Core.Models
|
||||
/// <para>If the value is of the expected type, it can be directly assigned to the property.
|
||||
/// Otherwise, some conversion is required.</para>
|
||||
/// </remarks>
|
||||
public bool IsOfExpectedPropertyType(object value)
|
||||
private bool IsOfExpectedPropertyType(object value)
|
||||
{
|
||||
// null values are assumed to be ok
|
||||
if (value == null)
|
||||
@@ -275,19 +251,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a value can be assigned to a property.
|
||||
/// </summary>
|
||||
public bool IsValueAssignable(object value) => TryConvertAssignedValue(value, false, out _);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value assigned to a property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The input value can be pretty much anything, and is converted to the actual CLR type
|
||||
/// expected by the property (eg an integer if the property values are integers).</para>
|
||||
/// <para>Throws if the value cannot be converted.</para>
|
||||
/// </remarks>
|
||||
/// <inheritdoc />
|
||||
public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null;
|
||||
|
||||
/// <summary>
|
||||
@@ -296,8 +260,6 @@ namespace Umbraco.Core.Models
|
||||
/// <remarks>
|
||||
/// <para></para>
|
||||
/// </remarks>
|
||||
public bool TryConvertAssignedValue(object value, out object converted) => TryConvertAssignedValue(value, false, out converted);
|
||||
|
||||
private bool TryConvertAssignedValue(object value, bool throwOnError, out object converted)
|
||||
{
|
||||
var isOfExpectedType = IsOfExpectedPropertyType(value);
|
||||
@@ -332,6 +294,7 @@ namespace Umbraco.Core.Models
|
||||
converted = convInt.Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (throwOnError)
|
||||
ThrowTypeException(value, typeof(int), Alias);
|
||||
return false;
|
||||
@@ -347,6 +310,7 @@ namespace Umbraco.Core.Models
|
||||
converted = convDecimal.Result.Normalize();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (throwOnError)
|
||||
ThrowTypeException(value, typeof(decimal), Alias);
|
||||
return false;
|
||||
@@ -360,6 +324,7 @@ namespace Umbraco.Core.Models
|
||||
converted = convDateTime.Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (throwOnError)
|
||||
ThrowTypeException(value, typeof(DateTime), Alias);
|
||||
return false;
|
||||
@@ -413,7 +378,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.PerformDeepClone(clone);
|
||||
|
||||
var clonedEntity = (PropertyType)clone;
|
||||
var clonedEntity = (PropertyType) clone;
|
||||
|
||||
//need to manually assign the Lazy value as it will not be automatically mapped
|
||||
if (PropertyGroupId != null)
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// we have to have all this, because we're an IUmbracoEntity, because that is
|
||||
// required by the query expression visitor / SimpleContentTypeMapper
|
||||
// TODO: Make the query expression visitor use a different common interface, or investigate removing IRememberBeingDirty from being a requirement on that interface and expliclty checking for that throughout the code?
|
||||
|
||||
string ITreeEntity.Name { get => this.Name; set => throw new NotImplementedException(); }
|
||||
int IEntity.Id { get => this.Id; set => throw new NotImplementedException(); }
|
||||
@@ -130,5 +131,7 @@ namespace Umbraco.Core.Models
|
||||
bool ICanBeDirty.IsPropertyDirty(string propName) => throw new NotImplementedException();
|
||||
IEnumerable<string> ICanBeDirty.GetDirtyProperties() => throw new NotImplementedException();
|
||||
void ICanBeDirty.ResetDirtyProperties() => throw new NotImplementedException();
|
||||
public void DisableChangeTracking() => throw new NotImplementedException();
|
||||
public void EnableChangeTracking() => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user