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
This commit is contained in:
Morten@Thinkpad-X220
2012-10-10 08:42:54 -02:00
parent 90108e344f
commit 74ecbac7d7
14 changed files with 885 additions and 1368 deletions

View File

@@ -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
/// </summary>
[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
/// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param>
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<Content, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.Path);
private static readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.Template);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Trashed);
private static readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Published);
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.Language);
private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.ContentTypeId);
private static readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ReleaseDate);
private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<Content, PropertyCollection>(x => x.Properties);
void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyCollectionSelector);
}
/// <summary>
/// Gets or sets the Id of the Parent entity
/// </summary>
/// <remarks>Might not be necessary if handled as a relation?</remarks>
[DataMember]
public int ParentId
{
get { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the current entity
/// </summary>
[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(" ", "-"); }
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public int Level
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets or sets the path
/// </summary>
[DataMember]
public string Path //Setting this value should be handled by the class not the user
{
get { return _path; }
set
{
_path = value;
OnPropertyChanged(PathSelector);
}
}
/// <summary>
/// Path to the template used by this Content
@@ -176,20 +66,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Id of the user who created this Content
/// </summary>
[DataMember]
public int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Gets the current status of the Content
/// </summary>
@@ -213,22 +89,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Boolean indicating whether this Content is Trashed or not.
/// If Content is Trashed it will be located in the Recyclebin.
/// </summary>
/// <remarks>When content is trashed it should be unpublished</remarks>
[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);
}
}
/// <summary>
/// Boolean indicating whether this Content is Published or not
/// </summary>
@@ -258,52 +118,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Guid Id of the curent Version
/// </summary>
[DataMember]
public Guid Version { get; internal set; }
/// <summary>
/// Integer Id of the default ContentType
/// </summary>
[DataMember]
public int ContentTypeId
{
get { return _contentTypeId; }
protected set
{
_contentTypeId = value;
OnPropertyChanged(DefaultContentTypeIdSelector);
}
}
/// <summary>
/// Collection of properties, which make up all the data available for this Content object
/// </summary>
[DataMember]
public PropertyCollection Properties
{
get { return _properties; }
set
{
_properties = value;
_properties.CollectionChanged += PropertiesChanged;
}
}
/// <summary>
/// List of PropertyGroups available on this Content object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> PropertyGroups { get { return _contentType.CompositionPropertyGroups; } }
/// <summary>
/// List of PropertyTypes available on this Content object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes { get { return _contentType.CompositionPropertyTypes; } }
/// <summary>
/// The date this Content should be released and thus be published
/// </summary>
@@ -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;
}
/// <summary>
@@ -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);
}
/// <summary>
/// Indicates whether the content object has a property with the supplied alias
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns>True if Property with given alias exists, otherwise False</returns>
public bool HasProperty(string propertyTypeAlias)
{
return Properties.Contains(propertyTypeAlias);
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as an <see cref="object"/></returns>
public object GetValue(string propertyTypeAlias)
{
return Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <typeparam name="TPassType">Type of the value to return</typeparam>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public TPassType GetValue<TPassType>(string propertyTypeAlias)
{
return (TPassType)Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Sets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <param name="value">Value to set for the Property</param>
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
/// <summary>

View File

@@ -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
{
/// <summary>
/// Represents an abstract class for base Content properties and methods
/// </summary>
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<ContentBase, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Path);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentBase, bool>(x => x.Trashed);
private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyCollectionSelector);
}
/// <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 { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the entity
/// </summary>
[DataMember]
public virtual string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(NameSelector);
}
}
/// <summary>
/// Gets the Url name of the entity
/// </summary>
[IgnoreDataMember]
public virtual string UrlName
{
//TODO Needs to implement proper url casing/syntax
get { return Name.ToLower().Replace(" ", "-"); }
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public virtual int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public virtual int Level
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets or sets the path
/// </summary>
[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);
}
}
/// <summary>
/// Id of the user who created this Content
/// </summary>
[DataMember]
public virtual int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Boolean indicating whether this Content is Trashed or not.
/// If Content is Trashed it will be located in the Recyclebin.
/// </summary>
/// <remarks>When content is trashed it should be unpublished</remarks>
[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);
}
}
/// <summary>
/// Guid Id of the curent Version
/// </summary>
[DataMember]
public Guid Version { get; internal set; }
/// <summary>
/// Integer Id of the default ContentType
/// </summary>
[DataMember]
public virtual int ContentTypeId
{
get { return _contentTypeId; }
protected set
{
_contentTypeId = value;
OnPropertyChanged(DefaultContentTypeIdSelector);
}
}
/// <summary>
/// Collection of properties, which make up all the data available for this Content object
/// </summary>
[DataMember]
public virtual PropertyCollection Properties
{
get { return _properties; }
set
{
_properties = value;
_properties.CollectionChanged += PropertiesChanged;
}
}
/// <summary>
/// List of PropertyGroups available on this Content object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> PropertyGroups { get { return ContentTypeBase.CompositionPropertyGroups; } }
/// <summary>
/// List of PropertyTypes available on this Content object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes { get { return ContentTypeBase.CompositionPropertyTypes; } }
/// <summary>
/// Indicates whether the content object has a property with the supplied alias
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns>True if Property with given alias exists, otherwise False</returns>
public virtual bool HasProperty(string propertyTypeAlias)
{
return Properties.Contains(propertyTypeAlias);
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as an <see cref="object"/></returns>
public virtual object GetValue(string propertyTypeAlias)
{
return Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <typeparam name="TPassType">Type of the value to return</typeparam>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
return (TPassType)Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Sets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <param name="value">Value to set for the Property</param>
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));
}
}
}

