示例#1
0
        /// <summary>
        /// Determines if the category has any child categories or items.
        /// </summary>
        /// <param name="options">The options that describe the current operation.</param>
        /// <param name="categoryService">The category service.</param>
        /// <param name="serviceInstance">The service instance used to access the items.</param>
        /// <param name="categoryId">The category item identifier.</param>
        /// <returns><c>true</c> if the category has children, <c>false</c> otherwise.</returns>
        private bool DoesCategoryHaveChildren(CategoryItemTreeOptions options, CategoryService categoryService, IService serviceInstance, string categoryId)
        {
            var parentGuid = categoryId.AsGuid();

            // First try a simple query on categories. This is the cheaper
            // of the two operations.
            foreach (var childCategory in categoryService.Queryable().Where(c => c.ParentCategory.Guid == parentGuid))
            {
                if (childCategory.IsAuthorized(Authorization.VIEW, Person))
                {
                    return(true);
                }
            }

            // If we didn't find any children from the above then try looking
            // for any items that reference this category.

            var itemOptions = new CategorizedItemQueryOptions
            {
                CategoryGuid              = parentGuid,
                IncludeInactiveItems      = options.IncludeInactiveItems,
                IncludeUnnamedEntityItems = options.IncludeUnnamedEntityItems,
                ItemFilterPropertyName    = options.ItemFilterPropertyName,
                ItemFilterPropertyValue   = options.ItemFilterPropertyValue
            };

            var childItems = categoryService.GetCategorizedItemQuery(serviceInstance, itemOptions);

            if (childItems != null)
            {
                foreach (var categorizedItem in childItems)
                {
                    if (categorizedItem != null && categorizedItem.IsAuthorized(Authorization.VIEW, Person))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Gets the categorized item query that matches the options.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="options">The options that describe the current operation.</param>
        /// <returns>A queryable of items in this category.</returns>
        public IQueryable <ICategorized> GetCategorizedItemQuery(IService serviceInstance, CategorizedItemQueryOptions options)
        {
            options = options ?? DefaultCategorizedItemQueryOptions;

            if (serviceInstance != null)
            {
                var getMethod = serviceInstance.GetType()
                                .GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression) });

                if (getMethod != null)
                {
                    var paramExpression = serviceInstance.ParameterExpression;
                    BinaryExpression whereExpression;

                    // Build the expression that checks the categoryGuid value for
                    // a match.
                    var categoryPropertyExpression     = Expression.Property(paramExpression, "Category");
                    var categoryGuidPropertyExpression = Expression.Property(categoryPropertyExpression, "Guid");

                    if (options.CategoryGuid.HasValue)
                    {
                        var categoryConstantExpression = Expression.Constant(options.CategoryGuid);
                        whereExpression = Expression.Equal(categoryGuidPropertyExpression, categoryConstantExpression);
                    }
                    else
                    {
                        var categoryIdPropertyExpression = Expression.Property(paramExpression, "CategoryId");
                        var nullConstant = Expression.Constant(null, typeof(int?));

                        whereExpression = Expression.Equal(categoryIdPropertyExpression, nullConstant);
                    }

                    // Exclude any inactive items. This value is only set if we
                    // have already determined that the entity has an IsActive
                    // property to query.
                    if (!options.IncludeInactiveItems && typeof(IHasActiveFlag).IsAssignableFrom(paramExpression.Type))
                    {
                        var isActivePropertyExpression = Expression.Property(paramExpression, "IsActive");
                        var isActiveConstantExpression = Expression.Convert(Expression.Constant(true), isActivePropertyExpression.Type);
                        var isActiveExpression         = Expression.Equal(isActivePropertyExpression, isActiveConstantExpression);
                        whereExpression = Expression.And(whereExpression, isActiveExpression);
                    }

                    // Custom filtering based on property names and values provided
                    // by the caller.
                    if (!string.IsNullOrEmpty(options.ItemFilterPropertyName))
                    {
                        var itemFilterPropertyNameExpression = Expression.Property(paramExpression, options.ItemFilterPropertyName);
                        ConstantExpression itemFilterPropertyValueExpression;

                        // Special checks for integer and Guid values supplied
                        // by the caller. Otherwise treat it as a string.
                        if (itemFilterPropertyNameExpression.Type == typeof(int?) || itemFilterPropertyNameExpression.Type == typeof(int))
                        {
                            itemFilterPropertyValueExpression = Expression.Constant(options.ItemFilterPropertyValue.AsIntegerOrNull(), typeof(int?));
                        }
                        else if (itemFilterPropertyNameExpression.Type == typeof(Guid? ) || itemFilterPropertyNameExpression.Type == typeof(Guid))
                        {
                            itemFilterPropertyValueExpression = Expression.Constant(options.ItemFilterPropertyValue.AsGuidOrNull(), typeof(Guid? ));
                        }
                        else
                        {
                            itemFilterPropertyValueExpression = Expression.Constant(options.ItemFilterPropertyValue);
                        }

                        // Build the comparison as a standard equality check.
                        var binaryExpression = Expression.Equal(itemFilterPropertyNameExpression, itemFilterPropertyValueExpression);

                        whereExpression = Expression.And(whereExpression, binaryExpression);
                    }

                    var result = getMethod.Invoke(serviceInstance, new object[] { paramExpression, whereExpression }) as IQueryable <ICategorized>;

                    // If they don't want to include entities without a name
                    // then exclude them from the results.
                    if (!options.IncludeUnnamedEntityItems)
                    {
                        result = result.Where(a => a.Name != null && a.Name != string.Empty);
                    }

                    return(result);
                }
            }

            return(null);
        }
