using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Web; using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { /// /// Represents an abstract class for base Content properties and methods /// [DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")] public abstract class ContentBase : Entity, IContentBase { protected IContentTypeComposition ContentTypeBase; private Lazy _parentId; private string _name;//NOTE Once localization is introduced this will be the localized Name of the Content/Media. private int _sortOrder; private int _level; private string _path; private int _creatorId; private bool _trashed; private int _contentTypeId; private PropertyCollection _properties; /// /// Protected constructor for ContentBase (Base for Content and Media) /// /// Localized Name of the entity /// /// /// protected ContentBase(string name, int parentId, IContentTypeComposition contentType, PropertyCollection properties) { Mandate.ParameterCondition(parentId != 0, "parentId"); Mandate.ParameterNotNull(contentType, "contentType"); Mandate.ParameterNotNull(properties, "properties"); ContentTypeBase = contentType; Version = Guid.NewGuid(); _parentId = new Lazy(() => parentId); _name = name; _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture)); _properties = properties; _properties.EnsurePropertyTypes(PropertyTypes); } /// /// Protected constructor for ContentBase (Base for Content and Media) /// /// Localized Name of the entity /// /// /// protected ContentBase(string name, IContentBase parent, IContentTypeComposition contentType, PropertyCollection properties) { Mandate.ParameterNotNull(parent, "parent"); Mandate.ParameterNotNull(contentType, "contentType"); Mandate.ParameterNotNull(properties, "properties"); ContentTypeBase = contentType; Version = Guid.NewGuid(); _parentId = new Lazy(() => parent.Id); _name = name; _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture)); _properties = properties; _properties.EnsurePropertyTypes(PropertyTypes); } 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 CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId); 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 /// [DataMember] public virtual int ParentId { get { var val = _parentId.Value; if (val == 0) { throw new InvalidOperationException("The ParentId cannot have a value of 0. Perhaps the parent object used to instantiate this object has not been persisted to the data store."); } return val; } set { _parentId = new Lazy(() => 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 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); } } /// /// Profile of the user who created this Content /// [DataMember] public virtual int CreatorId { get { return _creatorId; } set { _creatorId = value; OnPropertyChanged(CreatorIdSelector); } } /// /// 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 (value == null) { SetValueOnProperty(propertyTypeAlias, value); return; } // .NET magic to call one of the 'SetPropertyValue' handlers with matching signature ((dynamic)this).SetPropertyValue(propertyTypeAlias, (dynamic)value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, string value) { SetValueOnProperty(propertyTypeAlias, value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, int value) { SetValueOnProperty(propertyTypeAlias, value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, long value) { string val = value.ToString(); SetValueOnProperty(propertyTypeAlias, val); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, bool value) { int val = Convert.ToInt32(value); SetValueOnProperty(propertyTypeAlias, val); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, DateTime value) { SetValueOnProperty(propertyTypeAlias, value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, HttpPostedFile value) { ContentExtensions.SetValue(this, propertyTypeAlias, value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, HttpPostedFileBase value) { ContentExtensions.SetValue(this, propertyTypeAlias, value); } /// /// Sets the value of a Property /// /// Alias of the PropertyType /// Value to set for the Property public virtual void SetPropertyValue(string propertyTypeAlias, HttpPostedFileWrapper value) { ContentExtensions.SetValue(this, propertyTypeAlias, value); } /// /// Private method to set the value of a property /// /// /// private void SetValueOnProperty(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)); } /// /// Boolean indicating whether the content and its properties are valid /// /// True if content is valid otherwise false public virtual bool IsValid() { return Properties.Any(property => !property.IsValid()) == false; } public abstract void ChangeTrashedState(bool isTrashed, int parentId = -20); } }