View File

@@ -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
/// </summary>
[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<IContentTypeComposition> _contentTypeComposition;
private IEnumerable<string> _allowedTemplates;
private IEnumerable<ContentTypeSort> _allowedContentTypes;
public ContentType(int parentId)
public ContentType(int parentId) : base(parentId)
{
_parentId = parentId;
_allowedTemplates = new List<string>();
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_contentTypeComposition = new List<IContentTypeComposition>();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Path);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Alias);
private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Description);
private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Icon);
private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.Thumbnail);
private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, string>(x => x.DefaultTemplate);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentType, bool>(x => x.Trashed);
private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<string>>(x => x.AllowedTemplates);
private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo<ContentType, List<IContentTypeComposition>>(x => x.ContentTypeComposition);
private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentType, PropertyGroupCollection>(x => x.PropertyGroups);
void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyGroupCollectionSelector);
}
/// <summary>
/// Gets or sets the Id of the Parent entity
/// </summary>
/// <remarks>Might not be necessary if handled as a relation?</remarks>
[DataMember]
public int ParentId
{
get { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the current entity
/// </summary>
[DataMember]
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(NameSelector);
}
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public int Level //NOTE Is this relevant for a ContentType?
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets of sets the path
/// </summary>
[DataMember]
public string Path //NOTE Is this relevant for a ContentType?
{
get { return _path; }
set
{
_path = value;
OnPropertyChanged(PathSelector);
}
}
/// <summary>
/// The Alias of the ContentType
/// </summary>
[DataMember]
public string Alias
{
get { return _alias; }
set
{
_alias = value;
OnPropertyChanged(AliasSelector);
}
}
/// <summary>
/// Description for the ContentType
/// </summary>
[DataMember]
public string Description
{
get { return _description; }
set
{
_description = value;
OnPropertyChanged(DescriptionSelector);
}
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Name of the icon (sprite class) used to identify the ContentType
/// </summary>
[DataMember]
public string Icon
{
get { return _icon; }
set
{
_icon = value;
OnPropertyChanged(IconSelector);
}
}
/// <summary>
/// Name of the thumbnail used to identify the ContentType
/// </summary>
[DataMember]
public string Thumbnail
{
get { return _thumbnail; }
set
{
_thumbnail = value;
OnPropertyChanged(ThumbnailSelector);
}
}
/// <summary>
/// Gets or sets the Path to default Template
/// </summary>
@@ -203,35 +37,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Id of the user who created this Content
/// </summary>
[DataMember]
public int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Boolean indicating whether this ContentType is Trashed or not.
/// If ContentType is Trashed it will be located in the Recyclebin.
/// </summary>
[DataMember]
public bool Trashed //NOTE Is this relevant for a ContentType?
{
get { return _trashed; }
set
{
_trashed = value;
OnPropertyChanged(TrashedSelector);
}
}
/// <summary>
/// Gets or sets a list of aliases for allowed Templates
/// </summary>
@@ -245,148 +50,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>
[DataMember]
public IEnumerable<ContentTypeSort> AllowedContentTypes
{
get { return _allowedContentTypes; }
set
{
_allowedContentTypes = value;
OnPropertyChanged(AllowedContentTypesSelector);
}
}
/// <summary>
/// List of PropertyGroups available on this ContentType
/// </summary>
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
[DataMember]
public PropertyGroupCollection PropertyGroups
{
get { return _propertyGroups; }
set
{
_propertyGroups = value;
_propertyGroups.CollectionChanged += PropertyGroupsChanged;
}
}
/// <summary>
/// List of PropertyTypes available on this ContentType.
/// This list aggregates PropertyTypes across the PropertyGroups.
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes
{
get { return PropertyGroups.SelectMany(x => x.PropertyTypes); }
}
/// <summary>
/// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
[DataMember]
public List<IContentTypeComposition> ContentTypeComposition
{
get { return _contentTypeComposition; }
set
{
_contentTypeComposition = value;
OnPropertyChanged(ContentTypeCompositionSelector);
}
}
/// <summary>
/// Returns a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> CompositionPropertyGroups
{
get
{
var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups));
return groups;
}
}
/// <summary>
/// Returns a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> CompositionPropertyTypes
{
get
{
var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes));
return propertyTypes;
}
}
/// <summary>
/// Adds a new ContentType to the list of composite ContentTypes
/// </summary>
/// <param name="contentType"><see cref="ContentType"/> to add</param>
/// <returns>True if ContentType was added, otherwise returns False</returns>
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;
}
/// <summary>
/// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType was removed, otherwise returns False</returns>
public bool RemoveContentType(string alias)
{
if (!ContentTypeCompositionExists(alias))
{
var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias);
return ContentTypeComposition.Remove(contentTypeComposition);
}
return false;
}
/// <summary>
/// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType with alias exists, otherwise returns False</returns>
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;
}
/// <summary>
/// Gets a list of ContentType aliases from the current composition
/// </summary>
/// <returns></returns>
/// <remarks>Does not contain the alias of the Current ContentType</remarks>
public IEnumerable<string> 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)
{}*/
/// <summary>
/// Method to call when Entity is being saved
/// </summary>

