From 74ecbac7d7398debdf2db091309bbbb2cf996a8d Mon Sep 17 00:00:00 2001 From: "Morten@Thinkpad-X220" Date: Wed, 10 Oct 2012 08:42:54 -0200 Subject: [PATCH] Refactoring Content/Media and ContentTypes/MediaTypes so the two are as close as possible. By doing this Media and Content are practically the same witht the except of a few properties. This implements U4-10 --- src/Umbraco.Core/Models/Content.cs | 254 +------------ src/Umbraco.Core/Models/ContentBase.cs | 262 +++++++++++++ src/Umbraco.Core/Models/ContentType.cs | 343 +----------------- src/Umbraco.Core/Models/ContentTypeBase.cs | 254 +++++++++++++ .../Models/ContentTypeCompositionBase.cs | 118 ++++++ src/Umbraco.Core/Models/IContent.cs | 5 + src/Umbraco.Core/Models/IMedia.cs | 5 + src/Umbraco.Core/Models/IMediaType.cs | 2 +- src/Umbraco.Core/Models/Media.cs | 266 +------------- src/Umbraco.Core/Models/MediaType.cs | 239 +----------- .../Repositories/ContentTypeBaseRepository.cs | 198 ++++++++++ .../Repositories/ContentTypeRepository.cs | 167 +-------- .../Repositories/MediaTypeRepository.cs | 136 +------ src/Umbraco.Core/Umbraco.Core.csproj | 4 + 14 files changed, 885 insertions(+), 1368 deletions(-) create mode 100644 src/Umbraco.Core/Models/ContentBase.cs create mode 100644 src/Umbraco.Core/Models/ContentTypeBase.cs create mode 100644 src/Umbraco.Core/Models/ContentTypeCompositionBase.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 67afd5974c..d18e6b46a9 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -1,11 +1,6 @@ using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; -using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -14,21 +9,12 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class Content : Entity, IContent + public class Content : ContentBase, IContent { private IContentType _contentType; - private int _parentId; - private string _name; - private int _sortOrder; - private int _level; - private string _path; private string _template; - private int _userId; - private bool _trashed; private bool _published; private string _language; - private int _contentTypeId; - private PropertyCollection _properties; private DateTime? _releaseDate; private DateTime? _expireDate; @@ -47,112 +33,16 @@ namespace Umbraco.Core.Models /// Id of the Parent content /// ContentType for the current Content object /// Collection of properties - public Content(int parentId, IContentType contentType, PropertyCollection properties) + public Content(int parentId, IContentType contentType, PropertyCollection properties) : base(parentId, contentType, properties) { - _parentId = parentId; - _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture)); _contentType = contentType; - _properties = properties; - _properties.EnsurePropertyTypes(PropertyTypes); - Version = Guid.NewGuid(); } - - private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); + private static readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.Template); - private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); - private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); private static readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo(x => x.Published); private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.Language); - private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); private static readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate); private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate); - private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); - void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(PropertyCollectionSelector); - } - - /// - /// Gets or sets the Id of the Parent entity - /// - /// Might not be necessary if handled as a relation? - [DataMember] - public int ParentId - { - get { return _parentId; } - set - { - _parentId = value; - OnPropertyChanged(ParentIdSelector); - } - } - - /// - /// Gets or sets the name of the current entity - /// - [DataMember] - public string Name - { - get { return _name; } - set - { - _name = value; - OnPropertyChanged(NameSelector); - } - } - - [IgnoreDataMember] - public string UrlName - { - //TODO Needs to implement proper url casing/syntax - get { return Name.ToLower().Replace(" ", "-"); } - } - - /// - /// Gets or sets the sort order of the content entity - /// - [DataMember] - public int SortOrder - { - get { return _sortOrder; } - set - { - _sortOrder = value; - OnPropertyChanged(SortOrderSelector); - } - } - - /// - /// Gets or sets the level of the content entity - /// - [DataMember] - public int Level - { - get { return _level; } - set - { - _level = value; - OnPropertyChanged(LevelSelector); - } - } - - /// - /// Gets or sets the path - /// - [DataMember] - public string Path //Setting this value should be handled by the class not the user - { - get { return _path; } - set - { - _path = value; - OnPropertyChanged(PathSelector); - } - } /// /// Path to the template used by this Content @@ -176,20 +66,6 @@ namespace Umbraco.Core.Models } } - /// - /// Id of the user who created this Content - /// - [DataMember] - public int UserId - { - get { return _userId; } - set - { - _userId = value; - OnPropertyChanged(UserIdSelector); - } - } - /// /// Gets the current status of the Content /// @@ -213,22 +89,6 @@ namespace Umbraco.Core.Models } } - /// - /// Boolean indicating whether this Content is Trashed or not. - /// If Content is Trashed it will be located in the Recyclebin. - /// - /// When content is trashed it should be unpublished - [DataMember] - public bool Trashed //Setting this value should be handled by the class not the user - { - get { return _trashed; } - internal set - { - _trashed = value; - OnPropertyChanged(TrashedSelector); - } - } - /// /// Boolean indicating whether this Content is Published or not /// @@ -258,52 +118,6 @@ namespace Umbraco.Core.Models } } - /// - /// Guid Id of the curent Version - /// - [DataMember] - public Guid Version { get; internal set; } - - /// - /// Integer Id of the default ContentType - /// - [DataMember] - public int ContentTypeId - { - get { return _contentTypeId; } - protected set - { - _contentTypeId = value; - OnPropertyChanged(DefaultContentTypeIdSelector); - } - } - - /// - /// Collection of properties, which make up all the data available for this Content object - /// - [DataMember] - public PropertyCollection Properties - { - get { return _properties; } - set - { - _properties = value; - _properties.CollectionChanged += PropertiesChanged; - } - } - - /// - /// List of PropertyGroups available on this Content object - /// - [IgnoreDataMember] - public IEnumerable PropertyGroups { get { return _contentType.CompositionPropertyGroups; } } - - /// - /// List of PropertyTypes available on this Content object - /// - [IgnoreDataMember] - public IEnumerable PropertyTypes { get { return _contentType.CompositionPropertyTypes; } } - /// /// The date this Content should be released and thus be published /// @@ -359,8 +173,9 @@ namespace Umbraco.Core.Models { ContentTypeId = contentType.Id; _contentType = contentType; - _properties.EnsurePropertyTypes(PropertyTypes); - _properties.CollectionChanged += PropertiesChanged; + ContentTypeBase = contentType; + Properties.EnsurePropertyTypes(PropertyTypes); + Properties.CollectionChanged += PropertiesChanged; } /// @@ -375,66 +190,15 @@ namespace Umbraco.Core.Models { ContentTypeId = contentType.Id; _contentType = contentType; - _properties.EnsureCleanPropertyTypes(PropertyTypes); - _properties.CollectionChanged += PropertiesChanged; + ContentTypeBase = contentType; + Properties.EnsureCleanPropertyTypes(PropertyTypes); + Properties.CollectionChanged += PropertiesChanged; return; } ChangeContentType(contentType); } - /// - /// Indicates whether the content object has a property with the supplied alias - /// - /// Alias of the PropertyType - /// True if Property with given alias exists, otherwise False - public bool HasProperty(string propertyTypeAlias) - { - return Properties.Contains(propertyTypeAlias); - } - - /// - /// Gets the value of a Property - /// - /// Alias of the PropertyType - /// Value as an - public object GetValue(string propertyTypeAlias) - { - return Properties[propertyTypeAlias].Value; - } - - /// - /// Gets the value of a Property - /// - /// Type of the value to return - /// Alias of the PropertyType - /// Value as a - public TPassType GetValue(string propertyTypeAlias) - { - return (TPassType)Properties[propertyTypeAlias].Value; - } - - /// - /// Sets the value of a Property - /// - /// Alias of the PropertyType - /// Value to set for the Property - public void SetValue(string propertyTypeAlias, object value) - { - if (Properties.Contains(propertyTypeAlias)) - { - Properties[propertyTypeAlias].Value = value; - return; - } - - var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias); - if(propertyType == null) - { - throw new Exception(string.Format("No PropertyType exists with the supplied alias: {0}", propertyTypeAlias)); - } - Properties.Add(propertyType.CreatePropertyFromValue(value)); - } - //TODO Possibly add a ToXml method, which will generate valid xml for the current Content object /// diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs new file mode 100644 index 0000000000..cb18a7693f --- /dev/null +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -0,0 +1,262 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + /// + /// Represents an abstract class for base Content properties and methods + /// + public abstract class ContentBase : Entity, IContentBase + { + protected IContentTypeComposition ContentTypeBase; + private int _parentId; + private string _name; + private int _sortOrder; + private int _level; + private string _path; + private int _userId; + private bool _trashed; + private int _contentTypeId; + private PropertyCollection _properties; + + protected ContentBase(int parentId, IContentTypeComposition contentType, PropertyCollection properties) + { + _parentId = parentId; + _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture)); + ContentTypeBase = contentType; + _properties = properties; + _properties.EnsurePropertyTypes(PropertyTypes); + Version = Guid.NewGuid(); + } + + private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); + private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); + private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); + private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); + private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); + private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); + private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); + private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); + private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); + + protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) + { + OnPropertyChanged(PropertyCollectionSelector); + } + + /// + /// Gets or sets the Id of the Parent entity + /// + /// Might not be necessary if handled as a relation? + [DataMember] + public virtual int ParentId + { + get { return _parentId; } + set + { + _parentId = value; + OnPropertyChanged(ParentIdSelector); + } + } + + /// + /// Gets or sets the name of the entity + /// + [DataMember] + public virtual string Name + { + get { return _name; } + set + { + _name = value; + OnPropertyChanged(NameSelector); + } + } + + /// + /// Gets the Url name of the entity + /// + [IgnoreDataMember] + public virtual string UrlName + { + //TODO Needs to implement proper url casing/syntax + get { return Name.ToLower().Replace(" ", "-"); } + } + + /// + /// Gets or sets the sort order of the content entity + /// + [DataMember] + public virtual int SortOrder + { + get { return _sortOrder; } + set + { + _sortOrder = value; + OnPropertyChanged(SortOrderSelector); + } + } + + /// + /// Gets or sets the level of the content entity + /// + [DataMember] + public virtual int Level + { + get { return _level; } + set + { + _level = value; + OnPropertyChanged(LevelSelector); + } + } + + /// + /// Gets or sets the path + /// + [DataMember] + public virtual string Path //Setting this value should be handled by the class not the user + { + get { return _path; } + set + { + _path = value; + OnPropertyChanged(PathSelector); + } + } + + /// + /// Id of the user who created this Content + /// + [DataMember] + public virtual int UserId + { + get { return _userId; } + set + { + _userId = value; + OnPropertyChanged(UserIdSelector); + } + } + + /// + /// Boolean indicating whether this Content is Trashed or not. + /// If Content is Trashed it will be located in the Recyclebin. + /// + /// When content is trashed it should be unpublished + [DataMember] + public virtual bool Trashed //Setting this value should be handled by the class not the user + { + get { return _trashed; } + internal set + { + _trashed = value; + OnPropertyChanged(TrashedSelector); + } + } + + /// + /// Guid Id of the curent Version + /// + [DataMember] + public Guid Version { get; internal set; } + + /// + /// Integer Id of the default ContentType + /// + [DataMember] + public virtual int ContentTypeId + { + get { return _contentTypeId; } + protected set + { + _contentTypeId = value; + OnPropertyChanged(DefaultContentTypeIdSelector); + } + } + + /// + /// Collection of properties, which make up all the data available for this Content object + /// + [DataMember] + public virtual PropertyCollection Properties + { + get { return _properties; } + set + { + _properties = value; + _properties.CollectionChanged += PropertiesChanged; + } + } + + /// + /// List of PropertyGroups available on this Content object + /// + [IgnoreDataMember] + public IEnumerable PropertyGroups { get { return ContentTypeBase.CompositionPropertyGroups; } } + + /// + /// List of PropertyTypes available on this Content object + /// + [IgnoreDataMember] + public IEnumerable PropertyTypes { get { return ContentTypeBase.CompositionPropertyTypes; } } + + /// + /// Indicates whether the content object has a property with the supplied alias + /// + /// Alias of the PropertyType + /// True if Property with given alias exists, otherwise False + public virtual bool HasProperty(string propertyTypeAlias) + { + return Properties.Contains(propertyTypeAlias); + } + + /// + /// Gets the value of a Property + /// + /// Alias of the PropertyType + /// Value as an + public virtual object GetValue(string propertyTypeAlias) + { + return Properties[propertyTypeAlias].Value; + } + + /// + /// Gets the value of a Property + /// + /// Type of the value to return + /// Alias of the PropertyType + /// Value as a + public virtual TPassType GetValue(string propertyTypeAlias) + { + return (TPassType)Properties[propertyTypeAlias].Value; + } + + /// + /// Sets the value of a Property + /// + /// Alias of the PropertyType + /// Value to set for the Property + public virtual void SetValue(string propertyTypeAlias, object value) + { + if (Properties.Contains(propertyTypeAlias)) + { + Properties[propertyTypeAlias].Value = value; + return; + } + + var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias); + if (propertyType == null) + { + throw new Exception(String.Format("No PropertyType exists with the supplied alias: {0}", propertyTypeAlias)); + } + Properties.Add(propertyType.CreatePropertyFromValue(value)); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs index e41ff06429..5a1408f5d5 100644 --- a/src/Umbraco.Core/Models/ContentType.cs +++ b/src/Umbraco.Core/Models/ContentType.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -13,182 +10,19 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class ContentType : Entity, IContentType + public class ContentType : ContentTypeCompositionBase, IContentType { - private int _parentId; - private string _name; - private int _level; - private string _path; - private string _alias; - private string _description; - private int _sortOrder; - private string _icon; - private string _thumbnail; private string _defaultTemplate; - private int _userId; - private bool _trashed; - private PropertyGroupCollection _propertyGroups; - private List _contentTypeComposition; private IEnumerable _allowedTemplates; - private IEnumerable _allowedContentTypes; - public ContentType(int parentId) + public ContentType(int parentId) : base(parentId) { - _parentId = parentId; _allowedTemplates = new List(); - _allowedContentTypes = new List(); - _propertyGroups = new PropertyGroupCollection(); - _contentTypeComposition = new List(); } - private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); - private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); - private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description); - private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); - private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.DefaultTemplate); - private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); - private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedTemplates); - private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); - private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo>(x => x.ContentTypeComposition); - private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); - void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(PropertyGroupCollectionSelector); - } - - /// - /// Gets or sets the Id of the Parent entity - /// - /// Might not be necessary if handled as a relation? - [DataMember] - public int ParentId - { - get { return _parentId; } - set - { - _parentId = value; - OnPropertyChanged(ParentIdSelector); - } - } - - /// - /// Gets or sets the name of the current entity - /// - [DataMember] - public string Name - { - get { return _name; } - set - { - _name = value; - OnPropertyChanged(NameSelector); - } - } - - /// - /// Gets or sets the level of the content entity - /// - [DataMember] - public int Level //NOTE Is this relevant for a ContentType? - { - get { return _level; } - set - { - _level = value; - OnPropertyChanged(LevelSelector); - } - } - - /// - /// Gets of sets the path - /// - [DataMember] - public string Path //NOTE Is this relevant for a ContentType? - { - get { return _path; } - set - { - _path = value; - OnPropertyChanged(PathSelector); - } - } - - /// - /// The Alias of the ContentType - /// - [DataMember] - public string Alias - { - get { return _alias; } - set - { - _alias = value; - OnPropertyChanged(AliasSelector); - } - } - - /// - /// Description for the ContentType - /// - [DataMember] - public string Description - { - get { return _description; } - set - { - _description = value; - OnPropertyChanged(DescriptionSelector); - } - } - - /// - /// Gets or sets the sort order of the content entity - /// - [DataMember] - public int SortOrder - { - get { return _sortOrder; } - set - { - _sortOrder = value; - OnPropertyChanged(SortOrderSelector); - } - } - - /// - /// Name of the icon (sprite class) used to identify the ContentType - /// - [DataMember] - public string Icon - { - get { return _icon; } - set - { - _icon = value; - OnPropertyChanged(IconSelector); - } - } - - /// - /// Name of the thumbnail used to identify the ContentType - /// - [DataMember] - public string Thumbnail - { - get { return _thumbnail; } - set - { - _thumbnail = value; - OnPropertyChanged(ThumbnailSelector); - } - } - + /// /// Gets or sets the Path to default Template /// @@ -203,35 +37,6 @@ namespace Umbraco.Core.Models } } - /// - /// Id of the user who created this Content - /// - [DataMember] - public int UserId - { - get { return _userId; } - set - { - _userId = value; - OnPropertyChanged(UserIdSelector); - } - } - - /// - /// Boolean indicating whether this ContentType is Trashed or not. - /// If ContentType is Trashed it will be located in the Recyclebin. - /// - [DataMember] - public bool Trashed //NOTE Is this relevant for a ContentType? - { - get { return _trashed; } - set - { - _trashed = value; - OnPropertyChanged(TrashedSelector); - } - } - /// /// Gets or sets a list of aliases for allowed Templates /// @@ -245,148 +50,6 @@ namespace Umbraco.Core.Models } } - /// - /// Gets or sets a list of integer Ids for allowed ContentTypes - /// - [DataMember] - public IEnumerable AllowedContentTypes - { - get { return _allowedContentTypes; } - set - { - _allowedContentTypes = value; - OnPropertyChanged(AllowedContentTypesSelector); - } - } - - /// - /// List of PropertyGroups available on this ContentType - /// - /// A PropertyGroup corresponds to a Tab in the UI - [DataMember] - public PropertyGroupCollection PropertyGroups - { - get { return _propertyGroups; } - set - { - _propertyGroups = value; - _propertyGroups.CollectionChanged += PropertyGroupsChanged; - } - } - - /// - /// List of PropertyTypes available on this ContentType. - /// This list aggregates PropertyTypes across the PropertyGroups. - /// - [IgnoreDataMember] - public IEnumerable PropertyTypes - { - get { return PropertyGroups.SelectMany(x => x.PropertyTypes); } - } - - /// - /// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType - /// - [DataMember] - public List ContentTypeComposition - { - get { return _contentTypeComposition; } - set - { - _contentTypeComposition = value; - OnPropertyChanged(ContentTypeCompositionSelector); - } - } - - /// - /// Returns a list of objects from the composition - /// - [IgnoreDataMember] - public IEnumerable CompositionPropertyGroups - { - get - { - var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups)); - return groups; - } - } - - /// - /// Returns a list of objects from the composition - /// - [IgnoreDataMember] - public IEnumerable CompositionPropertyTypes - { - get - { - var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes)); - return propertyTypes; - } - } - - /// - /// Adds a new ContentType to the list of composite ContentTypes - /// - /// to add - /// True if ContentType was added, otherwise returns False - public bool AddContentType(IContentTypeComposition contentType) - { - if(contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists))) - return false; - - if (!ContentTypeCompositionExists(contentType.Alias)) - { - ContentTypeComposition.Add(contentType); - return true; - } - return false; - } - - /// - /// Removes a ContentType with the supplied alias from the the list of composite ContentTypes - /// - /// Alias of a - /// True if ContentType was removed, otherwise returns False - public bool RemoveContentType(string alias) - { - if (!ContentTypeCompositionExists(alias)) - { - var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias); - return ContentTypeComposition.Remove(contentTypeComposition); - } - return false; - } - - /// - /// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes - /// - /// Alias of a - /// True if ContentType with alias exists, otherwise returns False - public bool ContentTypeCompositionExists(string alias) - { - if (ContentTypeComposition.Any(x => x.Alias.Equals(alias))) - return true; - - if (ContentTypeComposition.Any(x => x.ContentTypeCompositionExists(alias))) - return true; - - return false; - } - - /// - /// Gets a list of ContentType aliases from the current composition - /// - /// - /// Does not contain the alias of the Current ContentType - public IEnumerable CompositionAliases() - { - return ContentTypeComposition.Select(x => x.Alias).Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases())); - } - - //TODO Implement moving PropertyType between groups. - /*public bool MovePropertyTypeToGroup(string propertyTypeAlias, string groupName) - {}*/ - /// /// Method to call when Entity is being saved /// diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs new file mode 100644 index 0000000000..e806aa956f --- /dev/null +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -0,0 +1,254 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + /// + /// Represents an abstract class for base ContentType properties and methods + /// + public abstract class ContentTypeBase : Entity, IContentTypeBase + { + private int _parentId; + private string _name; + private int _level; + private string _path; + private string _alias; + private string _description; + private int _sortOrder; + private string _icon; + private string _thumbnail; + private int _userId; + private bool _trashed; + private PropertyGroupCollection _propertyGroups; + private IEnumerable _allowedContentTypes; + + protected ContentTypeBase(int parentId) + { + _parentId = parentId; + _allowedContentTypes = new List(); + _propertyGroups = new PropertyGroupCollection(); + } + + private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); + private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); + private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); + private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); + private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); + private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); + private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description); + private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); + private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); + private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); + private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); + private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); + private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); + + protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + OnPropertyChanged(PropertyGroupCollectionSelector); + } + + /// + /// Gets or sets the Id of the Parent entity + /// + /// Might not be necessary if handled as a relation? + [DataMember] + public int ParentId + { + get { return _parentId; } + set + { + _parentId = value; + OnPropertyChanged(ParentIdSelector); + } + } + + /// + /// Gets or sets the name of the current entity + /// + [DataMember] + public string Name + { + get { return _name; } + set + { + _name = value; + OnPropertyChanged(NameSelector); + } + } + + /// + /// Gets or sets the level of the content entity + /// + [DataMember] + public int Level //NOTE Is this relevant for a ContentType? + { + get { return _level; } + set + { + _level = value; + OnPropertyChanged(LevelSelector); + } + } + + /// + /// Gets of sets the path + /// + [DataMember] + public string Path //NOTE Is this relevant for a ContentType? + { + get { return _path; } + set + { + _path = value; + OnPropertyChanged(PathSelector); + } + } + + /// + /// The Alias of the ContentType + /// + [DataMember] + public string Alias + { + get { return _alias; } + set + { + _alias = value; + OnPropertyChanged(AliasSelector); + } + } + + /// + /// Description for the ContentType + /// + [DataMember] + public string Description + { + get { return _description; } + set + { + _description = value; + OnPropertyChanged(DescriptionSelector); + } + } + + /// + /// Gets or sets the sort order of the content entity + /// + [DataMember] + public int SortOrder + { + get { return _sortOrder; } + set + { + _sortOrder = value; + OnPropertyChanged(SortOrderSelector); + } + } + + /// + /// Name of the icon (sprite class) used to identify the ContentType + /// + [DataMember] + public string Icon + { + get { return _icon; } + set + { + _icon = value; + OnPropertyChanged(IconSelector); + } + } + + /// + /// Name of the thumbnail used to identify the ContentType + /// + [DataMember] + public string Thumbnail + { + get { return _thumbnail; } + set + { + _thumbnail = value; + OnPropertyChanged(ThumbnailSelector); + } + } + + /// + /// Id of the user who created this Content + /// + [DataMember] + public int UserId + { + get { return _userId; } + set + { + _userId = value; + OnPropertyChanged(UserIdSelector); + } + } + + /// + /// Boolean indicating whether this ContentType is Trashed or not. + /// If ContentType is Trashed it will be located in the Recyclebin. + /// + [DataMember] + public bool Trashed //NOTE Is this relevant for a ContentType? + { + get { return _trashed; } + set + { + _trashed = value; + OnPropertyChanged(TrashedSelector); + } + } + + /// + /// Gets or sets a list of integer Ids for allowed ContentTypes + /// + [DataMember] + public IEnumerable AllowedContentTypes + { + get { return _allowedContentTypes; } + set + { + _allowedContentTypes = value; + OnPropertyChanged(AllowedContentTypesSelector); + } + } + + /// + /// List of PropertyGroups available on this ContentType + /// + /// A PropertyGroup corresponds to a Tab in the UI + [DataMember] + public PropertyGroupCollection PropertyGroups + { + get { return _propertyGroups; } + set + { + _propertyGroups = value; + _propertyGroups.CollectionChanged += PropertyGroupsChanged; + } + } + + /// + /// List of PropertyTypes available on this ContentType. + /// This list aggregates PropertyTypes across the PropertyGroups. + /// + [IgnoreDataMember] + public IEnumerable PropertyTypes + { + get { return PropertyGroups.SelectMany(x => x.PropertyTypes); } + } + + //TODO Implement moving PropertyType between groups. + /*public bool MovePropertyTypeToGroup(string propertyTypeAlias, string groupName) + {}*/ + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs new file mode 100644 index 0000000000..b09669c2c6 --- /dev/null +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; + +namespace Umbraco.Core.Models +{ + public abstract class ContentTypeCompositionBase : ContentTypeBase, IContentTypeComposition + { + private List _contentTypeComposition; + + protected ContentTypeCompositionBase(int parentId) : base(parentId) + { + _contentTypeComposition = new List(); + } + + private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo>(x => x.ContentTypeComposition); + + /// + /// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType + /// + [DataMember] + public List ContentTypeComposition + { + get { return _contentTypeComposition; } + set + { + _contentTypeComposition = value; + OnPropertyChanged(ContentTypeCompositionSelector); + } + } + + /// + /// Returns a list of objects from the composition + /// + [IgnoreDataMember] + public IEnumerable CompositionPropertyGroups + { + get + { + var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups)); + return groups; + } + } + + /// + /// Returns a list of objects from the composition + /// + [IgnoreDataMember] + public IEnumerable CompositionPropertyTypes + { + get + { + var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes)); + return propertyTypes; + } + } + + /// + /// Adds a new ContentType to the list of composite ContentTypes + /// + /// to add + /// True if ContentType was added, otherwise returns False + public bool AddContentType(IContentTypeComposition contentType) + { + if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists))) + return false; + + if (!ContentTypeCompositionExists(contentType.Alias)) + { + ContentTypeComposition.Add(contentType); + return true; + } + return false; + } + + /// + /// Removes a ContentType with the supplied alias from the the list of composite ContentTypes + /// + /// Alias of a + /// True if ContentType was removed, otherwise returns False + public bool RemoveContentType(string alias) + { + if (!ContentTypeCompositionExists(alias)) + { + var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias); + return ContentTypeComposition.Remove(contentTypeComposition); + } + return false; + } + + /// + /// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes + /// + /// Alias of a + /// True if ContentType with alias exists, otherwise returns False + public bool ContentTypeCompositionExists(string alias) + { + if (ContentTypeComposition.Any(x => x.Alias.Equals(alias))) + return true; + + if (ContentTypeComposition.Any(x => x.ContentTypeCompositionExists(alias))) + return true; + + return false; + } + + /// + /// Gets a list of ContentType aliases from the current composition + /// + /// + /// Does not contain the alias of the Current ContentType + public IEnumerable CompositionAliases() + { + return ContentTypeComposition.Select(x => x.Alias).Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases())); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index ddec41f3b6..d6aafe009f 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -33,6 +33,11 @@ namespace Umbraco.Core.Models /// DateTime? ExpireDate { get; set; } + /// + /// Gets the ContentType used by this content object + /// + IContentType ContentType { get; } + /// /// Changes the for the current content object /// diff --git a/src/Umbraco.Core/Models/IMedia.cs b/src/Umbraco.Core/Models/IMedia.cs index 1f1e2c78c7..dd58421cb6 100644 --- a/src/Umbraco.Core/Models/IMedia.cs +++ b/src/Umbraco.Core/Models/IMedia.cs @@ -2,6 +2,11 @@ { public interface IMedia : IContentBase { + /// + /// Gets the ContentType used by this Media object + /// + IMediaType ContentType { get; } + /// /// Changes the for the current content object /// diff --git a/src/Umbraco.Core/Models/IMediaType.cs b/src/Umbraco.Core/Models/IMediaType.cs index 8d36168015..e72471fc88 100644 --- a/src/Umbraco.Core/Models/IMediaType.cs +++ b/src/Umbraco.Core/Models/IMediaType.cs @@ -3,7 +3,7 @@ /// /// Defines a ContentType, which Media is based on /// - public interface IMediaType : IContentTypeBase + public interface IMediaType : IContentTypeComposition { } diff --git a/src/Umbraco.Core/Models/Media.cs b/src/Umbraco.Core/Models/Media.cs index c2ff051eee..fbad998829 100644 --- a/src/Umbraco.Core/Models/Media.cs +++ b/src/Umbraco.Core/Models/Media.cs @@ -1,12 +1,5 @@ using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; -using System.Linq; -using System.Reflection; using System.Runtime.Serialization; -using Umbraco.Core.IO; -using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -15,17 +8,8 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class Media : Entity, IMedia + public class Media : ContentBase, IMedia { - private int _parentId; - private string _name; - private int _sortOrder; - private int _level; - private string _path; - private int _userId; - private bool _trashed; - private int _contentTypeId; - private PropertyCollection _properties; private IMediaType _contentType; /// @@ -44,193 +28,9 @@ namespace Umbraco.Core.Models /// /// MediaType for the current Media object /// Collection of properties - public Media(int parentId, IMediaType contentType, PropertyCollection properties) + public Media(int parentId, IMediaType contentType, PropertyCollection properties) : base(parentId, contentType, properties) { - _parentId = parentId; - _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture)); _contentType = contentType; - _properties = properties; - _properties.EnsurePropertyTypes(PropertyTypes); - Version = Guid.NewGuid(); - } - - private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); - private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); - private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); - private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); - private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); - void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(PropertyCollectionSelector); - } - - /// - /// Gets or Sets the Id of the Parent for the Media - /// - [DataMember] - public int ParentId - { - get { return _parentId; } - set - { - _parentId = value; - OnPropertyChanged(ParentIdSelector); - } - } - - /// - /// Gets or Sets the Name of the Media - /// - [DataMember] - public string Name - { - get { return _name; } - set - { - _name = value; - OnPropertyChanged(NameSelector); - } - } - - /// - /// Gets the Url name of the Media item - /// - [IgnoreDataMember] - public string UrlName - { - //TODO: Should return the relative path to the media - if it should be implemented at all - get - { - string url = string.Concat(SystemDirectories.Media.Replace("~", ""), "/", _name); - return url; - } - } - - /// - /// Gets or Sets the Sort Order of the Media - /// - [DataMember] - public int SortOrder - { - get { return _sortOrder; } - set - { - _sortOrder = value; - OnPropertyChanged(SortOrderSelector); - } - } - - /// - /// Gets or Sets the Level of the Media - /// - [DataMember] - public int Level - { - get { return _level; } - set - { - _level = value; - OnPropertyChanged(LevelSelector); - } - } - - /// - /// Gets or Sets the Path of the Media - /// - [DataMember] - public string Path - { - get { return _path; } - set - { - _path = value; - OnPropertyChanged(PathSelector); - } - } - - /// - /// Id of the user who created the Media - /// - [DataMember] - public int UserId - { - get { return _userId; } - set - { - _userId = value; - OnPropertyChanged(UserIdSelector); - } - } - - /// - /// Boolean indicating whether this Media is Trashed or not. - /// If Media is Trashed it will be located in the Recyclebin. - /// - [DataMember] - public bool Trashed - { - get { return _trashed; } - internal set - { - _trashed = value; - OnPropertyChanged(TrashedSelector); - } - } - - /// - /// Integer Id of the default MediaType - /// - [DataMember] - public int ContentTypeId - { - get { return _contentTypeId; } - protected set - { - _contentTypeId = value; - OnPropertyChanged(DefaultContentTypeIdSelector); - } - } - - /// - /// Guid Id of the curent Version - /// - [DataMember] - public Guid Version { get; internal set; } - - /// - /// List of properties, which make up all the data available for this Media object - /// - [DataMember] - public PropertyCollection Properties - { - get { return _properties; } - set - { - _properties = value; - _properties.CollectionChanged += PropertiesChanged; - } - } - - /// - /// List of PropertyGroups available on this Media object - /// - [IgnoreDataMember] - public IEnumerable PropertyGroups - { - get { return _contentType.PropertyGroups; } - } - - /// - /// List of PropertyTypes available on this Media object - /// - [IgnoreDataMember] - public IEnumerable PropertyTypes - { - get { return _contentType.PropertyTypes; } } /// @@ -242,58 +42,6 @@ namespace Umbraco.Core.Models get { return _contentType; } } - /// - /// Indicates whether the Media object has a property with the supplied alias - /// - /// Alias of the PropertyType - /// True if Property with given alias exists, otherwise False - public bool HasProperty(string propertyTypeAlias) - { - return Properties.Contains(propertyTypeAlias); - } - - /// - /// Gets the value of a Property - /// - /// Alias of the PropertyType - /// Value as an - public object GetValue(string propertyTypeAlias) - { - return Properties[propertyTypeAlias].Value; - } - - /// - /// Gets the value of a Property - /// - /// Type of the value to return - /// Alias of the PropertyType - /// Value as a - public TPassType GetValue(string propertyTypeAlias) - { - return (TPassType)Properties[propertyTypeAlias].Value; - } - - /// - /// Sets the value of a Property - /// - /// Alias of the PropertyType - /// Value to set for the Property - public void SetValue(string propertyTypeAlias, object value) - { - if (Properties.Contains(propertyTypeAlias)) - { - Properties[propertyTypeAlias].Value = value; - return; - } - - var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias); - if (propertyType == null) - { - throw new Exception(string.Format("No PropertyType exists with the supplied alias: {0}", propertyTypeAlias)); - } - Properties.Add(propertyType.CreatePropertyFromValue(value)); - } - /// /// Changes the for the current Media object /// @@ -303,8 +51,9 @@ namespace Umbraco.Core.Models { ContentTypeId = contentType.Id; _contentType = contentType; - _properties.EnsurePropertyTypes(PropertyTypes); - _properties.CollectionChanged += PropertiesChanged; + ContentTypeBase = contentType; + Properties.EnsurePropertyTypes(PropertyTypes); + Properties.CollectionChanged += PropertiesChanged; } /// @@ -319,8 +68,9 @@ namespace Umbraco.Core.Models { ContentTypeId = contentType.Id; _contentType = contentType; - _properties.EnsureCleanPropertyTypes(PropertyTypes); - _properties.CollectionChanged += PropertiesChanged; + ContentTypeBase = contentType; + Properties.EnsureCleanPropertyTypes(PropertyTypes); + Properties.CollectionChanged += PropertiesChanged; return; } diff --git a/src/Umbraco.Core/Models/MediaType.cs b/src/Umbraco.Core/Models/MediaType.cs index 354982b85d..cacfadf930 100644 --- a/src/Umbraco.Core/Models/MediaType.cs +++ b/src/Umbraco.Core/Models/MediaType.cs @@ -1,10 +1,5 @@ using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Reflection; using System.Runtime.Serialization; -using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -13,240 +8,10 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class MediaType : Entity, IMediaType + public class MediaType : ContentTypeCompositionBase, IMediaType { - private int _parentId; - private string _name; - private int _level; - private string _path; - private string _alias; - private string _description; - private int _sortOrder; - private string _icon; - private string _thumbnail; - private int _userId; - private bool _trashed; - private PropertyGroupCollection _propertyGroups; - private IEnumerable _allowedContentTypes; - - public MediaType(int parentId) + public MediaType(int parentId) : base(parentId) { - _parentId = parentId; - _allowedContentTypes = new List(); - _propertyGroups = new PropertyGroupCollection(); - } - - private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); - private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); - private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description); - private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); - private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); - private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId); - private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); - private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); - private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); - void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(PropertyGroupCollectionSelector); - } - - /// - /// Gets or sets the Id of the Parent entity - /// - /// Might not be necessary if handled as a relation? - [DataMember] - public int ParentId - { - get { return _parentId; } - set - { - _parentId = value; - OnPropertyChanged(ParentIdSelector); - } - } - - /// - /// Gets or sets the name of the current entity - /// - [DataMember] - public string Name - { - get { return _name; } - set - { - _name = value; - OnPropertyChanged(NameSelector); - } - } - - /// - /// Gets or sets the level of the content entity - /// - [DataMember] - public int Level //NOTE Is this relevant for a ContentType? - { - get { return _level; } - set - { - _level = value; - OnPropertyChanged(LevelSelector); - } - } - - /// - /// Gets of sets the path - /// - [DataMember] - public string Path //NOTE Is this relevant for a ContentType? - { - get { return _path; } - set - { - _path = value; - OnPropertyChanged(PathSelector); - } - } - - /// - /// The Alias of the ContentType - /// - [DataMember] - public string Alias - { - get { return _alias; } - set - { - _alias = value; - OnPropertyChanged(AliasSelector); - } - } - - /// - /// Description for the ContentType - /// - [DataMember] - public string Description - { - get { return _description; } - set - { - _description = value; - OnPropertyChanged(DescriptionSelector); - } - } - - /// - /// Gets or sets the sort order of the content entity - /// - [DataMember] - public int SortOrder - { - get { return _sortOrder; } - set - { - _sortOrder = value; - OnPropertyChanged(SortOrderSelector); - } - } - - /// - /// Name of the icon (sprite class) used to identify the ContentType - /// - [DataMember] - public string Icon - { - get { return _icon; } - set - { - _icon = value; - OnPropertyChanged(IconSelector); - } - } - - /// - /// Name of the thumbnail used to identify the ContentType - /// - [DataMember] - public string Thumbnail - { - get { return _thumbnail; } - set - { - _thumbnail = value; - OnPropertyChanged(ThumbnailSelector); - } - } - - /// - /// Id of the user who created this Content - /// - [DataMember] - public int UserId - { - get { return _userId; } - set - { - _userId = value; - OnPropertyChanged(UserIdSelector); - } - } - - /// - /// Boolean indicating whether this ContentType is Trashed or not. - /// If ContentType is Trashed it will be located in the Recyclebin. - /// - [DataMember] - public bool Trashed //NOTE Is this relevant for a ContentType? - { - get { return _trashed; } - set - { - _trashed = value; - OnPropertyChanged(TrashedSelector); - } - } - - /// - /// Gets or sets a list of integer Ids for allowed ContentTypes - /// - [DataMember] - public IEnumerable AllowedContentTypes - { - get { return _allowedContentTypes; } - set - { - _allowedContentTypes = value; - OnPropertyChanged(AllowedContentTypesSelector); - } - } - - /// - /// List of PropertyGroups available on this ContentType - /// - /// A PropertyGroup corresponds to a Tab in the UI - [DataMember] - public PropertyGroupCollection PropertyGroups - { - get { return _propertyGroups; } - set - { - _propertyGroups = value; - _propertyGroups.CollectionChanged += PropertyGroupsChanged; - } - } - - /// - /// List of PropertyTypes available on this ContentType. - /// This list aggregates PropertyTypes across the PropertyGroups. - /// - [IgnoreDataMember] - public IEnumerable PropertyTypes - { - get { return PropertyGroups.SelectMany(x => x.PropertyTypes); } } /// diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs new file mode 100644 index 0000000000..586b520d65 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.Caching; +using Umbraco.Core.Persistence.Factories; +using Umbraco.Core.Persistence.Relators; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Persistence.Repositories +{ + /// + /// Represent an abstract Repository for ContentType based repositories + /// + /// Exposes shared functionality + /// + /// + internal abstract class ContentTypeBaseRepository : PetaPocoRepositoryBase + where TEntity : IContentTypeComposition + { + protected ContentTypeBaseRepository(IUnitOfWork work) : base(work) + { + } + + protected ContentTypeBaseRepository(IUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + { + } + + protected void PersistNewBaseContentType(ContentTypeDto dto, IContentTypeComposition entity) + { + //Logic for setting Path, Level and SortOrder + var parent = Database.First("WHERE id = @ParentId", new { ParentId = entity.ParentId }); + int level = parent.Level + 1; + int sortOrder = + Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", + new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId }); + + //Create the (base) node data - umbracoNode + var nodeDto = dto.NodeDto; + nodeDto.Path = parent.Path; + nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); + nodeDto.SortOrder = sortOrder; + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + + //Update with new correct path + nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); + Database.Update(nodeDto); + + //Update entity with correct values + entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set + entity.Path = nodeDto.Path; + entity.SortOrder = sortOrder; + entity.Level = level; + + //Insert new ContentType entry + Database.Insert(dto); + + //Insert ContentType composition in new table + foreach (var composition in entity.ContentTypeComposition) + { + if (composition.Id == entity.Id) continue;//Just to ensure that we aren't creating a reference to ourself. + + Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id }); + } + + //Insert collection of allowed content types + foreach (var allowedContentType in entity.AllowedContentTypes) + { + Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder }); + } + + var propertyFactory = new PropertyGroupFactory(nodeDto.NodeId); + + //Insert Tabs + foreach (var propertyGroup in entity.PropertyGroups) + { + var tabDto = propertyFactory.BuildGroupDto(propertyGroup); + var primaryKey = Convert.ToInt32(Database.Insert(tabDto)); + propertyGroup.Id = primaryKey;//Set Id on PropertyGroup + } + + //Insert PropertyTypes + foreach (var propertyGroup in entity.PropertyGroups) + { + foreach (var propertyType in propertyGroup.PropertyTypes) + { + var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType); + var primaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto)); + propertyType.Id = primaryKey;//Set Id on PropertyType + } + } + } + + protected void PersistUpdatedBaseContentType(ContentTypeDto dto, IContentTypeComposition entity) + { + var propertyFactory = new PropertyGroupFactory(entity.Id); + + var nodeDto = dto.NodeDto; + var o = Database.Update(nodeDto); + + //Look up ContentType entry to get PrimaryKey for updating the DTO + var dtoPk = Database.First("WHERE nodeId = @Id", new { Id = entity.Id }); + dto.PrimaryKey = dtoPk.PrimaryKey; + Database.Update(dto); + + //Delete the ContentType composition entries before adding the updated collection + Database.Delete("WHERE childContentTypeId = @Id", new { Id = entity.Id }); + //Update ContentType composition in new table + foreach (var composition in entity.ContentTypeComposition) + { + Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id }); + } + + //Delete the allowed content type entries before adding the updated collection + Database.Delete("WHERE Id = @Id", new { Id = entity.Id }); + //Insert collection of allowed content types + foreach (var allowedContentType in entity.AllowedContentTypes) + { + Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder }); + } + + //Check Dirty properties for Tabs/Groups and PropertyTypes - insert and delete accordingly + if (((ICanBeDirty)entity).IsPropertyDirty("PropertyGroups") || entity.PropertyGroups.Any(x => x.IsDirty())) + { + //Delete PropertyTypes by excepting entries from db with entries from collections + var dbPropertyTypes = Database.Fetch("WHERE contentTypeId = @Id", new { Id = entity.Id }).Select(x => x.Alias); + var entityPropertyTypes = entity.PropertyTypes.Select(x => x.Alias); + var aliases = dbPropertyTypes.Except(entityPropertyTypes); + foreach (var alias in aliases) + { + Database.Delete("WHERE contentTypeId = @Id AND Alias = @Alias", new { Id = entity.Id, Alias = alias }); + } + //Delete Tabs/Groups by excepting entries from db with entries from collections + var dbPropertyGroups = Database.Fetch("WHERE contenttypeNodeId = @Id", new { Id = entity.Id }).Select(x => x.Text); + var entityPropertyGroups = entity.PropertyGroups.Select(x => x.Name); + var tabs = dbPropertyGroups.Except(entityPropertyGroups); + foreach (var tabName in tabs) + { + Database.Delete("WHERE contenttypeNodeId = @Id AND text = @Name", new { Id = entity.Id, Name = tabName }); + } + + //Run through all groups and types to insert or update entries + foreach (var propertyGroup in entity.PropertyGroups) + { + var tabDto = propertyFactory.BuildGroupDto(propertyGroup); + int groupPrimaryKey = propertyGroup.HasIdentity + ? Database.Update(tabDto) + : Convert.ToInt32(Database.Insert(tabDto)); + if (!propertyGroup.HasIdentity) + propertyGroup.Id = groupPrimaryKey;//Set Id on new PropertyGroup + + //This should indicate that neither group nor property types has been touched, but this implies a deeper 'Dirty'-lookup + //if(!propertyGroup.IsDirty()) continue; + + foreach (var propertyType in propertyGroup.PropertyTypes) + { + var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType); + int typePrimaryKey = propertyType.HasIdentity + ? Database.Update(propertyTypeDto) + : Convert.ToInt32(Database.Insert(propertyTypeDto)); + if (!propertyType.HasIdentity) + propertyType.Id = typePrimaryKey;//Set Id on new PropertyType + } + } + } + } + + protected IEnumerable GetAllowedContentTypeIds(int id) + { + var allowedContentTypesSql = new Sql(); + allowedContentTypesSql.Select("*"); + allowedContentTypesSql.From("cmsContentTypeAllowedContentType"); + allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id }); + + var allowedContentTypeDtos = Database.Fetch(allowedContentTypesSql); + return allowedContentTypeDtos.Select(x => new ContentTypeSort { Id = x.AllowedId, SortOrder = x.SortOrder }).ToList(); + } + + protected PropertyGroupCollection GetPropertyGroupCollection(int id) + { + var propertySql = new Sql(); + propertySql.Select("*"); + propertySql.From("cmsTab"); + propertySql.RightJoin("cmsPropertyType ON [cmsTab].[id] = [cmsPropertyType].[tabId]"); + propertySql.InnerJoin("cmsDataType ON [cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]"); + propertySql.Where("[cmsPropertyType].[contentTypeId] = @Id", new { Id = id }); + + var dtos = Database.Fetch(new TabPropertyTypeRelator().Map, propertySql); + + var propertyFactory = new PropertyGroupFactory(id); + var propertyGroups = propertyFactory.BuildEntity(dtos); + return new PropertyGroupCollection(propertyGroups); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index 6ea8e1ce8c..51add6ed09 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -1,14 +1,11 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core.Models; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -16,7 +13,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class ContentTypeRepository : PetaPocoRepositoryBase, IContentTypeRepository + internal class ContentTypeRepository : ContentTypeBaseRepository, IContentTypeRepository { public ContentTypeRepository(IUnitOfWork work) : base(work) { @@ -147,72 +144,11 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new ContentTypeFactory(NodeObjectTypeId); var dto = factory.BuildDto(entity); - //Logic for setting Path, Level and SortOrder - var parent = Database.First("WHERE id = @ParentId", new { ParentId = entity.ParentId }); - int level = parent.Level + 1; - int sortOrder = - Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId }); - - //Create the (base) node data - umbracoNode - var nodeDto = dto.ContentTypeDto.NodeDto; - nodeDto.Path = parent.Path; - nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); - nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); - - //Update with new correct path - nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); - Database.Update(nodeDto); - - //Update entity with correct values - entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set - entity.Path = nodeDto.Path; - entity.SortOrder = sortOrder; - entity.Level = level; - - //Insert new ContentType entry - var contentTypeDto = dto.ContentTypeDto; - Database.Insert(contentTypeDto); + PersistNewBaseContentType(dto.ContentTypeDto, entity); //TODO Insert new DocumentType entries - NOTE only seems relevant as long as Templates resides in the DB? //TODO Insert allowed Templates - - //Insert ContentType composition in new table - foreach (var composition in entity.ContentTypeComposition) - { - if(composition.Id == entity.Id) continue;//Just to ensure that we aren't creating a reference to ourself. - - Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id}); - } - - //Insert collection of allowed content types - foreach (var allowedContentType in entity.AllowedContentTypes) - { - Database.Insert(new ContentTypeAllowedContentTypeDto {Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder}); - } - - var propertyFactory = new PropertyGroupFactory(nodeDto.NodeId); - - //Insert Tabs - foreach (var propertyGroup in entity.PropertyGroups) - { - var tabDto = propertyFactory.BuildGroupDto(propertyGroup); - var primaryKey = Convert.ToInt32(Database.Insert(tabDto)); - propertyGroup.Id = primaryKey;//Set Id on PropertyGroup - } - - //Insert PropertyTypes - foreach (var propertyGroup in entity.PropertyGroups) - { - foreach (var propertyType in propertyGroup.PropertyTypes) - { - var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType); - var primaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto)); - propertyType.Id = primaryKey;//Set Id on PropertyType - } - } - + ((ContentType)entity).ResetDirtyProperties(); } @@ -221,114 +157,19 @@ namespace Umbraco.Core.Persistence.Repositories //Updates Modified date ((ContentType)entity).UpdatingEntity(); - var propertyFactory = new PropertyGroupFactory(entity.Id); var factory = new ContentTypeFactory(NodeObjectTypeId); var dto = factory.BuildDto(entity); - var nodeDto = dto.ContentTypeDto.NodeDto; - var o = Database.Update(nodeDto); - //Look up ContentType entry to get PrimaryKey for updating the DTO - var dtoPk = Database.First("WHERE nodeId = @Id", new { Id = entity.Id }); - var contentTypeDto = dto.ContentTypeDto; - contentTypeDto.PrimaryKey = dtoPk.PrimaryKey; - Database.Update(contentTypeDto); + PersistUpdatedBaseContentType(dto.ContentTypeDto, entity); //Look up DocumentType entries for updating - this could possibly be a "remove all, insert all"-approach //TODO Update new DocumentType entries - NOTE only seems relevant as long as Templates resides in the DB? //TODO Update allowed Templates - //Delete the ContentType composition entries before adding the updated collection - Database.Delete("WHERE childContentTypeId = @Id", new { Id = entity.Id }); - //Update ContentType composition in new table - foreach (var composition in entity.ContentTypeComposition) - { - Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id }); - } - - //Delete the allowed content type entries before adding the updated collection - Database.Delete("WHERE Id = @Id", new {Id = entity.Id}); - //Insert collection of allowed content types - foreach (var allowedContentType in entity.AllowedContentTypes) - { - Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder}); - } - - //Check Dirty properties for Tabs/Groups and PropertyTypes - insert and delete accordingly - if (((ICanBeDirty)entity).IsPropertyDirty("PropertyGroups") || entity.PropertyGroups.Any(x => x.IsDirty())) - { - //Delete PropertyTypes by excepting entries from db with entries from collections - var dbPropertyTypes = Database.Fetch("WHERE contentTypeId = @Id", new { Id = entity.Id }).Select(x => x.Alias); - var entityPropertyTypes = entity.PropertyTypes.Select(x => x.Alias); - var aliases = dbPropertyTypes.Except(entityPropertyTypes); - foreach (var alias in aliases) - { - Database.Delete("WHERE contentTypeId = @Id AND Alias = @Alias", new { Id = entity.Id, Alias = alias }); - } - //Delete Tabs/Groups by excepting entries from db with entries from collections - var dbPropertyGroups = Database.Fetch("WHERE contenttypeNodeId = @Id", new { Id = entity.Id }).Select(x => x.Text); - var entityPropertyGroups = entity.PropertyGroups.Select(x => x.Name); - var tabs = dbPropertyGroups.Except(entityPropertyGroups); - foreach (var tabName in tabs) - { - Database.Delete("WHERE contenttypeNodeId = @Id AND text = @Name", new { Id = entity.Id, Name = tabName }); - } - - //Run through all groups and types to insert or update entries - foreach (var propertyGroup in entity.PropertyGroups) - { - var tabDto = propertyFactory.BuildGroupDto(propertyGroup); - int groupPrimaryKey = propertyGroup.HasIdentity - ? Database.Update(tabDto) - : Convert.ToInt32(Database.Insert(tabDto)); - if (!propertyGroup.HasIdentity) - propertyGroup.Id = groupPrimaryKey;//Set Id on new PropertyGroup - - //This should indicate that neither group nor property types has been touched, but this implies a deeper 'Dirty'-lookup - //if(!propertyGroup.IsDirty()) continue; - - foreach (var propertyType in propertyGroup.PropertyTypes) - { - var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType); - int typePrimaryKey = propertyType.HasIdentity - ? Database.Update(propertyTypeDto) - : Convert.ToInt32(Database.Insert(propertyTypeDto)); - if (!propertyType.HasIdentity) - propertyType.Id = typePrimaryKey;//Set Id on new PropertyType - } - } - } - ((ContentType)entity).ResetDirtyProperties(); } #endregion - - private IEnumerable GetAllowedContentTypeIds(int id) - { - var allowedContentTypesSql = new Sql(); - allowedContentTypesSql.Select("*"); - allowedContentTypesSql.From("cmsContentTypeAllowedContentType"); - allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id }); - - var allowedContentTypeDtos = Database.Fetch(allowedContentTypesSql); - return allowedContentTypeDtos.Select(x => new ContentTypeSort { Id = x.AllowedId, SortOrder = x.SortOrder }).ToList(); - } - - private PropertyGroupCollection GetPropertyGroupCollection(int id) - { - var propertySql = new Sql(); - propertySql.Select("*"); - propertySql.From("cmsTab"); - propertySql.RightJoin("cmsPropertyType ON [cmsTab].[id] = [cmsPropertyType].[tabId]"); - propertySql.InnerJoin("cmsDataType ON [cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]"); - propertySql.Where("[cmsPropertyType].[contentTypeId] = @Id", new { Id = id }); - - var dtos = Database.Fetch(new TabPropertyTypeRelator().Map, propertySql); - - var propertyFactory = new PropertyGroupFactory(id); - var propertyGroups = propertyFactory.BuildEntity(dtos); - return new PropertyGroupCollection(propertyGroups); - } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index d5dbf4d73c..72dc6b2b8c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -1,14 +1,11 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core.Models; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -16,7 +13,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class MediaTypeRepository : PetaPocoRepositoryBase, IMediaTypeRepository + internal class MediaTypeRepository : ContentTypeBaseRepository, IMediaTypeRepository { public MediaTypeRepository(IUnitOfWork work) : base(work) { @@ -44,6 +41,13 @@ namespace Umbraco.Core.Persistence.Repositories contentType.AllowedContentTypes = GetAllowedContentTypeIds(id); contentType.PropertyGroups = GetPropertyGroupCollection(id); + var list = Database.Fetch("WHERE childContentTypeId = @Id"); + foreach (var contentTypeDto in list) + { + bool result = contentType.AddContentType(Get(contentTypeDto.ParentId)); + //Do something if adding fails? (Should hopefully not be possible unless someone create a circular reference) + } + ((MediaType)contentType).ResetDirtyProperties(); return contentType; } @@ -134,38 +138,9 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new MediaTypeFactory(NodeObjectTypeId); var dto = factory.BuildDto(entity); - //Logic for setting Path, Level and SortOrder - var parent = Database.First("WHERE id = @ParentId", new { ParentId = entity.ParentId }); - int level = parent.Level + 1; - int sortOrder = - Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId }); + PersistNewBaseContentType(dto, entity); - //Create the (base) node data - umbracoNode - var nodeDto = dto.NodeDto; - nodeDto.Path = parent.Path; - nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); - nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); - - //Update with new correct path - nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); - Database.Update(nodeDto); - - //Update entity with correct values - entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set - entity.Path = nodeDto.Path; - entity.SortOrder = sortOrder; - entity.Level = level; - - //Insert new ContentType entry - Database.Insert(dto); - - //Insert collection of allowed content types - foreach (var allowedContentType in entity.AllowedContentTypes) - { - Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder}); - } + ((MediaType)entity).ResetDirtyProperties(); } protected override void PersistUpdatedItem(IMediaType entity) @@ -173,101 +148,14 @@ namespace Umbraco.Core.Persistence.Repositories //Updates Modified date ((MediaType)entity).UpdatingEntity(); - var propertyFactory = new PropertyGroupFactory(entity.Id); var factory = new MediaTypeFactory(NodeObjectTypeId); var dto = factory.BuildDto(entity); - var nodeDto = dto.NodeDto; - var o = Database.Update(nodeDto); - - //Look up ContentType entry to get PrimaryKey for updating the DTO - var dtoPk = Database.First("WHERE nodeId = @Id", new { Id = entity.Id }); - dto.PrimaryKey = dtoPk.PrimaryKey; - Database.Update(dto); - - //Delete the allowed content type entries before adding the updated collection - Database.Delete("WHERE Id = @Id", new { Id = entity.Id }); - - //Insert collection of allowed content types - foreach (var allowedContentType in entity.AllowedContentTypes) - { - Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id, SortOrder = allowedContentType.SortOrder }); - } - - //Check Dirty properties for Tabs/Groups and PropertyTypes - insert and delete accordingly - if (((ICanBeDirty)entity).IsPropertyDirty("PropertyGroups") || entity.PropertyGroups.Any(x => x.IsDirty())) - { - //Delete PropertyTypes by excepting entries from db with entries from collections - var dbPropertyTypes = Database.Fetch("WHERE contentTypeId = @Id", new { Id = entity.Id }).Select(x => x.Alias); - var entityPropertyTypes = entity.PropertyTypes.Select(x => x.Alias); - var aliases = dbPropertyTypes.Except(entityPropertyTypes); - foreach (var alias in aliases) - { - Database.Delete("WHERE contentTypeId = @Id AND Alias = @Alias", new { Id = entity.Id, Alias = alias }); - } - //Delete Tabs/Groups by excepting entries from db with entries from collections - var dbPropertyGroups = Database.Fetch("WHERE contenttypeNodeId = @Id", new { Id = entity.Id }).Select(x => x.Text); - var entityPropertyGroups = entity.PropertyGroups.Select(x => x.Name); - var tabs = dbPropertyGroups.Except(entityPropertyGroups); - foreach (var tabName in tabs) - { - Database.Delete("WHERE contenttypeNodeId = @Id AND text = @Name", new { Id = entity.Id, Name = tabName }); - } - - //Run through all groups and types to insert or update entries - foreach (var propertyGroup in entity.PropertyGroups) - { - var tabDto = propertyFactory.BuildGroupDto(propertyGroup); - int groupPrimaryKey = propertyGroup.HasIdentity - ? Database.Update(tabDto) - : Convert.ToInt32(Database.Insert(tabDto)); - if (!propertyGroup.HasIdentity) - propertyGroup.Id = groupPrimaryKey;//Set Id on new PropertyGroup - - //This should indicate that neither group nor property types has been touched, but this implies a deeper 'Dirty'-lookup - //if(!propertyGroup.IsDirty()) continue; - - foreach (var propertyType in propertyGroup.PropertyTypes) - { - var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType); - int typePrimaryKey = propertyType.HasIdentity - ? Database.Update(propertyTypeDto) - : Convert.ToInt32(Database.Insert(propertyTypeDto)); - if (!propertyType.HasIdentity) - propertyType.Id = typePrimaryKey;//Set Id on new PropertyType - } - } - } + + PersistUpdatedBaseContentType(dto, entity); ((MediaType)entity).ResetDirtyProperties(); } #endregion - - private IEnumerable GetAllowedContentTypeIds(int id) - { - var allowedContentTypesSql = new Sql(); - allowedContentTypesSql.Select("*"); - allowedContentTypesSql.From("cmsContentTypeAllowedContentType"); - allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id }); - - var allowedContentTypeDtos = Database.Fetch(allowedContentTypesSql); - return allowedContentTypeDtos.Select(x => new ContentTypeSort { Id = x.AllowedId, SortOrder = x.SortOrder}).ToList(); - } - - private PropertyGroupCollection GetPropertyGroupCollection(int id) - { - var propertySql = new Sql(); - propertySql.Select("*"); - propertySql.From("cmsTab"); - propertySql.RightJoin("cmsPropertyType ON [cmsTab].[id] = [cmsPropertyType].[tabId]"); - propertySql.InnerJoin("cmsDataType ON [cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]"); - propertySql.Where("[cmsPropertyType].[contentTypeId] = @Id", new { Id = id }); - - var tabDtos = Database.Fetch(new TabPropertyTypeRelator().Map, propertySql); - - var propertyFactory = new PropertyGroupFactory(id); - var propertyGroups = propertyFactory.BuildEntity(tabDtos); - return new PropertyGroupCollection(propertyGroups); - } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 43429738c0..1bcb9ffa2a 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -74,8 +74,11 @@ + + + @@ -124,6 +127,7 @@ +