示例#1
0
        /// <summary>
        /// Determines whether [is view in filter] [the specified data view id].
        /// </summary>
        /// <param name="dataViewId">The data view id.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>
        ///   <c>true</c> if [is view in filter] [the specified data view id]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsViewInFilter(int dataViewId, Rock.Model.DataViewFilter filter)
        {
            if (filter.EntityTypeId.HasValue)
            {
                var entityType = EntityTypeCache.Get(filter.EntityTypeId.Value);
                var component  = Rock.Reporting.DataFilterContainer.GetComponent(entityType.Name);
                if (component is OtherDataViewFilter otherDataViewFilter)
                {
                    var otherDataView = otherDataViewFilter.GetSelectedDataView(filter.Selection);
                    if (otherDataView.Id == dataViewId)
                    {
                        // if we discover that this DataView is also used in one of its child views, we've got infinite recursion
                        return(true);
                    }
                    else
                    {
                        // dig down recursively thru the *other* DataView's child filters to see if any of it's child filters is using this dataview
                        return(IsViewInFilter(dataViewId, otherDataView.DataViewFilter));
                    }
                }
            }

            foreach (var childFilter in filter.ChildFilters)
            {
                // dig down recursively thru *this* DataView's child filters
                if (IsViewInFilter(dataViewId, childFilter))
                {
                    return(true);
                }
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Reset all of the identifiers on a DataViewFilter that uniquely identify it in the permanent store.
        /// </summary>
        /// <param name="filter">The data view filter.</param>
        private void ResetPermanentStoreIdentifiers(DataViewFilter filter)
        {
            if (filter == null)
            {
                return;
            }

            filter.Id          = 0;
            filter.Guid        = Guid.NewGuid();
            filter.ForeignId   = null;
            filter.ForeignGuid = null;
            filter.ForeignKey  = null;

            // Recursively reset any contained filters.
            foreach (var childFilter in filter.ChildFilters)
            {
                this.ResetPermanentStoreIdentifiers(childFilter);
            }
        }
示例#3
0
        /// <summary>
        /// Determines whether [is view in filter] [the specified data view id].
        /// </summary>
        /// <param name="dataViewId">The data view id.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>
        ///   <c>true</c> if [is view in filter] [the specified data view id]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsViewInFilter(int dataViewId, Rock.Model.DataViewFilter filter)
        {
            if (filter.EntityTypeId == EntityTypeCache.Read(this.GetType()).Id)
            {
                int?filterDataViewId = filter.Selection.AsIntegerOrNull();
                if (filterDataViewId.HasValue)
                {
                    if (filterDataViewId == dataViewId)
                    {
                        return(true);
                    }
                }
            }

            foreach (var childFilter in filter.ChildFilters)
            {
                if (IsViewInFilter(dataViewId, childFilter))
                {
                    return(true);
                }
            }

            return(false);
        }
示例#4
0
        /// <summary>
        /// Determines whether [is view in filter] [the specified data view id].
        /// </summary>
        /// <param name="dataViewId">The data view id.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>
        ///   <c>true</c> if [is view in filter] [the specified data view id]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsViewInFilter(int dataViewId, Rock.Model.DataViewFilter filter)
        {
            if (filter.EntityTypeId == EntityTypeCache.Read(this.GetType()).Id)
            {
                int filterDataViewId = int.MinValue;
                if (int.TryParse(filter.Selection, out filterDataViewId))
                {
                    if (filterDataViewId == dataViewId)
                    {
                        return(true);
                    }
                }
            }

            foreach (var childFilter in filter.ChildFilters)
            {
                if (IsViewInFilter(dataViewId, childFilter))
                {
                    return(true);
                }
            }

            return(false);
        }
示例#5
0
        /// <summary>
        /// Determines whether the specified Data View forms part of a filter.
        /// </summary>
        /// <param name="dataViewId">The unique identifier of a Data View.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>
        ///   <c>true</c> if the specified Data View forms part of the conditions for the specified filter.
        /// </returns>
        public bool IsViewInFilter(int dataViewId, DataViewFilter filter)
        {
            var dataViewFilterEntityId = new EntityTypeService(( RockContext )this.Context).Get(typeof(OtherDataViewFilter), false, null).Id;

            return(IsViewInFilter(dataViewId, filter, dataViewFilterEntityId));
        }
示例#6
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <returns></returns>
        /// <exception cref="Rock.Reporting.RockReportingException">
        /// Unable to determine Assembly for EntityTypeId { EntityTypeId }
        /// or
        /// Unable to determine DataView EntityType for { dataViewEntityTypeCache }.
        /// or
        /// Unable to determine transform expression for TransformEntityTypeId: {TransformEntityTypeId}
        /// </exception>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides)
        {
            var dataViewEntityTypeCache = EntityTypeCache.Get(EntityTypeId.Value);

            if (dataViewEntityTypeCache?.AssemblyName == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine DataView Assembly for EntityTypeId { EntityTypeId }");
            }

            Type dataViewEntityTypeType = dataViewEntityTypeCache.GetEntityType();

            if (dataViewEntityTypeType == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine DataView EntityType for { dataViewEntityTypeCache }.");
            }

            // DataViews must have a DataViewFilter (something has gone wrong it doesn't have one)
            // Note that DataViewFilterId might be null even though DataViewFilter is not null
            // This is because the DataViewFilter might be just in memory and not saved to the database (for example, a Preview or a DynamicReport)
            if (this.DataViewFilter == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"DataViewFilter is null for DataView { this.Name } ({this.Id}).");
            }

            bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;

            if (dataViewFilterOverrides != null)
            {
                // don't use persisted values if this DataView in the list of DataViews that should not be persisted due to override
                usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
            }

            // If dataViewFilterOverrides is null assume true in order to preserve current functionality.
            RockLogger.Log.Debug(RockLogDomains.Reporting, "{methodName} dataViewFilterOverrides: {@dataViewFilterOverrides} DataviewId: {DataviewId}", nameof(GetExpression), dataViewFilterOverrides, DataViewFilter.DataViewId);
            if (dataViewFilterOverrides == null || dataViewFilterOverrides.ShouldUpdateStatics)
            {
                DataViewService.AddRunDataViewTransaction(Id);
            }

            // We need to call GetExpression regardless of whether or not usePresistedValues is true so the child queries get their stats updated.
            var filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(dataViewEntityTypeType, serviceInstance, paramExpression, dataViewFilterOverrides) : null;

            if (usePersistedValues)
            {
                // If this is a persisted DataView, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                var rockContext = serviceInstance.Context as RockContext;
                if (rockContext == null)
                {
                    rockContext = new RockContext();
                }

                var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                var ids = persistedValuesQuery.Select(v => v.EntityId);
                MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                if (!(serviceInstance.Context is RockContext))
                {
                    // if this DataView doesn't use a RockContext get the EntityIds into memory as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                    ids = ids.ToList().AsQueryable();
                }

                var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                return(expression);
            }
            else
            {
                if (dataViewEntityTypeCache.Id == EntityTypeCache.Get(typeof(Rock.Model.Person)).Id)
                {
                    var        qry = new PersonService(( RockContext )serviceInstance.Context).Queryable(this.IncludeDeceased);
                    Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, paramExpression, "p");
                    if (filterExpression == null)
                    {
                        filterExpression = extractedFilterExpression;
                    }
                    else
                    {
                        filterExpression = Expression.AndAlso(filterExpression, extractedFilterExpression);
                    }
                }

                if (this.TransformEntityTypeId.HasValue)
                {
                    Expression transformedExpression = GetTransformExpression(this.TransformEntityTypeId.Value, serviceInstance, paramExpression, filterExpression);
                    if (transformedExpression == null)
                    {
                        // if TransformEntityTypeId is defined, but we got null back, we'll get unexpected results, so throw an exception
                        throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine transform expression for TransformEntityTypeId: {TransformEntityTypeId}");
                    }

                    return(transformedExpression);
                }

                return(filterExpression);
            }
        }