示例#3
0
        /// <summary>
        /// Gets the categorized tree items. This supports various options
        /// for filtering and determine how much data to load.
        /// </summary>
        /// <param name="options">The options that describe the request.</param>
        /// <returns>A list of view models that describe the tree of categories and items.</returns>
        public List <TreeItemViewModel> GetCategorizedTreeItems(CategoryItemTreeOptions options = null)
        {
            options = options ?? DefaultCategoryItemTreeOptions;

            // Initialize the basic query.
            var categoryService = new CategoryService(RockContext);

            var childQueryOptions = new ChildCategoryQueryOptions
            {
                ParentGuid                = options.ParentGuid,
                EntityTypeGuid            = options.EntityTypeGuid,
                IncludeCategoryGuids      = options.IncludeCategoryGuids,
                ExcludeCategoryGuids      = options.ExcludeCategoryGuids,
                EntityTypeQualifierColumn = options.EntityTypeQualifierColumn,
                EntityTypeQualifierValue  = options.EntityTypeQualifierValue
            };

            var qry = categoryService.GetChildCategoryQuery(childQueryOptions);

            // Cache the service instance for later use. If we have specified an
            // entity type then this ends up getting set.
            IService serviceInstance  = null;
            var      cachedEntityType = options.EntityTypeGuid.HasValue
                ? EntityTypeCache.Get(options.EntityTypeGuid.Value)
                : null;

            // If we have been requested to limit the results to a specific entity
            // type then apply those filters.
            if (cachedEntityType != null)
            {
                // Attempt to initialize the entity service instance. This also
                // checks if the entity supports the active flag.
                if (cachedEntityType.AssemblyName != null)
                {
                    Type entityType = cachedEntityType.GetEntityType();
                    if (entityType != null)
                    {
                        Type[] modelType          = { entityType };
                        Type   genericServiceType = typeof(Rock.Data.Service <>);
                        Type   modelServiceType   = genericServiceType.MakeGenericType(modelType);

                        serviceInstance = Activator.CreateInstance(modelServiceType, new object[] { new RockContext() }) as IService;
                    }
                }
            }

            var categoryList = qry.OrderBy(c => c.Order).ThenBy(c => c.Name).ToList();

            // Get all the categories from the query and then filter on security.
            var categoryItemList = categoryList
                                   .Where(c => c.IsAuthorized(Authorization.VIEW, Person))
                                   .Select(c => new TreeItemViewModel
            {
                Value        = c.Guid.ToString(),
                Text         = c.Name,
                IsFolder     = true,
                IconCssClass = c.IconCssClass
            })
                                   .ToList();

            if (options.GetCategorizedItems)
            {
                var itemOptions = new CategorizedItemQueryOptions
                {
                    CategoryGuid              = options.ParentGuid,
                    IncludeInactiveItems      = options.IncludeInactiveItems,
                    IncludeUnnamedEntityItems = options.IncludeUnnamedEntityItems,
                    ItemFilterPropertyName    = options.ItemFilterPropertyName,
                    ItemFilterPropertyValue   = options.ItemFilterPropertyValue
                };

                var itemsQry = categoryService.GetCategorizedItemQuery(serviceInstance, itemOptions);

                if (itemsQry != null)
                {
                    var childItems = GetChildrenItems(options, cachedEntityType, itemsQry);

                    categoryItemList.AddRange(childItems);
                }
            }

            if (options.LazyLoad)
            {
                // Try to figure out which items have viewable children in
                // the existing list and set them appropriately.
                foreach (var categoryItemListItem in categoryItemList)
                {
                    if (categoryItemListItem.IsFolder)
                    {
                        categoryItemListItem.HasChildren = DoesCategoryHaveChildren(options, categoryService, serviceInstance, categoryItemListItem.Value);
                    }
                }
            }
            else
            {
                foreach (var item in categoryItemList)
                {
                    var parentGuid = item.Value.AsGuidOrNull();

                    if (item.Children == null)
                    {
                        item.Children = new List <TreeItemViewModel>();
                    }

                    GetAllDescendants(item, Person, categoryService, serviceInstance, cachedEntityType, options);
                }
            }

            // If they don't want empty categories then filter out categories
            // that do not have child items.
            if (!options.IncludeCategoriesWithoutChildren)
            {
                categoryItemList = categoryItemList
                                   .Where(a => !a.IsFolder || (a.IsFolder && a.HasChildren))
                                   .ToList();
            }

            return(categoryItemList);
        }
