using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web
{
///
/// Provides extension methods for IPublishedElement.
///
public static class PublishedElementExtensions
{
#region IsComposedOf
///
/// Gets a value indicating whether the content is of a content type composed of the given alias
///
/// The content.
/// The content type alias.
/// A value indicating whether the content is of a content type composed of a content type identified by the alias.
public static bool IsComposedOf(this IPublishedElement content, string alias)
{
return content.ContentType.CompositionAliases.Contains(alias);
}
#endregion
#region HasProperty
///
/// Gets a value indicating whether the content has a property identified by its alias.
///
/// The content.
/// The property alias.
/// A value indicating whether the content has the property identified by the alias.
/// The content may have a property, and that property may not have a value.
public static bool HasProperty(this IPublishedElement content, string alias)
{
return content.ContentType.GetPropertyType(alias) != null;
}
#endregion
#region HasValue
///
/// Gets a value indicating whether the content has a value for a property identified by its alias.
///
/// Returns true if GetProperty(alias) is not null and GetProperty(alias).HasValue is true.
public static bool HasValue(this IPublishedElement content, string alias, string culture = null, string segment = null)
{
var prop = content.GetProperty(alias);
return prop != null && prop.HasValue(culture, segment);
}
///
/// Returns one of two strings depending on whether the content has a value for a property identified by its alias.
///
/// The content.
/// The property alias.
/// The value to return if the content has a value for the property.
/// The value to return if the content has no value for the property.
/// Either or depending on whether the content
/// has a value for the property identified by the alias.
public static IHtmlString IfHasValue(this IPublishedElement content, string alias, string valueIfTrue, string valueIfFalse = null)
{
return content.HasValue(alias)
? new HtmlString(valueIfTrue)
: new HtmlString(valueIfFalse ?? string.Empty);
}
#endregion
#region Value
///
/// Gets the value of a content's property identified by its alias.
///
/// The content.
/// The property alias.
/// The variation language.
/// The variation segment.
/// The value of the content's property identified by the alias.
///
/// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content.
/// If no property with the specified alias exists, or if the property has no value, returns null.
/// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.
/// The alias is case-insensitive.
///
public static object Value(this IPublishedElement content, string alias, string culture = null, string segment = null)
{
var property = content.GetProperty(alias);
return property?.GetValue(culture, segment);
}
///
/// Gets the value of a content's property identified by its alias, if it exists, otherwise a default value.
///
/// The content.
/// The property alias.
/// The default value.
/// The variation language.
/// The variation segment.
/// The value of the content's property identified by the alias, if it exists, otherwise a default value.
///
/// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content.
/// If no property with the specified alias exists, or if the property has no value, returns .
/// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.
/// The alias is case-insensitive.
///
public static object Value(this IPublishedElement content, string alias, string defaultValue, string culture = null, string segment = null) // fixme - kill
{
var property = content.GetProperty(alias);
return property == null || property.HasValue(culture, segment) == false ? defaultValue : property.GetValue(culture, segment);
}
///
/// Gets the value of a content's property identified by its alias, if it exists, otherwise a default value.
///
/// The content.
/// The property alias.
/// The default value.
/// The variation language.
/// The variation segment.
/// The value of the content's property identified by the alias, if it exists, otherwise a default value.
///
/// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content.
/// If no property with the specified alias exists, or if the property has no value, returns .
/// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.
/// The alias is case-insensitive.
///
public static object Value(this IPublishedElement content, string alias, object defaultValue, string culture = null, string segment = null)
{
var property = content.GetProperty(alias);
return property == null || property.HasValue(culture, segment) == false ? defaultValue : property.GetValue(culture, segment);
}
#endregion
#region Value
///
/// Gets the value of a content's property identified by its alias, converted to a specified type.
///
/// The target property type.
/// The content.
/// The property alias.
/// The variation language.
/// The variation segment.
/// The value of the content's property identified by the alias, converted to the specified type.
///
/// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content.
/// If no property with the specified alias exists, or if the property has no value, or if it could not be converted, returns default(T).
/// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.
/// The alias is case-insensitive.
///
public static T Value(this IPublishedElement content, string alias, string culture = null, string segment = null)
{
return content.Value(alias, false, default(T), culture, segment);
}
///
/// Gets the value of a content's property identified by its alias, converted to a specified type, if it exists, otherwise a default value.
///
/// The target property type.
/// The content.
/// The property alias.
/// The default value.
/// The variation language.
/// The variation segment.
/// The value of the content's property identified by the alias, converted to the specified type, if it exists, otherwise a default value.
///
/// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content.
/// If no property with the specified alias exists, or if the property has no value, or if it could not be converted, returns .
/// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.
/// The alias is case-insensitive.
///
public static T Value(this IPublishedElement content, string alias, T defaultValue, string culture = null, string segment = null)
{
return content.Value(alias, true, defaultValue, culture, segment);
}
internal static T Value(this IPublishedElement content, string alias, bool withDefaultValue, T defaultValue, string culture = null, string segment = null) // fixme uh?
{
var property = content.GetProperty(alias);
if (property == null) return defaultValue;
return property.Value(withDefaultValue, defaultValue, culture, segment);
}
#endregion
#region Value or Umbraco.Field - WORK IN PROGRESS
// trying to reproduce Umbraco.Field so we can get rid of it
//
// what we want:
// - alt aliases
// - recursion
// - default value
// - before & after (if value)
//
// convertLineBreaks: should be an extension string.ConvertLineBreaks()
// stripParagraphs: should be an extension string.StripParagraphs()
// format: should use the standard .ToString(format)
//
// see UmbracoComponentRenderer.Field - which is ugly ;-(
// recurse first, on each alias (that's how it's done in Field)
// TODO: strongly typed properties howto?
// there is no strongly typed recurse, etc => needs to be in ModelsBuilder?
public static IHtmlString Value(this IPublishedElement content, string aliases, Func format, string alt = "")
{
if (format == null) format = x => x.ToString();
var property = aliases.Split(',')
.Where(x => string.IsNullOrWhiteSpace(x) == false)
.Select(x => content.GetProperty(x.Trim()))
.FirstOrDefault(x => x != null);
return property != null
? new HtmlString(format(property.Value()))
: new HtmlString(alt);
}
// fixme - move that one!
public static IHtmlString Value(this IPublishedContent content, string aliases, Func format, string alt = "", bool recurse = false)
{
if (format == null) format = x => x.ToString();
var property = aliases.Split(',')
.Where(x => string.IsNullOrWhiteSpace(x) == false)
.Select(x => content.GetProperty(x.Trim(), recurse))
.FirstOrDefault(x => x != null);
return property != null
? new HtmlString(format(property.Value()))
: new HtmlString(alt);
}
#endregion
#region ToIndexedArray
public static IndexedArrayItem[] ToIndexedArray(this IEnumerable source)
where TContent : class, IPublishedElement
{
var set = source.Select((content, index) => new IndexedArrayItem(content, index)).ToArray();
foreach (var setItem in set) setItem.TotalCount = set.Length;
return set;
}
#endregion
#region OfTypes
// the .OfType() filter is nice when there's only one type
// this is to support filtering with multiple types
public static IEnumerable OfTypes(this IEnumerable contents, params string[] types)
where T : IPublishedElement
{
types = types.Select(x => x.ToLowerInvariant()).ToArray();
return contents.Where(x => types.Contains(x.ContentType.Alias.ToLowerInvariant()));
}
#endregion
}
}