示例#7
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var cachedEntityType = EntityTypeCache.Get(EntityTypeId.Value);

            if (cachedEntityType?.AssemblyName == null)
            {
                return(null);
            }

            Type filteredEntityType = cachedEntityType.GetEntityType();

            if (filteredEntityType == null)
            {
                return(null);
            }

            bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;

            if (dataViewFilterOverrides != null)
            {
                // don't use persisted values if this dataview is in the list of dataviews that should not be persisted due to override
                usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
            }

            DataViewService.AddRunDataViewTransaction(Id);

            if (usePersistedValues)
            {
                // If this is a persisted dataview, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                var rockContext = serviceInstance.Context as RockContext;
                if (rockContext == null)
                {
                    rockContext = new RockContext();
                }

                var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                var ids = persistedValuesQuery.Select(v => v.EntityId);
                MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                if (!(serviceInstance.Context is RockContext))
                {
                    // if this DataView doesn't use a RockContext get the EntityIds into memory as as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                    ids = ids.ToList().AsQueryable();
                }

                var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                return(expression);
            }
            else
            {
                Expression filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(filteredEntityType, serviceInstance, paramExpression, dataViewFilterOverrides, errorMessages) : null;

                if (cachedEntityType.Id == EntityTypeCache.Get(typeof(Rock.Model.Person)).Id)
                {
                    var        qry = new PersonService(( RockContext )serviceInstance.Context).Queryable(this.IncludeDeceased);
                    Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, paramExpression, "p");
                    if (filterExpression == null)
                    {
                        filterExpression = extractedFilterExpression;
                    }
                    else
                    {
                        filterExpression = Expression.AndAlso(filterExpression, extractedFilterExpression);
                    }
                }

                Expression transformedExpression = GetTransformExpression(serviceInstance, paramExpression, filterExpression, errorMessages);
                if (transformedExpression != null)
                {
                    return(transformedExpression);
                }

                return(filterExpression);
            }
        }
