示例#1
0
        public void LavaHelperRemoveComments_CommentsInIncludeFile_AreRemoved()
        {
            var fileProvider = GetFileProviderWithComments();

            var input = @"
{%- include '_comments.lava' -%}
";

            var expectedOutput = @"
Line 1<br>
Line 2<br>
Line 3<br>
Line 4<br>
";

            var options = new LavaEngineConfigurationOptions
            {
                FileSystem = GetFileProviderWithComments()
            };

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                // Create a new engine instance of the same type, but with a test file system configuration.
                var testEngine = LavaService.NewEngineInstance(engine.GetType(), options);

                TestHelper.AssertTemplateOutput(testEngine, expectedOutput, input);
            });
        }
        /// <summary>
        /// For each of the currently enabled Lava Engines, process the specified action.
        /// </summary>
        /// <param name="testMethod"></param>
        public void ExecuteForActiveEngines(Action <ILavaEngine> testMethod)
        {
            var engines = GetActiveTestEngines();

            var exceptions = new List <Exception>();

            foreach (var engine in engines)
            {
                LavaService.SetCurrentEngine(engine);

                Debug.Print($"\n**\n** Lava Render Test: {engine.EngineName}\n**\n");

                try
                {
                    testMethod(engine);
                }
                catch (Exception ex)
                {
                    // Write the error to debug output.
                    Debug.Print($"\n** ERROR:\n{ex.ToString()}");

                    exceptions.Add(ex);
                }
            }

            if (exceptions.Any())
            {
                throw new AggregateException("Test failed for one or more Lava engines.", exceptions);
            }
        }
        /// <summary>
        /// Use Lava to resolve any merge codes within the content using the values in the merge objects.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="mergeObjects">The merge objects.</param>
        /// <param name="currentPersonOverride">The current person override.</param>
        /// <param name="enabledLavaCommands">A comma-delimited list of the lava commands that are enabled for this template.</param>
        /// <returns>If lava present returns merged string, if no lava returns original string, if null returns empty string</returns>
        public static string RenderLava(this string content, IDictionary <string, object> mergeObjects, Person currentPersonOverride, string enabledLavaCommands)
        {
            try
            {
                // If there have not been any EnabledLavaCommands explicitly set, then use the global defaults.
                if (enabledLavaCommands == null)
                {
                    enabledLavaCommands = GlobalAttributesCache.Value("DefaultEnabledLavaCommands");
                }

                var context = LavaService.NewRenderContext();

                context.SetEnabledCommands(enabledLavaCommands, ",");

                context.SetMergeField("CurrentPerson", currentPersonOverride);
                context.SetMergeFields(mergeObjects);

                var result = LavaService.RenderTemplate(content, LavaRenderParameters.WithContext(context));

                if (result.HasErrors)
                {
                    throw result.GetLavaException();
                }

                return(result.Text);
            }
            catch (Exception ex)
            {
                ExceptionLogService.LogException(ex, System.Web.HttpContext.Current);
                return("Error resolving Lava merge fields: " + ex.Message);
            }
        }
        public ILavaEngine GetEngineInstance(Type engineType)
        {
            ILavaEngine engine = null;

            if (engineType == typeof(DotLiquidEngine))
            {
                engine = _dotliquidEngine;
            }
            else if (engineType == typeof(FluidEngine))
            {
                engine = _fluidEngine;
            }
            else if (engineType == typeof(RockLiquidEngine))
            {
                engine = _rockliquidEngine;
            }

            if (engine == null)
            {
                throw new Exception($"Lava Engine instance not available. Engine Type \"{engineType}\" is not configured for this test run.");
            }

            // Set the global instance of the engine to ensure that it is available to Lava components.
            LavaService.SetCurrentEngine(engine);

            return(engine);
        }
示例#5
0
        /// <summary>
        /// Use Lava to resolve any merge codes within the content using the values in the merge objects.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="mergeObjects">The merge objects.</param>
        /// <param name="currentPersonOverride">The current person override.</param>
        /// <param name="enabledLavaCommands">A comma-delimited list of the lava commands that are enabled for this template.</param>
        /// <param name="encodeStringOutput">if set to <c>true</c> [encode string output].</param>
        /// <returns>If lava present returns merged string, if no lava returns original string, if null returns empty string</returns>
        private static LavaRenderResult ResolveMergeFieldsWithCurrentLavaEngine(string content, IDictionary <string, object> mergeObjects, Person currentPersonOverride, string enabledLavaCommands, bool encodeStringOutput)
        {
            // If there have not been any EnabledLavaCommands explicitly set, then use the global defaults.
            if (enabledLavaCommands == null)
            {
                enabledLavaCommands = GlobalAttributesCache.Value("DefaultEnabledLavaCommands");
            }

            var context = LavaService.NewRenderContext();

            context.SetEnabledCommands(enabledLavaCommands, ",");

            if (currentPersonOverride != null)
            {
                context.SetMergeField("CurrentPerson", currentPersonOverride);
            }

            context.SetMergeFields(mergeObjects);

            var parameters = LavaRenderParameters.WithContext(context);

            parameters.ShouldEncodeStringsAsXml = encodeStringOutput;

            var result = LavaService.RenderTemplate(content, parameters);

            if (result.HasErrors &&
                LavaService.ExceptionHandlingStrategy == ExceptionHandlingStrategySpecifier.RenderToOutput)
            {
                // If the result is an error, encode the error message to prevent any part of it from appearing as rendered content, and then add markup for line breaks.
                result.Text = result.Text.EncodeHtml().ConvertCrLfToHtmlBr();
            }

            return(result);
        }
示例#6
0
        private static void InitializeGlobalLavaEngineInstance(Type engineType)
        {
            // Initialize the Lava engine.
            var options = new LavaEngineConfigurationOptions();

            if (engineType != typeof(RockLiquidEngine))
            {
                var defaultEnabledLavaCommands = GlobalAttributesCache.Value("DefaultEnabledLavaCommands").SplitDelimitedValues(",").ToList();

                options.FileSystem             = new WebsiteLavaFileSystem();
                options.CacheService           = new WebsiteLavaTemplateCacheService();
                options.DefaultEnabledCommands = defaultEnabledLavaCommands;
            }

            LavaService.SetCurrentEngine(engineType, options);

            // Subscribe to exception notifications from the Lava Engine.
            var engine = LavaService.GetCurrentEngine();

            engine.ExceptionEncountered += Engine_ExceptionEncountered;

            // Initialize Lava extensions.
            InitializeLavaFilters(engine);
            InitializeLavaTags(engine);
            InitializeLavaBlocks(engine);
            InitializeLavaShortcodes(engine);
            InitializeLavaSafeTypes(engine);
        }
