/// <summary> /// Gets the entity fields for a specific Entity /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="entity">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> private static List <EntityField> GetEntityFields(Type entityType, IEntity entity, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true) { List <EntityField> entityFields = null; _workflowTypeNameLookup = null; _entityFieldsLookup = _entityFieldsLookup ?? new Dictionary <string, List <EntityField> >(); entityFields = _entityFieldsLookup.GetValueOrNull(EntityHelper.GetCacheKey(entityType, entity, includeOnlyReportingFields, limitToFilterableFields)); if (entityFields != null) { return(entityFields); } if (entityFields == null) { entityFields = new List <EntityField>(); } List <PropertyInfo> entityProperties = entityType.GetProperties().ToList(); // filter the properties to narrow down the ones that we want to include in EntityFields var filteredEntityProperties = entityProperties .Where((p) => { var includeForReportingAttribute = p.GetCustomAttribute <IncludeForReportingAttribute>() != null; // if the property has an IncludeForReportingAttribute, include it regardless if (includeForReportingAttribute) { return(true); } bool hideFromReporting = false; if (includeOnlyReportingFields) { hideFromReporting = p.GetCustomAttribute <HideFromReportingAttribute>() != null; } // if the property should be hidden from reporting, don't show it if (hideFromReporting) { return(false); } bool isMappedDatabaseField = Reflection.IsMappedDatabaseProperty(p); if (!isMappedDatabaseField) { return(false); } return(true); }).ToList(); // Go thru filteredEntityProperties and create the list of EntityFields that we can include foreach (var property in filteredEntityProperties) { 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)) { // intentionally blank, entity field is already setup } // Enum Properties else if (property.PropertyType.IsEnum) { entityField.FieldType = FieldTypeCache.Get(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.Get(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.Get(SystemGuid.FieldType.DATE.AsGuid()); } else { entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DATE_TIME.AsGuid()); } } // Decimal properties else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal? )) { entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.DECIMAL.AsGuid()); } // Text Properties else if (property.PropertyType == typeof(string)) { entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.TEXT.AsGuid()); } // Integer Properties (which may be a DefinedValue) else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?)) { entityField.FieldType = FieldTypeCache.Get(SystemGuid.FieldType.INTEGER.AsGuid()); var definedValueAttribute = property.GetCustomAttribute <Rock.Data.DefinedValueAttribute>(); if (definedValueAttribute != null) { // Defined Value Properties Guid?definedTypeGuid = definedValueAttribute.DefinedTypeGuid; if (definedTypeGuid.HasValue) { var definedType = DefinedTypeCache.Get(definedTypeGuid.Value); entityField.Title = definedType != null ? definedType.Name : property.Name.Replace("ValueId", string.Empty).SplitCase(); if (definedType != null) { entityField.FieldType = FieldTypeCache.Get(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.Get(entityType, true); if (entityTypeCache != null) { int entityTypeId = entityTypeCache.Id; List <AttributeCache> cacheAttributeList; if (entity != null) { // if a specific entity is set, we only need to get the Attributes that the Entity has if (entity is IHasAttributes) { (entity as IHasAttributes).LoadAttributes(); cacheAttributeList = (entity as IHasAttributes).Attributes.Select(a => a.Value).ToList(); } else { cacheAttributeList = new List <AttributeCache>(); } } else { using (var rockContext = new RockContext()) { var qryAttributes = new AttributeService(rockContext).GetByEntityTypeId(entityTypeId); if (entityType == typeof(Group) || entityType == typeof(GroupMember)) { // in the case of Group or GroupMember, 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(ConnectionRequest)) { // in the case of Connection Requests, show attributes that are entity global, but also ones that are qualified by ConnectionOpportunityId qryAttributes = qryAttributes .Where(a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || a.EntityTypeQualifierColumn == "ConnectionOpportunityId" ); } else if (entityType == typeof(Registration)) { // in the case of Registrations, show attributes that are entity global, but also ones that are qualified by RegistrationTemplateId qryAttributes = qryAttributes .Where(a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || a.EntityTypeQualifierColumn == "RegistrationTemplateId" ); } else if (entityType == typeof(ContentChannelItem)) { // in the case of ContentChannelItem, show attributes that are entity global, but also ones that are qualified by ContentChannelTypeId or ContentChannelId qryAttributes = qryAttributes .Where(a => a.EntityTypeQualifierColumn == null || a.EntityTypeQualifierColumn == string.Empty || a.EntityTypeQualifierColumn == "ContentChannelTypeId" || a.EntityTypeQualifierColumn == "ContentChannelId" ); } 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 => string.IsNullOrEmpty(a.EntityTypeQualifierColumn) && string.IsNullOrEmpty(a.EntityTypeQualifierValue)); } cacheAttributeList = qryAttributes.ToAttributeCacheList(); } } EntityHelper.AddEntityFieldsForAttributeList(entityFields, cacheAttributeList); } // 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); } _entityFieldsLookup.AddOrReplace(EntityHelper.GetCacheKey(entityType, entity, includeOnlyReportingFields, limitToFilterableFields), sortedFields); return(sortedFields); }
/// <summary> /// Gets the filter list recursive. /// </summary> /// <param name="filterList">The filter list.</param> /// <param name="filter">The filter.</param> /// <param name="reportEntityType">Type of the report entity.</param> private static void GetFilterListRecursive(List <FilterInfo> filterList, DataViewFilter filter, EntityType reportEntityType) { var result = new Dictionary <Guid, string>(); var entityType = EntityTypeCache.Get(filter.EntityTypeId ?? 0); var reportEntityTypeCache = EntityTypeCache.Get(reportEntityType); var reportEntityTypeModel = reportEntityTypeCache.GetEntityType(); var filterInfo = new FilterInfo(filter); filterInfo.FilterList = filterList; if (entityType != null) { var component = Rock.Reporting.DataFilterContainer.GetComponent(entityType.Name); filterInfo.Component = component; filterInfo.ReportEntityTypeModel = reportEntityTypeModel; if (component != null) { if (component is Rock.Reporting.DataFilter.EntityFieldFilter) { var entityFieldFilter = component as Rock.Reporting.DataFilter.EntityFieldFilter; var fieldName = entityFieldFilter.GetSelectedFieldName(filter.Selection); if (!string.IsNullOrWhiteSpace(fieldName)) { var entityFields = EntityHelper.GetEntityFields(reportEntityTypeModel); var entityField = entityFields.Where(a => a.Name == fieldName).FirstOrDefault(); if (entityField != null) { filterInfo.Title = entityField.Title; } else { filterInfo.Title = fieldName; } } } else { filterInfo.Title = component.GetTitle(reportEntityType.GetType()); } } } filterList.Add(filterInfo); if (filterInfo.Component is Rock.Reporting.DataFilter.OtherDataViewFilter) { Rock.Reporting.DataFilter.OtherDataViewFilter otherDataViewFilter = filterInfo.Component as Rock.Reporting.DataFilter.OtherDataViewFilter; var otherDataView = otherDataViewFilter.GetSelectedDataView(filterInfo.Selection); if (otherDataView != null) { var otherDataViewFilterList = new List <FilterInfo>(); GetFilterListRecursive(otherDataViewFilterList, otherDataView.DataViewFilter, reportEntityType); foreach (var otherFilter in otherDataViewFilterList) { if (otherFilter.FromOtherDataView == null) { otherFilter.FromOtherDataView = otherDataView.Name; } } filterList.AddRange(otherDataViewFilterList); } } foreach (var childFilter in filter.ChildFilters) { GetFilterListRecursive(filterList, childFilter, reportEntityType); } }
/// <summary> /// Finds from field selection in a way that is backwards compatible with filters saved using pre-v1.7 and pre-v1.1 versions of Rock /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="fieldSelection">The field selection.</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 EntityField FindFromFilterSelection(Type entityType, string fieldSelection, bool includeOnlyReportingFields = true, bool limitToFilterableFields = true) { var entityFields = EntityHelper.GetEntityFields(entityType, includeOnlyReportingFields, limitToFilterableFields); return(entityFields.FindFromFilterSelection(fieldSelection)); }