View File

@@ -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
{
/// <summary>
/// Represents an abstract class for base ContentType properties and methods
/// </summary>
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<ContentTypeSort> _allowedContentTypes;
protected ContentTypeBase(int parentId)
{
_parentId = parentId;
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Path);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Alias);
private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Description);
private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.Trashed);
private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentType, PropertyGroupCollection>(x => x.PropertyGroups);
protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyGroupCollectionSelector);
}
/// <summary>
/// Gets or sets the Id of the Parent entity
/// </summary>
/// <remarks>Might not be necessary if handled as a relation?</remarks>
[DataMember]
public int ParentId
{
get { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the current entity
/// </summary>
[DataMember]
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(NameSelector);
}
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public int Level //NOTE Is this relevant for a ContentType?
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets of sets the path
/// </summary>
[DataMember]
public string Path //NOTE Is this relevant for a ContentType?
{
get { return _path; }
set
{
_path = value;
OnPropertyChanged(PathSelector);
}
}
/// <summary>
/// The Alias of the ContentType
/// </summary>
[DataMember]
public string Alias
{
get { return _alias; }
set
{
_alias = value;
OnPropertyChanged(AliasSelector);
}
}
/// <summary>
/// Description for the ContentType
/// </summary>
[DataMember]
public string Description
{
get { return _description; }
set
{
_description = value;
OnPropertyChanged(DescriptionSelector);
}
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Name of the icon (sprite class) used to identify the ContentType
/// </summary>
[DataMember]
public string Icon
{
get { return _icon; }
set
{
_icon = value;
OnPropertyChanged(IconSelector);
}
}
/// <summary>
/// Name of the thumbnail used to identify the ContentType
/// </summary>
[DataMember]
public string Thumbnail
{
get { return _thumbnail; }
set
{
_thumbnail = value;
OnPropertyChanged(ThumbnailSelector);
}
}
/// <summary>
/// Id of the user who created this Content
/// </summary>
[DataMember]
public int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Boolean indicating whether this ContentType is Trashed or not.
/// If ContentType is Trashed it will be located in the Recyclebin.
/// </summary>
[DataMember]
public bool Trashed //NOTE Is this relevant for a ContentType?
{
get { return _trashed; }
set
{
_trashed = value;
OnPropertyChanged(TrashedSelector);
}
}
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>
[DataMember]
public IEnumerable<ContentTypeSort> AllowedContentTypes
{
get { return _allowedContentTypes; }
set
{
_allowedContentTypes = value;
OnPropertyChanged(AllowedContentTypesSelector);
}
}
/// <summary>
/// List of PropertyGroups available on this ContentType
/// </summary>
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
[DataMember]
public PropertyGroupCollection PropertyGroups
{
get { return _propertyGroups; }
set
{
_propertyGroups = value;
_propertyGroups.CollectionChanged += PropertyGroupsChanged;
}
}
/// <summary>
/// List of PropertyTypes available on this ContentType.
/// This list aggregates PropertyTypes across the PropertyGroups.
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes
{
get { return PropertyGroups.SelectMany(x => x.PropertyTypes); }
}
//TODO Implement moving PropertyType between groups.
/*public bool MovePropertyTypeToGroup(string propertyTypeAlias, string groupName)
{}*/
}
}