示例#7
0
        public void WebsiteLavaTemplateCacheService_WhitespaceTemplatesWithDifferentLengths_AreCachedIndependently()
        {
            var options = new LavaEngineConfigurationOptions();

            ILavaTemplateCacheService cacheService = new WebsiteLavaTemplateCacheService();

            options.CacheService = cacheService;

            TestHelper.ExecuteForActiveEngines((defaultEngineInstance) =>
            {
                if (defaultEngineInstance.GetType() == typeof(RockLiquidEngine))
                {
                    Debug.Write("Template caching cannot be tested by this methodology for the RockLiquid implementation.");
                    return;
                }

                // Remove all existing items from the cache.
                cacheService.ClearCache();

                var engine = LavaService.NewEngineInstance(defaultEngineInstance.GetType(), options);

                // Process a zero-length whitespace template - this should be cached separately.
                var input0 = string.Empty;
                var key0   = cacheService.GetCacheKeyForTemplate(input0);

                // Verify that the template does not initially exist in the cache.
                var exists = cacheService.ContainsKey(key0);

                Assert.IsFalse(exists, "String-0 Template found in cache unexpectedly.");

                // Render the template, which will automatically add it to the cache.
                var output0 = engine.RenderTemplate(input0);

                // Verify that the template now exists in the cache.
                exists = cacheService.ContainsKey(key0);

                Assert.IsTrue(exists, "String-0 Template not found in cache.");

                // Render a whitespace template of a different length - this should be cached separately from the first template.
                // If not, the caching mechanism would cause some whitespace to be rendered incorrectly.
                var input1 = new string( ' ', 1 );
                var key1   = engine.TemplateCacheService.GetCacheKeyForTemplate(input1);

                var output1 = engine.RenderTemplate(input1);

                // Verify that the 100-character whitespace template now exists in the cache.
                exists = cacheService.ContainsKey(key1);

                Assert.IsTrue(exists, "String-1 Template not found in cache.");

                // Verify that a whitespace template of some other length is not equated with the whitespace templates we have specifically added.
                var keyX = engine.TemplateCacheService.GetCacheKeyForTemplate(new string( ' ', 9 ));

                exists = cacheService.ContainsKey(keyX);

                Assert.IsFalse(exists, "String-9 Template found in cache unexpectedly.");
            });
        }
        private static void RegisterLavaEngines()
        {
            // Register the RockLiquid Engine (pre-v13).
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engine = new RockLiquidEngine();

                engine.Initialize(options as LavaEngineConfigurationOptions);

                // Initialize the RockLiquid Engine
                RegisterFilters(engine);
                RegisterTags(engine);
                RegisterBlocks(engine);

                RegisterStaticShortcodes(engine);
                RegisterDynamicShortcodes(engine);

                return(engine);
            });

            // Register the DotLiquid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engine = new DotLiquidEngine();

                engine.Initialize(options as LavaEngineConfigurationOptions);

                // Initialize the DotLiquid Engine
                RegisterFilters(engine);
                RegisterTags(engine);
                RegisterBlocks(engine);

                RegisterStaticShortcodes(engine);
                RegisterDynamicShortcodes(engine);

                return(engine);
            });

            // Register the Fluid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engine = new FluidEngine();

                engine.Initialize(options as LavaEngineConfigurationOptions);

                // Initialize Fluid Engine
                RegisterFilters(engine);
                RegisterTags(engine);
                RegisterBlocks(engine);

                RegisterStaticShortcodes(engine);
                RegisterDynamicShortcodes(engine);

                return(engine);
            });
        }
示例#9
0
        public void FluidEngineValueConverterPerformance_DictionaryKeyResolution_OutputsPerformanceMeasures()
        {
            var totalSets             = 10;
            var totalIterationsPerSet = 1000000;

            // Create a Fluid engine with template caching disabled.
            var engineOptions = new LavaEngineConfigurationOptions {
                CacheService = new MockTemplateCacheService()
            };

            var engine = LavaService.NewEngineInstance(typeof(FluidEngine), engineOptions);

            var standardLavaDictionary = new Dictionary <string, object>();

            var formatString = new string( '0', totalIterationsPerSet.ToString().Length );

            for (int i = 0; i < totalIterationsPerSet; i++)
            {
                standardLavaDictionary.Add(i.ToString(formatString), i);
            }

            var mergeFields = new LavaDataDictionary {
                { "Dictionary", standardLavaDictionary }
            };

            var totalTime = TestHelper.ExecuteAndGetElapsedTime(() =>
            {
                engine.ClearTemplateCache();

                for (int repeatCount = 1; repeatCount <= totalSets; repeatCount++)
                {
                    var elapsedTime = TestHelper.ExecuteAndGetElapsedTime(() =>
                    {
                        for (int i = 0; i < totalIterationsPerSet; i++)
                        {
                            var template = "{{ Dictionary['" + i.ToString(formatString) + "']}}";

                            var options = new LavaTestRenderOptions {
                                MergeFields = mergeFields
                            };

                            var output = TestHelper.GetTemplateOutput(engine, template, mergeFields);

                            // Verify that the correct entry was retrieved.
                            Assert.AreEqual(i.ToString(), output);
                        }
                    });

                    Debug.Print($"Pass {repeatCount} Elapsed Time: {elapsedTime.TotalMilliseconds} ");
                }
            });

            Debug.Print($"Average Time: {totalTime.TotalMilliseconds / totalSets} ");
        }
示例#10
0
        private static void InitializeRockLiquidLibrary()
        {
            _ = LavaService.NewEngineInstance(typeof(RockLiquidEngine));

            // Register the set of filters that are compatible with RockLiquid.
            Template.RegisterFilter(typeof(Rock.Lava.Filters.TemplateFilters));
            Template.RegisterFilter(typeof(Rock.Lava.RockFilters));

            // Initialize the RockLiquid file system.
            Template.FileSystem = new LavaFileSystem();
        }
示例#11
0
        private static void InitializeLavaEngines()
        {
            // Register the RockLiquid Engine (pre-v13).
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engineOptions = new LavaEngineConfigurationOptions();

                var rockLiquidEngine = new RockLiquidEngine();

                rockLiquidEngine.Initialize(engineOptions);

                return(rockLiquidEngine);
            });

            // Register the DotLiquid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var defaultEnabledLavaCommands = GlobalAttributesCache.Value("DefaultEnabledLavaCommands").SplitDelimitedValues(",").ToList();

                var engineOptions = new LavaEngineConfigurationOptions
                {
                    FileSystem             = new WebsiteLavaFileSystem(),
                    CacheService           = new WebsiteLavaTemplateCacheService(),
                    DefaultEnabledCommands = defaultEnabledLavaCommands
                };

                var dotLiquidEngine = new DotLiquidEngine();

                dotLiquidEngine.Initialize(engineOptions);

                return(dotLiquidEngine);
            });

            // Register the Fluid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var defaultEnabledLavaCommands = GlobalAttributesCache.Value("DefaultEnabledLavaCommands").SplitDelimitedValues(",").ToList();

                var engineOptions = new LavaEngineConfigurationOptions
                {
                    FileSystem             = new WebsiteLavaFileSystem(),
                    CacheService           = new WebsiteLavaTemplateCacheService(),
                    DefaultEnabledCommands = defaultEnabledLavaCommands
                };

                var fluidEngine = new FluidEngine();

                fluidEngine.Initialize(engineOptions);

                return(fluidEngine);
            });
        }
示例#12
0
        private static void AssertTemplateResult(string expected, string template)
        {
            // Tests in this class are only compatible with the DotLiquid engine.
            // If/when these tests are reworked for the Fluid engine, they should be moved to the Rock.Tests.UnitTests.Lava namespace.
            if (_lavaEngine == null)
            {
                _lavaEngine = LavaService.NewEngineInstance(typeof(global::Rock.Lava.DotLiquid.DotLiquidEngine), new LavaEngineConfigurationOptions());
            }

            var result = _lavaEngine.RenderTemplate(template);

            Assert.That.AreEqual(expected, result.Text);
        }