示例#8
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var cachedEntityType = EntityTypeCache.Get(EntityTypeId.Value);

            if (cachedEntityType != null && cachedEntityType.AssemblyName != null)
            {
                Type filteredEntityType = cachedEntityType.GetEntityType();

                if (filteredEntityType != null)
                {
                    bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;
                    if (dataViewFilterOverrides != null)
                    {
                        usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
                    }

                    // don't use persisted values if there are dataViewFilterOverrides
                    if (usePersistedValues && dataViewFilterOverrides?.Any() == true)
                    {
                        usePersistedValues = false;
                    }

                    if (usePersistedValues)
                    {
                        // If this is a persisted dataview, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                        var rockContext = serviceInstance.Context as RockContext;
                        if (rockContext == null)
                        {
                            rockContext = new RockContext();
                        }

                        var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                        var ids = persistedValuesQuery.Select(v => v.EntityId);
                        MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                        if (!(serviceInstance.Context is RockContext))
                        {
                            // if this DataView doesn't use a RockContext get the EntityIds into memory as as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                            ids = ids.ToList().AsQueryable();
                        }

                        var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                        Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                        return(expression);
                    }
                    else
                    {
                        Expression filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(filteredEntityType, serviceInstance, paramExpression, dataViewFilterOverrides, errorMessages) : null;

                        Expression transformedExpression = GetTransformExpression(serviceInstance, paramExpression, filterExpression, errorMessages);
                        if (transformedExpression != null)
                        {
                            return(transformedExpression);
                        }

                        return(filterExpression);
                    }
                }
            }

            return(null);
        }
示例#9
0
        /// <summary>
        /// Determines whether the specified Data View forms part of a filter.
        /// </summary>
        /// <param name="dataViewId">The unique identifier of a Data View.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>
        ///   <c>true</c> if the specified Data View forms part of the conditions for the specified filter.
        /// </returns>
        public bool IsViewInFilter(int dataViewId, DataViewFilter filter)
        {
            var dataView = Get(dataViewId);

            return(IsViewInFilter(dataView, filter));
        }