예제 #1
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            try
            {
                var dataSource = new EventOccurrencesLavaDataSource();

                _settings.ParseFromMarkup(_attributesMarkup, context);

                var events = dataSource.GetEventOccurrencesForCalendar(_settings, LavaHelper.GetRockContextFromLavaContext(context));

                AddLavaMergeFieldsToContext(context, events);

                base.OnRender(context, result);
            }
            catch (Exception ex)
            {
                var message = "Calendar Events not available. " + ex.Message;

                if (_renderErrors)
                {
                    result.Write(message);
                }
                else
                {
                    ExceptionLogService.LogException(ex);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            // first ensure that sql commands are allowed in the context
            if (!this.IsAuthorized(context))
            {
                result.Write(string.Format(LavaBlockBase.NotAuthorizedMessage, this.SourceElementName));
                return;
            }

            using (TextWriter sql = new StringWriter())
            {
                base.OnRender(context, sql);

                var parms = ParseMarkup(_markup, context);

                var sqlTimeout = (int?)null;
                if (parms.ContainsKey("timeout"))
                {
                    sqlTimeout = parms["timeout"].AsIntegerOrNull();
                }

                switch (parms["statement"])
                {
                case "select":

                    var stopWatch = new Stopwatch();
                    stopWatch.Start();
                    var results = DbService.GetDataSet(sql.ToString(), CommandType.Text, parms.ToDictionary(i => i.Key, i => (object)i.Value), sqlTimeout);
                    stopWatch.Stop();

                    context.SetMergeField(parms["return"], results.Tables[0].ToDynamic());

                    // Manually add query timings
                    var rockMockContext = LavaHelper.GetRockContextFromLavaContext(context);
                    rockMockContext.QueryCount++;
                    if (rockMockContext.QueryMetricDetailLevel == QueryMetricDetailLevel.Full)
                    {
                        rockMockContext.QueryMetricDetails.Add(new QueryMetricDetail
                        {
                            Sql      = sql.ToString(),
                            Duration = stopWatch.ElapsedTicks,
                            Database = rockMockContext.Database.Connection.Database,
                            Server   = rockMockContext.Database.Connection.DataSource
                        });
                    }
                    break;

                case "command":
                    var sqlParameters = new List <System.Data.SqlClient.SqlParameter>();

                    foreach (var p in parms)
                    {
                        sqlParameters.Add(new System.Data.SqlClient.SqlParameter(p.Key, p.Value));
                    }

                    using (var rockContext = LavaHelper.GetRockContextFromLavaContext(context))
                    {
                        if (sqlTimeout != null)
                        {
                            rockContext.Database.CommandTimeout = sqlTimeout;
                        }
                        int numOfRowsAffected = rockContext.Database.ExecuteSqlCommand(sql.ToString(), sqlParameters.ToArray());

                        context.SetMergeField(parms["return"], numOfRowsAffected);
                    }
                    break;

                default:
                    break;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            // first ensure that entity commands are allowed in the context
            if (!this.IsAuthorized(context, "rockentity"))
            {
                result.Write(string.Format(LavaBlockBase.NotAuthorizedMessage, "rockentity"));
                base.OnRender(context, result);
                return;
            }

            bool hasFilter = false;

            var modelName = string.Empty;

            // get a service for the entity based off it's friendly name
            if (EntityName == "business")
            {
                modelName = "Rock.Model.Person";
            }
            else
            {
                modelName = "Rock.Model." + EntityName;
            }

            // Check first to see if this is a core model. use the createIfNotFound = false option
            var entityTypeCache = EntityTypeCache.Get(modelName, false);

            if (entityTypeCache == null)
            {
                var entityTypes = EntityTypeCache.All();

                // If not, look for first plug-in model that has same friendly name
                entityTypeCache = entityTypes
                                  .Where(e =>
                                         e.IsEntity &&
                                         !e.Name.StartsWith("Rock.Model") &&
                                         e.FriendlyName != null &&
                                         e.FriendlyName.RemoveSpaces().ToLower() == EntityName)
                                  .OrderBy(e => e.Id)
                                  .FirstOrDefault();

                // If still null check to see if this was a duplicate class and full class name was used as entity name
                if (entityTypeCache == null)
                {
                    modelName       = EntityName.Replace('_', '.');
                    entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, modelName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                }
            }

            if (entityTypeCache != null)
            {
                Type entityType = entityTypeCache.GetEntityType();
                if (entityType != null)
                {
                    // Get the appropriate database context for this entity type.
                    // Note that this may be different from the standard RockContext if the entity is sourced from a plug-in.
                    var dbContext = Reflection.GetDbContextForEntityType(entityType);

                    // Check if there is a RockContext in the Lava context, if so (and the entity is using a RockContext) we should use that one
                    if (dbContext is RockContext)
                    {
                        dbContext = LavaHelper.GetRockContextFromLavaContext(context);
                    }

                    // Disable change-tracking for this data context to improve performance - objects supplied to a Lava context are read-only.
                    dbContext.Configuration.AutoDetectChangesEnabled = false;

                    // Create an instance of the entity's service
                    IService serviceInstance = Reflection.GetServiceForEntityType(entityType, dbContext);

                    ParameterExpression paramExpression = Expression.Parameter(entityType, "x");
                    Expression          queryExpression = null; // the base expression we'll use to build our query from

                    // Parse markup
                    var parms = ParseMarkup(_markup, context);

                    if (parms.Any(p => p.Key == "id"))
                    {
                        string propertyName = "Id";

                        List <string> selectionParms = new List <string>();
                        selectionParms.Add(PropertyComparisonConversion("==").ToString());
                        selectionParms.Add(parms["id"].ToString());
                        selectionParms.Add(propertyName);

                        var entityProperty = entityType.GetProperty(propertyName);
                        queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType);

                        hasFilter = true;
                    }
                    else
                    {
                        // where clause expression
                        if (parms.Any(p => p.Key == "where"))
                        {
                            queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache);

                            if (queryExpression != null)
                            {
                                hasFilter = true;
                            }
                        }

                        // DataView expression
                        if (parms.Any(p => p.Key == "dataview"))
                        {
                            var dataViewId = parms["dataview"].AsIntegerOrNull();

                            if (dataViewId.HasValue)
                            {
                                var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache);

                                if (queryExpression == null)
                                {
                                    queryExpression = dataViewExpression;
                                    hasFilter       = true;
                                }
                                else
                                {
                                    queryExpression = Expression.AndAlso(queryExpression, dataViewExpression);
                                }
                            }
                        }

                        // process dynamic filter expressions (from the query string)
                        if (parms.Any(p => p.Key == "dynamicparameters"))
                        {
                            var dynamicFilters = parms["dynamicparameters"].Split(',')
                                                 .Select(x => x.Trim())
                                                 .Where(x => !string.IsNullOrWhiteSpace(x))
                                                 .ToList();

                            foreach (var dynamicFilter in dynamicFilters)
                            {
                                var dynamicFilterValue      = HttpContext.Current.Request[dynamicFilter];
                                var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression);
                                if (dynamicFilterExpression != null)
                                {
                                    if (queryExpression == null)
                                    {
                                        queryExpression = dynamicFilterExpression;
                                        hasFilter       = true;
                                    }
                                    else
                                    {
                                        queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression);
                                    }
                                }
                            }
                        }
                    }

                    // Make the query from the expression.

                    /* [2020-10-08] DL
                     * "Get" is intentionally used here rather than "GetNoTracking" to allow lazy-loading of navigation properties from the Lava context.
                     * (Refer https://github.com/SparkDevNetwork/Rock/issues/4293)
                     */
                    MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) });

                    if (getMethod != null)
                    {
                        // get a listing of ids and build it into the query expression
                        if (parms.Any(p => p.Key == "ids"))
                        {
                            List <int>         value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList();
                            MemberExpression   propertyExpression = Expression.Property(paramExpression, "Id");
                            ConstantExpression constantExpression = Expression.Constant(value, typeof(List <int>));
                            Expression         containsExpression = Expression.Call(constantExpression, typeof(List <int>).GetMethod("Contains", new Type[] { typeof(int) }), propertyExpression);
                            if (queryExpression != null)
                            {
                                queryExpression = Expression.AndAlso(queryExpression, containsExpression);
                            }
                            else
                            {
                                queryExpression = containsExpression;
                            }

                            hasFilter = true;
                        }

                        var getResult   = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null });
                        var queryResult = getResult as IQueryable <IEntity>;

                        // process entity specific filters
                        switch (EntityName)
                        {
                        case "person":
                        {
                            queryResult = PersonFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }

                        case "business":
                        {
                            queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }
                        }

                        // if there was a dynamic expression add it now
                        if (parms.Any(p => p.Key == "expression"))
                        {
                            queryResult = queryResult.Where(parms["expression"]);
                            hasFilter   = true;
                        }

                        var queryResultExpression = queryResult.Expression;

                        // add sort expressions
                        if (parms.Any(p => p.Key == "sort"))
                        {
                            string orderByMethod = "OrderBy";

                            foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList())
                            {
                                string propertyName;
                                var    direction = SortDirection.Ascending;

                                if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase))
                                {
                                    direction    = SortDirection.Descending;
                                    propertyName = column.Left(column.Length - 5);
                                }
                                else
                                {
                                    propertyName = column;
                                }

                                string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod;

                                if (entityType.GetProperty(propertyName) != null)
                                {
                                    // sorting a entity property
                                    var memberExpression          = Expression.Property(paramExpression, propertyName);
                                    LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression);
                                    queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                }
                                else
                                {
                                    // sorting on an attribute

                                    // get attribute id
                                    int?attributeId = null;
                                    foreach (var attribute in AttributeCache.GetByEntityType(entityTypeCache.Id))
                                    {
                                        if (attribute.Key == propertyName)
                                        {
                                            attributeId = attribute.Id;
                                            break;
                                        }
                                    }

                                    if (attributeId.HasValue)
                                    {
                                        // get AttributeValue queryable and parameter
                                        if (dbContext is RockContext)
                                        {
                                            var attributeValues = new AttributeValueService(dbContext as RockContext).Queryable();
                                            ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v");
                                            MemberExpression    idExpression            = Expression.Property(paramExpression, "Id");
                                            var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value);

                                            LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression);
                                            queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                        }
                                        else
                                        {
                                            throw new Exception(string.Format("The database context for type {0} does not support RockContext attribute value queries.", entityTypeCache.FriendlyName));
                                        }
                                    }
                                }

                                orderByMethod = "ThenBy";
                            }
                        }

                        // check to ensure we had some form of filter (otherwise we'll return all results in the table)
                        if (!hasFilter)
                        {
                            throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.");
                        }

                        // Disable lazy loading if requested
                        if (parms.Any(p => p.Key == "lazyloadenabled"))
                        {
                            if (!parms["lazyloadenabled"].AsBoolean())
                            {
                                dbContext.Configuration.LazyLoadingEnabled = false;
                            }
                        }

                        // Reassemble the queryable with the sort expressions
                        queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>;

                        // Add included entities
                        if (parms.Any(p => p.Key == "include"))
                        {
                            var includeList = parms["include"].Split(',')
                                              .Select(x => x.Trim())
                                              .Where(x => !string.IsNullOrWhiteSpace(x));

                            foreach (var includeItem in includeList)
                            {
                                queryResult = queryResult.Include(includeItem);
                            }
                        }

                        if (parms.GetValueOrNull("count").AsBoolean())
                        {
                            int countResult = queryResult.Count();
                            context.SetMergeField("count", countResult, LavaContextRelativeScopeSpecifier.Root);
                        }
                        else
                        {
                            // Run security check on each result if enabled and entity is not a person (we do not check security on people)
                            if (parms["securityenabled"].AsBoolean() && EntityName != "person")
                            {
                                var items        = queryResult.ToList();
                                var itemsSecured = new List <IEntity>();

                                Person person = GetCurrentPerson(context);

                                foreach (IEntity item in items)
                                {
                                    ISecured itemSecured = item as ISecured;
                                    if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person))
                                    {
                                        itemsSecured.Add(item);

                                        /*
                                         *      8/13/2020 - JME
                                         *      It might seem logical to break out of the loop if there is limit parameter provided once the
                                         *  limit is reached. This though has two issues.
                                         *
                                         *  FIRST
                                         *  Depending how it was implemented it can have the effect of breaking when an offset is
                                         *  provided.
                                         *          {% contentchannelitem where:'ContentChannelId == 1' limit:'3' %}
                                         *          {% for item in contentchannelitemItems %}
                                         *              {{ item.Id }} - {{ item.Title }}<br>
                                         *          {% endfor %}
                                         *      {% endcontentchannelitem %}
                                         *  Returns 3 items (correct)
                                         *
                                         *      {% contentchannelitem where:'ContentChannelId == 1' limit:'3' offset:'1' %}
                                         *          {% for item in contentchannelitemItems %}
                                         *              {{ item.Id }} - {{ item.Title }}<br>
                                         *          {% endfor %}
                                         *      {% endcontentchannelitem %}
                                         *  Returns only 2 items (incorrect) - because of the offset
                                         *
                                         *  SECOND
                                         *  If the limit is moved before the security check it's possible that the security checks
                                         *  will remove items and will therefore not give you the amount of items that you asked for.
                                         *
                                         *  Unfortunately this has to be an inefficent process to ensure pagination works. I will also
                                         *  add a detailed note to the documentation to encourage people to disable security checks,
                                         *  especially when used with pagination, in the Lava docs.
                                         */
                                    }
                                }

                                queryResult = itemsSecured.AsQueryable();
                            }

                            // offset
                            if (parms.Any(p => p.Key == "offset"))
                            {
                                queryResult = queryResult.Skip(parms["offset"].AsInteger());
                            }

                            // limit, default to 1000
                            if (parms.Any(p => p.Key == "limit"))
                            {
                                queryResult = queryResult.Take(parms["limit"].AsInteger());
                            }
                            else
                            {
                                queryResult = queryResult.Take(1000);
                            }

                            // Process logic to be able to return an anonymous types and group bys. We have to abstract the return types as
                            // the select returns a type of List<dynamic> while the normal entity command returns List<IEntity>.
                            // Using a type of List<object> for both did not work (that would have eliminated the need for the
                            // firstItem and returnCount.
                            object returnValues = null;
                            object firstItem    = null;
                            int    returnCount  = 0;

                            if (parms.ContainsKey("groupby") || parms.ContainsKey("select") || parms.ContainsKey("selectmany"))
                            {
                                /*
                                 * 3/1/2021 - JME
                                 * Ensure that lazy loading is enabled. If this is false it throws a null reference exception.
                                 * I confirmed that the anonymous type is getting it's data from the single source SQL (no lazy loading).
                                 * Not sure why this exception is happening. It looks to be within the ZZZ Project System.Linq.Dynamic.Core
                                 * package. The important part is that the data is coming back in a single query.
                                 */
                                dbContext.Configuration.LazyLoadingEnabled = true;


                                List <dynamic> results = null;

                                // Logic here is a groupby has to have a select, but a select doesn't need a groupby.
                                if (parms.ContainsKey("groupby") && parms.ContainsKey("select"))
                                {
                                    results = queryResult.Cast(entityType)
                                              .GroupBy(parms["groupby"])
                                              .Select(parms["select"])
                                              .ToDynamicList();
                                }
                                else
                                {
                                    if (parms.ContainsKey("select"))
                                    {
                                        results = queryResult.Cast(entityType)
                                                  .Select(parms["select"])
                                                  .ToDynamicList();
                                    }
                                    else  // selectmany
                                    {
                                        results = queryResult.Cast(entityType)
                                                  .SelectMany(parms["selectmany"])
                                                  .ToDynamicList();
                                    }
                                }

                                returnValues = results;
                                firstItem    = results.FirstOrDefault();
                                returnCount  = results.Count();
                            }
                            else
                            {
                                var results = queryResult.ToList();
                                returnValues = results;
                                firstItem    = results.FirstOrDefault();
                                returnCount  = results.Count();
                            }

                            // Add the result to the current context.
                            context.SetMergeField(parms["iterator"], returnValues, LavaContextRelativeScopeSpecifier.Current);

                            if (returnCount == 1)
                            {
                                // If there is only one item, set a singleton variable in addition to the result list.
                                context.SetMergeField(EntityName, firstItem, LavaContextRelativeScopeSpecifier.Current);
                            }
                        }
                    }
                }
            }
            else
            {
                result.Write(string.Format("Could not find a model for {0}.", EntityName));
                base.OnRender(context, result);
            }

            base.OnRender(context, result);
        }