示例#13
0
        private void ClearCache()
        {
            SyndicationFeedHelper.ClearCachedFeed(GetAttributeValue(AttributeKey.RSSFeedUrl));

            if (LavaService.RockLiquidIsEnabled)
            {
#pragma warning disable CS0618 // Type or member is obsolete
                LavaTemplateCache.Remove(this.TemplateCacheKey);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            LavaService.RemoveTemplateCacheEntry(this.TemplateCacheKey);
        }
示例#14
0
        /// <summary>
        /// Handles the BlockUpdated event of the PageMenu control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void PageMenu_BlockUpdated(object sender, EventArgs e)
        {
            if (LavaService.RockLiquidIsEnabled)
            {
                // Remove the template from the DotLiquid cache.
#pragma warning disable CS0618 // Type or member is obsolete
                LavaTemplateCache.Remove(CacheKey());
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // Remove the existing template from the cache.
            var cacheKey = CacheKey();

            LavaService.RemoveTemplateCacheEntry(cacheKey);
        }
示例#15
0
        public void IncludeStatement_ShouldRenderError_IfFileSystemIsNotConfigured()
        {
            var input = @"
{% include '_template.lava' %}
";

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                var testEngine = LavaService.NewEngineInstance(engine.GetType(), new LavaEngineConfigurationOptions());

                var result = testEngine.RenderTemplate(input);

                Assert.That.Contains(result.Error.Messages().JoinStrings("//"), "File Load Failed.");
            });
        }
示例#16
0
        public void ExceptionHandling_RenderMergeFieldsExtensionMethod_IsRenderedToOutput()
        {
            var input = @"{% invalidTagName %}";

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                engine.ExceptionHandlingStrategy = ExceptionHandlingStrategySpecifier.RenderToOutput;

                LavaService.SetCurrentEngine(engine);

                var outputText = input.ResolveMergeFields(new Dictionary <string, object>());

                TestHelper.DebugWriteRenderResult(engine, input, outputText);

                Assert.IsTrue(outputText.StartsWith("Error resolving Lava merge fields: Unknown tag 'invalidTagName'\n"));
            });
        }
示例#17
0
        public void Initialize(bool testRockLiquidEngine, bool testDotLiquidEngine, bool testFluidEngine)
        {
            // Verify the test environment: RockLiquidEngine and DotLiquidEngine are mutually exclusive test environments.
            if (testRockLiquidEngine && testDotLiquidEngine)
            {
                throw new Exception("RockLiquidEngine/DotLiquidEngine cannot be tested simultaneously because they require different global configurations of the DotLiquid library.");
            }

            RockLiquidEngineIsEnabled = testRockLiquidEngine;
            DotLiquidEngineIsEnabled  = testDotLiquidEngine;
            FluidEngineIsEnabled      = testFluidEngine;

            RegisterLavaEngines();

            if (RockLiquidEngineIsEnabled)
            {
                // Initialize the Rock variant of the DotLiquid Engine
                var engineOptions = new LavaEngineConfigurationOptions();

                _rockliquidEngine = LavaService.NewEngineInstance(typeof(RockLiquidEngine), engineOptions);

                // Register the common Rock.Lava filters first, then overwrite with the web-based RockFilters as needed.
                RegisterFilters(_rockliquidEngine);
            }

            if (DotLiquidEngineIsEnabled)
            {
                // Initialize the DotLiquid Engine
                var engineOptions = new LavaEngineConfigurationOptions();

                _dotliquidEngine = LavaService.NewEngineInstance(typeof(DotLiquidEngine), engineOptions);

                RegisterFilters(_dotliquidEngine);
            }

            if (FluidEngineIsEnabled)
            {
                // Initialize Fluid Engine
                var engineOptions = new LavaEngineConfigurationOptions();

                _fluidEngine = LavaService.NewEngineInstance(typeof(FluidEngine), engineOptions);

                RegisterFilters(_fluidEngine);
            }
        }
示例#18
0
        public void IncludeStatement_ModifyingLocalVariableSameAsOuterVariable_ModifiesOuterVariable()
        {
            var fileSystem = GetMockFileProvider();

            var input = @"
{% assign a = 'a' %}
Outer 'a' = {{ a }}
{% include '_assign.lava' %}
Outer 'a' =  {{ a }}
";

            if (LavaIntegrationTestHelper.DotLiquidEngineIsEnabled)
            {
                var expectedOutputLiquid = @"
Outer 'a' = a
Included 'a' = b
Outer 'a' = b
";

                var testEngineDotLiquid = LavaService.NewEngineInstance(typeof(DotLiquidEngine), new LavaEngineConfigurationOptions {
                    FileSystem = fileSystem
                });

                TestHelper.AssertTemplateOutput(testEngineDotLiquid, expectedOutputLiquid, input);
            }

            if (LavaIntegrationTestHelper.FluidEngineIsEnabled)
            {
                // The behavior in Fluid is different from standard Liquid.
                // The include file maintains a local scope for new variables.
                var expectedOutputFluid = @"
Outer 'a' = a
Included 'a' = b
Outer 'a' = a
";

                var testEngineFluid = LavaService.NewEngineInstance(typeof(FluidEngine), new LavaEngineConfigurationOptions {
                    FileSystem = fileSystem
                });

                TestHelper.AssertTemplateOutput(testEngineFluid, expectedOutputFluid, input);
            }
        }
示例#19
0
        public void Configuration_SetDefaultEntityCommandExecute_IsEnabledForNewDefaultContext()
        {
            var options = new LavaEngineConfigurationOptions
            {
                DefaultEnabledCommands = new List <string> {
                    "Execute"
                }
            };

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                var testEngine = LavaService.NewEngineInstance(engine.GetType(), options);

                var context = testEngine.NewRenderContext();

                var enabledCommands = context.GetEnabledCommands();

                Assert.That.Contains(enabledCommands, "Execute");
            });
        }
示例#20
0
        public void IncludeStatement_ForFileContainingMergeFields_ReturnsMergedOutput()
        {
            var fileSystem = GetMockFileProvider();

            var input = @"
Name: Ted Decker

** Contact
{% include '_contact.lava' %}
**
";

            var expectedOutput = @"
Name: Ted Decker

** Contact
Mobile: (623) 555-3323
Home: (623) 555-3322
Work : (623) 555-2444
Email: [email protected]
**
";

            var mergeValues = new LavaDataDictionary {
                { "mobilePhone", "(623) 555-3323" }, { "homePhone", "(623) 555-3322" }, { "workPhone", "(623) 555-2444" }, { "email", "*****@*****.**" }
            };

            var options = new LavaTestRenderOptions {
                MergeFields = mergeValues
            };

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                // Create a new engine instance of the same type, but with a test file system configuration.
                var testEngine = LavaService.NewEngineInstance(engine.GetType(), new LavaEngineConfigurationOptions {
                    FileSystem = fileSystem
                });

                TestHelper.AssertTemplateOutput(testEngine, expectedOutput, input, options);
            });
        }
        /// <summary>
        /// Handles the Click event of the btnDelete control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnDelete_Click(object sender, EventArgs e)
        {
            LinkButton   btn           = ( LinkButton )sender;
            RepeaterItem item          = ( RepeaterItem )btn.NamingContainer;
            HiddenField  hfShortcodeId = ( HiddenField )item.FindControl("hfShortcodeId");

            var rockContext = new RockContext();
            LavaShortcodeService lavaShortcodeService = new LavaShortcodeService(rockContext);
            LavaShortcode        lavaShortcode        = lavaShortcodeService.Get(hfShortcodeId.ValueAsInt());

            if (lavaShortcode != null)
            {
                // unregister the shortcode
                LavaService.DeregisterShortcode(lavaShortcode.TagName);

                lavaShortcodeService.Delete(lavaShortcode);
                rockContext.SaveChanges();
            }

            LoadLavaShortcodes();
        }