View File

@@ -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<IContentTypeComposition> _contentTypeComposition;
protected ContentTypeCompositionBase(int parentId) : base(parentId)
{
_contentTypeComposition = new List<IContentTypeComposition>();
}
private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo<ContentType, List<IContentTypeComposition>>(x => x.ContentTypeComposition);
/// <summary>
/// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
[DataMember]
public List<IContentTypeComposition> ContentTypeComposition
{
get { return _contentTypeComposition; }
set
{
_contentTypeComposition = value;
OnPropertyChanged(ContentTypeCompositionSelector);
}
}
/// <summary>
/// Returns a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> CompositionPropertyGroups
{
get
{
var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups));
return groups;
}
}
/// <summary>
/// Returns a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> CompositionPropertyTypes
{
get
{
var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes));
return propertyTypes;
}
}
/// <summary>
/// Adds a new ContentType to the list of composite ContentTypes
/// </summary>
/// <param name="contentType"><see cref="ContentType"/> to add</param>
/// <returns>True if ContentType was added, otherwise returns False</returns>
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;
}
/// <summary>
/// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType was removed, otherwise returns False</returns>
public bool RemoveContentType(string alias)
{
if (!ContentTypeCompositionExists(alias))
{
var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias);
return ContentTypeComposition.Remove(contentTypeComposition);
}
return false;
}
/// <summary>
/// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType with alias exists, otherwise returns False</returns>
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;
}
/// <summary>
/// Gets a list of ContentType aliases from the current composition
/// </summary>
/// <returns></returns>
/// <remarks>Does not contain the alias of the Current ContentType</remarks>
public IEnumerable<string> CompositionAliases()
{
return ContentTypeComposition.Select(x => x.Alias).Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases()));
}
}
}

View File

@@ -33,6 +33,11 @@ namespace Umbraco.Core.Models
/// </summary>
DateTime? ExpireDate { get; set; }
/// <summary>
/// Gets the ContentType used by this content object
/// </summary>
IContentType ContentType { get; }
/// <summary>
/// Changes the <see cref="IContentType"/> for the current content object
/// </summary>

View File

