private void WriteParameters([NotNull] LayoutCompileContext context, [NotNull] XmlTextWriter output, [NotNull] ITextNode renderingTextNode, [NotNull] Item renderingItem, [NotNull] string id)
        {
            var fields = new Dictionary<string, string>();

            var parametersTemplateItemId = renderingItem.Fields.FirstOrDefault(f => f.FieldName == "Parameters Template")?.Value ?? string.Empty;
            var parametersTemplateItem = context.Field.Item.Project.FindQualifiedItem<Template>(parametersTemplateItemId);
            if (parametersTemplateItem != null)
            {
                foreach (var field in parametersTemplateItem.GetAllFields())
                {
                    fields[field.FieldName.ToLowerInvariant()] = field.Type;
                }
            }

            var properties = new Dictionary<string, string>();

            foreach (var attribute in renderingTextNode.Attributes)
            {
                properties[attribute.Key] = attribute.Value;
            }

            foreach (var child in renderingTextNode.ChildNodes)
            {
                if (IsContentProperty(renderingTextNode, child))
                {
                    var name = child.Key.Mid(renderingTextNode.Key.Length + 1);
                    var value = string.Join(string.Empty, child.ChildNodes.Select(n => n.ToString()).ToArray());

                    properties[name] = value;
                }
            }

            var par = new UrlString();
            foreach (var pair in properties)
            {
                var attributeName = pair.Key;
                if (IgnoreAttributes.Contains(attributeName))
                {
                    continue;
                }

                var value = pair.Value;

                string type;
                if (fields.TryGetValue(attributeName.ToLowerInvariant(), out type))
                {
                    switch (type.ToLowerInvariant())
                    {
                        case "checkbox":
                            if (!value.StartsWith("{Binding") && !value.StartsWith("{@"))
                            {
                                if (value != "True" && value != "False")
                                {
                                    context.CompileContext.Trace.TraceError(Msg.C1039, $"{id}: Boolean parameter must have value \"True\", \"False\", \"{{Binding ... }}\" or \"{{@ ... }}\".", renderingTextNode, attributeName);
                                }

                                value = value == "1" || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase) ? "1" : "0";
                            }

                            break;
                    }
                }
                else
                {
                    context.CompileContext.Trace.TraceWarning(Msg.C1040, Texts._1___Parameter___0___is_not_defined_in_the_parameters_template_, renderingTextNode, id + "." + attributeName);
                }

                if (value.StartsWith("/sitecore", StringComparison.InvariantCultureIgnoreCase))
                {
                    var item = context.Field.Item.Project.FindQualifiedItem<IProjectItem>(value);
                    if (item != null)
                    {
                        value = item.Uri.Guid.Format();
                    }
                }

                par[attributeName] = value;
            }

            output.WriteAttributeString("par", par.ToString());
        }
 public void Append([NotNull] UrlString url)
 {
     Append(url.Parameters);
 }
        private void WriteLiteral([NotNull] BuildContext context)
        {
            var text = context.Literal.ToString();
            context.Literal = new StringWriter();

            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            var par = new UrlString();
            par.Parameters["text"] = text;

            context.Output.WriteStartElement("r");
            context.Output.WriteAttributeString("id", context.LiteralRendering.RenderingItemUri.Guid.Format());
            context.Output.WriteAttributeString("ph", context.Placeholder);
            context.Output.WriteAttributeString("par", par.ToString());
            context.Output.WriteEndElement();
        }
        private void WriteRendering([NotNull] BuildContext context, [NotNull] XElement element)
        {
            WriteLiteral(context);

            var rendering = FindRendering(context, element.Name.LocalName, element.GetAttributeValue("renderingid"), new TextSpan(element));
            if (rendering == null)
            {
                return;
            }

            context.Output.WriteStartElement("r");
            context.Output.WriteAttributeString("id", rendering.RenderingItemUri.Guid.Format());
            context.Output.WriteAttributeString("ph", context.Placeholder);

            var parameters = new UrlString();

            foreach (var attribute in element.Attributes())
            {
                switch (attribute.Name.LocalName.ToLowerInvariant())
                {
                    case "renderingid":
                        continue;
                    case "datasource":
                        context.Output.WriteAttributeString("ds", attribute.Value);
                        continue;
                    case "cacheable":
                        context.Output.WriteAttributeString("cac", attribute.Value);
                        continue;
                    case "conditions":
                        context.Output.WriteAttributeString("cnd", attribute.Value);
                        continue;
                    case "tests":
                        context.Output.WriteAttributeString("mvt", attribute.Value);
                        continue;
                    case "placeholder":
                        context.Output.WriteAttributeString("ph", attribute.Value);
                        continue;
                    case "uniqueid":
                        context.Output.WriteAttributeString("uid", attribute.Value);
                        continue;
                    case "varybydata":
                        context.Output.WriteAttributeString("vbd", attribute.Value);
                        continue;
                    case "varybydevice":
                        context.Output.WriteAttributeString("vbdev", attribute.Value);
                        continue;
                    case "varybylogin":
                        context.Output.WriteAttributeString("vbl", attribute.Value);
                        continue;
                    case "varybyparameters":
                        context.Output.WriteAttributeString("vbp", attribute.Value);
                        continue;
                    case "varybyquerystring":
                        context.Output.WriteAttributeString("vbqs", attribute.Value);
                        continue;
                    case "varybyuser":
                        context.Output.WriteAttributeString("vbu", attribute.Value);
                        continue;
                    case "rules":
                        context.Output.WriteAttributeString("rls", attribute.Value);
                        continue;
                    default:
                        parameters.Parameters[attribute.Name.LocalName] = attribute.Value;
                        break;
                }
            }

            var p = parameters.ToString();
            if (!string.IsNullOrEmpty(p))
            {
                context.Output.WriteAttributeString("par", p);
            }

            context.Output.WriteEndElement();

            var placeholder = context.Placeholder;

            foreach (var placeholderElement in element.Elements())
            {
                if (placeholderElement.Name.NamespaceName != PlaceholderNamespaceName)
                {
                    context.CompileContext.Trace.TraceError(0, "Placeholder expected", context.SourceFile.AbsoluteFileName, new TextSpan(placeholderElement), placeholderElement.Name.LocalName);
                }

                context.Placeholder = placeholderElement.Name.LocalName;

                foreach (var node in placeholderElement.Nodes())
                {
                    WriteRenderings(context, node);
                }

                WriteLiteral(context);
            }

            context.Placeholder = placeholder;
        }
        protected virtual void BuildRendering([Diagnostics.NotNull] RenderingBuilder renderingBuilder, [Diagnostics.NotNull] Item renderingItem, [Diagnostics.NotNull] XElement renderingElement, [Diagnostics.NotNull] [ItemNotNull] List<Item> renderingItems)
        {
            var parameters = new UrlString(renderingElement.GetAttributeValue("par"));
            renderingBuilder.Id = parameters.Parameters["Id"];
            renderingBuilder.Placeholder = renderingElement.GetAttributeValue("ph");

            foreach (var placeholder in renderingItem["Place Holders"].Split(Constants.Comma, StringSplitOptions.RemoveEmptyEntries))
            {
                renderingBuilder.Placeholders.Add(placeholder.Replace("$Id", renderingBuilder.Id).Trim());
            }

            var fields = new Dictionary<string, TemplateField>();

            var parametersTemplateItem = renderingItem.Database.GetItem(renderingItem["Parameters Template"]);
            if (parametersTemplateItem != null)
            {
                var template = TemplateManager.GetTemplate(parametersTemplateItem.ID, renderingItem.Database);
                if (template != null)
                {
                    foreach (var field in template.GetFields(true))
                    {
                        if (field.Template.BaseIDs.Length != 0)
                        {
                            fields[field.Name.ToLowerInvariant()] = field;
                        }
                    }
                }
            }

            // rendering name
            var name = renderingItem.Name;

            var duplicates = renderingItems.Where(i => i.Name == renderingItem.Name).ToList();
            if (duplicates.Count > 1)
            {
                name = GetUniqueRenderingName(duplicates, renderingItem);
            }

            renderingBuilder.UnsafeName = !SafeName.IsMatch(name);
            renderingBuilder.Name = name;

            // parameters
            foreach (var key in parameters.Parameters.Keys.OfType<string>().Where(k => !string.IsNullOrEmpty(k)).OrderBy(k => k))
            {
                var value = parameters.Parameters[key];
                if (string.IsNullOrEmpty(value))
                {
                    continue;
                }

                value = HttpUtility.UrlDecode(value) ?? string.Empty;

                TemplateField field;
                if (fields.TryGetValue(key.ToLowerInvariant(), out field))
                {
                    switch (field.Type.ToLowerInvariant())
                    {
                        case "checkbox":
                            if (!value.StartsWith("{Binding"))
                            {
                                value = MainUtil.GetBool(value, false) ? "True" : "False";
                            }

                            break;

                        case "droptree":
                            if (ID.IsID(value))
                            {
                                var i = renderingItem.Database.GetItem(value);
                                if (i != null)
                                {
                                    value = i.Paths.Path;
                                }
                            }

                            break;
                    }

                    var source = new Sitecore.Text.UrlString(field.Source);
                    var defaultValue = source.Parameters["defaultvalue"] ?? string.Empty;

                    if (string.Equals(value, defaultValue, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                }

                // todo: Hacky, hacky, hacky
                if ((key == "IsEnabled" || key == "IsVisible") && value == "True")
                {
                    continue;
                }

                renderingBuilder.Attributes[key] = value;
            }

            // data source
            var dataSource = renderingElement.GetAttributeValue("ds");
            if (ID.IsID(dataSource))
            {
                var dataSourceItem = renderingItem.Database.GetItem(dataSource);
                if (dataSourceItem != null)
                {
                    dataSource = dataSourceItem.Paths.Path;
                }
            }

            renderingBuilder.DataSource = dataSource;

            // caching
            renderingBuilder.Cacheable = renderingElement.GetAttributeValue("cac") == @"1";
            renderingBuilder.VaryByData = renderingElement.GetAttributeValue("vbd") == @"1";
            renderingBuilder.VaryByDevice = renderingElement.GetAttributeValue("vbdev") == @"1";
            renderingBuilder.VaryByLogin = renderingElement.GetAttributeValue("vbl") == @"1";
            renderingBuilder.VaryByParameters = renderingElement.GetAttributeValue("vbp") == @"1";
            renderingBuilder.VaryByQueryString = renderingElement.GetAttributeValue("vbqs") == @"1";
            renderingBuilder.VaryByUser = renderingElement.GetAttributeValue("vbu") == @"1";
        }