public virtual RenderingResult BeginRenderLink <T>(T model, Expression <Func <T, object> > field, TextWriter writer, object parameters = null, bool isEditable = false) { NameValueCollection attrs; if (parameters is NameValueCollection) { attrs = parameters as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(parameters, true); } if (IsInEditingMode && isEditable) { if (attrs != null) { attrs.Add("haschildren", "true"); return(MakeEditable(field, null, model, attrs, _context, SitecoreContext.Database, writer)); } return(MakeEditable(field, null, model, "haschildren=true", _context, SitecoreContext.Database, writer)); } else { return(BeginRenderLink(field.Compile().Invoke(model) as Fields.Link, attrs, string.Empty, writer)); } }
/// <summary> /// Render HTML for a link /// </summary> /// <param name="link">The link to render</param> /// <param name="model">The model containing the link</param> /// <param name="field">An expression that points to the link</param> /// <param name="attributes">A collection of parameters to added to the link</param> /// <param name="isEditable">Indicate if the link should be editable in the page editor</param> /// <param name="contents">Content to go in the link</param> /// <returns>An "a" HTML element</returns> public virtual string RenderLink <T>(T model, Expression <Func <T, object> > field, object attributes = null, bool isEditable = false, string contents = null) { NameValueCollection attrs = null; if (attributes is NameValueCollection) { attrs = attributes as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(attributes, true); } var sb = new StringBuilder(); var writer = new StringWriter(sb); var linkField = field.Compile().Invoke(model) as Fields.Link; RenderingResult result = null; if (IsInEditingMode && isEditable) { if (!string.IsNullOrEmpty(contents)) { attrs["haschildren"] = "true"; } if (contents.IsNotNullOrEmpty()) { attrs.Add("haschildren", "true"); } if (linkField != null) { AttributeCheck(attrs, "class", linkField.Class); AttributeCheck(attrs, "title", linkField.Title); } result = MakeEditable( field, null, model, Utilities.ConstructQueryString(attrs), _context, SitecoreContext.Database, writer); if (contents.IsNotNullOrEmpty()) { sb.Append(contents); } } else { result = BeginRenderLink( GetCompiled(field).Invoke(model) as Fields.Link, attrs, contents, writer ); } result.Dispose(); writer.Flush(); writer.Close(); return(sb.ToString()); }
/// <summary> /// Renders an image allowing simple page editor support /// </summary> /// <typeparam name="T">The model type</typeparam> /// <param name="model">The model that contains the image field</param> /// <param name="field">A lambda expression to the image field, should be of type Glass.Mapper.Sc.Fields.Image</param> /// <param name="parameters">Image parameters, e.g. width, height</param> /// <param name="isEditable">Indicates if the field should be editable</param> /// <returns></returns> public virtual string RenderImage <T>(T model, Expression <Func <T, object> > field, object parameters = null, bool isEditable = false) { if (parameters is ImageParameters) { var imageParameters = parameters as ImageParameters; if (IsInEditingMode && isEditable) { return(Editable(model, field, imageParameters)); } else { return(RenderImage(field.Compile().Invoke(model) as Fields.Image, parameters == null ? null : imageParameters.Parameters)); } } else { var attrs = Utilities.GetPropertiesCollection(parameters, true); if (IsInEditingMode && isEditable) { var url = new UrlString(); url.Parameters.Add(attrs); return(Editable(model, field, url.Query)); } else { return(RenderImage(field.Compile().Invoke(model) as Fields.Image, parameters == null ? null : attrs)); } } }
/// <summary> /// Renders an image allowing simple page editor support /// </summary> /// <typeparam name="T">The model type</typeparam> /// <param name="model">The model that contains the image field</param> /// <param name="field">A lambda expression to the image field, should be of type Glass.Mapper.Sc.Fields.Image</param> /// <param name="parameters">Image parameters, e.g. width, height</param> /// <param name="isEditable">Indicates if the field should be editable</param> /// <param name="outputHeightWidth">Indicates if the height and width attributes should be output when rendering the image</param> /// <returns></returns> public virtual string RenderImage <T>(T model, Expression <Func <T, object> > field, object parameters = null, bool isEditable = false, bool outputHeightWidth = false) { var attrs = Utilities.GetPropertiesCollection(parameters, true).ToSafeDictionary(); if (IsInEditingMode && isEditable) { var url = new UrlString(); foreach (var pair in attrs) { url.Parameters.Add(pair.Key, pair.Value); } if (!outputHeightWidth) { url.Parameters.Add("width", "-1"); url.Parameters.Add("height", "-1"); } return(Editable(model, field, url.Query)); } else { return(RenderImage(GetCompiled(field).Invoke(model) as Image, parameters == null ? null : attrs, outputHeightWidth)); } }
protected SafeDictionary <string> ProcessParameters(object parameters) { string parametersStringTemp = string.Empty; SafeDictionary <string> dictionary = new SafeDictionary <string>(); if (parameters == null) { parametersStringTemp = string.Empty; } else if (parameters is string) { parametersStringTemp = parameters as string; dictionary = WebUtil.ParseQueryString(parametersStringTemp ?? string.Empty); } else if (parameters is NameValueCollection) { var collection = (NameValueCollection)parameters; foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } else { var collection = Utilities.GetPropertiesCollection(parameters, true); foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } return(dictionary); }
public virtual RenderingResult BeginRenderLink <T>(T model, Expression <Func <T, object> > field, TextWriter writer, object parameters = null, bool isEditable = false, bool alwaysRender = false, string aElementTemplate = LinkTagFormat) { NameValueCollection attrs; if (parameters is NameValueCollection) { attrs = parameters as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(parameters, true); } if (IsInEditingMode && isEditable) { if (attrs != null) { attrs.Add("haschildren", "true"); return(MakeEditable(field, null, model, attrs, _context, SitecoreService.Database, writer)); } return(MakeEditable(field, null, model, "haschildren=true", _context, SitecoreService.Database, writer)); } else { return(BeginRenderLink(GetCompiled(field).Invoke(model) as Link, attrs.ToSafeDictionary(), string.Empty, writer, alwaysRender, aElementTemplate)); } }
/// <summary> /// Render HTML for a link /// </summary> /// <param name="model">The model containing the link</param> /// <param name="field">An expression that points to the link</param> /// <param name="attributes">A collection of parameters to added to the link</param> /// <param name="isEditable">Indicate if the link should be editable in the page editor</param> /// <param name="contents">Content to go in the link</param> /// <param name="alwaysRender">Renders an A element even if the link is null</param> /// <returns>An "a" HTML element</returns> public virtual string RenderLink <T>( T model, Expression <Func <T, object> > field, object attributes = null, bool isEditable = false, string contents = null, bool alwaysRender = false, string aElementTemplate = LinkTagFormat) { NameValueCollection attrs; if (attributes is NameValueCollection) { attrs = attributes as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(attributes, true); } var sb = new StringBuilder(); var writer = new StringWriter(sb); RenderingResult result; if (IsInEditingMode && isEditable) { if (contents.HasValue()) { attrs.Add("haschildren", "true"); attrs.Add("text", contents); } result = MakeEditable( field, null, model, attrs, _context, SitecoreService.Database, writer); if (contents.HasValue()) { sb.Append(contents); } } else { result = BeginRenderLink( GetCompiled(field).Invoke(model) as Link, attrs.ToSafeDictionary(), contents, writer, alwaysRender, aElementTemplate ); } result.Dispose(); writer.Flush(); writer.Close(); return(sb.ToString()); }
/// <summary> /// Render HTML for a link /// </summary> /// <param name="link">The link to render</param> /// <param name="model">The model containing the link</param> /// <param name="field">An expression that points to the link</param> /// <param name="attributes">A collection of parameters to added to the link</param> /// <param name="isEditable">Indicate if the link should be editable in the page editor</param> /// <param name="contents">Content to go in the link</param> /// <returns>An "a" HTML element</returns> public virtual string RenderLink <T>(T model, Expression <Func <T, object> > field, object attributes = null, bool isEditable = false, string contents = null) { NameValueCollection attrs = null; if (attributes is NameValueCollection) { attrs = attributes as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(attributes, true); } var sb = new StringBuilder(); var writer = new StringWriter(sb); RenderingResult result = null; if (IsInEditingMode && isEditable) { result = MakeEditable( field, null, model, contents == null ? string.Empty: "haschildren=true", _context, SitecoreContext.Database, writer); } else { result = BeginRenderLink( field.Compile().Invoke(model) as Fields.Link, attrs, contents, writer ); } result.Dispose(); writer.Flush(); writer.Close(); return(sb.ToString()); }
/// <summary> /// Makes the editable. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="field">The field.</param> /// <param name="standardOutput">The standard output.</param> /// <param name="model">The model.</param> /// <param name="parameters">The parameters.</param> /// <returns>System.String.</returns> /// <exception cref="Glass.Mapper.MapperException"> /// To many parameters in linq expression {0}.Formatted(field.Body) /// or /// Expression doesn't evaluate to a member {0}.Formatted(field.Body) /// or /// Page editting error. Could not find property {0} on type {1}.Formatted(memberExpression.Member.Name, config.Type.FullName) /// or /// Page editting error. Could not find data handler for property {2} {0}.{1}.Formatted( /// prop.DeclaringType, prop.Name, prop.MemberType) /// </exception> /// <exception cref="System.NullReferenceException">Context cannot be null</exception> private RenderingResult MakeEditable <T>( Expression <Func <T, object> > field, Expression <Func <T, string> > standardOutput, T model, object parameters, Context context, Database database, TextWriter writer) { string firstPart = string.Empty; string lastPart = string.Empty; try { if (field == null) { throw new NullReferenceException("No field set"); } if (model == null) { throw new NullReferenceException("No model set"); } string parametersStringTemp = string.Empty; SafeDictionary <string> dictionary = new SafeDictionary <string>(); if (parameters == null) { parametersStringTemp = string.Empty; } else if (parameters is string) { parametersStringTemp = parameters as string; dictionary = WebUtil.ParseQueryString(parametersStringTemp ?? string.Empty); } else if (parameters is NameValueCollection) { var collection = (NameValueCollection)parameters; foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } else { var collection = Utilities.GetPropertiesCollection(parameters, true); foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } if (IsInEditingMode) { if (field.Parameters.Count > 1) { throw new MapperException("To many parameters in linq expression {0}".Formatted(field.Body)); } MemberExpression memberExpression; if (field.Body is UnaryExpression) { memberExpression = ((UnaryExpression)field.Body).Operand as MemberExpression; } else if (!(field.Body is MemberExpression)) { throw new MapperException("Expression doesn't evaluate to a member {0}".Formatted(field.Body)); } else { memberExpression = (MemberExpression)field.Body; } //we have to deconstruct the lambda expression to find the //correct model object //For example if we have the lambda expression x =>x.Children.First().Content //we have to evaluate what the first Child object is, then evaluate the field to edit from there. //this contains the expression that will evaluate to the object containing the property var objectExpression = memberExpression.Expression; var finalTarget = Expression.Lambda(objectExpression, field.Parameters).Compile().DynamicInvoke(model); var site = global::Sitecore.Context.Site; if (context == null) { throw new NullReferenceException("Context cannot be null"); } var config = context.GetTypeConfiguration <SitecoreTypeConfiguration>(finalTarget); var scClass = config.ResolveItem(finalTarget, database); //lambda expression does not always return expected memberinfo when inheriting //c.f. http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo var prop = config.Type.GetProperty(memberExpression.Member.Name); //interfaces don't deal with inherited properties well if (prop == null && config.Type.IsInterface) { Func <Type, PropertyInfo> interfaceCheck = null; interfaceCheck = (inter) => { var interfaces = inter.GetInterfaces(); var properties = interfaces.Select(x => x.GetProperty(memberExpression.Member.Name)).Where( x => x != null); if (properties.Any()) { return(properties.First()); } else { return(interfaces.Select(x => interfaceCheck(x)).FirstOrDefault(x => x != null)); } }; prop = interfaceCheck(config.Type); } if (prop != null && prop.DeclaringType != prop.ReflectedType) { //properties mapped in data handlers are based on declaring type when field is inherited, make sure we match prop = prop.DeclaringType.GetProperty(prop.Name); } if (prop == null) { throw new MapperException( "Page editting error. Could not find property {0} on type {1}".Formatted( memberExpression.Member.Name, config.Type.FullName)); } //ME - changed this to work by name because properties on interfaces do not show up as declared types. var dataHandler = config.Properties.FirstOrDefault(x => x.PropertyInfo.Name == prop.Name); if (dataHandler == null) { throw new MapperException( "Page editing error. Could not find data handler for property {2} {0}.{1}".Formatted( prop.DeclaringType, prop.Name, prop.MemberType)); } using (new ContextItemSwitcher(scClass)) { RenderFieldArgs renderFieldArgs = new RenderFieldArgs(); renderFieldArgs.Item = scClass; var fieldConfig = (SitecoreFieldConfiguration)dataHandler; if (fieldConfig.FieldId != (Sitecore.Data.ID)null && fieldConfig.FieldId != ID.Null) { renderFieldArgs.FieldName = fieldConfig.FieldId.ToString(); } else { renderFieldArgs.FieldName = fieldConfig.FieldName; } renderFieldArgs.Parameters = dictionary; renderFieldArgs.DisableWebEdit = false; CorePipeline.Run("renderField", (PipelineArgs)renderFieldArgs); firstPart = renderFieldArgs.Result.FirstPart; lastPart = renderFieldArgs.Result.LastPart; } } else { if (standardOutput != null) { firstPart = GetCompiled <T>(standardOutput)(model).ToString(); } else { var type = field.Body.Type; object target = (GetCompiled <T>(field)(model) ?? string.Empty); if (type == ImageType) { var image = target as Image; firstPart = RenderImage(image, dictionary); } else if (type == LinkType) { var link = target as Link; var sb = new StringBuilder(); var linkWriter = new StringWriter(sb); var result = BeginRenderLink(link, dictionary, null, linkWriter); result.Dispose(); linkWriter.Flush(); linkWriter.Close(); firstPart = sb.ToString(); } else { firstPart = target.ToString(); } } } } catch (Exception ex) { firstPart = "<p>{0}</p><pre>{1}</pre>".Formatted(ex.Message, ex.StackTrace); Sitecore.Diagnostics.Log.Error("Failed to render field", ex, typeof(IGlassHtml)); } return(new RenderingResult(writer, firstPart, lastPart)); //return field.Compile().Invoke(model).ToString(); }
/// <summary> /// Makes the editable. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="field">The field.</param> /// <param name="standardOutput">The standard output.</param> /// <param name="model">The model.</param> /// <param name="parameters">The parameters.</param> /// <returns>System.String.</returns> /// <exception cref="Glass.Mapper.MapperException"> /// To many parameters in linq expression {0}.Formatted(field.Body) /// or /// Expression doesn't evaluate to a member {0}.Formatted(field.Body) /// or /// Page editting error. Could not find property {0} on type {1}.Formatted(memberExpression.Member.Name, config.Type.FullName) /// or /// Page editting error. Could not find data handler for property {2} {0}.{1}.Formatted( /// prop.DeclaringType, prop.Name, prop.MemberType) /// </exception> /// <exception cref="System.NullReferenceException">Context cannot be null</exception> private RenderingResult MakeEditable <T>( Expression <Func <T, object> > field, Expression <Func <T, string> > standardOutput, T model, object parameters, Context context, Database database, TextWriter writer) { string firstPart = string.Empty; string lastPart = string.Empty; try { if (field == null) { throw new NullReferenceException("No field set"); } if (model == null) { throw new NullReferenceException("No model set"); } string parametersStringTemp = string.Empty; SafeDictionary <string> dictionary = new SafeDictionary <string>(); if (parameters == null) { parametersStringTemp = string.Empty; } else if (parameters is string) { parametersStringTemp = parameters as string; dictionary = WebUtil.ParseQueryString(parametersStringTemp ?? string.Empty); } else if (parameters is NameValueCollection) { var collection = (NameValueCollection)parameters; foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } else { var collection = Utilities.GetPropertiesCollection(parameters, true); foreach (var key in collection.AllKeys) { dictionary.Add(key, collection[key]); } } if (IsInEditingMode) { MemberExpression memberExpression; var finalTarget = Mapper.Utilities.GetTargetObjectOfLamba(field, model, out memberExpression); var config = Mapper.Utilities.GetTypeConfig <T, SitecoreTypeConfiguration>(field, context, model); var dataHandler = Mapper.Utilities.GetGlassProperty <T, SitecoreTypeConfiguration>(field, context, model); var scClass = config.ResolveItem(finalTarget, database); using (new ContextItemSwitcher(scClass)) { RenderFieldArgs renderFieldArgs = new RenderFieldArgs(); renderFieldArgs.Item = scClass; var fieldConfig = (SitecoreFieldConfiguration)dataHandler; if (fieldConfig.FieldId != (ID)null && fieldConfig.FieldId != ID.Null) { renderFieldArgs.FieldName = fieldConfig.FieldId.ToString(); } else { renderFieldArgs.FieldName = fieldConfig.FieldName; } renderFieldArgs.Parameters = dictionary; renderFieldArgs.DisableWebEdit = false; CorePipeline.Run("renderField", (PipelineArgs)renderFieldArgs); firstPart = renderFieldArgs.Result.FirstPart; lastPart = renderFieldArgs.Result.LastPart; } } else { if (standardOutput != null) { firstPart = GetCompiled(standardOutput)(model).ToString(); } else { object target = (GetCompiled(field)(model) ?? string.Empty); if (ImageType.IsInstanceOfType(target)) { var image = target as Image; firstPart = RenderImage(image, dictionary); } else if (LinkType.IsInstanceOfType(target)) { var link = target as Link; var sb = new StringBuilder(); var linkWriter = new StringWriter(sb); var result = BeginRenderLink(link, dictionary, null, linkWriter); result.Dispose(); linkWriter.Flush(); linkWriter.Close(); firstPart = sb.ToString(); } else { firstPart = target.ToString(); } } } } catch (Exception ex) { firstPart = "<p>{0}</p><pre>{1}</pre>".Formatted(ex.Message, ex.StackTrace); Sitecore.Diagnostics.Log.Error("Failed to render field", ex, typeof(IGlassHtml)); } return(new RenderingResult(writer, firstPart, lastPart)); //return field.Compile().Invoke(model).ToString(); }