@@ -2,6 +2,11 @@
{
public interface IMedia : IContentBase
{
/// <summary>
/// Gets the ContentType used by this Media object
/// </summary>
IMediaType ContentType { get; }
/// <summary>
/// Changes the <see cref="IMediaType"/> for the current content object
/// </summary>

View File

@@ -3,7 +3,7 @@
/// <summary>
/// Defines a ContentType, which Media is based on
/// </summary>
public interface IMediaType : IContentTypeBase
public interface IMediaType : IContentTypeComposition
{
}

View File

@@ -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
/// </summary>
[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;
/// <summary>
@@ -44,193 +28,9 @@ namespace Umbraco.Core.Models
/// <param name="parentId"> </param>
/// <param name="contentType">MediaType for the current Media object</param>
/// <param name="properties">Collection of properties</param>
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<Media, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<Media, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<Media, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<Media, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<Media, string>(x => x.Path);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<Media, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<Media, bool>(x => x.Trashed);
private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<Media, int>(x => x.ContentTypeId);
private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<Media, PropertyCollection>(x => x.Properties);
void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyCollectionSelector);
}
/// <summary>
/// Gets or Sets the Id of the Parent for the Media
/// </summary>
[DataMember]
public int ParentId
{
get { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or Sets the Name of the Media
/// </summary>
[DataMember]
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(NameSelector);
}
}
/// <summary>
/// Gets the Url name of the Media item
/// </summary>
[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;
}
}
/// <summary>
/// Gets or Sets the Sort Order of the Media
/// </summary>
[DataMember]
public int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Gets or Sets the Level of the Media
/// </summary>
[DataMember]
public int Level
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets or Sets the Path of the Media
/// </summary>
[DataMember]
public string Path
{
get { return _path; }
set
{
_path = value;
OnPropertyChanged(PathSelector);
}
}
/// <summary>
/// Id of the user who created the Media
/// </summary>
[DataMember]
public int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Boolean indicating whether this Media is Trashed or not.
/// If Media is Trashed it will be located in the Recyclebin.
/// </summary>
[DataMember]
public bool Trashed
{
get { return _trashed; }
internal set
{
_trashed = value;
OnPropertyChanged(TrashedSelector);
}
}
/// <summary>
/// Integer Id of the default MediaType
/// </summary>
[DataMember]
public int ContentTypeId
{
get { return _contentTypeId; }
protected set
{
_contentTypeId = value;
OnPropertyChanged(DefaultContentTypeIdSelector);
}
}
/// <summary>
/// Guid Id of the curent Version
/// </summary>
[DataMember]
public Guid Version { get; internal set; }
/// <summary>
/// List of properties, which make up all the data available for this Media object
/// </summary>
[DataMember]
public PropertyCollection Properties
{
get { return _properties; }
set
{
_properties = value;
_properties.CollectionChanged += PropertiesChanged;
}
}
/// <summary>
/// List of PropertyGroups available on this Media object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> PropertyGroups
{
get { return _contentType.PropertyGroups; }
}
/// <summary>
/// List of PropertyTypes available on this Media object
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes
{
get { return _contentType.PropertyTypes; }
}
/// <summary>
@@ -242,58 +42,6 @@ namespace Umbraco.Core.Models
get { return _contentType; }
}
/// <summary>
/// Indicates whether the Media object has a property with the supplied alias
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns>True if Property with given alias exists, otherwise False</returns>
public bool HasProperty(string propertyTypeAlias)
{
return Properties.Contains(propertyTypeAlias);
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as an <see cref="object"/></returns>
public object GetValue(string propertyTypeAlias)
{
return Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Gets the value of a Property
/// </summary>
/// <typeparam name="TPassType">Type of the value to return</typeparam>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public TPassType GetValue<TPassType>(string propertyTypeAlias)
{
return (TPassType)Properties[propertyTypeAlias].Value;
}
/// <summary>
/// Sets the value of a Property
/// </summary>
/// <param name="propertyTypeAlias">Alias of the PropertyType</param>
/// <param name="value">Value to set for the Property</param>
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));
}
/// <summary>
/// Changes the <see cref="IMediaType"/> for the current Media object
/// </summary>
@@ -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;
}
/// <summary>
@@ -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;
}

View File