예제 #4
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            // first ensure that entity commands are allowed in the context
            if (!this.IsAuthorized(context))
            {
                result.Write(string.Format(LavaBlockBase.NotAuthorizedMessage, this.SourceElementName));
                return;
            }

            var    attributes       = new Dictionary <string, string>();
            string parmWorkflowType = null;
            string parmWorkflowName = null;
            string parmWorkflowId   = null;
            string parmActivityType = null;

            /* Parse the markup text to pull out configuration parameters. */
            var parms = ParseMarkup(_markup, context);

            foreach (var p in parms)
            {
                if (p.Key.ToLower() == "workflowtype")
                {
                    parmWorkflowType = p.Value;
                }
                else if (p.Key.ToLower() == "workflowname")
                {
                    parmWorkflowName = p.Value;
                }
                else if (p.Key.ToLower() == "workflowid")
                {
                    parmWorkflowId = p.Value;
                }
                else if (p.Key.ToLower() == "activitytype")
                {
                    parmActivityType = p.Value;
                }
                else
                {
                    attributes.AddOrReplace(p.Key, p.Value);
                }
            }

            /* Process inside a new stack level so our own created variables do not
             * persist throughout the rest of the workflow. */
            context.ExecuteInChildScope((System.Action <ILavaRenderContext>)((newContext) =>
            {
                var rockContext = LavaHelper.GetRockContextFromLavaContext(context);

                WorkflowService workflowService = new WorkflowService(rockContext);
                Rock.Model.Workflow workflow    = null;
                WorkflowActivity activity       = null;

                /* They provided a WorkflowType, so we need to kick off a new workflow. */
                if (parmWorkflowType != null)
                {
                    string type = parmWorkflowType;
                    string name = parmWorkflowName ?? string.Empty;
                    WorkflowTypeCache workflowType = null;

                    /* Get the type of workflow */
                    if (type.AsGuidOrNull() != null)
                    {
                        workflowType = WorkflowTypeCache.Get(type.AsGuid());
                    }
                    else if (type.AsIntegerOrNull() != null)
                    {
                        workflowType = WorkflowTypeCache.Get(type.AsInteger());
                    }

                    /* Try to activate the workflow */
                    if (workflowType != null)
                    {
                        workflow = Rock.Model.Workflow.Activate(( WorkflowTypeCache )workflowType, ( string )parmWorkflowName);

                        /* Set any workflow attributes that were specified. */
                        foreach (var attr in attributes)
                        {
                            if (workflow.Attributes.ContainsKey(attr.Key))
                            {
                                workflow.SetAttributeValue(attr.Key, attr.Value.ToString());
                            }
                        }

                        if (workflow != null)
                        {
                            List <string> errorMessages;

                            workflowService.Process(workflow, out errorMessages);

                            if (errorMessages.Any())
                            {
                                context["Error"] = string.Join("; ", errorMessages.ToArray());
                            }

                            context["Workflow"] = workflow;
                        }
                        else
                        {
                            context["Error"] = "Could not activate workflow.";
                        }
                    }
                    else
                    {
                        context["Error"] = "Workflow type not found.";
                    }
                }

                /* They instead provided a WorkflowId, so we are working with an existing Workflow. */
                else if (parmWorkflowId != null)
                {
                    string id = parmWorkflowId.ToString();

                    /* Get the workflow */
                    if (id.AsGuidOrNull() != null)
                    {
                        workflow = workflowService.Get(id.AsGuid());
                    }
                    else if (id.AsIntegerOrNull() != null)
                    {
                        workflow = workflowService.Get(id.AsInteger());
                    }

                    if (workflow != null)
                    {
                        if (workflow.CompletedDateTime == null)
                        {
                            /* Currently we cannot activate an activity in a workflow that is currently
                             * being processed. The workflow is held in-memory so the activity we would
                             * activate would not show up for the processor and probably never run.
                             */
                            if (!workflow.IsProcessing)
                            {
                                bool hasError = false;

                                /* If they provided an ActivityType parameter then we need to activate
                                 * a new activity in the workflow.
                                 */
                                if (parmActivityType != null)
                                {
                                    string type = parmActivityType.ToString();
                                    WorkflowActivityTypeCache activityType = null;

                                    /* Get the type of activity */
                                    if (type.AsGuidOrNull() != null)
                                    {
                                        activityType = WorkflowActivityTypeCache.Get(type.AsGuid());
                                    }
                                    else if (type.AsIntegerOrNull() != null)
                                    {
                                        activityType = WorkflowActivityTypeCache.Get(type.AsInteger());
                                    }

                                    if (activityType != null)
                                    {
                                        activity = WorkflowActivity.Activate(activityType, workflow);

                                        /* Set any workflow attributes that were specified. */
                                        foreach (var attr in attributes)
                                        {
                                            if (activity.Attributes.ContainsKey(attr.Key))
                                            {
                                                activity.SetAttributeValue(attr.Key, attr.Value.ToString());
                                            }
                                        }
                                    }
                                    else
                                    {
                                        context["Error"] = "Activity type was not found.";
                                        hasError         = true;
                                    }
                                }

                                /* Process the existing Workflow. */
                                if (!hasError)
                                {
                                    List <string> errorMessages;
                                    workflowService.Process(workflow, out errorMessages);

                                    if (errorMessages.Any())
                                    {
                                        context["Error"] = string.Join("; ", errorMessages.ToArray());
                                    }

                                    context["Workflow"] = workflow;
                                    context["Activity"] = activity;
                                }
                            }
                            else
                            {
                                context["Error"] = "Cannot activate activity on workflow that is currently being processed.";
                            }
                        }
                        else
                        {
                            context["Error"] = "Workflow has already been completed.";
                        }
                    }
                    else
                    {
                        context["Error"] = "Workflow not found.";
                    }
                }
                else
                {
                    context["Error"] = "Must specify one of WorkflowType or WorkflowId.";
                }

                base.OnRender(context, result);
                //RenderAll( NodeList, context, result );
                // TODO: Test this! - NodeList is empty here, so the call to RenderAll seems unnecessary?
            }));
        }
