DataType refactoring preparation - Entity refactoring

This commit is contained in:
Stephan
2018-01-15 11:32:30 +01:00
parent 988aa661ea
commit d23933a5b1
213 changed files with 2149 additions and 2478 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
using System;
using Umbraco.Core.Events;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Sync;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Cache
{
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -1,4 +1,4 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Cache
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Collections
{
@@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Events
{
@@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Events
{
@@ -224,32 +224,32 @@ namespace Umbraco.Core.Migrations.Install
private void CreateDataTypeData()
{
//TODO Check which of the DataTypeIds below doesn't exist in umbracoNode, which results in a foreign key constraint errors.
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 1, DataTypeId = -49, PropertyEditorAlias = Constants.PropertyEditors.TrueFalseAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 2, DataTypeId = -51, PropertyEditorAlias = Constants.PropertyEditors.IntegerAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 3, DataTypeId = -87, PropertyEditorAlias = Constants.PropertyEditors.TinyMCEAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, PropertyEditorAlias = Constants.PropertyEditors.TextboxAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, PropertyEditorAlias = Constants.PropertyEditors.TextboxMultipleAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, PropertyEditorAlias = Constants.PropertyEditors.UploadFieldAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, PropertyEditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, PropertyEditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListMultipleAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.DataTypes.DefaultContentListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.DataTypes.DefaultMediaListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.DataTypes.DefaultMembersListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 1, DataTypeId = -49, EditorAlias = Constants.PropertyEditors.TrueFalseAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 2, DataTypeId = -51, EditorAlias = Constants.PropertyEditors.IntegerAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 3, DataTypeId = -87, EditorAlias = Constants.PropertyEditors.TinyMCEAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, EditorAlias = Constants.PropertyEditors.TextboxAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, EditorAlias = Constants.PropertyEditors.TextboxMultipleAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, EditorAlias = Constants.PropertyEditors.UploadFieldAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, EditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, EditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, EditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, EditorAlias = Constants.PropertyEditors.DropDownListMultipleAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, EditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, EditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, EditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, EditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, EditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, EditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.DataTypes.DefaultContentListView, EditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.DataTypes.DefaultMediaListView, EditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.DataTypes.DefaultMembersListView, EditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
//New UDI pickers with newer Ids
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, EditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, EditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, EditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, EditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, EditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
//TODO: We're not creating these for 7.0
//_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" });
+2 -2
View File
@@ -1,8 +1,8 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
public sealed class AuditItem : EntityBase.EntityBase
public sealed class AuditItem : EntityBase
{
public AuditItem(int objectId, string comment, AuditType type, int userId)
{
+18 -119
View File
@@ -7,8 +7,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Services;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -18,20 +17,13 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")]
public abstract class ContentBase : EntityBase.EntityBase, IContentBase
public abstract class ContentBase : TreeEntityBase, IContentBase
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private IDictionary<string, object> _additionalData;
private int _contentTypeId;
protected IContentTypeComposition ContentTypeBase;
private Lazy<int> _parentId;
private int _level;
private string _path;
private int _sortOrder;
private bool _trashed;
private int _creatorId;
private int _writerId;
// fixme need to deal with localized names, how?
@@ -40,10 +32,6 @@ namespace Umbraco.Core.Models
private PropertyCollection _properties;
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _lazyAdditionalData.Value;
private readonly Lazy<Dictionary<string, object>> _lazyAdditionalData = new Lazy<Dictionary<string, object>>();
/// <summary>
/// Initializes a new instance of the <see cref="ContentBase"/> class.
/// </summary>
@@ -51,7 +39,7 @@ namespace Umbraco.Core.Models
: this(name, contentType, properties)
{
if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId));
_parentId = new Lazy<int>(() => parentId);
ParentId = parentId;
}
/// <summary>
@@ -61,7 +49,7 @@ namespace Umbraco.Core.Models
: this(name, contentType, properties)
{
if (parent == null) throw new ArgumentNullException(nameof(parent));
_parentId = new Lazy<int>(() => parent.Id);
SetParent(parent);
}
private ContentBase(string name, IContentTypeComposition contentType, PropertyCollection properties)
@@ -72,7 +60,7 @@ namespace Umbraco.Core.Models
Id = 0; // no identity
VersionId = 0; // no versions
_name = name;
Name = _name = name;
_contentTypeId = contentType.Id;
_properties = properties ?? throw new ArgumentNullException(nameof(properties));
_properties.EnsurePropertyTypes(PropertyTypes);
@@ -81,116 +69,27 @@ namespace Umbraco.Core.Models
// ReSharper disable once ClassNeverInstantiated.Local
private class PropertySelectors
{
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ParentId);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Path);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.SortOrder);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentBase, bool>(x => x.Trashed);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Name);
public readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.CreatorId);
public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.WriterId);
}
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[DataMember]
[DoNotClone]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary<string, object>());
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[IgnoreDataMember]
bool IUmbracoEntity.HasAdditionalData => _additionalData != null;
protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertyCollectionSelector);
}
/// <summary>
/// Gets or sets the identifier of the parent entity.
/// </summary>
[DataMember]
public virtual int ParentId
{
get
{
var val = _parentId.Value;
if (val == 0)
{
throw new InvalidOperationException("The ParentId cannot have a value of 0. Perhaps the parent object used to instantiate this object has not been persisted to the data store.");
}
return val;
}
set
{
_parentId = new Lazy<int>(() => value);
OnPropertyChanged(Ps.Value.ParentIdSelector);
}
}
/// <summary>
/// Sets the identifier of the parent entity.
/// </summary>
/// <param name="parentId">Id of the Parent</param>
protected internal void SetLazyParentId(Lazy<int> parentId)
{
_parentId = parentId;
OnPropertyChanged(Ps.Value.ParentIdSelector);
}
/// <summary>
/// Gets or sets the level of the entity.
/// </summary>
[DataMember]
public virtual int Level
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector);
}
/// <summary>
/// Gets or sets the path of the entity.
/// </summary>
[DataMember]
public virtual string Path //Setting this value should be handled by the class not the user
{
get => _path;
set => SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector);
}
/// <summary>
/// Gets or sets the sort order of the entity.
/// </summary>
[DataMember]
public virtual int SortOrder
{
get => _sortOrder;
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector);
}
/// <summary>
/// Gets or sets a value indicating whether the entity is trashed.
/// </summary>
/// <remarks>A trashed entity is unpublished and in the recycle bin.</remarks>
[DataMember]
public virtual bool Trashed // fixme setting this value should be handled by the class not the user
{
get => _trashed;
internal set => SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
}
/// <summary>
/// Gets or sets the name of the entity.
/// </summary>
[DataMember]
public virtual string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector);
}
/// <summary>
/// Gets or sets the identifier of the user who created the entity.
/// </summary>
[DataMember]
public virtual int CreatorId
{
get => _creatorId;
set => SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.CreatorIdSelector);
}
/// <summary>
/// Id of the user who wrote/updated this entity
/// </summary>
@@ -220,7 +119,7 @@ namespace Umbraco.Core.Models
}
return _contentTypeId;
}
protected set { SetPropertyValueAndDetectChanges(value, ref _contentTypeId, Ps.Value.DefaultContentTypeIdSelector); }
protected set => SetPropertyValueAndDetectChanges(value, ref _contentTypeId, Ps.Value.DefaultContentTypeIdSelector);
}
/// <summary>
+1 -1
View File
@@ -9,7 +9,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+16 -120
View File
@@ -6,7 +6,7 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
@@ -17,23 +17,17 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public abstract class ContentTypeBase : EntityBase.EntityBase, IContentTypeBase
public abstract class ContentTypeBase : TreeEntityBase, IContentTypeBase
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private Lazy<int> _parentId;
private string _name;
private int _level;
private string _path;
private IDictionary<string, object> _additionalData;
private string _alias;
private string _description;
private int _sortOrder;
private string _icon = "icon-folder";
private string _thumbnail = "folder.png";
private int _creatorId;
private bool _allowedAsRoot; // note: only one that's not 'pure element type'
private bool _isContainer;
private bool _trashed;
private PropertyGroupCollection _propertyGroups;
private PropertyTypeCollection _propertyTypes;
private IEnumerable<ContentTypeSort> _allowedContentTypes;
@@ -43,11 +37,10 @@ namespace Umbraco.Core.Models
protected ContentTypeBase(int parentId)
{
if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId));
ParentId = parentId;
_parentId = new Lazy<int>(() => parentId);
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_additionalData = new Dictionary<string, object>();
// actually OK as IsPublishing is constant
// ReSharper disable once VirtualMemberCallInConstructor
@@ -64,12 +57,11 @@ namespace Umbraco.Core.Models
protected ContentTypeBase(IContentTypeBase parent, string alias)
{
if (parent == null) throw new ArgumentNullException(nameof(parent));
SetParent(parent);
_alias = alias;
_parentId = new Lazy<int>(() => parent.Id);
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_additionalData = new Dictionary<string, object>();
// actually OK as IsPublishing is constant
// ReSharper disable once VirtualMemberCallInConstructor
@@ -79,6 +71,17 @@ namespace Umbraco.Core.Models
_variations = ContentVariation.InvariantNeutral;
}
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[DataMember]
[DoNotClone]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary<string, object>());
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[IgnoreDataMember]
bool IUmbracoEntity.HasAdditionalData => _additionalData != null;
/// <summary>
/// Gets a value indicating whether the content type is publishing.
/// </summary>
@@ -95,19 +98,12 @@ namespace Umbraco.Core.Models
// ReSharper disable once ClassNeverInstantiated.Local
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.SortOrder);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Path);
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Alias);
public readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Description);
public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
public readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.CreatorId);
public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.Trashed);
public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
public readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<PropertyType>>(x => x.PropertyTypes);
@@ -131,59 +127,6 @@ namespace Umbraco.Core.Models
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
}
/// <summary>
/// Gets or sets the Id of the Parent entity
/// </summary>
/// <remarks>Might not be necessary if handled as a relation?</remarks>
[DataMember]
public virtual int ParentId
{
get
{
var val = _parentId.Value;
if (val == 0)
{
throw new InvalidOperationException("The ParentId cannot be a value of 0. Perhaps the parent object used to instantiate this object has not been persisted to the data store.");
}
return val;
}
set
{
_parentId = new Lazy<int>(() => value);
OnPropertyChanged(Ps.Value.ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the current entity
/// </summary>
[DataMember]
public virtual string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector);
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public virtual int Level //NOTE Is this relevant for a ContentType?
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector);
}
/// <summary>
/// Gets of sets the path
/// </summary>
[DataMember]
public virtual string Path //NOTE Is this relevant for a ContentType?
{
get => _path;
set => SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector);
}
/// <summary>
/// The Alias of the ContentType
/// </summary>
@@ -207,16 +150,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _description, Ps.Value.DescriptionSelector);
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public virtual int SortOrder
{
get => _sortOrder;
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector);
}
/// <summary>
/// Name of the icon (sprite class) used to identify the ContentType
/// </summary>
@@ -237,16 +170,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _thumbnail, Ps.Value.ThumbnailSelector);
}
/// <summary>
/// Gets or sets the Id of the user who created this ContentType
/// </summary>
[DataMember]
public virtual int CreatorId
{
get => _creatorId;
set => SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.CreatorIdSelector);
}
/// <summary>
/// Gets or Sets a boolean indicating whether this ContentType is allowed at the root
/// </summary>
@@ -270,24 +193,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector);
}
/// <summary>
/// Boolean indicating whether this ContentType is Trashed or not.
/// If ContentType is Trashed it will be located in the Recyclebin.
/// </summary>
[DataMember]
public virtual bool Trashed //NOTE Is this relevant for a ContentType?
{
get => _trashed;
set => SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
}
private readonly IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData;
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>
@@ -493,15 +398,6 @@ namespace Umbraco.Core.Models
OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector);
}
/// <summary>
/// Sets the ParentId from the lazy integer id
/// </summary>
/// <param name="id">Id of the Parent</param>
public void SetLazyParentId(Lazy<int> id)
{
_parentId = id;
}
/// <summary>
/// PropertyTypes that are not part of a PropertyGroup
/// </summary>
+1 -1
View File
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+13 -104
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -12,18 +12,11 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class DataType : EntityBase.EntityBase, IDataType
public class DataType : TreeEntityBase, IDataType
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private readonly IDictionary<string, object> _additionalData;
private IDictionary<string, object> _additionalData;
private int _parentId;
private string _name;
private int _sortOrder;
private int _level;
private string _path;
private int _creatorId;
private bool _trashed;
private string _propertyEditorAlias;
private DataTypeDatabaseType _databaseType;
@@ -32,10 +25,8 @@ namespace Umbraco.Core.Models
/// </summary>
public DataType(int parentId, string propertyEditorAlias)
{
_parentId = parentId;
ParentId = parentId;
_propertyEditorAlias = propertyEditorAlias;
_additionalData = new Dictionary<string, object>();
}
/// <summary>
@@ -43,106 +34,34 @@ namespace Umbraco.Core.Models
/// </summary>
public DataType(string propertyEditorAlias)
{
_parentId = -1;
ParentId = -1;
_propertyEditorAlias = propertyEditorAlias;
_additionalData = new Dictionary<string, object>();
}
// ReSharper disable once ClassNeverInstantiated.Local
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataType, string>(x => x.Name);
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DataType, int>(x => x.ParentId);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<DataType, int>(x => x.SortOrder);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<DataType, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<DataType, string>(x => x.Path);
public readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<DataType, int>(x => x.CreatorId);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<DataType, bool>(x => x.Trashed);
public readonly PropertyInfo PropertyEditorAliasSelector = ExpressionHelper.GetPropertyInfo<DataType, string>(x => x.EditorAlias);
public readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo<DataType, DataTypeDatabaseType>(x => x.DatabaseType);
}
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[DataMember]
public int ParentId
{
get => _parentId;
set => SetPropertyValueAndDetectChanges(value, ref _parentId, Ps.Value.ParentIdSelector);
}
[DoNotClone]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary<string, object>());
/// <inheritdoc />
[DataMember]
public string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector);
}
/// <inheritdoc />
[DataMember]
public int SortOrder
{
get => _sortOrder;
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector);
}
/// <inheritdoc />
[DataMember]
public int Level
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector);
}
/// <inheritdoc />
// fixme - setting this value should be handled by the class not the user
[DataMember]
public string Path
{
get => _path;
set => SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector);
}
/// <inheritdoc />
[DataMember]
public int CreatorId
{
get => _creatorId;
set => SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.UserIdSelector);
}
/// <inheritdoc />
// fixme - data types cannot be trashed?
[DataMember]
public bool Trashed
{
get => _trashed;
internal set
{
SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
// this is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["Trashed"] = value;
}
}
// fixme - what exactly are we doing with _additionalData?
// are we allocating 1 dictionary for *every* entity?
// not doing it for other entities?
[EditorBrowsable(EditorBrowsableState.Never)]
[IgnoreDataMember]
bool IUmbracoEntity.HasAdditionalData => _additionalData != null;
/// <inheritdoc />
[DataMember]
public string EditorAlias
{
get => _propertyEditorAlias;
set
{
SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, Ps.Value.PropertyEditorAliasSelector);
// this is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["DatabaseType"] = value;
}
set => SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, Ps.Value.PropertyEditorAliasSelector);
}
/// <inheritdoc />
@@ -150,21 +69,11 @@ namespace Umbraco.Core.Models
public DataTypeDatabaseType DatabaseType
{
get => _databaseType;
set
{
SetPropertyValueAndDetectChanges(value, ref _databaseType, Ps.Value.DatabaseTypeSelector);
// this is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["DatabaseType"] = value;
}
set => SetPropertyValueAndDetectChanges(value, ref _databaseType, Ps.Value.DatabaseTypeSelector);
}
// fixme - implement that one !!
[DataMember]
public object Configuration { get; set; }
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData;
}
}
+2 -2
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class DictionaryItem : EntityBase.EntityBase, IDictionaryItem
public class DictionaryItem : EntityBase, IDictionaryItem
{
public Func<int, ILanguage> GetLanguage { get; set; }
private Guid? _parentId;
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class DictionaryTranslation : EntityBase.EntityBase, IDictionaryTranslation
public class DictionaryTranslation : EntityBase, IDictionaryTranslation
{
internal Func<int, ILanguage> GetLanguage { get; set; }
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Reflection;
namespace Umbraco.Core.Models.EntityBase
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Provides a concrete implementation of <see cref="BeingDirtyBase"/>.
@@ -5,9 +5,8 @@ using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Models.EntityBase
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Provides a base implementation of <see cref="ICanBeDirty"/> and <see cref="IRememberBeingDirty"/>.
@@ -0,0 +1,17 @@
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Implements <see cref="IContentEntitySlim"/>.
/// </summary>
public class ContentEntitySlim : EntitySlim, IContentEntitySlim
{
/// <inheritdoc />
public string ContentTypeAlias { get; set; }
/// <inheritdoc />
public string ContentTypeIcon { get; set; }
/// <inheritdoc />
public string ContentTypeThumbnail { get; set; }
}
}
@@ -0,0 +1,14 @@
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Implements <see cref="IDocumentEntitySlim"/>.
/// </summary>
public class DocumentEntitySlim : ContentEntitySlim, IDocumentEntitySlim
{
/// <inheritdoc />
public bool Published { get; set; }
/// <inheritdoc />
public bool Edited { get; set; }
}
}
@@ -3,7 +3,7 @@ using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.EntityBase
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Provides a base class for entities.
@@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models.Entities
{
// fixme - changing the name of some properties that were in additionalData => must update corresponding javascript?
/// <summary>
/// Implementation of <see cref="IEntitySlim"/> for internal use.
/// </summary>
/// <remarks>
/// <para>Although it implements <see cref="IEntitySlim"/>, this class does not
/// implement <see cref="IRememberBeingDirty"/> and everything this interface defines, throws.</para>
/// <para>Although it implements <see cref="IEntitySlim"/>, this class does not
/// implement <see cref="IDeepCloneable"/> and deep-cloning throws.</para>
/// </remarks>
public class EntitySlim : IEntitySlim
{
private IDictionary<string, object> _additionalData;
/// <summary>
/// Gets an entity representing "root".
/// </summary>
public static readonly IEntitySlim Root = new EntitySlim { Path = "-1", Name = "root", HasChildren = true };
// implement IEntity
/// <inheritdoc />
[DataMember]
public int Id { get; set; }
/// <inheritdoc />
[DataMember]
public Guid Key { get; set; }
/// <inheritdoc />
[DataMember]
public DateTime CreateDate { get; set; }
/// <inheritdoc />
[DataMember]
public DateTime UpdateDate { get; set; }
/// <inheritdoc />
[DataMember]
public DateTime? DeleteDate { get; set; }
/// <inheritdoc />
[DataMember]
public bool HasIdentity => Id != 0;
// implement ITreeEntity
/// <inheritdoc />
[DataMember]
public string Name { get; set; }
/// <inheritdoc />
[DataMember]
public int CreatorId { get; set; }
/// <inheritdoc />
[DataMember]
public int ParentId { get; set; }
/// <inheritdoc />
public void SetParent(ITreeEntity parent) => throw new WontImplementException();
/// <inheritdoc />
[DataMember]
public int Level { get; set; }
/// <inheritdoc />
[DataMember]
public string Path { get; set; }
/// <inheritdoc />
[DataMember]
public int SortOrder { get; set; }
/// <inheritdoc />
[DataMember]
public bool Trashed { get; set; }
// implement IUmbracoEntity
/// <inheritdoc />
[DataMember]
public IDictionary<string, object> AdditionalData => _additionalData ?? (_additionalData = new Dictionary<string, object>());
/// <inheritdoc />
[IgnoreDataMember]
public bool HasAdditionalData => _additionalData != null;
// implement IEntitySlim
/// <inheritdoc />
[DataMember]
public Guid NodeObjectType { get; set; }
/// <inheritdoc />
[DataMember]
public bool HasChildren { get; set; }
/// <inheritdoc />
[DataMember]
public virtual bool IsContainer { get; set; }
/// <summary>
/// Represents a lightweight property.
/// </summary>
public class PropertySlim
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertySlim"/> class.
/// </summary>
public PropertySlim(string editorAlias, object value)
{
PropertyEditorAlias = editorAlias;
Value = value;
}
/// <summary>
/// Gets the property editor alias.
/// </summary>
public string PropertyEditorAlias { get; }
/// <summary>
/// Gets the property value.
/// </summary>
public object Value { get; }
protected bool Equals(PropertySlim other)
{
return PropertyEditorAlias.Equals(other.PropertyEditorAlias) && Equals(Value, other.Value);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((PropertySlim) obj);
}
public override int GetHashCode()
{
unchecked
{
return (PropertyEditorAlias.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
}
}
}
#region IDeepCloneable
/// <inheritdoc />
public object DeepClone()
{
throw new WontImplementException();
}
#endregion
#region IRememberBeingDirty
// IEntitySlim does *not* track changes, but since it indirectly implements IUmbracoEntity,
// and therefore IRememberBeingDirty, we have to have those methods - which all throw.
public bool IsDirty()
{
throw new WontImplementException();
}
public bool IsPropertyDirty(string propName)
{
throw new WontImplementException();
}
public IEnumerable<string> GetDirtyProperties()
{
throw new WontImplementException();
}
public void ResetDirtyProperties()
{
throw new WontImplementException();
}
public bool WasDirty()
{
throw new WontImplementException();
}
public bool WasPropertyDirty(string propertyName)
{
throw new WontImplementException();
}
public void ResetWereDirtyProperties()
{
throw new WontImplementException();
}
public void ResetDirtyProperties(bool rememberDirty)
{
throw new WontImplementException();
}
#endregion
}
}
@@ -1,30 +1,30 @@
using System.Collections.Generic;
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// Defines an entity that tracks property changes and can be dirty.
/// </summary>
public interface ICanBeDirty
{
/// <summary>
/// Determines whether the current entity is dirty.
/// </summary>
bool IsDirty();
/// <summary>
/// Determines whether a specific property is dirty.
/// </summary>
bool IsPropertyDirty(string propName);
/// <summary>
/// Gets properties that are dirty.
/// </summary>
IEnumerable<string> GetDirtyProperties();
/// <summary>
/// Resets dirty properties.
/// </summary>
void ResetDirtyProperties();
}
}
using System.Collections.Generic;
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Defines an entity that tracks property changes and can be dirty.
/// </summary>
public interface ICanBeDirty
{
/// <summary>
/// Determines whether the current entity is dirty.
/// </summary>
bool IsDirty();
/// <summary>
/// Determines whether a specific property is dirty.
/// </summary>
bool IsPropertyDirty(string propName);
/// <summary>
/// Gets properties that are dirty.
/// </summary>
IEnumerable<string> GetDirtyProperties();
/// <summary>
/// Resets dirty properties.
/// </summary>
void ResetDirtyProperties();
}
}
@@ -0,0 +1,23 @@
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Represents a lightweight content entity, managed by the entity service.
/// </summary>
public interface IContentEntitySlim : IEntitySlim
{
/// <summary>
/// Gets the content type alias.
/// </summary>
string ContentTypeAlias { get; }
/// <summary>
/// Gets the content type icon.
/// </summary>
string ContentTypeIcon { get; }
/// <summary>
/// Gets the content type thumbnail.
/// </summary>
string ContentTypeThumbnail { get; }
}
}
@@ -0,0 +1,18 @@
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Represents a lightweight document entity, managed by the entity service.
/// </summary>
public interface IDocumentEntitySlim : IContentEntitySlim
{
/// <summary>
/// Gets a value indicating whether the document is published.
/// </summary>
bool Published { get; }
/// <summary>
/// Gets a value indicating whether the document has edited properties.
/// </summary>
bool Edited { get; }
}
}
@@ -1,46 +1,45 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// Defines an entity.
/// </summary>
public interface IEntity : IDeepCloneable
{
/// <summary>
/// Gets or sets the integer identifier of the entity.
/// </summary>
int Id { get; set; }
/// <summary>
/// Gets or sets the Guid unique identifier of the entity.
/// </summary>
Guid Key { get; set; }
/// <summary>
/// Gets or sets the creation date.
/// </summary>
DateTime CreateDate { get; set; }
/// <summary>
/// Gets or sets the last update date.
/// </summary>
DateTime UpdateDate { get; set; }
/// <summary>
/// Gets or sets the delete date.
/// </summary>
/// <remarks>
/// <para>The delete date is null when the entity has not been deleted.</para>
/// <para>The delete date has a value when the entity instance has been deleted, but this value
/// is transient and not persisted in database (since the entity does not exist anymore).</para>
/// </remarks>
DateTime? DeleteDate { get; set; }
/// <summary>
/// Gets a value indicating whether the entity has an identity.
/// </summary>
bool HasIdentity { get; }
}
}
using System;
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Defines an entity.
/// </summary>
public interface IEntity : IDeepCloneable
{
/// <summary>
/// Gets or sets the integer identifier of the entity.
/// </summary>
int Id { get; set; }
/// <summary>
/// Gets or sets the Guid unique identifier of the entity.
/// </summary>
Guid Key { get; set; }
/// <summary>
/// Gets or sets the creation date.
/// </summary>
DateTime CreateDate { get; set; }
/// <summary>
/// Gets or sets the last update date.
/// </summary>
DateTime UpdateDate { get; set; }
/// <summary>
/// Gets or sets the delete date.
/// </summary>
/// <remarks>
/// <para>The delete date is null when the entity has not been deleted.</para>
/// <para>The delete date has a value when the entity instance has been deleted, but this value
/// is transient and not persisted in database (since the entity does not exist anymore).</para>
/// </remarks>
DateTime? DeleteDate { get; set; }
/// <summary>
/// Gets a value indicating whether the entity has an identity.
/// </summary>
bool HasIdentity { get; }
}
}
@@ -0,0 +1,25 @@
using System;
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Represents a lightweight entity, managed by the entity service.
/// </summary>
public interface IEntitySlim : IUmbracoEntity
{
/// <summary>
/// Gets or sets the entity object type.
/// </summary>
Guid NodeObjectType { get; }
/// <summary>
/// Gets or sets a value indicating whether the entity has children.
/// </summary>
bool HasChildren { get; }
/// <summary>
/// Gets a value indicating whether the entity is a container.
/// </summary>
bool IsContainer { get; }
}
}
@@ -1,33 +1,33 @@
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// Defines an entity that tracks property changes and can be dirty, and remembers
/// which properties were dirty when the changes were committed.
/// </summary>
public interface IRememberBeingDirty : ICanBeDirty
{
/// <summary>
/// Determines whether the current entity is dirty.
/// </summary>
/// <remarks>A property was dirty if it had been changed and the changes were committed.</remarks>
bool WasDirty();
/// <summary>
/// Determines whether a specific property was dirty.
/// </summary>
/// <remarks>A property was dirty if it had been changed and the changes were committed.</remarks>
bool WasPropertyDirty(string propertyName);
/// <summary>
/// Resets properties that were dirty.
/// </summary>
void ResetWereDirtyProperties();
/// <summary>
/// Resets dirty properties.
/// </summary>
/// <param name="rememberDirty">A value indicating whether to remember dirty properties.</param>
/// <remarks>When <paramref name="rememberDirty"/> is true, dirty properties are saved so they can be checked with WasDirty.</remarks>
void ResetDirtyProperties(bool rememberDirty);
}
}
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Defines an entity that tracks property changes and can be dirty, and remembers
/// which properties were dirty when the changes were committed.
/// </summary>
public interface IRememberBeingDirty : ICanBeDirty
{
/// <summary>
/// Determines whether the current entity is dirty.
/// </summary>
/// <remarks>A property was dirty if it had been changed and the changes were committed.</remarks>
bool WasDirty();
/// <summary>
/// Determines whether a specific property was dirty.
/// </summary>
/// <remarks>A property was dirty if it had been changed and the changes were committed.</remarks>
bool WasPropertyDirty(string propertyName);
/// <summary>
/// Resets properties that were dirty.
/// </summary>
void ResetWereDirtyProperties();
/// <summary>
/// Resets dirty properties.
/// </summary>
/// <param name="rememberDirty">A value indicating whether to remember dirty properties.</param>
/// <remarks>When <paramref name="rememberDirty"/> is true, dirty properties are saved so they can be checked with WasDirty.</remarks>
void ResetDirtyProperties(bool rememberDirty);
}
}
@@ -1,6 +1,4 @@
using System;
namespace Umbraco.Core.Models.EntityBase
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Defines an entity that belongs to a tree.
@@ -12,11 +10,25 @@ namespace Umbraco.Core.Models.EntityBase
/// </summary>
string Name { get; set; }
/// <summary>
/// Gets or sets the identifier of the user who created this entity.
/// </summary>
int CreatorId { get; set; }
/// <summary>
/// Gets or sets the identifier of the parent entity.
/// </summary>
int ParentId { get; set; }
/// <summary>
/// Sets the parent entity.
/// </summary>
/// <remarks>Use this method to set the parent entity when the parent entity is known, but has not
/// been persistent and does not yet have an identity. The parent identifier will we retrieved
/// from the parent entity when needed. If the parent entity still does not have an entity by that
/// time, an exception will be thrown by <see cref="ParentId"/> getter.</remarks>
void SetParent(ITreeEntity parent);
/// <summary>
/// Gets or sets the level of the entity.
/// </summary>
@@ -40,10 +52,5 @@ namespace Umbraco.Core.Models.EntityBase
/// <para>Always false for entities that do not support being trashed.</para>
/// </remarks>
bool Trashed { get; }
/// <summary>
/// Gets or sets the identifier of the user who created this entity.
/// </summary>
int CreatorId { get; set; }
}
}
@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Represents an entity that can be managed by the entity service.
/// </summary>
/// <remarks>
/// <para>An IUmbracoEntity can be related to another via the IRelationService.</para>
/// <para>IUmbracoEntities can be retrieved with the IEntityService.</para>
/// <para>An IUmbracoEntity can participate in notifications.</para>
/// </remarks>
public interface IUmbracoEntity : ITreeEntity, IRememberBeingDirty
{
/// <summary>
/// Gets additional data for this entity.
/// </summary>
/// <remarks>Can be empty, but never null. To avoid allocating, do not
/// test for emptyness, but use <see cref="HasAdditionalData"/> instead.</remarks>
IDictionary<string, object> AdditionalData { get; }
/// <summary>
/// Determines whether this entity has additional data.
/// </summary>
/// <remarks>Use this property to check for additional data without
/// getting <see cref="AdditionalData"/>, to avoid allocating.</remarks>
bool HasAdditionalData { get; }
}
}
@@ -1,11 +1,11 @@
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// Marker interface for value object, eg. objects without
/// the same kind of identity as an Entity (with its Id).
/// </summary>
public interface IValueObject
{
}
}
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Marker interface for value object, eg. objects without
/// the same kind of identity as an Entity (with its Id).
/// </summary>
public interface IValueObject
{
}
}
@@ -0,0 +1,124 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Provides a base class for tree entities.
/// </summary>
public abstract class TreeEntityBase : EntityBase, ITreeEntity
{
private static PropertySelectors _selectors;
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
private string _name;
private int _creatorId;
private int _parentId;
private bool _hasParentId;
private ITreeEntity _parent;
private int _level;
private string _path;
private int _sortOrder;
private bool _trashed;
private class PropertySelectors
{
public readonly PropertyInfo Name = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Name);
public readonly PropertyInfo CreatorId = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.CreatorId);
public readonly PropertyInfo ParentId = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ParentId);
public readonly PropertyInfo Level = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.Level);
public readonly PropertyInfo Path = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Path);
public readonly PropertyInfo SortOrder = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.SortOrder);
public readonly PropertyInfo Trashed = ExpressionHelper.GetPropertyInfo<ContentBase, bool>(x => x.Trashed);
}
// fixme
// ParentId, Path, Level and Trashed all should be consistent, and all derive from parentId, really
/// <inheritdoc />
[DataMember]
public string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, Selectors.Name);
}
/// <inheritdoc />
[DataMember]
public int CreatorId
{
get => _creatorId;
set => SetPropertyValueAndDetectChanges(value, ref _creatorId, Selectors.CreatorId);
}
/// <inheritdoc />
[DataMember]
public int ParentId
{
get
{
if (_hasParentId) return _parentId;
if (_parent == null) throw new InvalidOperationException("Content does not have a parent.");
if (!_parent.HasIdentity) throw new InvalidOperationException("Content's parent does not have an identity.");
_parentId = _parent.Id;
if (_parentId == 0)
throw new Exception("Panic: parent has an identity but id is zero.");
_hasParentId = true;
_parent = null;
return _parentId;
}
set
{
if (value == 0)
throw new ArgumentException("Value cannot be zero.", nameof(value));
SetPropertyValueAndDetectChanges(value, ref _parentId, Selectors.ParentId);
_hasParentId = true;
_parent = null;
}
}
/// <inheritdoc />
public void SetParent(ITreeEntity parent)
{
_hasParentId = false;
_parent = parent;
OnPropertyChanged(Selectors.ParentId);
}
/// <inheritdoc />
[DataMember]
public int Level
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, Selectors.Level);
}
/// <inheritdoc />
[DataMember]
public string Path
{
get => _path;
set => SetPropertyValueAndDetectChanges(value, ref _path, Selectors.Path);
}
/// <inheritdoc />
[DataMember]
public int SortOrder
{
get => _sortOrder;
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, Selectors.SortOrder);
}
/// <inheritdoc />
[DataMember]
public bool Trashed
{
get => _trashed;
set => SetPropertyValueAndDetectChanges(value, ref _trashed, Selectors.Trashed);
}
}
}
@@ -1,4 +1,4 @@
namespace Umbraco.Core.Models.EntityBase
namespace Umbraco.Core.Models.Entities
{
/// <summary>
/// Represents the path of a tree entity.
@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// Represents fixme what exactly?
/// </summary>
/// <remarks>
/// <para>An IUmbracoEntity can be related to another via the IRelationService.</para>
/// <para>IUmbracoEntities can be retrieved with the IEntityService.</para>
/// <para>An IUmbracoEntity can participate in notifications.</para>
/// </remarks>
public interface IUmbracoEntity : ITreeEntity, IRememberBeingDirty
{
/// <summary>
/// Gets additional data for this entity.
/// </summary>
IDictionary<string, object> AdditionalData { get; }
// fixme AdditionalData is never null, then we need a HasAdditionalData for checking values?
///// <summary>
///// Gets a value indicating whether this entity has children.
///// </summary>
//bool HasChildren { get; }
///// <summary>
///// Gets the node object type of the entity.
///// </summary>
//Guid NodeObjectType { get; }
}
}
+21 -12
View File
@@ -1,15 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a folder for organizing entities such as content types and data types.
/// </summary>
public sealed class EntityContainer : UmbracoEntity
public sealed class EntityContainer : TreeEntityBase, IUmbracoEntity
{
private readonly Guid _containedObjectType;
private IDictionary<string, object> _additionalData;
private static readonly Dictionary<Guid, Guid> ObjectTypeMap = new Dictionary<Guid, Guid>
{
@@ -24,7 +28,7 @@ namespace Umbraco.Core.Models
public EntityContainer(Guid containedObjectType)
{
if (ObjectTypeMap.ContainsKey(containedObjectType) == false)
throw new ArgumentException("Not a contained object type.", "containedObjectType");
throw new ArgumentException("Not a contained object type.", nameof(containedObjectType));
_containedObjectType = containedObjectType;
ParentId = -1;
@@ -52,18 +56,12 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets or sets the node object type of the contained objects.
/// </summary>
public Guid ContainedObjectType
{
get { return _containedObjectType; }
}
public Guid ContainedObjectType => _containedObjectType;
/// <summary>
/// Gets the node object type of the container objects.
/// </summary>
public Guid ContainerObjectType
{
get { return ObjectTypeMap[_containedObjectType]; }
}
public Guid ContainerObjectType => ObjectTypeMap[_containedObjectType];
/// <summary>
/// Gets the container object type corresponding to a contained object type.
@@ -73,7 +71,7 @@ namespace Umbraco.Core.Models
public static Guid GetContainerObjectType(Guid containedObjectType)
{
if (ObjectTypeMap.ContainsKey(containedObjectType) == false)
throw new ArgumentException("Not a contained object type.", "containedObjectType");
throw new ArgumentException("Not a contained object type.", nameof(containedObjectType));
return ObjectTypeMap[containedObjectType];
}
@@ -86,8 +84,19 @@ namespace Umbraco.Core.Models
{
var contained = ObjectTypeMap.FirstOrDefault(x => x.Value == containerObjectType).Key;
if (contained == null)
throw new ArgumentException("Not a container object type.", "containerObjectType");
throw new ArgumentException("Not a container object type.", nameof(containerObjectType));
return contained;
}
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[DataMember]
[DoNotClone]
IDictionary<string, object> IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary<string, object>());
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
[IgnoreDataMember]
bool IUmbracoEntity.HasAdditionalData => _additionalData != null;
}
}
+3 -4
View File
@@ -1,4 +1,4 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -14,10 +14,9 @@ namespace Umbraco.Core.Models
/// This is useful when handling events to determine if an entity is a brand new entity or was
/// already existing.
/// </remarks>
public static bool IsNewEntity(this IEntity entity)
public static bool IsNewEntity(this IRememberBeingDirty entity)
{
var dirty = (IRememberBeingDirty) entity;
return dirty.WasPropertyDirty("Id");
return entity.WasPropertyDirty("Id");
}
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public abstract class File : EntityBase.EntityBase, IFile
public abstract class File : EntityBase, IFile
{
private string _path;
private string _originalPath;
+2 -2
View File
@@ -1,8 +1,8 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
internal sealed class Folder : EntityBase.EntityBase
internal sealed class Folder : EntityBase
{
public Folder(string folderPath)
{
+1 -1
View File
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -7
View File
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -80,12 +80,6 @@ namespace Umbraco.Core.Models
/// <param name="propertyGroupName">Name of the <see cref="PropertyGroup"/> to remove</param>
void RemovePropertyGroup(string propertyGroupName);
/// <summary>
/// Sets the ParentId from the lazy integer id
/// </summary>
/// <param name="id">Id of the Parent</param>
void SetLazyParentId(Lazy<int> id);
/// <summary>
/// Checks whether a PropertyType with a given alias already exists
/// </summary>
+1 -1
View File
@@ -1,4 +1,4 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -1,5 +1,5 @@
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
+1 -1
View File
@@ -1,4 +1,4 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System.Globalization;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using Semver;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,5 +1,5 @@
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Sync;
namespace Umbraco.Core.Models
+1 -1
View File
@@ -1,5 +1,5 @@
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -6,7 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Threading.Tasks;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
@@ -1,4 +1,4 @@
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Identity
{
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Identity
{
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Models.Identity
/// Entity type for a user's login (i.e. facebook, google)
///
/// </summary>
public class IdentityUserLogin : EntityBase.EntityBase, IIdentityUserLogin
public class IdentityUserLogin : EntityBase, IIdentityUserLogin
{
public IdentityUserLogin(string loginProvider, string providerKey, int userId)
{
+2 -2
View File
@@ -2,7 +2,7 @@
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Language : EntityBase.EntityBase, ILanguage
public class Language : EntityBase, ILanguage
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
+2 -2
View File
@@ -5,7 +5,7 @@ using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Macro : EntityBase.EntityBase, IMacro
public class Macro : EntityBase, IMacro
{
public Macro()
{
+2 -2
View File
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Models
@@ -84,7 +84,7 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Alias);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Name);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, int>(x => x.SortOrder);
public readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<EntityBase.EntityBase, int>(x => x.Id);
public readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<EntityBase, int>(x => x.Id);
public readonly PropertyInfo PropertyTypeSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.EditorAlias);
}
+2 -2
View File
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class MemberGroup : EntityBase.EntityBase, IMemberGroup
public class MemberGroup : EntityBase, IMemberGroup
{
public MemberGroup()
{
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
+1 -1
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
+2 -2
View File
@@ -9,7 +9,7 @@ using System.Runtime.Serialization;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class User : EntityBase.EntityBase, IUser, IProfile
public class User : EntityBase, IUser, IProfile
{
/// <summary>
/// Constructor for creating a new/empty user
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models.Membership
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
internal class UserGroup : EntityBase.EntityBase, IUserGroup, IReadOnlyUserGroup
internal class UserGroup : EntityBase, IUserGroup, IReadOnlyUserGroup
{
private int? _startContentId;
private int? _startMediaId;
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models.Membership
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Membership
[EditorBrowsable(EditorBrowsableState.Never)]
[Serializable]
[DataContract(IsReference = true)]
internal class UserType : EntityBase.EntityBase, IUserType
internal class UserType : EntityBase, IUserType
{
private string _alias;
private string _name;
+2 -2
View File
@@ -1,11 +1,11 @@
using System;
using System.Reflection;
using Semver;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
public class MigrationEntry : EntityBase.EntityBase, IMigrationEntry
public class MigrationEntry : EntityBase, IMigrationEntry
{
public MigrationEntry()
{
+163
View File
@@ -0,0 +1,163 @@
using System;
using System.Collections.Concurrent;
using System.Reflection;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.Models
{
/// <summary>
/// Provides utilities and extension methods to handle object types.
/// </summary>
public static class ObjectTypes
{
// must be concurrent to avoid thread collisions!
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Guid> UmbracoGuids = new ConcurrentDictionary<UmbracoObjectTypes, Guid>();
private static readonly ConcurrentDictionary<UmbracoObjectTypes, string> UmbracoUdiTypes = new ConcurrentDictionary<UmbracoObjectTypes, string>();
private static readonly ConcurrentDictionary<UmbracoObjectTypes, string> UmbracoFriendlyNames = new ConcurrentDictionary<UmbracoObjectTypes, string>();
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Type> UmbracoTypes = new ConcurrentDictionary<UmbracoObjectTypes, Type>();
private static readonly ConcurrentDictionary<Guid, string> GuidUdiTypes = new ConcurrentDictionary<Guid, string>();
private static readonly ConcurrentDictionary<Guid, UmbracoObjectTypes> GuidObjectTypes = new ConcurrentDictionary<Guid, UmbracoObjectTypes>();
private static readonly ConcurrentDictionary<Guid, Type> GuidTypes = new ConcurrentDictionary<Guid, Type>();
private static FieldInfo GetEnumField(string name)
{
return typeof (UmbracoObjectTypes).GetField(name, BindingFlags.Public | BindingFlags.Static);
}
private static FieldInfo GetEnumField(Guid guid)
{
var fields = typeof (UmbracoObjectTypes).GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var field in fields)
{
var attribute = field.GetCustomAttribute<UmbracoObjectTypeAttribute>(false);
if (attribute != null && attribute.ObjectId == guid) return field;
}
return null;
}
/// <summary>
/// Gets the Umbraco object type corresponding to a name.
/// </summary>
public static UmbracoObjectTypes GetUmbracoObjectType(string name)
{
return (UmbracoObjectTypes) Enum.Parse(typeof (UmbracoObjectTypes), name, false);
}
#region Guid object type utilities
/// <summary>
/// Gets the Umbraco object type corresponding to an object type Guid.
/// </summary>
public static UmbracoObjectTypes GetUmbracoObjectType(Guid objectType)
{
return GuidObjectTypes.GetOrAdd(objectType, t =>
{
var field = GetEnumField(objectType);
if (field == null) return UmbracoObjectTypes.Unknown;
return (UmbracoObjectTypes) field.GetValue(null);
});
}
/// <summary>
/// Gets the Udi type corresponding to an object type Guid.
/// </summary>
public static string GetUdiType(Guid objectType)
{
return GuidUdiTypes.GetOrAdd(objectType, t =>
{
var field = GetEnumField(objectType);
if (field == null) return Constants.UdiEntityType.Unknown;
var attribute = field.GetCustomAttribute<UmbracoUdiTypeAttribute>(false);
return attribute?.UdiType ?? Constants.UdiEntityType.Unknown;
});
}
/// <summary>
/// Gets the Clr type corresponding to an object type Guid.
/// </summary>
public static Type GetClrType(Guid objectType)
{
return GuidTypes.GetOrAdd(objectType, t =>
{
var field = GetEnumField(objectType);
if (field == null) return null;
var attribute = field.GetCustomAttribute<UmbracoObjectTypeAttribute>(false);
return attribute?.ModelType;
});
}
#endregion
#region UmbracoObjectTypes extension methods
/// <summary>
/// Gets the object type Guid corresponding to this Umbraco object type.
/// </summary>
public static Guid GetGuid(this UmbracoObjectTypes objectType)
{
return UmbracoGuids.GetOrAdd(objectType, t =>
{
var field = GetEnumField(t.ToString());
var attribute = field.GetCustomAttribute<UmbracoObjectTypeAttribute>(false);
return attribute?.ObjectId ?? Guid.Empty;
});
}
/// <summary>
/// Gets the Udi type corresponding to this Umbraco object type.
/// </summary>
public static string GetUdiType(this UmbracoObjectTypes objectType)
{
return UmbracoUdiTypes.GetOrAdd(objectType, t =>
{
var field = GetEnumField(t.ToString());
var attribute = field.GetCustomAttribute<UmbracoUdiTypeAttribute>(false);
return attribute?.UdiType ?? Constants.UdiEntityType.Unknown;
});
}
/// <summary>
/// Gets the name corresponding to this Umbraco object type.
/// </summary>
public static string GetName(this UmbracoObjectTypes objectType)
{
return Enum.GetName(typeof (UmbracoObjectTypes), objectType);
}
/// <summary>
/// Gets the friendly name corresponding to this Umbraco object type.
/// </summary>
public static string GetFriendlyName(this UmbracoObjectTypes objectType)
{
return UmbracoFriendlyNames.GetOrAdd(objectType, t =>
{
var field = GetEnumField(t.ToString());
var attribute = field.GetCustomAttribute<FriendlyNameAttribute>(false);
return attribute?.ToString() ?? string.Empty;
});
}
/// <summary>
/// Gets the Clr type corresponding to this Umbraco object type.
/// </summary>
public static Type GetClrType(this UmbracoObjectTypes objectType)
{
return UmbracoTypes.GetOrAdd(objectType, t =>
{
var field = GetEnumField(t.ToString());
var attribute = field.GetCustomAttribute<UmbracoObjectTypeAttribute>(false);
return attribute?.ModelType;
});
}
#endregion
}
}
@@ -0,0 +1,115 @@
using System;
using System.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Models
{
/// <summary>
/// Provides extension methods for path validation.
/// </summary>
internal static class PathValidationExtensions
{
/// <summary>
/// Does a quick check on the entity's set path to ensure that it's valid and consistent
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static void ValidatePathWithException(this NodeDto entity)
{
//don't validate if it's empty and it has no id
if (entity.NodeId == default(int) && entity.Path.IsNullOrWhiteSpace())
return;
if (entity.Path.IsNullOrWhiteSpace())
throw new InvalidDataException($"The content item {entity.NodeId} has an empty path: {entity.Path} with parentID: {entity.ParentId}");
var pathParts = entity.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (pathParts.Length < 2)
{
//a path cannot be less than 2 parts, at a minimum it must be root (-1) and it's own id
throw new InvalidDataException($"The content item {entity.NodeId} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
}
if (entity.ParentId != default(int) && pathParts[pathParts.Length - 2] != entity.ParentId.ToInvariantString())
{
//the 2nd last id in the path must be it's parent id
throw new InvalidDataException($"The content item {entity.NodeId} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
}
}
/// <summary>
/// Does a quick check on the entity's set path to ensure that it's valid and consistent
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static bool ValidatePath(this IUmbracoEntity entity)
{
//don't validate if it's empty and it has no id
if (entity.HasIdentity == false && entity.Path.IsNullOrWhiteSpace())
return true;
if (entity.Path.IsNullOrWhiteSpace())
return false;
var pathParts = entity.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (pathParts.Length < 2)
{
//a path cannot be less than 2 parts, at a minimum it must be root (-1) and it's own id
return false;
}
if (entity.ParentId != default(int) && pathParts[pathParts.Length - 2] != entity.ParentId.ToInvariantString())
{
//the 2nd last id in the path must be it's parent id
return false;
}
return true;
}
/// <summary>
/// This will validate the entity's path and if it's invalid it will fix it, if fixing is required it will recursively
/// check and fix all ancestors if required.
/// </summary>
/// <param name="entity"></param>
/// <param name="logger"></param>
/// <param name="getParent">A callback specified to retrieve the parent entity of the entity</param>
/// <param name="update">A callback specified to update a fixed entity</param>
public static void EnsureValidPath<T>(this T entity,
ILogger logger,
Func<T, T> getParent,
Action<T> update)
where T: IUmbracoEntity
{
if (entity.HasIdentity == false)
throw new InvalidOperationException("Could not ensure the entity path, the entity has not been assigned an identity");
if (entity.ValidatePath() == false)
{
logger.Warn(typeof(UmbracoEntityExtensions), $"The content item {entity.Id} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
if (entity.ParentId == -1)
{
entity.Path = string.Concat("-1,", entity.Id);
//path changed, update it
update(entity);
}
else
{
var parent = getParent(entity);
if (parent == null)
throw new NullReferenceException("Could not ensure path for entity " + entity.Id + " could not resolve it's parent " + entity.ParentId);
//the parent must also be valid!
parent.EnsureValidPath(logger, getParent, update);
entity.Path = string.Concat(parent.Path, ",", entity.Id);
//path changed, update it
update(entity);
}
}
}
}
}
+2 -2
View File
@@ -5,7 +5,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Property : EntityBase.EntityBase
public class Property : EntityBase
{
private List<PropertyTagChange> _tagChanges;
+2 -2
View File
@@ -3,7 +3,7 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}")]
public class PropertyGroup : EntityBase.EntityBase, IEquatable<PropertyGroup>
public class PropertyGroup : EntityBase, IEquatable<PropertyGroup>
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
@@ -5,7 +5,6 @@ using System.Collections.Specialized;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
+2 -2
View File
@@ -3,7 +3,7 @@ using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Strings;
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public class PropertyType : EntityBase.EntityBase, IEquatable<PropertyType>
public class PropertyType : EntityBase, IEquatable<PropertyType>
{
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
+2 -2
View File
@@ -5,13 +5,13 @@ using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
[Serializable]
[DataContract(IsReference = true)]
public class PublicAccessEntry : EntityBase.EntityBase
public class PublicAccessEntry : EntityBase
{
private readonly ObservableCollection<PublicAccessRule> _ruleCollection;
private int _protectedNodeId;
+2 -2
View File
@@ -1,13 +1,13 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
[Serializable]
[DataContract(IsReference = true)]
public class PublicAccessRule : EntityBase.EntityBase
public class PublicAccessRule : EntityBase
{
private string _ruleValue;
private string _ruleType;
+2 -2
View File
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class RedirectUrl : EntityBase.EntityBase, IRedirectUrl
public class RedirectUrl : EntityBase, IRedirectUrl
{
/// <summary>
/// Initializes a new instance of the <see cref="RedirectUrl"/> class.
+2 -2
View File
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Relation : EntityBase.EntityBase, IRelation
public class Relation : EntityBase, IRelation
{
//NOTE: The datetime column from umbracoRelation is set on CreateDate on the Entity
private int _parentId;
+2 -2
View File
@@ -2,7 +2,7 @@
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class RelationType : EntityBase.EntityBase, IRelationType
public class RelationType : EntityBase, IRelationType
{
private string _name;
private string _alias;
@@ -1,14 +1,14 @@
using System;
using System.Globalization;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a registered server in a multiple-servers environment.
/// </summary>
public class ServerRegistration : EntityBase.EntityBase, IServerRegistration
public class ServerRegistration : EntityBase, IServerRegistration
{
private string _serverAddress;
private string _serverIdentity;
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
+2 -2
View File
@@ -2,13 +2,13 @@
using System.Collections;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
[Serializable]
[DataContract(IsReference = true)]
public class Tag : EntityBase.EntityBase, ITag
public class Tag : EntityBase, ITag
{
public Tag()
{
+2 -2
View File
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Task : EntityBase.EntityBase
public class Task : EntityBase
{
private bool _closed;
private TaskType _taskType;
+2 -2
View File
@@ -1,7 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class TaskType : EntityBase.EntityBase
public class TaskType : EntityBase
{
private string _alias;
-1
View File
@@ -8,7 +8,6 @@ using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
+2 -2
View File
@@ -1,13 +1,13 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
[Serializable]
[DataContract(IsReference = true)]
public class UmbracoDomain : EntityBase.EntityBase, IDomain
public class UmbracoDomain : EntityBase, IDomain
{
public UmbracoDomain(string domainName)
{
-251
View File
@@ -1,251 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
// fixme - changing the name of some properties that were in additionalData => must update corresponding javascript?
public class UmbracoContentEntity : UmbracoEntity
{
private static PropertySelectors _selectors;
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
private string _contentTypeAlias;
private class PropertySelectors
{
public readonly PropertyInfo ContentTypeAlias = ExpressionHelper.GetPropertyInfo<UmbracoContentEntity, string>(x => x.ContentTypeAlias);
}
public string ContentTypeAlias
{
get => _contentTypeAlias;
set => SetPropertyValueAndDetectChanges(value, ref _contentTypeAlias, Selectors.ContentTypeAlias);
}
}
public class UmbracoDocumentEntity : UmbracoContentEntity
{
private static PropertySelectors _selectors;
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
private bool _published;
private bool _edited;
private class PropertySelectors
{
public readonly PropertyInfo Published = ExpressionHelper.GetPropertyInfo<UmbracoDocumentEntity, bool>(x => x.Published);
public readonly PropertyInfo Edited = ExpressionHelper.GetPropertyInfo<UmbracoDocumentEntity, bool>(x => x.Edited);
}
public bool Published
{
get => _published;
set => SetPropertyValueAndDetectChanges(value, ref _published, Selectors.Published);
}
public bool Edited
{
get => _edited;
set => SetPropertyValueAndDetectChanges(value, ref _edited, Selectors.Edited);
}
}
/// <summary>
/// Implementation of the <see cref="IUmbracoEntity"/> for internal use.
/// </summary>
public class UmbracoEntity : EntityBase.EntityBase, IUmbracoEntity
{
private static PropertySelectors _selectors;
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
private Guid _nodeObjectType;
private int _creatorId;
private int _level;
private string _name;
private int _parentId;
private string _path;
private int _sortOrder;
private bool _trashed;
private bool _hasChildren;
// fixme - usage
private string _contentTypeIcon;
private string _contentTypeThumbnail;
// fixme - are we tracking changes on something that's basically READONLY?
private class PropertySelectors
{
public readonly PropertyInfo CreatorId = ExpressionHelper.GetPropertyInfo<UmbracoEntity, int>(x => x.CreatorId);
public readonly PropertyInfo Level = ExpressionHelper.GetPropertyInfo<UmbracoEntity, int>(x => x.Level);
public readonly PropertyInfo Name = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.Name);
public readonly PropertyInfo ParentId = ExpressionHelper.GetPropertyInfo<UmbracoEntity, int>(x => x.ParentId);
public readonly PropertyInfo Path = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.Path);
public readonly PropertyInfo SortOrder = ExpressionHelper.GetPropertyInfo<UmbracoEntity, int>(x => x.SortOrder);
public readonly PropertyInfo Trashed = ExpressionHelper.GetPropertyInfo<UmbracoEntity, bool>(x => x.Trashed);
public readonly PropertyInfo HasChildren = ExpressionHelper.GetPropertyInfo<UmbracoEntity, bool>(x => x.HasChildren);
public readonly PropertyInfo NodeObjectType = ExpressionHelper.GetPropertyInfo<UmbracoEntity, Guid>(x => x.NodeObjectType);
public readonly PropertyInfo ContentTypeIcon = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.ContentTypeIcon);
public readonly PropertyInfo ContentTypeThumbnail = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.ContentTypeThumbnail);
}
public static readonly UmbracoEntity Root = new UmbracoEntity { Path = "-1", Name = "root", HasChildren = true };
public UmbracoEntity()
{
AdditionalData = new Dictionary<string, object>();
}
public int CreatorId
{
get => _creatorId;
set => SetPropertyValueAndDetectChanges(value, ref _creatorId, Selectors.CreatorId);
}
public int Level
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, Selectors.Level);
}
public string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, Selectors.Name);
}
public int ParentId
{
get => _parentId;
set => SetPropertyValueAndDetectChanges(value, ref _parentId, Selectors.ParentId);
}
public string Path
{
get => _path;
set => SetPropertyValueAndDetectChanges(value, ref _path, Selectors.Path);
}
public int SortOrder
{
get => _sortOrder;
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, Selectors.SortOrder);
}
public bool Trashed
{
get => _trashed;
set => SetPropertyValueAndDetectChanges(value, ref _trashed, Selectors.Trashed);
}
public bool HasChildren
{
get => _hasChildren;
set => SetPropertyValueAndDetectChanges(value, ref _hasChildren, Selectors.HasChildren);
}
public Guid NodeObjectType
{
get => _nodeObjectType;
set => SetPropertyValueAndDetectChanges(value, ref _nodeObjectType, Selectors.NodeObjectType);
}
public IDictionary<string, object> AdditionalData { get; }
public string ContentTypeIcon
{
get => _contentTypeIcon;
set
{
SetPropertyValueAndDetectChanges(value, ref _contentTypeIcon, Selectors.ContentTypeIcon);
AdditionalData["ContentTypeIcon"] = value; // custom and not in IUmbracoEntity
}
}
public string ContentTypeThumbnail
{
get => _contentTypeThumbnail;
set
{
SetPropertyValueAndDetectChanges(value, ref _contentTypeThumbnail, Selectors.ContentTypeThumbnail);
AdditionalData["ContentTypeThumbnail"] = value; // custom and not in IUmbracoEntity
}
}
public override object DeepClone()
{
var clone = (UmbracoEntity) base.DeepClone();
// disable change tracking
clone.DisableChangeTracking();
// deep clone additional data properties
// fixme - BUT the values are... only set in EntityRepository to non-deepclonable stuff?!
foreach (var key in clone.AdditionalData.Keys.ToArray())
{
if (clone.AdditionalData[key] is IDeepCloneable deepCloneable)
clone.AdditionalData[key] = deepCloneable.DeepClone();
}
// enable tracking
clone.EnableChangeTracking();
return clone;
}
// fixme
// wtf? is clone.AdditionalData at least shallow cloned?
// and, considering the only thing we put in EntityProperty are strings,
// what's the point of EntityProperty ???
/// <summary>
/// A struction that can be contained in the additional data of an UmbracoEntity representing
/// a user defined property
/// </summary>
public class EntityProperty : IDeepCloneable
{
public string PropertyEditorAlias { get; set; }
public object Value { get; set; }
public object DeepClone()
{
//Memberwise clone on Entity will work since it doesn't have any deep elements
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
var clone = MemberwiseClone();
return clone;
}
protected bool Equals(EntityProperty other)
{
return PropertyEditorAlias.Equals(other.PropertyEditorAlias) && Equals(Value, other.Value);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((EntityProperty) obj);
}
public override int GetHashCode()
{
unchecked
{
return (PropertyEditorAlias.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
}
}
}
}
}
@@ -1,153 +1,14 @@
using System;
using System.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
// fixme - this needs to go or be refactored!
internal static class UmbracoEntityExtensions
{
/// <summary>
/// Does a quick check on the entity's set path to ensure that it's valid and consistent
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static void ValidatePathWithException(this NodeDto entity)
{
//don't validate if it's empty and it has no id
if (entity.NodeId == default(int) && entity.Path.IsNullOrWhiteSpace())
return;
if (entity.Path.IsNullOrWhiteSpace())
throw new InvalidDataException($"The content item {entity.NodeId} has an empty path: {entity.Path} with parentID: {entity.ParentId}");
var pathParts = entity.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (pathParts.Length < 2)
{
//a path cannot be less than 2 parts, at a minimum it must be root (-1) and it's own id
throw new InvalidDataException($"The content item {entity.NodeId} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
}
if (entity.ParentId != default(int) && pathParts[pathParts.Length - 2] != entity.ParentId.ToInvariantString())
{
//the 2nd last id in the path must be it's parent id
throw new InvalidDataException($"The content item {entity.NodeId} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
}
}
/// <summary>
/// Does a quick check on the entity's set path to ensure that it's valid and consistent
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static bool ValidatePath(this IUmbracoEntity entity)
{
//don't validate if it's empty and it has no id
if (entity.HasIdentity == false && entity.Path.IsNullOrWhiteSpace())
return true;
if (entity.Path.IsNullOrWhiteSpace())
return false;
var pathParts = entity.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (pathParts.Length < 2)
{
//a path cannot be less than 2 parts, at a minimum it must be root (-1) and it's own id
return false;
}
if (entity.ParentId != default(int) && pathParts[pathParts.Length - 2] != entity.ParentId.ToInvariantString())
{
//the 2nd last id in the path must be it's parent id
return false;
}
return true;
}
/// <summary>
/// This will validate the entity's path and if it's invalid it will fix it, if fixing is required it will recursively
/// check and fix all ancestors if required.
/// </summary>
/// <param name="entity"></param>
/// <param name="logger"></param>
/// <param name="getParent">A callback specified to retrieve the parent entity of the entity</param>
/// <param name="update">A callback specified to update a fixed entity</param>
public static void EnsureValidPath<T>(this T entity,
ILogger logger,
Func<T, T> getParent,
Action<T> update)
where T: IUmbracoEntity
{
if (entity.HasIdentity == false)
throw new InvalidOperationException("Could not ensure the entity path, the entity has not been assigned an identity");
if (entity.ValidatePath() == false)
{
logger.Warn(typeof(UmbracoEntityExtensions), $"The content item {entity.Id} has an invalid path: {entity.Path} with parentID: {entity.ParentId}");
if (entity.ParentId == -1)
{
entity.Path = string.Concat("-1,", entity.Id);
//path changed, update it
update(entity);
}
else
{
var parent = getParent(entity);
if (parent == null)
throw new NullReferenceException("Could not ensure path for entity " + entity.Id + " could not resolve it's parent " + entity.ParentId);
//the parent must also be valid!
parent.EnsureValidPath(logger, getParent, update);
entity.Path = string.Concat(parent.Path, ",", entity.Id);
//path changed, update it
update(entity);
}
}
}
/// <summary>
/// When resolved from EntityService this checks if the entity has the HasChildren flag
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static bool HasChildren(this IUmbracoEntity entity)
{
// fixme
//return entity.HasChildren; // but then we would not need this extension method?
if (entity.AdditionalData.ContainsKey("HasChildren"))
{
var convert = entity.AdditionalData["HasChildren"].TryConvertTo<bool>();
if (convert)
{
return convert.Result;
}
}
return false;
}
public static object GetAdditionalDataValueIgnoreCase(this IUmbracoEntity entity, string key, object defaultVal)
{
if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal;
return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal);
}
/// <summary>
/// When resolved from EntityService this checks if the entity has the IsContainer flag
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public static bool IsContainer(this IUmbracoEntity entity)
{
if (entity.AdditionalData.ContainsKeyIgnoreCase("IsContainer") == false) return false;
var val = entity.AdditionalData.GetValueIgnoreCase("IsContainer", null);
if (val is bool && (bool) val)
{
return true;
}
return false;
}
}
}
@@ -1,138 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.Models
{
/// <summary>
/// Extension methods for the UmbracoObjectTypes enum
/// </summary>
public static class UmbracoObjectTypesExtensions
{
//MUST be concurrent to avoid thread collisions!
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Guid> UmbracoObjectTypeCache = new ConcurrentDictionary<UmbracoObjectTypes, Guid>();
private static readonly ConcurrentDictionary<UmbracoObjectTypes, string> UmbracoObjectTypeUdiCache = new ConcurrentDictionary<UmbracoObjectTypes, string>();
/// <summary>
/// Get an UmbracoObjectTypes value from it's name
/// </summary>
/// <param name="name">Enum value name</param>
/// <returns>an UmbracoObjectTypes Enum value</returns>
public static UmbracoObjectTypes GetUmbracoObjectType(string name)
{
return (UmbracoObjectTypes)Enum.Parse(typeof(UmbracoObjectTypes), name, false);
}
/// <summary>
/// Get an instance of an UmbracoObjectTypes enum value from it's GUID
/// </summary>
/// <param name="guid">Enum value GUID</param>
/// <returns>an UmbracoObjectTypes Enum value</returns>
public static UmbracoObjectTypes GetUmbracoObjectType(Guid guid)
{
var umbracoObjectType = UmbracoObjectTypes.Unknown;
foreach (var name in Enum.GetNames(typeof(UmbracoObjectTypes)))
{
if (GetUmbracoObjectType(name).GetGuid() == guid)
{
umbracoObjectType = GetUmbracoObjectType(name);
}
}
return umbracoObjectType;
}
public static string GetUdiType(Guid guid)
{
var umbracoObjectType = Constants.UdiEntityType.Unknown;
foreach (var name in Enum.GetNames(typeof(UmbracoObjectTypes)))
{
var objType = GetUmbracoObjectType(name);
if (objType.GetGuid() == guid)
{
umbracoObjectType = GetUdiType(objType);
}
}
return umbracoObjectType;
}
/// <summary>
/// Extension method for the UmbracoObjectTypes enum to return the enum GUID
/// </summary>
/// <param name="umbracoObjectType">UmbracoObjectTypes Enum value</param>
/// <returns>a GUID value of the UmbracoObjectTypes</returns>
public static Guid GetGuid(this UmbracoObjectTypes umbracoObjectType)
{
return UmbracoObjectTypeCache.GetOrAdd(umbracoObjectType, types =>
{
var type = typeof (UmbracoObjectTypes);
var memberInfo = type.GetMember(umbracoObjectType.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof (UmbracoObjectTypeAttribute), false);
if (attributes.Length == 0)
return Guid.Empty;
var attribute = (UmbracoObjectTypeAttribute) attributes[0];
if (attribute == null)
return Guid.Empty;
return attribute.ObjectId;
});
}
public static string GetUdiType(this UmbracoObjectTypes umbracoObjectType)
{
return UmbracoObjectTypeUdiCache.GetOrAdd(umbracoObjectType, types =>
{
var type = typeof(UmbracoObjectTypes);
var memInfo = type.GetMember(umbracoObjectType.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoUdiTypeAttribute),
false);
if (attributes.Length == 0)
return Constants.UdiEntityType.Unknown;
var attribute = ((UmbracoUdiTypeAttribute)attributes[0]);
if (attribute == null)
return Constants.UdiEntityType.Unknown;
return attribute.UdiType;
});
}
/// <summary>
/// Extension method for the UmbracoObjectTypes enum to return the enum name
/// </summary>
/// <param name="umbracoObjectType">UmbracoObjectTypes value</param>
/// <returns>The enum name of the UmbracoObjectTypes value</returns>
public static string GetName(this UmbracoObjectTypes umbracoObjectType)
{
return Enum.GetName(typeof(UmbracoObjectTypes), umbracoObjectType);
}
/// <summary>
/// Extension method for the UmbracoObejctTypes enum to return the enum friendly name
/// </summary>
/// <param name="umbracoObjectType">UmbracoObjectTypes value</param>
/// <returns>a string of the FriendlyName</returns>
public static string GetFriendlyName(this UmbracoObjectTypes umbracoObjectType)
{
var type = typeof(UmbracoObjectTypes);
var memInfo = type.GetMember(umbracoObjectType.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(FriendlyNameAttribute),
false);
if (attributes.Length == 0)
return string.Empty;
var attribute = ((FriendlyNameAttribute)attributes[0]);
if (attribute == null)
return string.Empty;
return attribute.ToString();
}
}
}
+1 -2
View File
@@ -6,8 +6,7 @@ using System.Net;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Dtos
public int DataTypeId { get; set; }
[Column("propertyEditorAlias")]
public string PropertyEditorAlias { get; set; }
public string EditorAlias { get; set; }
[Column("dbType")]
[Length(50)]
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Dtos;

Some files were not shown because too many files have changed in this diff Show More