public static void ReadPropertyNameAndAlias(PropertyInfo propInfo, DocumentTypePropertyAttribute propAttr, out string name, out string alias) { // set name name = string.IsNullOrEmpty(propAttr.Name) ? propInfo.Name : propAttr.Name; // set a default alias alias = propInfo.Name.Substring(0, 1).ToLower(); // if an alias has been set, use that one explicitly if (!String.IsNullOrEmpty(propAttr.Alias)) { alias = propAttr.Alias; // otherwise } else { // create the alias from the name if (propInfo.Name.Length > 1) { alias += propInfo.Name.Substring(1, propInfo.Name.Length - 1); } // This is required because it seems that Umbraco has a bug when property type alias is called pageName. if (alias == "pageName") { alias += "_"; } } }
private void ContentServiceOnCreating(IContentService sender, NewEventArgs <IContent> newEventArgs) { Type typeDocType = DocumentTypeManager.GetDocumentTypeType(newEventArgs.Alias); if (typeDocType != null) { foreach (PropertyInfo propInfo in typeDocType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a Document Type } string propertyName; string propertyAlias; ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); if (propAttr.DefaultValue != null) { try { newEventArgs.Entity.SetValue(propertyAlias, propAttr.DefaultValue); } catch (Exception exc) { throw new Exception(string.Format("Cannot set default value ('{0}') for property {1}.{2}. Error: {3}", propAttr.DefaultValue, typeDocType.Name, propInfo.Name, exc.Message), exc); } } } } }
public static string GetAliasFromAttribute(this MethodInfo property) { string propertyName = property.GetPropertyName(); PropertyInfo propertyInfo = property.DeclaringType.GetProperty(propertyName); DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propertyInfo); return(propAttr.Alias); }
/// <summary> /// The method saves values from the given properties of the valueSource specified to the content of the contentType type /// </summary> /// <param name="valueSource">An object to get property values from. Can be either DocumentTypeBase or mixin object reference</param> /// <param name="contentType">A content type information</param> /// <param name="content">A content to save values to</param> /// <param name="properties">A valueSource properties collection</param> private static void SaveProperties(object valueSource, IContentType contentType, IContent content, IEnumerable <PropertyInfo> properties) { foreach (var propInfo in properties) { try { var mixinAttribute = Util.GetAttribute <MixinPropertyAttribute>(propInfo); if (mixinAttribute != null) { var mixin = propInfo.GetValue(valueSource, null); if (mixin != null) { var mixinType = mixinAttribute.GetMixinType(propInfo); var mixinProperties = mixinType.GetProperties(BindingFlags.Public | BindingFlags.Instance); SaveProperties(mixin, contentType, content, mixinProperties); } continue; } DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a Document Type } string propertyName; string propertyAlias; DocumentTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); PropertyType property = content.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias); if (property == null) { throw new Exception(string.Format("Property '{0}' not found in this node: {1}. Content type: {2}.", propertyAlias, content.Id, contentType.Alias)); } if (PropertyConvertors.ContainsKey(propInfo.PropertyType)) { content.SetValue(propertyAlias, PropertyConvertors[propInfo.PropertyType].ConvertValueWhenWrite(propInfo.GetValue(valueSource, null))); } else { content.SetValue(propertyAlias, propInfo.GetValue(valueSource, null)); } } catch (Exception exc) { throw new Exception(String.Format("Error while saving property: {0}.{1}. Error: {2}, Stack trace: {3}", contentType.Alias, propInfo.Name, exc.Message, exc.StackTrace), exc); } } }
/// <summary> /// The method populates a given typedObject with values from the node using typeDocType as a information about typedObject properties. /// </summary> /// <param name="node">A node to get values from</param> /// <param name="typeDocType">A type to get properties information from</param> /// <param name="typedObject">Either DocumentTypeBase or mixin reference</param> private static void PopulateInstanceValues(Node node, Type typeDocType, ContentTypeBase typedObject) { foreach (PropertyInfo propInfo in typeDocType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { // Let's support typed access to mixins var mixinAttribute = Util.GetAttribute <MixinPropertyAttribute>(propInfo); // if property is a mixin if (mixinAttribute != null // and property is not to be intercepted && (propInfo.GetGetMethod() != null && (!propInfo.GetGetMethod().IsVirtual || propInfo.GetGetMethod().IsFinal))) { var mixin = GetMixinValue(node, propInfo); propInfo.SetValue(typedObject, mixin, null); continue; } DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null || (propInfo.GetGetMethod() != null && propInfo.GetGetMethod().IsVirtual&& !propInfo.GetGetMethod().IsFinal)) { continue; // skip this property - not part of a Document Type or is virtual in which case value will be intercepted } object value = null; try { value = GetPropertyValue(node, propInfo, propAttr); propInfo.SetValue(typedObject, value, null); } catch (Exception exc) { throw new Exception(string.Format("Cannot set the value of a document type property {0}.{1} (document type: {2}) to value: '{3}' (value type: {4}). Error: {5}", typeDocType.Name, propInfo.Name, propInfo.PropertyType.FullName, value, value != null ? value.GetType().FullName : "", exc.Message)); } } }
public static DataTypeDefinition GetDataTypeDefinition(Type typeContentType, DocumentTypePropertyAttribute propAttr, PropertyInfo propInfo) { // getting data type definition DataTypeDefinition dataTypeDefinition = null; // Convention mapping for property types <==> Umbraco Property types if (propAttr.Type == null) { if (propInfo.PropertyType == typeof(string)) { return(DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.Textstring)); } if (propInfo.PropertyType == typeof(DateTime)) { return(DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.DatePicker)); } if (propInfo.PropertyType == typeof(bool)) { return(DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.TrueFalse)); } if (propInfo.PropertyType == typeof(HtmlString)) { return(DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.RichtextEditor)); } } if (propAttr.Type == UmbracoPropertyType.Other) { // If the OtherType is specified we need to do some reflection to get the name // from the attribute on the class definition if (propAttr.OtherType != null) { var dataTypeAttribute = (DataTypeAttribute) Attribute.GetCustomAttributes(propAttr.OtherType, typeof(DataTypeAttribute)).First(); var dataTypeName = dataTypeAttribute.Name; dataTypeDefinition = DataTypeDefinition.GetAll().FirstOrDefault(itm => itm.Text == dataTypeName); if (dataTypeDefinition == null) { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type ('{2}') but data type '{2}' cannot be found in Umbraco.", propInfo.Name, typeContentType.Name, dataTypeName)); } } else if (!string.IsNullOrEmpty(propAttr.OtherTypeName)) { dataTypeDefinition = DataTypeDefinition.GetAll().FirstOrDefault(itm => itm.Text == propAttr.OtherTypeName); if (dataTypeDefinition == null) { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type ('{2}') but data type '{2}' cannot be found in Umbraco.", propInfo.Name, typeContentType.Name, propAttr.OtherTypeName)); } } else { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type but 'OtherTypeName' on that property is empty. Please set 'OtherTypeName' on property '{1}.{0}'.", propInfo.Name, typeContentType.Name)); } } else { dataTypeDefinition = DataTypeDefinition.GetDataTypeDefinition((int)propAttr.Type); } return(dataTypeDefinition); }
//#region [Document type properties synchronization] /// <summary> /// Synchronizes content type properties /// </summary> /// <param name="typeContentType">ContentType type</param> /// <param name="contentType">Umbraco content type</param> /// <param name="hadDefaultValues">set to true if some of properties has default values</param> protected void SynchronizeContentTypeProperties(Type typeContentType, IContentType contentType, DocumentTypeAttribute documentTypeAttribute, out bool hadDefaultValues, bool updateMixins) { // sync the mixins first so that any properties are overwritten by the specific properties on the class if ((documentTypeAttribute.Mixins != null) && (updateMixins == false)) { foreach (Type mixinType in documentTypeAttribute.Mixins) { SynchronizeContentTypeProperties(mixinType, contentType, documentTypeAttribute, out hadDefaultValues, true); } } hadDefaultValues = false; int propertySortOrder = 0; foreach (PropertyInfo propInfo in typeContentType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a document type } // Getting name and alias string propertyName; string propertyAlias; DocumentTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); // Remove property if it has Obsolete attribute if (this.RemoveIfObsolete(contentType, propInfo, propertyAlias)) { continue; } if (propAttr.DefaultValue != null) { hadDefaultValues = true; // at least one property has a default value } DataTypeDefinition dataTypeDefinition = GetDataTypeDefinition(typeContentType, propAttr, propInfo); // getting property if already exists, or creating new if it not exists Umbraco.Core.Models.PropertyType propertyType = contentType.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias); if (propertyType == null) // if not exists, create it { Util.AddPropertyType(contentType, dataTypeDefinition, propertyAlias, propertyName, propAttr.TabAsString); propertyType = contentType.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias); } else { if (propertyType.DataTypeDefinitionId != dataTypeDefinition.Id) { propertyType.DataTypeDefinitionId = dataTypeDefinition.Id; } } // If propertyType is still null, skip it. It means it cannot be added and is probably present in a parent content type. // Reason for inability to create the propertyType must be resolved manually. if (propertyType != null) { // Setting up the tab of this property. If tab doesn't exists, create it. if (!string.IsNullOrEmpty(propAttr.TabAsString) && propAttr.TabAsString.ToLower() != DocumentTypeDefaultValues.TabGenericProperties.ToLower()) { // try to find this tab PropertyGroup pg = contentType.PropertyGroups.FirstOrDefault(x => x.Name == propAttr.TabAsString); if (pg == null) // if found { contentType.AddPropertyGroup(propAttr.TabAsString); pg = contentType.PropertyGroups.FirstOrDefault(x => x.Name == propAttr.TabAsString); } if (propAttr.TabOrder.HasValue) { pg.SortOrder = propAttr.TabOrder.Value; } if (!pg.PropertyTypes.Any(x => x.Alias == propertyType.Alias)) { contentType.MovePropertyType(propertyType.Alias, propAttr.TabAsString); } } else if ((propAttr.TabAsString == string.Empty) || (propAttr.TabAsString.ToLower() == "generic properties")) { // In case when some property exists and needs to be moved to "Generic Properties" tab contentType.MovePropertyType(propertyType.Alias, null); } propertyType.Name = propertyName; propertyType.Mandatory = propAttr.Mandatory; propertyType.ValidationRegExp = propAttr.ValidationRegExp; propertyType.Description = propAttr.Description; propertyType.SortOrder = propertySortOrder; propertySortOrder++; } } }
/// <summary> /// Updates or adds the member. If member already exists, it updates it. /// If member doesn't exists, it creates new member. /// </summary> /// <param name="member">Member to update/add</param> /// <param name="user">User used for add or updating the content</param> private static void Save(MemberTypeBase member, User user) { if (user == null) { throw new Exception("User cannot be null!"); } if (string.IsNullOrEmpty(member.LoginName)) { throw new Exception("Member Login Name cannot be empty"); } MemberType memberType = MemberTypeManager.GetMemberType(member.GetType()); Member umember; if (member.Id == 0) // member is new so create Member { umember = Member.MakeNew(member.LoginName, member.Email, memberType, user); // reload umember = Member.GetMemberFromLoginName(member.LoginName); umember.Password = member.Password; member.Id = umember.Id; } else // member already exists, so load it { umember = new Member(member.Id); } umember.Email = member.Email; umember.LoginName = member.LoginName; foreach (PropertyInfo propInfo in member.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a Document Type } string propertyName; string propertyAlias; MemberTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); umbraco.cms.businesslogic.property.Property property = umember.getProperty(propertyAlias); if (property == null) { throw new Exception(string.Format("Property '{0}' not found in this node: {1}. Content type: {2}.", propertyAlias, member.Id, memberType.Alias)); } if (ContentHelper.PropertyConvertors.ContainsKey(propInfo.PropertyType)) { property.Value = ContentHelper.PropertyConvertors[propInfo.PropertyType].ConvertValueWhenWrite(propInfo.GetValue(member, null)); } else { property.Value = propInfo.GetValue(member, null); } } umember.Save(); }
public static DataTypeDefinition GetDataTypeDefinition(Type typeContentType, DocumentTypePropertyAttribute propAttr, PropertyInfo propInfo) { // getting data type definition DataTypeDefinition dataTypeDefinition = null; // Convention mapping for property types <==> Umbraco Property types if (propAttr.Type == null) { if (propInfo.PropertyType == typeof(string)) { return DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.Textstring); } if (propInfo.PropertyType == typeof(DateTime)) { return DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.DatePicker); } if (propInfo.PropertyType == typeof(bool)) { return DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.TrueFalse); } if (propInfo.PropertyType == typeof(HtmlString)) { return DataTypeDefinition.GetDataTypeDefinition((int)UmbracoPropertyType.RichtextEditor); } } if (propAttr.Type == UmbracoPropertyType.Other) { // If the OtherType is specified we need to do some reflection to get the name // from the attribute on the class definition if (propAttr.OtherType != null) { var dataTypeAttribute = (DataTypeAttribute) Attribute.GetCustomAttributes(propAttr.OtherType, typeof(DataTypeAttribute)).First(); var dataTypeName = dataTypeAttribute.Name; dataTypeDefinition = DataTypeDefinition.GetAll().FirstOrDefault(itm => itm.Text == dataTypeName); if (dataTypeDefinition == null) { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type ('{2}') but data type '{2}' cannot be found in Umbraco.", propInfo.Name, typeContentType.Name, dataTypeName)); } } else if (!string.IsNullOrEmpty(propAttr.OtherTypeName)) { dataTypeDefinition = DataTypeDefinition.GetAll().FirstOrDefault(itm => itm.Text == propAttr.OtherTypeName); if (dataTypeDefinition == null) { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type ('{2}') but data type '{2}' cannot be found in Umbraco.", propInfo.Name, typeContentType.Name, propAttr.OtherTypeName)); } } else { throw new Exception( string.Format( "Property '{1}.{0}' is set as 'Other' umbraco data type but 'OtherTypeName' on that property is empty. Please set 'OtherTypeName' on property '{1}.{0}'.", propInfo.Name, typeContentType.Name)); } } else { dataTypeDefinition = DataTypeDefinition.GetDataTypeDefinition((int)propAttr.Type); } return dataTypeDefinition; }
internal static object GetPropertyValue(Node sourceNode, PropertyInfo propInfo, DocumentTypePropertyAttribute propAttr) { string propertyName; string propertyAlias; object value = null; if (propAttr == null) { propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); } DocumentTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); var property = sourceNode.GetProperty(propertyAlias); if (property == null) { value = null; } else if (propInfo.PropertyType.Equals(typeof(Boolean))) { if (String.IsNullOrEmpty(property.Value) || property.Value == "0") { value = false; } else { value = true; } } else if (propAttr.CustomTypeConverter != null) { value = ((ICustomTypeConvertor)Activator.Current.GetInstance(propAttr.CustomTypeConverter)).ConvertValueWhenRead(property.Value); } else if (ContentHelper.PropertyConvertors.ContainsKey(propInfo.PropertyType)) { // will be transformed later. TODO: move transformation here //value = ContentHelper.GetInnerXml(node.Id.ToString(), propertyAlias); value = PropertyConvertors[propInfo.PropertyType].ConvertValueWhenRead(property.Value); } else if (String.IsNullOrEmpty(property.Value)) { // if property type is string or if it's some custom type, try to get the inner xml of this property within a node. if (propInfo.PropertyType == typeof(string) || ContentHelper.PropertyConvertors.ContainsKey(propInfo.PropertyType)) { value = ContentHelper.GetInnerXml(sourceNode.Id.ToString(), propertyAlias); if (value == null && propInfo.PropertyType == typeof(string)) { value = string.Empty; } } else { value = null; } } else if (propInfo.PropertyType.IsGenericType && propInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { value = Convert.ChangeType(property.Value, Nullable.GetUnderlyingType(propInfo.PropertyType)); // TODO: If data type is DateTime and is nullable and is less than 1.1.1000 than set it to NULL } else if (propInfo.PropertyType.Equals(typeof(HtmlString))) { value = new HtmlString(property.Value); } else { value = Convert.ChangeType(property.Value, propInfo.PropertyType); } return(value); }
internal static object GetPropertyValue(DocumentTypeBase entity, PropertyInfo propInfo, DocumentTypePropertyAttribute propAttr) { return(GetPropertyValue(entity.Source, propInfo, propAttr)); }
private void SynchronizeMemberTypeProperties(Type typeMemberType, MemberType memberType) { int propertySortOrder = 0; foreach (PropertyInfo propInfo in typeMemberType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a document type } // getting name and alias string propertyName; string propertyAlias; DocumentTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); if (HasObsoleteAttribute(propInfo)) { Util.DeletePropertyType(memberType, propertyAlias); continue; } if (propAttr.DefaultValue != null) { _hadDefaultValues = true; // at least one property has a default value } umbraco.cms.businesslogic.datatype.DataTypeDefinition dataTypeDefinition = GetDataTypeDefinition(typeMemberType, propAttr, propInfo); // getting property if already exists, or creating new if it not exists umbraco.cms.businesslogic.propertytype.PropertyType propertyType = memberType.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias); if (propertyType == null) // if not exists, create it { memberType.AddPropertyType(dataTypeDefinition, propertyAlias, propertyName); propertyType = memberType.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias); } //// Setting up the tab of this property. If tab doesn't exists, create it. if (!string.IsNullOrEmpty(propAttr.TabAsString) && propAttr.TabAsString.ToLower() != DocumentTypeDefaultValues.TabGenericProperties.ToLower()) { // try to find this tab umbraco.cms.businesslogic.propertytype.PropertyTypeGroup pg = memberType.PropertyTypeGroups.FirstOrDefault(x => x.Name == propAttr.TabAsString); if (pg == null) // if found { memberType.AddVirtualTab(propAttr.TabAsString); pg = memberType.PropertyTypeGroups.FirstOrDefault(x => x.Name == propAttr.TabAsString); } if (propAttr.TabOrder.HasValue) { pg.SortOrder = propAttr.TabOrder.Value; } propertyType.PropertyTypeGroup = pg.Id; } propertyType.Name = propertyName; propertyType.Mandatory = propAttr.Mandatory; propertyType.ValidationRegExp = propAttr.ValidationRegExp; propertyType.Description = propAttr.Description; propertyType.SortOrder = propertySortOrder; propertySortOrder++; } }
public static void ReadProperties(Type contentType, Content content, object output) { foreach (PropertyInfo propInfo in contentType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { DocumentTypePropertyAttribute propAttr = Util.GetAttribute <DocumentTypePropertyAttribute>(propInfo); if (propAttr == null) { continue; // skip this property - not part of a Document Type } string propertyName; string propertyAlias; DocumentTypeManager.ReadPropertyNameAndAlias(propInfo, propAttr, out propertyName, out propertyAlias); umbraco.cms.businesslogic.property.Property property = content.getProperty(propertyAlias); object value = null; try { if (property == null) { value = null; } else if (propInfo.PropertyType.Equals(typeof(System.Boolean))) { if (String.IsNullOrEmpty(Convert.ToString(property.Value)) || Convert.ToString(property.Value) == "0") { value = false; } else { value = true; } } else if (PropertyConvertors.ContainsKey(propInfo.PropertyType)) { value = ContentUtil.GetInnerXml(content.Id.ToString(), propertyAlias); } else if (String.IsNullOrEmpty(Convert.ToString(property.Value))) { // if property type is string or if it's some custom type, try to get the inner xml of this property within a node. if (propInfo.PropertyType == typeof(string) || PropertyConvertors.ContainsKey(propInfo.PropertyType)) { value = ContentUtil.GetInnerXml(content.Id.ToString(), propertyAlias); if (value == null && propInfo.PropertyType == typeof(string)) { value = string.Empty; } } else { value = null; } } else if (propInfo.PropertyType.IsGenericType && propInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { value = Convert.ChangeType(property.Value, Nullable.GetUnderlyingType(propInfo.PropertyType)); // TODO: If data type is DateTime and is nullable and is less than 1.1.1000 than set it to NULL } else { value = Convert.ChangeType(property.Value, propInfo.PropertyType); } if (PropertyConvertors.ContainsKey(propInfo.PropertyType)) { value = PropertyConvertors[propInfo.PropertyType].ConvertValueWhenRead(value); } propInfo.SetValue(output, value, null); } catch (Exception exc) { throw new Exception(string.Format("Cannot set the value of a document type property {0}.{1} (document type: {2}) to value: '{3}' (value type: {4}). Error: {5}", contentType.Name, propInfo.Name, propInfo.PropertyType.FullName, value, value != null ? value.GetType().FullName : "", exc.Message)); } } }