示例#22
0
        public void EventCalendarItemAllowsEventItemSummary()
        {
            RockEntityBlock.RegisterEntityCommands(LavaService.GetCurrentEngine());

            var expectedOutput = @"
3 [2]: <br>
5 [3]: <br>
7 [4]: <br>
8 [5]: Scelerisque eleifend donec pretium vulputate sapien. Proin sed libero enim sed faucibus turpis in eu mi. Vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Egestas erat imperdiet sed euismod. Metus aliquam eleifend mi in.<br>
".Trim();

            var mergeFields = new Dictionary <string, object>();

            var    lava   = @"{% eventcalendaritem where:'EventCalendarId == 1' %}
{% for item in eventcalendaritemItems %}
{{ item.Id }} [{{ item.EventItemId }}]: {{ item.EventItem.Summary }}<br>
{% endfor %}
{% endeventcalendaritem %}";
            string output = lava.ResolveMergeFields(mergeFields, "RockEntity").Trim();

            Assert.That.AreEqualIgnoreNewline(expectedOutput, output);
        }
示例#23
0
        private static void RegisterLavaEngines()
        {
            // Register the RockLiquid Engine (pre-v13).
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engineOptions = new LavaEngineConfigurationOptions();

                var rockLiquidEngine = new RockLiquidEngine();

                rockLiquidEngine.Initialize(engineOptions);

                return(rockLiquidEngine);
            });

            // Register the DotLiquid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engineOptions = GetCurrentEngineOptions();

                var dotLiquidEngine = new DotLiquidEngine();

                dotLiquidEngine.Initialize(engineOptions);

                return(dotLiquidEngine);
            });

            // Register the Fluid Engine.
            LavaService.RegisterEngine((engineServiceType, options) =>
            {
                var engineOptions = GetCurrentEngineOptions();

                var fluidEngine = new FluidEngine();

                fluidEngine.Initialize(engineOptions);

                return(fluidEngine);
            });
        }
示例#24
0
        public void IncludeStatement_ForNonexistentFile_ShouldRenderError()
        {
            var fileSystem = GetMockFileProvider();

            var input = @"
{% include '_unknown.lava' %}
";

            TestHelper.ExecuteForActiveEngines((engine) =>
            {
                var testEngine = LavaService.NewEngineInstance(engine.GetType(), new LavaEngineConfigurationOptions {
                    FileSystem = fileSystem
                });

                var result = testEngine.RenderTemplate(input, new LavaRenderParameters {
                    ExceptionHandlingStrategy = ExceptionHandlingStrategySpecifier.RenderToOutput
                });

                TestHelper.DebugWriteRenderResult(engine, input, result.Text);

                Assert.That.Contains(result.Error.Messages().JoinStrings("//"), "File Load Failed.");
            });
        }
示例#25
0
        private void Render()
        {
            string content = null;

            try
            {
                PageCache currentPage = PageCache.Get(RockPage.PageId);
                PageCache rootPage    = null;

                var pageRouteValuePair = GetAttributeValue(AttributeKey.RootPage).SplitDelimitedValues(false).AsGuidOrNullList();
                if (pageRouteValuePair.Any() && pageRouteValuePair[0].HasValue && !pageRouteValuePair[0].Value.IsEmpty())
                {
                    rootPage = PageCache.Get(pageRouteValuePair[0].Value);
                }

                // If a root page was not found, use current page
                if (rootPage == null)
                {
                    rootPage = currentPage;
                }

                int levelsDeep = Convert.ToInt32(GetAttributeValue(AttributeKey.NumberofLevels));

                Dictionary <string, string> pageParameters = null;
                if (GetAttributeValue(AttributeKey.IncludeCurrentParameters).AsBoolean())
                {
                    pageParameters = CurrentPageReference.Parameters;
                }

                NameValueCollection queryString = null;
                if (GetAttributeValue(AttributeKey.IncludeCurrentQueryString).AsBoolean())
                {
                    queryString = CurrentPageReference.QueryString;
                }

                // Get list of pages in current page's hierarchy
                var pageHeirarchy = new List <int>();
                if (currentPage != null)
                {
                    pageHeirarchy = currentPage.GetPageHierarchy().Select(p => p.Id).ToList();
                }

                // Get default merge fields.
                var pageProperties = Rock.Lava.LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson);
                pageProperties.Add("Site", GetSiteProperties(RockPage.Site));
                pageProperties.Add("IncludePageList", GetIncludePageList());
                pageProperties.Add("CurrentPage", this.PageCache);

                using (var rockContext = new RockContext())
                {
                    pageProperties.Add("Page", rootPage.GetMenuProperties(levelsDeep, CurrentPerson, rockContext, pageHeirarchy, pageParameters, queryString));
                }

                if (LavaService.RockLiquidIsEnabled)
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    var lavaTemplate = GetTemplate();
#pragma warning restore CS0618 // Type or member is obsolete

                    // Apply Enabled Lava Commands
                    var enabledCommands = GetAttributeValue(AttributeKey.EnabledLavaCommands);
                    lavaTemplate.Registers.AddOrReplace("EnabledCommands", enabledCommands);

                    content = lavaTemplate.Render(Hash.FromDictionary(pageProperties));

                    // Check for Lava rendering errors.
                    if (lavaTemplate.Errors.Any())
                    {
                        throw lavaTemplate.Errors.First();
                    }
                }
                else
                {
                    var templateText = GetAttributeValue(AttributeKey.Template);

                    // Apply Enabled Lava Commands
                    var lavaContext = LavaService.NewRenderContext(pageProperties);

                    var enabledCommands = GetAttributeValue(AttributeKey.EnabledLavaCommands);

                    lavaContext.SetEnabledCommands(enabledCommands.SplitDelimitedValues());

                    var result = LavaService.RenderTemplate(templateText,
                                                            new LavaRenderParameters {
                        Context = lavaContext, CacheKey = CacheKey()
                    });

                    content = result.Text;

                    if (result.HasErrors)
                    {
                        throw result.GetLavaException("PageMenu Block Lava Error");
                    }
                }

                phContent.Controls.Clear();
                phContent.Controls.Add(new LiteralControl(content));
            }
            catch (Exception ex)
            {
                LogException(ex);

                // Create a block showing the error and the attempted content render.
                // Show the error first to ensure that it is visible, because the rendered content may disrupt subsequent output if it is malformed.
                StringBuilder errorMessage = new StringBuilder();
                errorMessage.Append("<div class='alert alert-warning'>");
                errorMessage.Append("<h4>Warning</h4>");
                errorMessage.Append("An error has occurred while generating the page menu. Error details:<br/>");
                errorMessage.Append(ex.Message);

                if (!string.IsNullOrWhiteSpace(content))
                {
                    errorMessage.Append("<h4>Rendered Content</h4>");
                    errorMessage.Append(content);
                    errorMessage.Append("</div>");
                }

                phContent.Controls.Add(new LiteralControl(errorMessage.ToString()));
            }
        }