示例#4
0
        /// <summary>
        /// Gets all both category and non-category item decendents for the provided categoryItem.
        /// This method updates the provided categoryItem.
        /// </summary>
        /// <param name="categoryItem">The category item.</param>
        /// <param name="currentPerson">The current person.</param>
        /// <param name="categoryService">The category service.</param>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="cachedEntityType">The cached entity type of the items.</param>
        /// <param name="options">The options that describe the current operation.</param>
        /// <returns></returns>
        private TreeItemViewModel GetAllDescendants(TreeItemViewModel categoryItem, Person currentPerson, CategoryService categoryService, IService serviceInstance, EntityTypeCache cachedEntityType, CategoryItemTreeOptions options)
        {
            if (categoryItem.IsFolder)
            {
                var parentGuid      = categoryItem.Value.AsGuidOrNull();
                var childCategories = categoryService.Queryable()
                                      .AsNoTracking()
                                      .Where(c => c.ParentCategory.Guid == parentGuid)
                                      .OrderBy(c => c.Order)
                                      .ThenBy(c => c.Name);

                foreach (var childCategory in childCategories)
                {
                    if (childCategory.IsAuthorized(Authorization.VIEW, currentPerson))
                    {
                        // This category has child categories that the person can view so add them to categoryItemList
                        categoryItem.HasChildren = true;
                        var childCategoryItem = new TreeItemViewModel
                        {
                            Value        = childCategory.Guid.ToString(),
                            Text         = childCategory.Name,
                            IsFolder     = true,
                            IconCssClass = childCategory.GetPropertyValue("IconCssClass") as string ?? options.DefaultIconCssClass
                        };

                        if (childCategory is IHasActiveFlag activatedItem)
                        {
                            childCategoryItem.IsActive = activatedItem.IsActive;
                        }

                        var childCategorizedItemBranch = GetAllDescendants(childCategoryItem, currentPerson, categoryService, serviceInstance, cachedEntityType, options);
                        if (categoryItem.Children == null)
                        {
                            categoryItem.Children = new List <TreeItemViewModel>();
                        }

                        categoryItem.Children.Add(childCategorizedItemBranch);
                    }
                }

                // now that we have taken care of the child categories get the items for this category.
                if (options.GetCategorizedItems)
                {
                    var itemOptions = new CategorizedItemQueryOptions
                    {
                        CategoryGuid              = parentGuid,
                        IncludeInactiveItems      = options.IncludeInactiveItems,
                        IncludeUnnamedEntityItems = options.IncludeUnnamedEntityItems,
                        ItemFilterPropertyName    = options.ItemFilterPropertyName,
                        ItemFilterPropertyValue   = options.ItemFilterPropertyValue
                    };

                    var childQry = categoryService.GetCategorizedItemQuery(serviceInstance, itemOptions);

                    if (childQry != null)
                    {
                        var childItems = GetChildrenItems(options, cachedEntityType, childQry);

                        categoryItem.Children = new List <TreeItemViewModel>();
                        categoryItem.Children.AddRange(childItems);
                        categoryItem.HasChildren = childItems.Any();
                    }
                }
            }

            return(categoryItem);
        }