예제 #5
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            var rockContext = LavaHelper.GetRockContextFromLavaContext(context);

            // Get enabled security commands
            _enabledSecurityCommands = context.GetEnabledCommands().JoinStrings(",");

            using (TextWriter writer = new StringWriter())
            {
                bool filterProvided = false;

                base.OnRender(context, writer);

                var parms              = ParseMarkup(_markup, context);
                var lookAheadDays      = parms[LOOK_AHEAD_DAYS].AsInteger();
                var scheduleCategoryId = parms[SCHEDULE_CATEGORY_ID].AsIntegerOrNull();
                var asAtDate           = parms[AS_AT_DATE].AsDateTime();

                var now = asAtDate ?? RockDateTime.Now;

                var scheduleIds = new List <int>();

                var requestedSchedules = parms[SCHEDULE_ID].StringToIntList();

                var schedulesQry = new ScheduleService(rockContext).Queryable().AsNoTracking()
                                   .Where(s => s.IsActive == true);

                if (requestedSchedules.Count() > 0)
                {
                    schedulesQry   = schedulesQry.Where(s => requestedSchedules.Contains(s.Id));
                    filterProvided = true;
                }

                if (scheduleCategoryId.HasValue)
                {
                    schedulesQry   = schedulesQry.Where(s => s.CategoryId == scheduleCategoryId.Value);
                    filterProvided = true;
                }

                // If neither a schedule id nor a schedule category id was provided stop
                if (!filterProvided)
                {
                    return;
                }

                // Get the schedules are order them by the next start time
                var schedules = schedulesQry.ToList()
                                .Where(s => s.GetNextStartDateTime(now) != null)
                                .OrderBy(s => s.GetNextStartDateTime(now));

                if (schedules.Count() == 0)
                {
                    return;
                }

                var nextSchedule = schedules.FirstOrDefault();

                var      nextStartDateTime     = nextSchedule.GetNextStartDateTime(now);
                var      isLive                = false;
                DateTime?occurrenceEndDateTime = null;

                // Determine if we're live
                if (nextSchedule.WasScheduleActive(now))
                {
                    isLive = true;
                    var occurrences      = nextSchedule.GetICalOccurrences(now, now.AddDays(lookAheadDays)).Take(2);
                    var activeOccurrence = occurrences.FirstOrDefault();
                    occurrenceEndDateTime = (DateTime)activeOccurrence.Period.EndTime.Value;

                    // Set the next occurrence to be the literal next occurrence (vs the current occurrence)
                    nextStartDateTime = null;
                    if (occurrences.Count() > 1)
                    {
                        nextStartDateTime = occurrences.Last().Period.EndTime.Value;
                    }
                }

                // Determine when not to show the content
                if ((parms[SHOW_WHEN] == "notlive" && isLive) ||
                    (parms[SHOW_WHEN] == "live" && !isLive))
                {
                    return;
                }

                // Check role membership
                var roleId = parms[ROLE_ID].AsIntegerOrNull();

                if (roleId.HasValue)
                {
                    var currentPerson = GetCurrentPerson(context);

                    var isInRole = new GroupMemberService(rockContext).Queryable()
                                   .Where(m =>
                                          m.GroupId == roleId &&
                                          m.PersonId == currentPerson.Id
                                          )
                                   .Any();

                    if (!isInRole)
                    {
                        return;
                    }
                }

                var mergeFields = context.GetMergeFields();

                mergeFields.Add("NextOccurrenceDateTime", nextStartDateTime);
                mergeFields.Add("OccurrenceEndDateTime", occurrenceEndDateTime);
                mergeFields.Add("Schedule", nextSchedule);
                mergeFields.Add("IsLive", isLive);

                var engine = context.GetService <ILavaEngine>();

                var renderContext = engine.NewRenderContext(mergeFields, _enabledSecurityCommands.SplitDelimitedValues());

                var results = engine.RenderTemplate(_blockMarkup.ToString(), LavaRenderParameters.WithContext(renderContext));

                result.Write(results.Text.Trim());
            }
        }