示例#26
0
        private void Map()
        {
            string mapStylingFormat = @"
                        <style>
                            #map_wrapper {{
                                height: {0}px;
                            }}

                            #map_canvas {{
                                width: 100%;
                                height: 100%;
                                border-radius: var(--border-radius-base);
                            }}
                        </style>";

            lMapStyling.Text = string.Format(mapStylingFormat, GetAttributeValue("MapHeight"));

            string settingGroupTypeId     = GetAttributeValue("GroupType");
            string queryStringGroupTypeId = PageParameter("GroupTypeId");

            if ((string.IsNullOrWhiteSpace(settingGroupTypeId) && string.IsNullOrWhiteSpace(queryStringGroupTypeId)))
            {
                pnlMap.Visible = false;
                lMessages.Text = "<div class='alert alert-warning'><strong>Group Mapper</strong> Please configure a group type to display as a block setting or pass a GroupTypeId as a query parameter.</div>";
            }
            else
            {
                var rockContext = new RockContext();

                pnlMap.Visible = true;

                int groupsMapped    = 0;
                int groupsWithNoGeo = 0;

                StringBuilder sbGroupJson       = new StringBuilder();
                StringBuilder sbGroupsWithNoGeo = new StringBuilder();

                Guid?groupType   = null;
                int  groupTypeId = -1;

                if (!string.IsNullOrWhiteSpace(settingGroupTypeId))
                {
                    groupType = new Guid(settingGroupTypeId);
                }
                else
                {
                    if (!string.IsNullOrWhiteSpace(queryStringGroupTypeId) && Int32.TryParse(queryStringGroupTypeId, out groupTypeId))
                    {
                        groupType = new GroupTypeService(rockContext).Get(groupTypeId).Guid;
                    }
                }

                if (groupType != null)
                {
                    Template      template     = null;
                    ILavaTemplate lavaTemplate = null;

                    if (LavaService.RockLiquidIsEnabled)
                    {
                        if (GetAttributeValue("ShowMapInfoWindow").AsBoolean())
                        {
                            template = Template.Parse(GetAttributeValue("InfoWindowContents").Trim());

                            LavaHelper.VerifyParseTemplateForCurrentEngine(GetAttributeValue("InfoWindowContents").Trim());
                        }
                        else
                        {
                            template = Template.Parse(string.Empty);
                        }
                    }
                    else
                    {
                        string templateContent;

                        if (GetAttributeValue("ShowMapInfoWindow").AsBoolean())
                        {
                            templateContent = GetAttributeValue("InfoWindowContents").Trim();
                        }
                        else
                        {
                            templateContent = string.Empty;
                        }

                        var parseResult = LavaService.ParseTemplate(templateContent);

                        lavaTemplate = parseResult.Template;
                    }

                    var groupPageRef = new PageReference(GetAttributeValue("GroupDetailPage"));

                    // create group detail link for use in map's info window
                    var personPageParams = new Dictionary <string, string>();
                    personPageParams.Add("PersonId", string.Empty);
                    var personProfilePage = LinkedPageUrl("PersonProfilePage", personPageParams);

                    var groupEntityType = EntityTypeCache.Get(typeof(Group));
                    var dynamicGroups   = new List <dynamic>();


                    // Create query to get attribute values for selected attribute keys.
                    var attributeKeys   = GetAttributeValue("Attributes").SplitDelimitedValues().ToList();
                    var attributeValues = new AttributeValueService(rockContext).Queryable("Attribute")
                                          .Where(v =>
                                                 v.Attribute.EntityTypeId == groupEntityType.Id &&
                                                 attributeKeys.Contains(v.Attribute.Key));

                    GroupService groupService = new GroupService(rockContext);
                    var          groups       = groupService.Queryable()
                                                .Where(g => g.GroupType.Guid == groupType)
                                                .Select(g => new
                    {
                        Group           = g,
                        GroupId         = g.Id,
                        GroupName       = g.Name,
                        GroupGuid       = g.Guid,
                        GroupMemberTerm = g.GroupType.GroupMemberTerm,
                        GroupCampus     = g.Campus.Name,
                        IsActive        = g.IsActive,
                        GroupLocation   = g.GroupLocations
                                          .Where(l => l.Location.GeoPoint != null)
                                          .Select(l => new
                        {
                            l.Location.Street1,
                            l.Location.Street2,
                            l.Location.City,
                            l.Location.State,
                            PostalCode = l.Location.PostalCode,
                            Latitude   = l.Location.GeoPoint.Latitude,
                            Longitude  = l.Location.GeoPoint.Longitude,
                            Name       = l.GroupLocationTypeValue.Value
                        }).FirstOrDefault(),
                        GroupMembers    = g.Members,
                        AttributeValues = attributeValues
                                          .Where(v => v.EntityId == g.Id)
                    });


                    if (GetAttributeValue("IncludeInactiveGroups").AsBoolean() == false)
                    {
                        groups = groups.Where(g => g.IsActive == true);
                    }

                    // Create dynamic object to include attribute values
                    foreach (var group in groups)
                    {
                        dynamic dynGroup = new ExpandoObject();
                        dynGroup.GroupId   = group.GroupId;
                        dynGroup.GroupName = group.GroupName;

                        // create group detail link for use in map's info window
                        if (groupPageRef.PageId > 0)
                        {
                            var groupPageParams = new Dictionary <string, string>();
                            groupPageParams.Add("GroupId", group.GroupId.ToString());
                            groupPageRef.Parameters  = groupPageParams;
                            dynGroup.GroupDetailPage = groupPageRef.BuildUrl();
                        }
                        else
                        {
                            dynGroup.GroupDetailPage = string.Empty;
                        }

                        dynGroup.PersonProfilePage = personProfilePage;
                        dynGroup.GroupMemberTerm   = group.GroupMemberTerm;
                        dynGroup.GroupCampus       = group.GroupCampus;
                        dynGroup.GroupLocation     = group.GroupLocation;

                        var groupAttributes = new List <dynamic>();
                        foreach (AttributeValue value in group.AttributeValues)
                        {
                            var attrCache     = AttributeCache.Get(value.AttributeId);
                            var dictAttribute = new Dictionary <string, object>();
                            dictAttribute.Add("Key", attrCache.Key);
                            dictAttribute.Add("Name", attrCache.Name);

                            if (attrCache != null)
                            {
                                dictAttribute.Add("Value", attrCache.FieldType.Field.FormatValueAsHtml(null, attrCache.EntityTypeId, group.GroupId, value.Value, attrCache.QualifierValues, false));
                            }
                            else
                            {
                                dictAttribute.Add("Value", value.Value);
                            }

                            groupAttributes.Add(dictAttribute);
                        }

                        dynGroup.Attributes = groupAttributes;

                        var groupMembers = new List <dynamic>();
                        foreach (GroupMember member in group.GroupMembers)
                        {
                            var dictMember = new Dictionary <string, object>();
                            dictMember.Add("Id", member.Person.Id);
                            dictMember.Add("GuidP", member.Person.Guid);
                            dictMember.Add("NickName", member.Person.NickName);
                            dictMember.Add("LastName", member.Person.LastName);
                            dictMember.Add("RoleName", member.GroupRole.Name);
                            dictMember.Add("Email", member.Person.Email);
                            dictMember.Add("PhotoGuid", member.Person.Photo != null ? member.Person.Photo.Guid : Guid.Empty);

                            var phoneTypes = new List <dynamic>();
                            foreach (PhoneNumber p in member.Person.PhoneNumbers)
                            {
                                var dictPhoneNumber = new Dictionary <string, object>();
                                dictPhoneNumber.Add("Name", p.NumberTypeValue.Value);
                                dictPhoneNumber.Add("Number", p.ToString());
                                phoneTypes.Add(dictPhoneNumber);
                            }

                            dictMember.Add("PhoneTypes", phoneTypes);

                            groupMembers.Add(dictMember);
                        }

                        dynGroup.GroupMembers = groupMembers;

                        dynamicGroups.Add(dynGroup);
                    }

                    foreach (var group in dynamicGroups)
                    {
                        if (group.GroupLocation != null && group.GroupLocation.Latitude != null)
                        {
                            groupsMapped++;
                            var groupDict = group as IDictionary <string, object>;

                            string infoWindow;

                            if (LavaService.RockLiquidIsEnabled)
                            {
                                infoWindow = template.Render(Hash.FromDictionary(groupDict)).Replace("\n", string.Empty);
                            }
                            else
                            {
                                var result = LavaService.RenderTemplate(lavaTemplate, groupDict);

                                infoWindow = result.Text;

                                if (!result.HasErrors)
                                {
                                    infoWindow = infoWindow.Replace("\n", string.Empty);
                                }
                            }

                            sbGroupJson.Append(string.Format(
                                                   @"{{ ""name"":""{0}"" , ""latitude"":""{1}"", ""longitude"":""{2}"", ""infowindow"":""{3}"" }},",
                                                   HttpUtility.HtmlEncode(group.GroupName),
                                                   group.GroupLocation.Latitude,
                                                   group.GroupLocation.Longitude,
                                                   HttpUtility.HtmlEncode(infoWindow)));
                        }
                        else
                        {
                            groupsWithNoGeo++;

                            if (!string.IsNullOrWhiteSpace(group.GroupDetailPage))
                            {
                                sbGroupsWithNoGeo.Append(string.Format(@"<li><a href='{0}'>{1}</a></li>", group.GroupDetailPage, group.GroupName));
                            }
                            else
                            {
                                sbGroupsWithNoGeo.Append(string.Format(@"<li>{0}</li>", group.GroupName));
                            }
                        }
                    }

                    string groupJson = sbGroupJson.ToString();

                    // remove last comma
                    if (groupJson.Length > 0)
                    {
                        groupJson = groupJson.Substring(0, groupJson.Length - 1);
                    }

                    // add styling to map
                    string styleCode   = "null";
                    string markerColor = "FE7569";

                    DefinedValueCache dvcMapStyle = DefinedValueCache.Get(GetAttributeValue("MapStyle").AsGuid());
                    if (dvcMapStyle != null)
                    {
                        styleCode = dvcMapStyle.GetAttributeValue("DynamicMapStyle");
                        var colors = dvcMapStyle.GetAttributeValue("Colors").Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                        if (colors.Any())
                        {
                            markerColor = colors.First().Replace("#", "");
                        }
                    }

                    // write script to page
                    string mapScriptFormat = @" <script>
                                                Sys.Application.add_load(function () {{
                                                    var groupData = JSON.parse('{{ ""groups"" : [ {0} ]}}');
                                                    var showInfoWindow = {1};
                                                    var mapStyle = {2};
                                                    var pinColor = '{3}';

                                                    var pinImage = {{
                                                        path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z',
                                                        fillColor: '#' + pinColor,
                                                        fillOpacity: 1,
                                                        strokeColor: '#000',
                                                        strokeWeight: 1,
                                                        scale: 1,
                                                        labelOrigin: new google.maps.Point(0,-28)
                                                    }};

                                                    initializeMap();

                                                    function initializeMap() {{
                                                        console.log(mapStyle);
                                                        var map;
                                                        var bounds = new google.maps.LatLngBounds();
                                                        var mapOptions = {{
                                                            mapTypeId: 'roadmap',
                                                            styles: mapStyle
                                                        }};

                                                        // Display a map on the page
                                                        map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
                                                        map.setTilt(45);

                                                        // Display multiple markers on a map
                                                        if (showInfoWindow) {{
                                                            var infoWindow = new google.maps.InfoWindow(), marker, i;
                                                        }}

                                                        // Loop through our array of markers & place each one on the map
                                                        $.each(groupData.groups, function (i, group) {{

                                                            var position = new google.maps.LatLng(group.latitude, group.longitude);
                                                            bounds.extend(position);

                                                            marker = new google.maps.Marker({{
                                                                position: position,
                                                                map: map,
                                                                title: htmlDecode(group.name),
                                                                icon: pinImage,
                                                                label: String.fromCharCode(9679)
                                                            }});

                                                            // Allow each marker to have an info window
                                                            if (showInfoWindow) {{
                                                                google.maps.event.addListener(marker, 'click', (function (marker, i) {{
                                                                    return function () {{
                                                                        infoWindow.setContent(htmlDecode(groupData.groups[i].infowindow));
                                                                        infoWindow.open(map, marker);
                                                                    }}
                                                                }})(marker, i));
                                                            }}

                                                            map.fitBounds(bounds);

                                                        }});

                                                        // Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
                                                        var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {{
                                                            google.maps.event.removeListener(boundsListener);
                                                        }});
                                                    }}

                                                    function htmlDecode(input) {{
                                                        var e = document.createElement('div');
                                                        e.innerHTML = input;
                                                        return e.childNodes.length === 0 ? """" : e.childNodes[0].nodeValue;
                                                    }}
                                                }});
                                            </script>";

                    string mapScript = string.Format(
                        mapScriptFormat,
                        groupJson,
                        GetAttributeValue("ShowMapInfoWindow").AsBoolean().ToString().ToLower(),
                        styleCode,
                        markerColor);

                    ScriptManager.RegisterStartupScript(pnlMap, pnlMap.GetType(), "group-mapper-script", mapScript, false);

                    if (groupsMapped == 0)
                    {
                        pnlMap.Visible = false;
                        lMessages.Text = @" <p>
                                                <div class='alert alert-warning fade in'>No groups were able to be mapped. You may want to check your configuration.</div>
                                        </p>";
                    }
                    else
                    {
                        // output any warnings
                        if (groupsWithNoGeo > 0)
                        {
                            string messagesFormat = @" <p>
                                                <div class='alert alert-warning fade in'>Some groups could not be mapped.
                                                    <button type='button' class='close' data-dismiss='alert' aria-hidden='true'><i class='fa fa-times'></i></button>
                                                    <small><a data-toggle='collapse' data-parent='#accordion' href='#map-error-details'>Show Details</a></small>
                                                    <div id='map-error-details' class='collapse'>
                                                        <p class='margin-t-sm'>
                                                            <strong>Groups That Could Not Be Mapped</strong>
                                                            <ul>
                                                                {0}
                                                            </ul>
                                                        </p>
                                                    </div>
                                                </div>
                                            </p>";
                            lMessages.Text = string.Format(messagesFormat, sbGroupsWithNoGeo.ToString());
                        }
                    }
                }
                else
                {
                    pnlMap.Visible = false;
                    lMessages.Text = "<div class='alert alert-warning'><strong>Group Mapper</strong> Please configure a group type to display and a location type to use.</div>";
                }
            }
        }
        /// <summary>
        /// Handles the OnSave event of the masterPage control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void masterPage_OnSave(object sender, EventArgs e)
        {
            bool reloadPage = false;
            int  blockId    = Convert.ToInt32(PageParameter("BlockId"));

            if (!Page.IsValid)
            {
                return;
            }

            var rockContext = new RockContext();

            rockContext.WrapTransaction(() =>
            {
                var blockService = new Rock.Model.BlockService(rockContext);
                var block        = blockService.Get(blockId);

                block.LoadAttributes();

                block.Name                = tbBlockName.Text;
                block.CssClass            = tbCssClass.Text;
                block.PreHtml             = cePreHtml.Text;
                block.PostHtml            = cePostHtml.Text;
                block.OutputCacheDuration = 0; //Int32.Parse( tbCacheDuration.Text );

                avcAttributes.GetEditValues(block);
                avcMobileAttributes.GetEditValues(block);
                avcAdvancedAttributes.GetEditValues(block);

                foreach (var kvp in CustomSettingsProviders)
                {
                    kvp.Key.WriteSettingsToEntity(block, kvp.Value, rockContext);
                }

                SaveCustomColumnsConfigToViewState();
                if (this.CustomGridColumnsConfigState != null && this.CustomGridColumnsConfigState.ColumnsConfig.Any())
                {
                    if (!block.Attributes.Any(a => a.Key == CustomGridColumnsConfig.AttributeKey))
                    {
                        block.Attributes.Add(CustomGridColumnsConfig.AttributeKey, null);
                    }

                    var customGridColumnsJSON = this.CustomGridColumnsConfigState.ToJson();
                    if (block.GetAttributeValue(CustomGridColumnsConfig.AttributeKey) != customGridColumnsJSON)
                    {
                        block.SetAttributeValue(CustomGridColumnsConfig.AttributeKey, customGridColumnsJSON);

                        // if the CustomColumns changed, reload the whole page so that we can avoid issues with columns changing between postbacks
                        reloadPage = true;
                    }
                }
                else
                {
                    if (block.Attributes.Any(a => a.Key == CustomGridColumnsConfig.AttributeKey))
                    {
                        if (block.GetAttributeValue(CustomGridColumnsConfig.AttributeKey) != null)
                        {
                            // if the CustomColumns were removed, reload the whole page so that we can avoid issues with columns changing between postbacks
                            reloadPage = true;
                        }

                        block.SetAttributeValue(CustomGridColumnsConfig.AttributeKey, null);
                    }
                }

                // Save the custom action configs
                SaveCustomActionsConfigToViewState();

                if (CustomActionsConfigState != null && CustomActionsConfigState.Any())
                {
                    if (!block.Attributes.Any(a => a.Key == CustomGridOptionsConfig.CustomActionsConfigsAttributeKey))
                    {
                        block.Attributes.Add(CustomGridOptionsConfig.CustomActionsConfigsAttributeKey, null);
                    }

                    var json = CustomActionsConfigState.ToJson();

                    if (block.GetAttributeValue(CustomGridOptionsConfig.CustomActionsConfigsAttributeKey) != json)
                    {
                        block.SetAttributeValue(CustomGridOptionsConfig.CustomActionsConfigsAttributeKey, json);

                        // if the actions changed, reload the whole page so that we can avoid issues with launchers changing between postbacks
                        reloadPage = true;
                    }
                }
                else
                {
                    if (block.Attributes.Any(a => a.Key == CustomGridOptionsConfig.CustomActionsConfigsAttributeKey))
                    {
                        if (block.GetAttributeValue(CustomGridOptionsConfig.CustomActionsConfigsAttributeKey) != null)
                        {
                            // if the actions were removed, reload the whole page so that we can avoid issues with launchers changing between postbacks
                            reloadPage = true;
                        }

                        block.SetAttributeValue(CustomGridOptionsConfig.CustomActionsConfigsAttributeKey, null);
                    }
                }

                if (tglEnableStickyHeader.Checked)
                {
                    if (!block.Attributes.Any(a => a.Key == CustomGridOptionsConfig.EnableStickyHeadersAttributeKey))
                    {
                        block.Attributes.Add(CustomGridOptionsConfig.EnableStickyHeadersAttributeKey, null);
                    }
                }

                if (block.GetAttributeValue(CustomGridOptionsConfig.EnableStickyHeadersAttributeKey).AsBoolean() != tglEnableStickyHeader.Checked)
                {
                    block.SetAttributeValue(CustomGridOptionsConfig.EnableStickyHeadersAttributeKey, tglEnableStickyHeader.Checked.ToTrueFalse());

                    // if EnableStickyHeaders changed, reload the page
                    reloadPage = true;
                }

                // Save the default launcher enabled setting
                var isDefaultLauncherEnabled = tglEnableDefaultWorkflowLauncher.Checked;

                if (isDefaultLauncherEnabled && !block.Attributes.Any(a => a.Key == CustomGridOptionsConfig.EnableDefaultWorkflowLauncherAttributeKey))
                {
                    block.Attributes.Add(CustomGridOptionsConfig.EnableDefaultWorkflowLauncherAttributeKey, null);
                }

                if (block.GetAttributeValue(CustomGridOptionsConfig.EnableDefaultWorkflowLauncherAttributeKey).AsBoolean() != isDefaultLauncherEnabled)
                {
                    block.SetAttributeValue(CustomGridOptionsConfig.EnableDefaultWorkflowLauncherAttributeKey, isDefaultLauncherEnabled.ToTrueFalse());

                    // since the setting changed, reload the page
                    reloadPage = true;
                }

                rockContext.SaveChanges();
                block.SaveAttributeValues(rockContext);

                // If this is a PageMenu block then we need to also flush the lava template cache for the block here.
                // Changes to the PageMenu block configuration will handle this in the PageMenu_BlockUpdated event handler,
                // but here we address the situation where child pages are modified using the "CMS Configuration | Pages" menu option.
                if (block.BlockType.Guid == Rock.SystemGuid.BlockType.PAGE_MENU.AsGuid())
                {
                    var cacheKey = string.Format("Rock:PageMenu:{0}", block.Id);

                    if (LavaService.RockLiquidIsEnabled)
                    {
#pragma warning disable CS0618 // Type or member is obsolete
                        LavaTemplateCache.Remove(cacheKey);
#pragma warning restore CS0618 // Type or member is obsolete
                    }

                    LavaService.RemoveTemplateCacheEntry(cacheKey);
                }

                StringBuilder scriptBuilder = new StringBuilder();

                if (reloadPage)
                {
                    scriptBuilder.AppendLine("window.parent.location.reload();");
                }
                else
                {
                    scriptBuilder.AppendLine(string.Format("window.parent.Rock.controls.modal.close('BLOCK_UPDATED:{0}');", blockId));
                }

                ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "close-modal", scriptBuilder.ToString(), true);
            });
        }
        /// <summary>
        /// Uses Lava to resolve any merge codes within the content using the values in the merge objects.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="mergeObjects">The merge objects.</param>
        /// <param name="enabledLavaCommands">The enabled lava commands.</param>
        /// <param name="encodeStrings">if set to <c>true</c> [encode strings].</param>
        /// <param name="throwExceptionOnErrors">if set to <c>true</c> [throw exception on errors].</param>
        /// <returns></returns>
        public static string RenderLava(this string content, IDictionary <string, object> mergeObjects, IEnumerable <string> enabledLavaCommands, bool encodeStrings = false, bool throwExceptionOnErrors = false)
        {
            try
            {
                if (!content.HasMergeFields())
                {
                    return(content ?? string.Empty);
                }

                if (mergeObjects == null)
                {
                    mergeObjects = new Dictionary <string, object>();
                }

                if (GlobalAttributesCache.Get().LavaSupportLevel == Lava.LavaSupportLevel.LegacyWithWarning && mergeObjects.ContainsKey("GlobalAttribute"))
                {
                    if (hasLegacyGlobalAttributeLavaMergeFields.IsMatch(content))
                    {
                        Rock.Model.ExceptionLogService.LogException(new Rock.Lava.LegacyLavaSyntaxDetectedException("GlobalAttribute", ""), System.Web.HttpContext.Current);
                    }
                }

                var context = LavaService.NewRenderContext(mergeObjects);

                if (enabledLavaCommands != null)
                {
                    context.SetEnabledCommands(enabledLavaCommands);
                }

                var renderParameters = new LavaRenderParameters {
                    Context = context
                };

                renderParameters.ShouldEncodeStringsAsXml = encodeStrings;

                // Try and parse the template, or retrieve it from the cache if it has been previously parsed.
                var result = LavaService.RenderTemplate(content, renderParameters);

                if (result.HasErrors)
                {
                    throw result.GetLavaException();
                }

                return(result.Text);
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Do nothing...it's just a Lava PageRedirect that just happened.
                return(string.Empty);
            }
            catch (Exception ex)
            {
                if (throwExceptionOnErrors)
                {
                    throw;
                }
                else
                {
                    ExceptionLogService.LogException(ex, System.Web.HttpContext.Current);
                    return("Error resolving Lava merge fields: " + ex.Message);
                }
            }
        }
示例#29
0
        private static string ResolveMergeFieldsInternal(this string content, IDictionary <string, object> mergeObjects, Person currentPersonOverride, string enabledLavaCommands, bool encodeStrings = false, bool throwExceptionOnErrors = false)
        {
            try
            {
                if (!content.IsLavaTemplate())
                {
                    return(content ?? string.Empty);
                }

                if (mergeObjects == null)
                {
                    mergeObjects = new Dictionary <string, object>();
                }

                if (GlobalAttributesCache.Get().LavaSupportLevel == Lava.LavaSupportLevel.LegacyWithWarning && mergeObjects.ContainsKey("GlobalAttribute"))
                {
                    if (hasLegacyGlobalAttributeLavaMergeFields.IsMatch(content))
                    {
                        Rock.Model.ExceptionLogService.LogException(new Rock.Lava.LegacyLavaSyntaxDetectedException("GlobalAttribute", ""), System.Web.HttpContext.Current);
                    }
                }

                if (LavaService.RockLiquidIsEnabled)
                {
                    // If RockLiquid mode is enabled, try to render uncached templates using the current Lava engine and record any errors that occur.
                    // Render the final output using the RockLiquid legacy code.
                    var engine = LavaService.GetCurrentEngine();

                    string lavaEngineOutput = null;
                    string rockLiquidOutput;

                    if (engine != null)
                    {
                        var cacheKey = engine.TemplateCacheService.GetCacheKeyForTemplate(content);
                        var isCached = engine.TemplateCacheService.ContainsKey(cacheKey);

                        if (!isCached)
                        {
                            // Verify the Lava template using the current LavaEngine.
                            // Although it would improve performance, we can't execute this task on a background thread because some Lava filters require access to the current HttpRequest.
                            try
                            {
                                var result = ResolveMergeFieldsWithCurrentLavaEngine(content, mergeObjects, currentPersonOverride, enabledLavaCommands, encodeStrings);

                                // If an exception occurred during the render process, make sure it will be caught and logged.
                                if (result.HasErrors &&
                                    engine.ExceptionHandlingStrategy != ExceptionHandlingStrategySpecifier.Throw)
                                {
                                    throw result.Error;
                                }

                                lavaEngineOutput = result.Text;
                            }
                            catch (System.Threading.ThreadAbortException)
                            {
                                // Ignore abort error caused by Lava PageRedirect filter.
                            }
                            catch (Exception ex)
                            {
                                // Log the exception and continue, because the final render will be performed by RockLiquid.
                                ExceptionLogService.LogException(new LavaException("Lava Verification Error: Parse template failed.", ex), System.Web.HttpContext.Current);

                                // Add a placeholder to prevent this invalid template from being recompiled.
                                var emptyTemplate = engine.ParseTemplate(string.Empty).Template;

                                engine.TemplateCacheService.AddTemplate(emptyTemplate, cacheKey);
                            }
                        }
                    }

#pragma warning disable CS0618 // Type or member is obsolete
                    rockLiquidOutput = ResolveMergeFieldsForRockLiquid(content, mergeObjects, currentPersonOverride, enabledLavaCommands, encodeStrings, throwExceptionOnErrors);
#pragma warning restore CS0618 // Type or member is obsolete

                    if (lavaEngineOutput != null)
                    {
                        // Compare output to check for a possible mismatch, ignoring whitespace.
                        // This is a simplified content check, but we can't require an exact match because output may contain unique Guid and DateTime values.
                        var compareRockLiquid = _regexRemoveWhitespace.Replace(rockLiquidOutput, string.Empty);
                        var compareLavaEngine = _regexRemoveWhitespace.Replace(lavaEngineOutput, string.Empty);

                        if (compareLavaEngine.Length != compareRockLiquid.Length)
                        {
                            // The LavaEngine has produced different output from RockLiquid.
                            // Log the exception, with a simple top-level exception containing a warning message.
                            var renderException = new LavaRenderException(LavaService.CurrentEngineName, content, $"Lava engine render output is unexpected.\n[Expected={rockLiquidOutput},\nActual={lavaEngineOutput}]");

                            ExceptionLogService.LogException(new LavaException("Lava Verification Warning: Render output mismatch.", renderException), System.Web.HttpContext.Current);
                        }
                    }

                    return(rockLiquidOutput);
                }
                else
                {
                    var result = ResolveMergeFieldsWithCurrentLavaEngine(content, mergeObjects, currentPersonOverride, enabledLavaCommands, encodeStrings);

                    return(result.Text);
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Ignore abort errors that may be caused by previous implementations of the Lava PageRedirect filter.
                return(string.Empty);
            }
            catch (Exception ex)
            {
                if (throwExceptionOnErrors)
                {
                    throw;
                }
                else
                {
                    ExceptionLogService.LogException(ex, System.Web.HttpContext.Current);
                    return("Error resolving Lava merge fields: " + ex.Message + "\n[Engine: DotLiquid]");
                }
            }
        }
示例#30
0
        public void WebsiteLavaShortcodeProvider_ModifiedShortcode_ReturnsCorrectVersionAfterModification()
        {
            var options = new LavaEngineConfigurationOptions();

            ILavaTemplateCacheService cacheService = new WebsiteLavaTemplateCacheService();

            options.CacheService = cacheService;

            TestHelper.ExecuteForActiveEngines((defaultEngineInstance) =>
            {
                if (defaultEngineInstance.GetType() == typeof(DotLiquidEngine) ||
                    defaultEngineInstance.GetType() == typeof(RockLiquidEngine))
                {
                    Debug.Write("Shortcode caching is not currently implemented for RockLiquid/DotLiquid.");
                    return;
                }

                var engine = LavaService.NewEngineInstance(defaultEngineInstance.GetType(), options);

                var shortcodeProvider = new TestLavaDynamicShortcodeProvider();

                var rockContext          = new RockContext();
                var lavaShortCodeService = new LavaShortcodeService(rockContext);

                // Create a new Shortcode.
                var shortcodeGuid1 = TestGuids.Shortcodes.ShortcodeTest1.AsGuid();

                var lavaShortcode = lavaShortCodeService.Queryable().FirstOrDefault(x => x.Guid == shortcodeGuid1);

                if (lavaShortcode == null)
                {
                    lavaShortcode = new LavaShortcode();

                    lavaShortCodeService.Add(lavaShortcode);
                }

                lavaShortcode.Guid        = shortcodeGuid1;
                lavaShortcode.TagName     = "TestShortcode1";
                lavaShortcode.Name        = "Test Shortcode 1";
                lavaShortcode.IsActive    = true;
                lavaShortcode.Description = "Test shortcode";
                lavaShortcode.TagType     = TagType.Inline;

                lavaShortcode.Markup = "Hello!";

                rockContext.SaveChanges();

                shortcodeProvider.RegisterShortcode(engine, lavaShortcode);

                // Resolve a template using the new shortcode and verify the result.
                engine.ClearTemplateCache();

                shortcodeProvider.ClearCache();

                LavaService.SetCurrentEngine(engine);

                TestHelper.AssertTemplateOutput(engine, "Hello!", "{[ TestShortcode1 ]}");

                lavaShortcode.Markup = "Goodbye!";

                rockContext.SaveChanges();

                shortcodeProvider.ClearCache();

                engine.ClearTemplateCache();

                TestHelper.AssertTemplateOutput(engine, "Goodbye!", "{[ TestShortcode1 ]}");
            });
        }