@@ -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
/// </summary>
[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<ContentTypeSort> _allowedContentTypes;
public MediaType(int parentId)
public MediaType(int parentId) : base(parentId)
{
_parentId = parentId;
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<MediaType, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<MediaType, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<MediaType, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Path);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Alias);
private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Description);
private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Icon);
private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<MediaType, string>(x => x.Thumbnail);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<MediaType, int>(x => x.UserId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<MediaType, bool>(x => x.Trashed);
private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<MediaType, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<MediaType, PropertyGroupCollection>(x => x.PropertyGroups);
void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertyGroupCollectionSelector);
}
/// <summary>
/// Gets or sets the Id of the Parent entity
/// </summary>
/// <remarks>Might not be necessary if handled as a relation?</remarks>
[DataMember]
public int ParentId
{
get { return _parentId; }
set
{
_parentId = value;
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the name of the current entity
/// </summary>
[DataMember]
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(NameSelector);
}
}
/// <summary>
/// Gets or sets the level of the content entity
/// </summary>
[DataMember]
public int Level //NOTE Is this relevant for a ContentType?
{
get { return _level; }
set
{
_level = value;
OnPropertyChanged(LevelSelector);
}
}
/// <summary>
/// Gets of sets the path
/// </summary>
[DataMember]
public string Path //NOTE Is this relevant for a ContentType?
{
get { return _path; }
set
{
_path = value;
OnPropertyChanged(PathSelector);
}
}
/// <summary>
/// The Alias of the ContentType
/// </summary>
[DataMember]
public string Alias
{
get { return _alias; }
set
{
_alias = value;
OnPropertyChanged(AliasSelector);
}
}
/// <summary>
/// Description for the ContentType
/// </summary>
[DataMember]
public string Description
{
get { return _description; }
set
{
_description = value;
OnPropertyChanged(DescriptionSelector);
}
}
/// <summary>
/// Gets or sets the sort order of the content entity
/// </summary>
[DataMember]
public int SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
OnPropertyChanged(SortOrderSelector);
}
}
/// <summary>
/// Name of the icon (sprite class) used to identify the ContentType
/// </summary>
[DataMember]
public string Icon
{
get { return _icon; }
set
{
_icon = value;
OnPropertyChanged(IconSelector);
}
}
/// <summary>
/// Name of the thumbnail used to identify the ContentType
/// </summary>
[DataMember]
public string Thumbnail
{
get { return _thumbnail; }
set
{
_thumbnail = value;
OnPropertyChanged(ThumbnailSelector);
}
}
/// <summary>
/// Id of the user who created this Content
/// </summary>
[DataMember]
public int UserId
{
get { return _userId; }
set
{
_userId = value;
OnPropertyChanged(UserIdSelector);
}
}
/// <summary>
/// Boolean indicating whether this ContentType is Trashed or not.
/// If ContentType is Trashed it will be located in the Recyclebin.
/// </summary>
[DataMember]
public bool Trashed //NOTE Is this relevant for a ContentType?
{
get { return _trashed; }
set
{
_trashed = value;
OnPropertyChanged(TrashedSelector);
}
}
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>
[DataMember]
public IEnumerable<ContentTypeSort> AllowedContentTypes
{
get { return _allowedContentTypes; }
set
{
_allowedContentTypes = value;
OnPropertyChanged(AllowedContentTypesSelector);
}
}
/// <summary>
/// List of PropertyGroups available on this ContentType
/// </summary>
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
[DataMember]
public PropertyGroupCollection PropertyGroups
{
get { return _propertyGroups; }
set
{
_propertyGroups = value;
_propertyGroups.CollectionChanged += PropertyGroupsChanged;
}
}
/// <summary>
/// List of PropertyTypes available on this ContentType.
/// This list aggregates PropertyTypes across the PropertyGroups.
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes
{
get { return PropertyGroups.SelectMany(x => x.PropertyTypes); }
}
/// <summary>

View File

