/// <summary> /// Gets the entity fields. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="includeOnlyReportingFields">if set to <c>true</c> [include only reporting fields].</param> /// <param name="limitToFilterableFields">if set to <c>true</c> [limit to filterable fields].</param> /// <returns></returns> public static List<EntityField> GetEntityFields( Type entityType, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true ) { List<EntityField> entityFields = null; _workflowTypeNameLookup = null; if ( HttpContext.Current != null ) { entityFields = HttpContext.Current.Items[EntityHelper.GetCacheKey(entityType, includeOnlyReportingFields, limitToFilterableFields)] as List<EntityField>; if ( entityFields != null ) { return entityFields; } } if ( entityFields == null ) { entityFields = new List<EntityField>(); } // Find all non-virtual properties or properties that have the [IncludeForReporting] attribute var entityProperties = entityType.GetProperties().ToList(); var filteredEntityProperties = entityProperties .Where( p => !p.GetGetMethod().IsVirtual || p.GetCustomAttributes( typeof( IncludeForReportingAttribute ), true ).Any() || p.Name == "Order" ) .ToList(); // Get Properties foreach ( var property in filteredEntityProperties ) { bool isReportable = !property.GetCustomAttributes( typeof( HideFromReportingAttribute ), true ).Any(); if ( !includeOnlyReportingFields || isReportable ) { EntityField entityField = new EntityField( property.Name, FieldKind.Property, property ); entityField.IsPreviewable = property.GetCustomAttributes( typeof( PreviewableAttribute ), true ).Any(); var fieldTypeAttribute = property.GetCustomAttribute<Rock.Data.FieldTypeAttribute>(); // check if we can set it from the fieldTypeAttribute if ( ( fieldTypeAttribute != null ) && SetEntityFieldFromFieldTypeAttribute( entityField, fieldTypeAttribute ) ) { // intentially blank, entity field is already setup } // Enum Properties else if ( property.PropertyType.IsEnum ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.SINGLE_SELECT.AsGuid() ); var list = new List<string>(); foreach ( var value in Enum.GetValues( property.PropertyType ) ) { list.Add( string.Format( "{0}^{1}", value, value.ToString().SplitCase() ) ); } var listSource = string.Join( ",", list ); entityField.FieldConfig.Add( "values", new Field.ConfigurationValue( listSource ) ); entityField.FieldConfig.Add( "fieldtype", new Field.ConfigurationValue( "rb" ) ); } // Boolean properties else if ( property.PropertyType == typeof( bool ) || property.PropertyType == typeof( bool? ) ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.BOOLEAN.AsGuid() ); } // Datetime properties else if ( property.PropertyType == typeof( DateTime ) || property.PropertyType == typeof( DateTime? ) ) { var colAttr = property.GetCustomAttributes( typeof( ColumnAttribute ), true ).FirstOrDefault(); if ( colAttr != null && ( (ColumnAttribute)colAttr ).TypeName == "Date" ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.DATE.AsGuid() ); } else { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.DATE_TIME.AsGuid() ); } } // Decimal properties else if ( property.PropertyType == typeof( decimal ) || property.PropertyType == typeof( decimal? ) ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.DECIMAL.AsGuid() ); } // Text Properties else if ( property.PropertyType == typeof( string ) ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.TEXT.AsGuid() ); } // Integer Properties (which may be a DefinedValue) else if ( property.PropertyType == typeof( int ) || property.PropertyType == typeof( int? ) ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.INTEGER.AsGuid() ); var definedValueAttribute = property.GetCustomAttribute<Rock.Data.DefinedValueAttribute>(); if ( definedValueAttribute != null ) { // Defined Value Properties Guid? definedTypeGuid = ( (Rock.Data.DefinedValueAttribute)definedValueAttribute ).DefinedTypeGuid; if ( definedTypeGuid.HasValue ) { var definedType = DefinedTypeCache.Read( definedTypeGuid.Value ); entityField.Title = definedType != null ? definedType.Name : property.Name.Replace( "ValueId", string.Empty ).SplitCase(); if ( definedType != null ) { entityField.FieldType = FieldTypeCache.Read( SystemGuid.FieldType.DEFINED_VALUE.AsGuid() ); entityField.FieldConfig.Add( "definedtype", new Field.ConfigurationValue( definedType.Id.ToString() ) ); } } } } if ( entityField != null && entityField.FieldType != null ) { entityFields.Add( entityField ); } } } // Get Attributes var entityTypeCache = EntityTypeCache.Read( entityType, true ); if ( entityTypeCache != null ) { int entityTypeId = entityTypeCache.Id; using ( var rockContext = new RockContext() ) { var qryAttributes = new AttributeService( rockContext ).Queryable().Where( a => a.EntityTypeId == entityTypeId ); if ( entityType == typeof( Group ) ) { // in the case of Group, show attributes that are entity global, but also ones that are qualified by GroupTypeId qryAttributes = qryAttributes .Where( a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || a.EntityTypeQualifierColumn == "GroupTypeId" ); } else if ( entityType == typeof( ContentChannelItem ) ) { // in the case of ContentChannelItem, show attributes that are entity global, but also ones that are qualified by ContentChannelTypeId qryAttributes = qryAttributes .Where( a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || a.EntityTypeQualifierColumn == "ContentChannelTypeId" ); } else if ( entityType == typeof( Rock.Model.Workflow ) ) { // in the case of Workflow, show attributes that are entity global, but also ones that are qualified by WorkflowTypeId (and have a valid WorkflowTypeId) var validWorkflowTypeIds = new WorkflowTypeService(rockContext).Queryable().Select(a=> a.Id).ToList().Select(a => a.ToString()).ToList(); qryAttributes = qryAttributes .Where( a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || (a.EntityTypeQualifierColumn == "WorkflowTypeId" && validWorkflowTypeIds.Contains(a.EntityTypeQualifierValue) )); } else { qryAttributes = qryAttributes.Where( a => a.EntityTypeQualifierColumn == string.Empty && a.EntityTypeQualifierValue == string.Empty ); } var attributeIdList = qryAttributes.Select( a => a.Id ).ToList(); foreach ( var attributeId in attributeIdList ) { AddEntityFieldForAttribute( entityFields, AttributeCache.Read( attributeId ), limitToFilterableFields ); } } } // Order the fields by title, name int index = 0; var sortedFields = new List<EntityField>(); foreach ( var entityField in entityFields.OrderBy( p => !string.IsNullOrEmpty(p.AttributeEntityTypeQualifierName)).ThenBy( p => p.Title ).ThenBy( p => p.Name ) ) { entityField.Index = index; index++; sortedFields.Add( entityField ); } if ( HttpContext.Current != null ) { HttpContext.Current.Items[EntityHelper.GetCacheKey( entityType, includeOnlyReportingFields, limitToFilterableFields )] = sortedFields; } return sortedFields; }