internal KProperty GetProperty(List <CompilerError> compileErrors, HtmlAttribute dynamicAttribute, DocumentValidator documentValidator, string referenceObject, Dictionary <string, string> classNameAlias) { KProperty kProperty = null; KClass kClass = null; string expression = referenceObject; string baseExpression = expression.Split('.')[0].Split('[')[0].ToLower(); while (baseExpression != "kresult" && baseExpression != "search" && classNameAlias.ContainsKey(baseExpression)) { string[] expressionParts = expression.Split('.'); expressionParts[0] = classNameAlias[baseExpression]; expression = String.Join(".", expressionParts); baseExpression = expression.Split('.')[0].Split('[')[0].ToLower(); } string[] classHierarchyList = expression.Split('.'); KEntity entity = documentValidator?.GetKEntityFromEntityName(classHierarchyList[0]) ?? documentValidator?.GetKEntityFromEntityName(documentValidator.defaultEntity); if (entity != null) { kClass = entity.Classes.Where(x => x.ClassType == KClassType.BaseClass && x.Name.ToLower() == classHierarchyList[0].ToLower()).FirstOrDefault(); if (kClass == null) { compileErrors.Add(CompileResultHelper.GetCompileError(String.Format(ErrorCodeConstants.UnrecognizedType, classHierarchyList[0]), dynamicAttribute.Line, dynamicAttribute.LinePosition)); return(null); } for (int i = 1; i < classHierarchyList.Length - 1; i++) { string propName = classHierarchyList[i].Split('[')[0]; KProperty prop = kClass.PropertyList.Where(x => x.Name.ToLower() == propName.ToLower()).FirstOrDefault(); if (prop == null) { compileErrors.Add(CompileResultHelper.GetCompileError(String.Format(ErrorCodeConstants.UnrecognizedProperty, propName), dynamicAttribute.Line, dynamicAttribute.LinePosition)); return(null); } kClass = entity.Classes.Where(x => x.Name.ToLower() == prop.DataType.Name.ToLower()).FirstOrDefault(); if (kClass == null) { compileErrors.Add(CompileResultHelper.GetCompileError(String.Format(ErrorCodeConstants.UnrecognizedType, prop.DataType.Name), dynamicAttribute.Line, dynamicAttribute.LinePosition)); return(null); } } string finalPropName = classHierarchyList[classHierarchyList.Length - 1].Split('[')[0].ToLower(); kProperty = kClass.PropertyList.Where(x => x.Name == finalPropName && x.Type == PropertyType.array).FirstOrDefault(); } return(kProperty); }
/// <summary> /// Process nodes with k-script tags. /// </summary> /// <param name="request">Incoming request</param> /// <param name="compileErrors">list of errors during compilation</param> /// <param name="kentity">project language</param> /// <param name="customVariables">output list to hold custom variables</param> /// <param name="rootUrl">root url</param> /// <param name="filePath">file path</param> /// <param name="classNameAlias">aliases used either with k-repeat or k-object</param> /// <param name="classNameAliasdepth">depth based storage of aliases</param> /// <param name="depth">depth of the node in DOM</param> /// <param name="dynamicAttribute">key-value pair of the k-tag</param> public override void ProcessNode(CompileResourceRequest request, List <CompilerError> compileErrors, Dictionary <string, int> customVariables, string rootUrl, string filePath, Dictionary <string, string> classNameAlias, Dictionary <int, string> classNameAliasdepth, int depth, HtmlNode node, HtmlAttribute dynamicAttribute, List <MatchNode> objectNamesToValidate, DocumentValidator documentValidator) { Regex urlPattern = new Regex("http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?", RegexOptions.IgnoreCase); string getApiURL = node.Attributes["get-api"]?.Value; string postApiURL = node.Attributes["post-api"]?.Value; if (getApiURL == null && postApiURL == null) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KScriptNoApi, node.Line, node.LinePosition)); } else if (getApiURL != null && postApiURL != null) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KScriptMultipleApi, node.Line, node.LinePosition)); } else if (getApiURL != null && !urlPattern.IsMatch(getApiURL)) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KScriptGetApiNoURL, node.Line, node.LinePosition)); } else if (postApiURL != null && !urlPattern.IsMatch(postApiURL)) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KScriptPostApiNoURL, node.Line, node.LinePosition)); } else if (classNameAlias.ContainsKey("kresult")) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KScriptNested, node.Line, node.LinePosition)); } else { classNameAlias.Add("kresult", "-1"); if (classNameAliasdepth.ContainsKey(depth)) { string oldAliasDepth = classNameAliasdepth[depth]; classNameAliasdepth.Remove(depth); classNameAliasdepth.Add(depth, classNameAliasdepth[depth] + ",kresult"); } else { classNameAliasdepth.Add(depth, "kresult"); } } }
/// <summary> /// Process nodes with KDL tag. /// </summary> /// <param name="request">Incoming request</param> /// <param name="compileErrors">list of errors during compilation</param> /// <param name="kentity">project language</param> /// <param name="customVariables">output list to hold custom variables</param> /// <param name="rootUrl">root url</param> /// <param name="filePath">file path</param> /// <param name="classNameAlias">aliases used either with k-repeat or k-object</param> /// <param name="classNameAliasdepth">depth based storage of aliases</param> /// <param name="depth">depth of the node in DOM</param> /// <param name="dynamicAttribute">key-value pair of the k-tag</param> public override void ProcessNode(CompileResourceRequest request, List <CompilerError> compileErrors, Dictionary <string, int> customVariables, string rootUrl, string filePath, Dictionary <string, string> classNameAlias, Dictionary <int, string> classNameAliasdepth, int depth, HtmlNode node, HtmlAttribute dynamicAttribute, List <MatchNode> objectNamesToValidate, DocumentValidator documentValidator) { var pattern = dynamicAttribute.Value; if (!string.IsNullOrWhiteSpace(pattern)) { pattern = pattern.Trim().Trim('/'); if (pattern.IndexOf("currentpagenumber.urlencode()") < 0) { pattern = pattern.Replace("currentpagenumber", "currentpagenumber.urlencode()"); } KEntity kentity = documentValidator.GetKEntityFromEntityName(documentValidator.defaultEntity); #region Validate unique id exist for detailspage if (request.PageType == Models.Project.KitsunePageType.DETAILS) { //added support for multiple kobjects, check for the last objetcts unique param var kobjects = request.KObject.Split(':')[0].Split(','); var kobjParam = kobjects[kobjects.Length - 1].ToLower(); var kidRegex = Kitsune.Helper.Constants.GetKObjectIteratorRegex($"{kobjParam}._kid"); var _idRegex = Kitsune.Helper.Constants.GetKObjectIteratorRegex($"{kobjParam}._id"); var indexRegex = Kitsune.Helper.Constants.GetKObjectIteratorRegex($"{kobjParam}.index"); var idRegex = Kitsune.Helper.Constants.GetKObjectIteratorRegex($"{kobjParam}.id"); if (!(_idRegex.IsMatch(pattern.ToLower()) || kidRegex.IsMatch(pattern.ToLower()) || indexRegex.IsMatch(pattern.ToLower()) || idRegex.IsMatch(pattern.ToLower()))) { compileErrors.Add(new CompilerError() { LineNumber = dynamicAttribute.Line, LinePosition = dynamicAttribute.LinePosition, Message = string.Format(ErrorCodeConstants.MissingUniqueIndexForDetailsPage, request.KObject.Split(':').Length > 1 ? request.KObject.Split(':')[1] : kobjParam) }); } } #endregion var viewExist = KitsuneCompiler.ValidateView(ref pattern, kentity); if (viewExist != null) { viewExist.LineNumber = dynamicAttribute.Line; viewExist.LinePosition = dynamicAttribute.LinePosition; compileErrors.Add(viewExist); } var pagination = Kitsune.Helper.Constants.PaginationRegularExpression.Match(pattern); if (pagination != null && pagination.Success) { var matches = Kitsune.Helper.Constants.FunctionParameterExpression.Match(pagination.Value); if (matches != null && matches.Groups?.Count > 0) { request.UrlPattern = string.Format("[[{0}]]/{1}-[[{2}.currentpagenumber]]", rootUrl, matches.Groups[1].Value.Substring(matches.Groups[1].Value.IndexOf('.') + 1), request.ClassName); } } else { var expressions = Helper.HtmlHelper.GetExpressionFromElement(pattern, 0); //Add urlencode if (expressions != null && expressions.Any()) { var tmp = ""; var tmpValue = ""; var groupCout = 0; foreach (var exp in expressions) { groupCout++; tmp = exp.Value.Trim('[', ']'); tmpValue = exp.Value; if (!tmp.ToLower().EndsWith(".urlencode()")) { pattern = pattern.Replace(tmpValue, exp.Value.Replace(tmp, $"{tmp}.urlencode()")); } var objects = Parser.GetObjects(tmp); if (objects != null && objects.Any()) { foreach (var custObj in objects) { if (custObj.Split('.').Length == 1) { IList <KClass> allClasses = new List <KClass>(); if (documentValidator != null && documentValidator.entities != null && documentValidator.entities.Keys.Any(x => x == custObj.Trim('[', ']').ToLower())) { allClasses = documentValidator.entities[custObj.Trim('[', ']').ToLower()].Classes; } if (!allClasses.Any(x => x.ClassType == KClassType.BaseClass && x.Name.ToLower() == custObj.Trim('[', ']'))) { if (!customVariables.ContainsKey(custObj.Trim('[', ']')?.ToLower())) { customVariables.Add(custObj.Trim('[', ']')?.ToLower(), groupCout); } } } } } } } request.UrlPattern = string.Format("[[{0}]]/{1}", rootUrl, pattern); if (pattern != null && pattern.ToLower().IndexOf(@"search/") != -1) { request.PageType = Models.Project.KitsunePageType.SEARCH; } } //req.UrlPattern = pattern.Replace(kdl, req.UrlPattern); dynamicAttribute.Value = request.UrlPattern; } else if (filePath.ToLower().EndsWith(".dl")) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.NoDLTagInDLPage)); } else if (string.IsNullOrEmpty(request.UrlPattern)) { request.UrlPattern = string.Format("[[{0}]]/{1}", rootUrl, filePath.ToLower()); } }
public override void ProcessNode(CompileResourceRequest request, List <CompilerError> compileErrors, Dictionary <string, int> customVariables, string rootUrl, string filePath, Dictionary <string, string> classNameAlias, Dictionary <int, string> classNameAliasdepth, int depth, HtmlNode node, HtmlAttribute dynamicAttribute, List <MatchNode> objectNamesToValidate, DocumentValidator documentValidator) { Node result = LexerGenerator.Parse(dynamicAttribute.Value.Trim('[', ']')); if (result?.Token?.Value == ACTIONS.Loop) { string referenceObject = result.Children[0].Children[0].Token.Value; string iterator = result.Children[2].Children[0].Token.Value; //Fix issue with same iterator being used at same depth. if (classNameAlias.ContainsKey(iterator) && classNameAliasdepth.ContainsKey(depth) && classNameAliasdepth[depth].Contains(iterator)) { classNameAlias.Remove(iterator); string oldAliasDepth = classNameAliasdepth[depth]; classNameAliasdepth.Remove(depth); oldAliasDepth = oldAliasDepth.Replace(iterator, "").Replace(",,", ","); classNameAliasdepth.Add(depth, oldAliasDepth); } if (!classNameAlias.ContainsKey(iterator)) { classNameAlias.Add(iterator, ""); if (classNameAliasdepth.ContainsKey(depth)) { string oldAliasDepth = classNameAliasdepth[depth]; classNameAliasdepth.Remove(depth); classNameAliasdepth.Add(depth, oldAliasDepth + ',' + iterator); } else { classNameAliasdepth.Add(depth, iterator); } objectNamesToValidate.Add(new MatchNode { Value = referenceObject, Line = dynamicAttribute.Line, Column = dynamicAttribute.LinePosition }); try { if (result?.Children[4]?.Token?.Value?.ToString() == "ViewProperty" && result?.Children[4]?.Children[1]?.Token?.Value?.ToLower() == "offset") { //Added list type in condition as there might update in the offset and reference object so we have to update the meta also if (request.PageType == Models.Project.KitsunePageType.LIST || request.PageType == Models.Project.KitsunePageType.DEFAULT || request.PageType == Models.Project.KitsunePageType.DETAILS) { request.PageType = Models.Project.KitsunePageType.LIST; request.Offset = result.Children[6]?.Children[0]?.Token?.Value; request.KObject = referenceObject; } } } catch { } string[] classHierarchyList = referenceObject.Split('.'); if (classHierarchyList[0].StartsWith("kresult", System.StringComparison.InvariantCultureIgnoreCase) || classHierarchyList[0].Equals("search", System.StringComparison.InvariantCultureIgnoreCase)) { //pass } else if (classHierarchyList.Length >= 2) { KProperty kProperty = GetProperty(compileErrors, dynamicAttribute, documentValidator, referenceObject, classNameAlias); if (kProperty == null) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KRepeatVariableNotArray, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } if (iterator.Split('.').Length > 1) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KRepeatInvalidIterator, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } KEntity entity = documentValidator?.GetKEntityFromEntityName(classHierarchyList[0]) ?? documentValidator?.GetKEntityFromEntityName(documentValidator.defaultEntity); if (entity?.Classes?.Where(x => x.ClassType == KClassType.BaseClass && x.Name.ToLower() == iterator.ToLower()).FirstOrDefault() != null) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.BaseClassAsKRepeatIterator, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } } } else { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KRepeatVariableAlreadyInUse, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } } else if (result?.Token?.Value == ACTIONS.InLoop) { string loopVariable = result.Children[0].Children[0].Token.Value.ToLower(); string referenceObject = result.Children[2].Children[0].Token.Value.ToLower() + $"[{GenerateVariableName(5)}]"; objectNamesToValidate.Add(new MatchNode { Value = referenceObject, Line = dynamicAttribute.Line, Column = dynamicAttribute.LinePosition }); if (classNameAlias.ContainsKey(loopVariable)) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.KRepeatVariableAlreadyInUse, dynamicAttribute.Line, dynamicAttribute.LinePosition)); return; } KEntity entity = documentValidator?.GetKEntityFromEntityName(loopVariable) ?? documentValidator?.GetKEntityFromEntityName(documentValidator.defaultEntity); if (entity.Classes.Where(x => x.ClassType == KClassType.BaseClass && x.Name.ToLower() == loopVariable).Any()) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.BaseClassAsKRepeatVariable, dynamicAttribute.Line, dynamicAttribute.LinePosition)); return; } classNameAlias.Add(loopVariable, referenceObject); if (classNameAliasdepth.ContainsKey(depth)) { string oldAliasDepth = classNameAliasdepth[depth]; classNameAliasdepth.Remove(depth); classNameAliasdepth.Add(depth, oldAliasDepth + ',' + loopVariable); } else { classNameAliasdepth.Add(depth, loopVariable); } } else { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.InvalidKRepeatSyntax, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } dynamicAttribute.Value = ""; }
/// <summary> /// Process nodes with k-object tags. /// </summary> /// <param name="request">Incoming request</param> /// <param name="compileErrors">list of errors during compilation</param> /// <param name="kentity">project language</param> /// <param name="customVariables">output list to hold custom variables</param> /// <param name="rootUrl">root url</param> /// <param name="filePath">file path</param> /// <param name="classNameAlias">aliases used either with k-repeat or k-object</param> /// <param name="classNameAliasdepth">depth based storage of aliases</param> /// <param name="depth">depth of the node in DOM</param> /// <param name="dynamicAttribute">key-value pair of the k-tag</param> public override void ProcessNode(CompileResourceRequest request, List <CompilerError> compileErrors, Dictionary <string, int> customVariables, string rootUrl, string filePath, Dictionary <string, string> classNameAlias, Dictionary <int, string> classNameAliasdepth, int depth, HtmlNode node, HtmlAttribute dynamicAttribute, List <MatchNode> objectNamesToValidate, DocumentValidator documentValidator) { Node result = LexerGenerator.Parse(dynamicAttribute.Value.Trim('[', ']')); if (result?.Children?.Count == 3) { string referenceNames = result.Token.Value == ACTIONS.KObject ? result.Children[0].Token.Value : result.Children[0].Children[0].Token.Value.ToLower(); string referenceObject = result.Children[2].Children[0].Token.Value.ToLower(); var referenceKObjectArray = referenceNames.Split(','); KEntity kentity = documentValidator.GetKEntityFromEntityName(documentValidator.defaultEntity); var referenceObjectWithIterator = UpdateIterator(referenceObject, documentValidator); var tempRefObj = referenceObjectWithIterator.Trim(); for (int i = referenceKObjectArray.Length - 1, j = 0; i >= 0; i--, j++) { KEntity commEntity = documentValidator.GetKEntityFromEntityName(referenceKObjectArray[i]); if (commEntity != null || (kentity != null && kentity.Classes.Where(x => x.Name?.ToLower() == referenceObject?.Split('.')?[0] && x.ClassType == KClassType.BaseClass).Count() == 0)) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.BaseClassAsKObjectVariable, dynamicAttribute.Line, dynamicAttribute.LinePosition)); return; } else { if (commEntity != null) { kentity = commEntity; } if (j > 0) { tempRefObj = tempRefObj.Substring(0, tempRefObj.LastIndexOf('.')); } KProperty property = GetProperty(compileErrors, dynamicAttribute, documentValidator, tempRefObj, classNameAlias); if (property == null) { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.InvalidKObjectClass, dynamicAttribute.Line, dynamicAttribute.LinePosition)); return; } else if (property.Type == PropertyType.array) { classNameAlias.Add(referenceKObjectArray[i], tempRefObj); objectNamesToValidate.Add(new MatchNode { Value = tempRefObj, Line = dynamicAttribute.Line, Column = dynamicAttribute.LinePosition }); } else { classNameAlias.Add(referenceKObjectArray[i], tempRefObj); objectNamesToValidate.Add(new MatchNode { Value = tempRefObj, Line = dynamicAttribute.Line, Column = dynamicAttribute.LinePosition }); } } } request.PageType = Models.Project.KitsunePageType.DETAILS; var searchableProperty = IsSearchableProperty(referenceObject, out KClass kobjClass, documentValidator); if (referenceObject.StartsWith("webactions.") || kobjClass != null) { request.KObject = referenceNames.Trim() + ":" + referenceObject; } else { request.KObject = referenceNames.Trim(); } } else { compileErrors.Add(CompileResultHelper.GetCompileError(ErrorCodeConstants.InvalidKObjectSyntax, dynamicAttribute.Line, dynamicAttribute.LinePosition)); } dynamicAttribute.Value = ""; }