@@ -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
{
/// <summary>
/// Represent an abstract Repository for ContentType based repositories
/// </summary>
/// <remarks>Exposes shared functionality</remarks>
/// <typeparam name="TId"></typeparam>
/// <typeparam name="TEntity"></typeparam>
internal abstract class ContentTypeBaseRepository<TId, TEntity> : PetaPocoRepositoryBase<TId, TEntity>
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<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
int level = parent.Level + 1;
int sortOrder =
Database.ExecuteScalar<int>("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<ContentTypeDto>("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<ContentType2ContentTypeDto>("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<ContentTypeAllowedContentTypeDto>("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<PropertyTypeDto>("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<PropertyTypeDto>("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<PropertyTypeGroupDto>("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<PropertyTypeGroupDto>("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<ContentTypeSort> GetAllowedContentTypeIds(int id)
{
var allowedContentTypesSql = new Sql();
allowedContentTypesSql.Select("*");
allowedContentTypesSql.From("cmsContentTypeAllowedContentType");
allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id });
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(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<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new TabPropertyTypeRelator().Map, propertySql);
var propertyFactory = new PropertyGroupFactory(id);
var propertyGroups = propertyFactory.BuildEntity(dtos);
return new PropertyGroupCollection(propertyGroups);
}
}
}

View File

@@ -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
/// <summary>
/// Represents a repository for doing CRUD operations for <see cref="IContentType"/>
/// </summary>
internal class ContentTypeRepository : PetaPocoRepositoryBase<int, IContentType>, IContentTypeRepository
internal class ContentTypeRepository : ContentTypeBaseRepository<int, IContentType>, 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<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
int level = parent.Level + 1;
int sortOrder =
Database.ExecuteScalar<int>("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<ContentTypeDto>("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<ContentType2ContentTypeDto>("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<ContentTypeAllowedContentTypeDto>("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<PropertyTypeDto>("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<PropertyTypeDto>("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<PropertyTypeGroupDto>("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<PropertyTypeGroupDto>("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<ContentTypeSort> GetAllowedContentTypeIds(int id)
{
var allowedContentTypesSql = new Sql();
allowedContentTypesSql.Select("*");
allowedContentTypesSql.From("cmsContentTypeAllowedContentType");
allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id });
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(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<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new TabPropertyTypeRelator().Map, propertySql);
var propertyFactory = new PropertyGroupFactory(id);
var propertyGroups = propertyFactory.BuildEntity(dtos);
return new PropertyGroupCollection(propertyGroups);
}
}
}

View File

@@ -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
/// <summary>
/// Represents a repository for doing CRUD operations for <see cref="IMediaType"/>
/// </summary>
internal class MediaTypeRepository : PetaPocoRepositoryBase<int, IMediaType>, IMediaTypeRepository
internal class MediaTypeRepository : ContentTypeBaseRepository<int, IMediaType>, 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<ContentType2ContentTypeDto>("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<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
int level = parent.Level + 1;
int sortOrder =
Database.ExecuteScalar<int>("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<ContentTypeDto>("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<ContentTypeAllowedContentTypeDto>("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<PropertyTypeDto>("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<PropertyTypeDto>("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<PropertyTypeGroupDto>("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<PropertyTypeGroupDto>("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<ContentTypeSort> GetAllowedContentTypeIds(int id)
{
var allowedContentTypesSql = new Sql();
allowedContentTypesSql.Select("*");
allowedContentTypesSql.From("cmsContentTypeAllowedContentType");
allowedContentTypesSql.Where("[cmsContentTypeAllowedContentType].[Id] = @Id", new { Id = id });
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(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<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new TabPropertyTypeRelator().Map, propertySql);
var propertyFactory = new PropertyGroupFactory(id);
var propertyGroups = propertyFactory.BuildEntity(tabDtos);
return new PropertyGroupCollection(propertyGroups);
}
}
}

View File

@@ -74,8 +74,11 @@
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="Dictionary\CultureDictionaryFactoryResolver.cs" />
<Compile Include="Dictionary\ICultureDictionaryFactory.cs" />
<Compile Include="Models\ContentBase.cs" />
<Compile Include="Models\ContentExtensions.cs" />
<Compile Include="Enum.cs" />
<Compile Include="Models\ContentTypeBase.cs" />
<Compile Include="Models\ContentTypeCompositionBase.cs" />
<Compile Include="Models\ContentTypeSort.cs" />
<Compile Include="Models\Css\CssCompactor.cs" />
<Compile Include="Models\Css\CssParser.cs" />
@@ -124,6 +127,7 @@
<Compile Include="Persistence\Querying\SqlTranslator.cs" />
<Compile Include="Persistence\Relators\DictionaryLanguageTextRelator.cs" />
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
<Compile Include="Persistence\Repositories\ContentTypeBaseRepository.cs" />
<Compile Include="Persistence\Repositories\ContentTypeRepository.cs" />
<Compile Include="Persistence\Repositories\DataTypeDefinitionRepository.cs" />
<Compile Include="Persistence\Repositories\DictionaryRepository.cs" />