/// <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); } } }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); var parms = new Dictionary <string, string>(); parms.Add("return", "results"); parms.Add("statement", "select"); var markupItems = Regex.Matches(resolvedMarkup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { parms.AddOrReplace(itemParts[0].Trim().ToLower(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } } return(parms); }
/// <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 currentPerson = GetCurrentPerson(context); var parms = ParseMarkup(_markup, context); RenderToWriter(parms, currentPerson, result); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var parms = new Dictionary <string, string>(); parms.Add("key", string.Empty); parms.Add("tags", string.Empty); parms.Add("twopass", "false"); parms.Add("duration", "3600"); parms.Add("maxcachesize", "200000"); var markupItems = Regex.Matches(markup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { var value = itemParts[1]; value = MergeLava(value, context); parms.AddOrReplace(itemParts[0].Trim().ToLower(), value.Substring(1, value.Length - 2).Trim()); } } return(parms); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); var parms = new Dictionary <string, string>(); parms.Add(SCHEDULE_ID, ""); parms.Add(ROLE_ID, ""); parms.Add(SHOW_WHEN, "live"); parms.Add(LOOK_AHEAD_DAYS, "30"); parms.Add(SCHEDULE_CATEGORY_ID, ""); parms.Add(AS_AT_DATE, ""); var markupItems = Regex.Matches(resolvedMarkup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { parms.AddOrReplace(itemParts[0].Trim().ToLower(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } } return(parms); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); var parms = new Dictionary <string, string>(); parms.Add("iterator", "results"); parms.Add("searchtype", "wildcard"); var markupItems = Regex.Matches(resolvedMarkup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); if (markupItems.Count == 0) { throw new Exception("No parameters were found in your command. The syntax for a parameter is parmName:'' (note that you must use single quotes)."); } foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { parms.AddOrReplace(itemParts[0].Trim().ToLower(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } } return(parms); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); var parms = new Dictionary <string, string>(); parms.Add("method", "GET"); parms.Add("return", "results"); parms.Add("basicauth", ""); parms.Add("parameters", ""); parms.Add("headers", ""); parms.Add("responsecontenttype", "json"); parms.Add("body", ""); parms.Add("requesttype", "text/plain"); parms.Add("timeout", "12000"); var markupItems = Regex.Matches(resolvedMarkup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { parms.AddOrReplace(itemParts[0].Trim().ToLower(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } } return(parms); }
/// <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 engine = context.GetService <ILavaEngine>(); var tags = engine.GetRegisteredElements(); if (!tags.Any()) { return; } var tagList = new StringBuilder(); tagList.Append("<strong>Lava Tag List</strong>"); tagList.Append("<ul>"); foreach (var kvp in tags.OrderBy(t => t.Key)) { var tag = kvp.Value; var tagName = LavaUtilityHelper.GetShortcodeNameFromLiquidElementName(tag.Name); tagList.Append($"<li>{tagName} - {tag.SystemTypeName}</li>"); } tagList.Append("</ul>"); result.Write(tagList.ToString()); base.OnRender(context, result); }
/// <summary> /// Create a new instance from the specified markup. /// </summary> /// <param name="attributesMarkup"></param> /// <param name="context"></param> /// <returns></returns> public static LavaElementAttributes NewFromMarkup(string attributesMarkup, ILavaRenderContext context) { var attributes = new LavaElementAttributes(); attributes.ParseFromMarkup(attributesMarkup, context); return(attributes); }
/// <summary> /// Override this method to provide custom rendering for the block. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> public virtual void OnRender(ILavaRenderContext context, TextWriter result) { // By default, call the underlying engine to render this element. if (_baseRenderer != null) { _baseRenderer.Render(null, context, result, null); } }
/// <summary> /// Process the specified input template and return the result. /// </summary> /// <param name="inputTemplate"></param> /// <returns></returns> public string GetTemplateOutput(ILavaEngine engine, string inputTemplate, ILavaRenderContext context) { inputTemplate = inputTemplate ?? string.Empty; var result = engine.RenderTemplate(inputTemplate.Trim(), LavaRenderParameters.WithContext(context)); return(result.Text); }
/// <summary> /// Render the provided template in a new context with the specified parameters. /// </summary> /// <param name="inputTemplate"></param> /// <param name="context">The settings applied to the rendering process.</param> /// <returns> /// A LavaRenderResult object, containing the rendered output of the template or any errors encountered during the rendering process. /// </returns> public static LavaRenderResult RenderTemplate(ILavaTemplate inputTemplate, ILavaRenderContext context) { if (_engine == null) { return(null); } return(RenderTemplate(inputTemplate, LavaRenderParameters.WithContext(context))); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); return(ParseResolvedMarkup(resolvedMarkup)); }
/// <summary> /// Gets the rock context from lava context or returns a new one if one does not exist. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public static RockContext GetRockContextFromLavaContext(ILavaRenderContext context) { var rockContext = context.GetInternalField("rock_context", null) as RockContext; if (rockContext == null) { rockContext = new RockContext(); context.SetInternalField("rock_context", rockContext); } return(rockContext); }
/// <summary> /// Parses the Lava Command markup, first resolving merge fields and then harvesting any provided parameters. /// </summary> /// <param name="markup">The Lava Command markup.</param> /// <param name="context">The DotLiquid context.</param> /// <param name="parms"> /// A dictionary into which any parameters discovered within the <paramref name="markup"/> will be added or replaced. /// Default values may be pre-loaded into this collection, and will be overwritten if a matching key is present within the <paramref name="markup"/>. /// Note that parameter keys should be added in lower case. /// <para> /// When searching the <paramref name="markup"/> for key/value parameter pairs, the following <see cref="Regex"/> pattern will be used: @"\S+:('[^']+'|\d+)". /// This means that the following patterns will be matched: "key:'value'" OR "key:integer". While this should work for most - if not all - Lava Command parameters, /// you can always choose to not use this helper method and instead roll your own implementation. /// </para> /// </param> public static void ParseCommandMarkup(string markup, ILavaRenderContext context, Dictionary <string, string> parms) { if (markup.IsNull()) { return; } if (context == null) { throw new ArgumentNullException(nameof(context)); } if (parms == null) { throw new ArgumentNullException(nameof(parms)); } var mergeFields = context.GetMergeFields(); // Resolve merge fields. var resolvedMarkup = markup.ResolveMergeFields(mergeFields); // Harvest parameters. var markupParms = Regex.Matches(resolvedMarkup, @"\S+:('[^']+'|\d+)") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var parm in markupParms) { var itemParts = parm.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { var key = itemParts[0].Trim().ToLower(); var value = itemParts[1].Trim(); if (value[0] == '\'') { // key:'value' parms.AddOrReplace(key, value.Substring(1, value.Length - 2)); } else { // key:integer parms.AddOrReplace(key, value); } } } }
/// <summary> /// Initializes a new template context. /// </summary> /// <returns></returns> protected void InitializeRenderContext(ILavaRenderContext context, IEnumerable <string> enabledCommands = null) { if (context == null) { return; } if (enabledCommands != null) { context.SetEnabledCommands(enabledCommands); } // Set a reference to the current Lava Engine. context.SetInternalField(LavaUtilityHelper.GetContextKeyFromType(typeof(ILavaEngine)), this); }
/// <summary> /// Merges the lava. /// </summary> /// <param name="lavaTemplate">The lava template.</param> /// <param name="context">The context.</param> /// <returns></returns> private string MergeLava(string lavaTemplate, ILavaRenderContext context) { // Resolve the Lava template contained in this block in a new context. var engine = context.GetService <ILavaEngine>(); var newContext = engine.NewRenderContext(); newContext.SetMergeFields(context.GetMergeFields()); newContext.SetInternalFields(context.GetInternalFields()); // Resolve the inner template. var result = engine.RenderTemplate(lavaTemplate, LavaRenderParameters.WithContext(newContext)); return(result.Text); }
/// <summary> /// Parses the markup. /// </summary> /// <param name="markup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> private Dictionary <string, string> ParseMarkup(string markup, ILavaRenderContext context) { // first run lava across the inputted markup var internalMergeFields = context.GetMergeFields(); /* * var internalMergeFields = new Dictionary<string, object>(); * * // get variables defined in the lava source * foreach ( var scope in context.GetScopes ) * { * foreach ( var item in scope ) * { * internalMergeFields.AddOrReplace( item.Key, item.Value ); * } * } * * // get merge fields loaded by the block or container * if ( context.GetEnvironments.Count > 0 ) * { * foreach ( var item in context.GetEnvironments[0] ) * { * internalMergeFields.AddOrReplace( item.Key, item.Value ); * } * } */ var resolvedMarkup = markup.ResolveMergeFields(internalMergeFields); var parms = new Dictionary <string, string>(); parms.Add("cacheduration", "0"); var markupItems = Regex.Matches(resolvedMarkup, @"(\S*?:'[^']+')") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { parms.AddOrReplace(itemParts[0].Trim().ToLower(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } } return(parms); }
/// <summary> /// Gets the current person. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> private static Person GetCurrentPerson(ILavaRenderContext context) { // First check for a person override value included in lava context var currentPerson = context.GetMergeField("CurrentPerson", null) as Person; if (currentPerson == null) { var httpContext = System.Web.HttpContext.Current; if (httpContext != null && httpContext.Items.Contains("CurrentPerson")) { currentPerson = httpContext.Items["CurrentPerson"] as Person; } } return(currentPerson); }
private void AddLavaMergeFieldsToContext(ILavaRenderContext context, List <EventOccurrenceSummary> eventOccurrenceSummaries) { var eventSummaries = eventOccurrenceSummaries .OrderBy(e => e.DateTime) .GroupBy(e => e.EventItemOccurrence.Id) .Select(e => e.ToList()) .ToList(); eventOccurrenceSummaries = eventOccurrenceSummaries .OrderBy(e => e.DateTime) .ThenBy(e => e.Name) .ToList(); context["EventItems"] = eventSummaries; context["EventScheduledInstances"] = eventOccurrenceSummaries; }
/// <summary> /// Load the contents of a template file. /// </summary> /// <param name="context"></param> /// <param name="templatePath"></param> /// <returns></returns> /// <exception cref="LavaException">LavaFileSystem Template Not Found</exception> public string ReadTemplateFile(ILavaRenderContext context, string templatePath) { // Try to find exact file specified var resolvedPath = ResolveTemplatePath(templatePath); var file = new FileInfo(resolvedPath); if (file.Exists) { return(File.ReadAllText(file.FullName)); } // If requested template file does not include an extension if (string.IsNullOrWhiteSpace(file.Extension)) { // Try to find file with .lava extension string filePath = file.FullName + ".lava"; if (File.Exists(filePath)) { return(File.ReadAllText(filePath)); } // Try to find file with .liquid extension filePath = file.FullName + ".liquid"; if (File.Exists(filePath)) { return(File.ReadAllText(filePath)); } // If file still not found, try prefixing filename with an underscore if (!file.Name.StartsWith("_")) { filePath = Path.Combine(file.DirectoryName, string.Format("_{0}.lava", file.Name)); if (File.Exists(filePath)) { return(File.ReadAllText(filePath)); } filePath = Path.Combine(file.DirectoryName, string.Format("_{0}.liquid", file.Name)); if (File.Exists(filePath)) { return(File.ReadAllText(filePath)); } } } throw new LavaException($"LavaFileSystem Template Not Found. The file \"{templatePath}\" does not exist."); }
/// <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) { using (TextWriter writer = new StringWriter()) { base.OnRender(context, writer); var parms = ParseMarkup(_markup, context); string className = "alert alert-info"; if (parms.Any(p => p.Key == "type")) { className = $"alert alert-{ parms["type"] }"; } result.Write($"<div class='{className}'>{(writer.ToString())}</div>"); } }
/// <summary> /// Processes the Lava code in the source string. /// </summary> /// <param name="input">The lava source to process.</param> /// <example><![CDATA[ /// {% capture lava %}{% raw %}{% assign test = "hello" %}{{ test }}{% endraw %}{% endcapture %} /// {{ lava | RunLava }} /// ]]></example> public static string RunLava(ILavaRenderContext context, object input) { if (input == null) { return(null); } // Perform a safety check to avoid an unrecoverable recursion. // To minimize the resource impact of an unintentional infinite loop, this mechanism could be replaced with more specific recursion tracking in the Lava context. System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack(); var engine = context.GetService <ILavaEngine>(); var result = engine.RenderTemplate(input.ToString(), new LavaRenderParameters { Context = context }); return(result.Text); }
/// <summary> /// Determines whether the specified command is authorized within the context. /// </summary> /// <param name="context">The context.</param> /// <param name="command">The command.</param> /// <returns> /// <c>true</c> if the specified command is authorized; otherwise, <c>false</c>. /// </returns> public static bool IsAuthorized(ILavaRenderContext context, string command) { if (command.IsNullOrWhiteSpace()) { return(false); } var enabledCommands = context.GetEnabledCommands(); if (enabledCommands.Any()) { if (enabledCommands.Contains("All", StringComparer.OrdinalIgnoreCase) || enabledCommands.Contains(command, StringComparer.OrdinalIgnoreCase)) { return(true); } } return(false); }
/// <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) { using (TextWriter writer = new StringWriter()) { base.OnRender(context, writer); var parms = ParseMarkup(_markup, context); LandingSite?landingSite = (LandingSite)Enum.Parse(typeof(LandingSite), parms["landingsite"], true); if (landingSite == null) { result.Write("<!-- the landing site provided to the scripturize shortcode was not correct -->" + writer.ToString()); return; } var output = Rock.Utility.Scripturize.Parse(writer.ToString(), parms["defaulttranslation"], landingSite.Value, parms["cssclass"], parms["openintab"].AsBoolean()); result.Write(output); } }
/// <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 parms = ParseMarkup(_markup, context); // If no name given then skip this if (parms["name"].IsNullOrWhiteSpace()) { return; } // Make the format parameter case insensitive, because we're nice... or lazy... or both. parms["format"] = parms["format"].ToLower(); var parameterMarkup = string.Empty; using (TextWriter twBody = new StringWriter()) { base.OnRender(context, twBody); var body = twBody.ToString(); switch (parms["format"]) { case "number": case "boolean": { parameterMarkup = string.Format("\"{0}\": {1}", parms["name"], body.Trim()); break; } default: { parameterMarkup = string.Format("\"{0}\": {1}", parms["name"], body.Trim().ToJson()); break; } } result.Write(parameterMarkup); } }
/// <summary> /// Gets the current person. /// </summary> /// <param name="context">The context.</param> /// <returns>The current person or null if not found.</returns> /// <exception cref="ArgumentNullException">context</exception> public static Person GetCurrentPerson(ILavaRenderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } string currentPersonKey = "CurrentPerson"; Person currentPerson = null; // First, check for a person override value included in the lava context. currentPerson = context.GetMergeField(currentPersonKey, null) as Person; if (currentPerson == null) { var httpContext = HttpContext.Current; if (httpContext != null && httpContext.Items.Contains(currentPersonKey)) { currentPerson = httpContext.Items[currentPersonKey] as Person; } } return(currentPerson); }
public string ReadTemplateFile(ILavaRenderContext context, string templateName) { var fi = GetFileInfo(templateName); if (fi == null) { throw new Exception($"File Load Failed. The file \"{templateName}\" could not be found."); } var sb = new StringBuilder(); using (var fs = fi.CreateReadStream()) { byte[] byteArray = new byte[1024]; var fileContent = new UTF8Encoding(true); while (fs.Read(byteArray, 0, byteArray.Length) > 0) { sb.Append(fileContent.GetString(byteArray)); } } return(sb.ToString().Trim('\x0')); }
/// <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 cached commands are allowed in the context if (!this.IsAuthorized(context)) { result.Write(string.Format(LavaBlockBase.NotAuthorizedMessage, this.SourceElementName)); return; } var parms = ParseMarkup(_markup, context); var twoPassEnabled = parms["twopass"].AsBoolean(); var cacheKey = "lavacache-" + parms["key"]; if (cacheKey == string.Empty) { result.Write("* No cache key provided. *"); return; } var cacheDuration = parms["duration"].AsInteger(); if (cacheDuration > 0) { // Get content from cache var cachedResult = RockCache.Get(cacheKey, true) as CacheLavaTag; // Check that the cached value is current if (cachedResult != null) { var currentHash = CalculateContentHash(_blockMarkup.ToString()); if (currentHash != cachedResult.Hash) { cachedResult = null; } } // Use the cached value if (cachedResult != null) { if (twoPassEnabled) { result.Write(MergeLava(cachedResult.Content, context)); } else { result.Write(cachedResult.Content); } return; } } // Cached value not available so render the template and cache it var lavaResults = MergeLava(_blockMarkup.ToString(), context); if (lavaResults != null) { if (cacheDuration > 0) { // Don't cache if it's too large var maxCacheSize = parms["maxcachesize"].AsInteger(); if (lavaResults.Length < maxCacheSize) { var expiration = RockDateTime.Now.AddSeconds(cacheDuration); var cachedHash = CalculateContentHash(_blockMarkup.ToString()); RockCache.AddOrUpdate(cacheKey, string.Empty, new CacheLavaTag { Hash = cachedHash, Content = lavaResults }, expiration, parms["tags"]); } } // If twopass is enabled run the lava again if (twoPassEnabled) { lavaResults = MergeLava(lavaResults, context); } } result.Write(lavaResults); }
/// <summary> /// Parses the attributes of the Lava element tag to extract the parameter settings. /// Any merge fields in the attributes markup are resolved before the settings are extracted. /// </summary> /// <param name="elementAttributesMarkup">The markup.</param> /// <param name="context">The context.</param> /// <returns></returns> public static Dictionary <string, string> GetElementAttributes(string elementAttributesMarkup, ILavaRenderContext context = null) { // First, resolve any Lava merge fields that exist in the element attributes markup. if (context != null) { elementAttributesMarkup = elementAttributesMarkup.ResolveMergeFields(context.GetMergeFields()); } // Get the set of parameters using variations of the following pattern: // param1:'value1 with spaces' param2:value2_without_spaces param3:'value3 with spaces' var parms = new Dictionary <string, string>(); var markupItems = Regex.Matches(elementAttributesMarkup, @"(\S*?:('[^']+'|[\\d.]+|[\S*]+))") .Cast <Match>() .Select(m => m.Value) .ToList(); foreach (var item in markupItems) { var itemParts = item.ToString().Split(new char[] { ':' }, 2); if (itemParts.Length > 1) { if (itemParts[1].Trim()[0] == '\'') { parms.AddOrReplace(itemParts[0].Trim(), itemParts[1].Trim().Substring(1, itemParts[1].Length - 2)); } else { parms.AddOrReplace(itemParts[0].Trim(), itemParts[1].Trim()); } } } return(parms); }