예제 #6
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        public override void OnRender(ILavaRenderContext context, TextWriter result)
        {
            // First, ensure that this command is allowed in the context.
            if (!this.IsAuthorized(context))
            {
                result.Write(string.Format(LavaBlockBase.NotAuthorizedMessage, this.SourceElementName));
                base.OnRender(context, result);
                return;
            }

            // Parse the Lava Command markup to retrieve paramters.
            var parms = new Dictionary <string, string>
            {
                { ParameterKey.Operation, "View" }
            };

            LavaHelper.ParseCommandMarkup(this.ElementAttributesMarkup, context, parms);

            // Set local variables from parsed parameters.
            int?contentChannelItemId = parms.GetValueOrNull(ParameterKey.ContentChannelItemId).AsIntegerOrNull();

            if (!contentChannelItemId.HasValue)
            {
                // Do nothing if a ContentChannelItem ID wasn't specified.
                return;
            }

            ContentChannelItem contentChannelItem = null;
            var rockContext = LavaHelper.GetRockContextFromLavaContext(context);

            contentChannelItem = new ContentChannelItemService(rockContext)
                                 .Queryable("ContentChannel")
                                 .AsNoTracking()
                                 .FirstOrDefault(c => c.Id == contentChannelItemId.Value);


            ContentChannel contentChannel = contentChannelItem.ContentChannel;

            if (contentChannelItem == null || contentChannel == null)
            {
                // The caller supplied an invalid ContentChannelItem ID; nothing to do.
                return;
            }

            string operation = parms.GetValueOrNull(ParameterKey.Operation);
            string summary   = parms.GetValueOrNull(ParameterKey.Summary);
            string source    = parms.GetValueOrNull(ParameterKey.Source);
            string medium    = parms.GetValueOrNull(ParameterKey.Medium);
            string campaign  = parms.GetValueOrNull(ParameterKey.Campaign);
            string content   = parms.GetValueOrNull(ParameterKey.Content);
            string term      = parms.GetValueOrNull(ParameterKey.Term);

            int?personAliasId = parms.GetValueOrNull(ParameterKey.PersonAliasId).AsIntegerOrNull();

            if (!personAliasId.HasValue)
            {
                Person currentPerson = LavaHelper.GetCurrentPerson(context);
                personAliasId = LavaHelper.GetPrimaryPersonAliasId(currentPerson);
            }

            // Write the Interaction by way of a transaction.
            DefinedValueCache mediumType = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_CONTENTCHANNEL.AsGuid());

            if (mediumType == null)
            {
                return;
            }

            var info = new InteractionTransactionInfo
            {
                ChannelTypeMediumValueId = mediumType.Id,
                ChannelEntityId          = contentChannel.Id,
                ChannelName           = contentChannel.ToString(),
                ComponentEntityTypeId = contentChannel.TypeId,
                ComponentEntityId     = contentChannelItem.Id,
                ComponentName         = contentChannelItem.ToString(),
                InteractionOperation  = operation,
                InteractionSummary    = summary ?? contentChannelItem.Title,
                PersonAliasId         = personAliasId,
                InteractionSource     = source,
                InteractionMedium     = medium,
                InteractionCampaign   = campaign,
                InteractionContent    = content,
                InteractionTerm       = term
            };

            var interactionTransaction = new InteractionTransaction(info);

            interactionTransaction.Enqueue();
        }