Merge pull request #7618 from AndyButland/netcore/7617-published-content-element-property-extension-methods
Netcore: Migrate various extension methods on IPublishedContent, IPublishedElement and IPublishedProperty to Umbraco.Abstractions
This commit is contained in:
@@ -9,6 +9,56 @@ namespace Umbraco.Core
|
||||
{
|
||||
public static class PublishedContentExtensions
|
||||
{
|
||||
#region Name
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the content item.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">The specific culture to get the name for. If null is used the current culture is used (Default is null).</param>
|
||||
public static string Name(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
// invariant has invariant value (whatever the requested culture)
|
||||
if (!content.ContentType.VariesByCulture())
|
||||
return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.Name : null;
|
||||
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
// get
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Name : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Url segment
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url segment of the content item.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">The specific culture to get the url segment for. If null is used the current culture is used (Default is null).</param>
|
||||
public static string UrlSegment(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
// invariant has invariant value (whatever the requested culture)
|
||||
if (!content.ContentType.VariesByCulture())
|
||||
return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.UrlSegment : null;
|
||||
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
// get
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.UrlSegment : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Culture
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content has a culture.
|
||||
/// </summary>
|
||||
@@ -40,47 +90,6 @@ namespace Umbraco.Core
|
||||
return contents.Where(x => !x.ContentType.VariesByCulture() || HasCulture(x, culture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the content item.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">The specific culture to get the name for. If null is used the current culture is used (Default is null).</param>
|
||||
public static string Name(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
// invariant has invariant value (whatever the requested culture)
|
||||
if (!content.ContentType.VariesByCulture())
|
||||
return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.Name : null;
|
||||
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
// get
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Name : null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url segment of the content item.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">The specific culture to get the url segment for. If null is used the current culture is used (Default is null).</param>
|
||||
public static string UrlSegment(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
// invariant has invariant value (whatever the requested culture)
|
||||
if (!content.ContentType.VariesByCulture())
|
||||
return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.UrlSegment : null;
|
||||
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
// get
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.UrlSegment : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the culture date of the content item.
|
||||
/// </summary>
|
||||
@@ -101,53 +110,211 @@ namespace Umbraco.Core
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Date : DateTime.MinValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsComposedOf
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content item.
|
||||
/// Gets a value indicating whether the content is of a content type composed of the given alias
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">
|
||||
/// The specific culture to get the url children for. Default is null which will use the current culture in <see cref="VariationContext"/>
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// <para>Gets children that are available for the specified culture.</para>
|
||||
/// <para>Children are sorted by their sortOrder.</para>
|
||||
/// <para>
|
||||
/// For culture,
|
||||
/// if null is used the current culture is used.
|
||||
/// If an empty string is used only invariant children are returned.
|
||||
/// If "*" is used all children are returned.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If a variant culture is specified or there is a current culture in the <see cref="VariationContext"/> then the Children returned
|
||||
/// will include both the variant children matching the culture AND the invariant children because the invariant children flow with the current culture.
|
||||
/// However, if an empty string is specified only invariant children are returned.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The content type alias.</param>
|
||||
/// <returns>A value indicating whether the content is of a content type composed of a content type identified by the alias.</returns>
|
||||
public static bool IsComposedOf(this IPublishedContent content, string alias)
|
||||
{
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
var children = content.ChildrenForAllCultures;
|
||||
return culture == "*"
|
||||
? children
|
||||
: children.Where(x => x.IsInvariantOrHasCulture(culture));
|
||||
return content.ContentType.CompositionAliases.InvariantContains(alias);
|
||||
}
|
||||
|
||||
#region Writer and creator
|
||||
#endregion
|
||||
|
||||
public static string GetCreatorName(this IPublishedContent content, IUserService userService)
|
||||
#region Template
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current template Alias
|
||||
/// </summary>
|
||||
/// <returns>Empty string if none is set.</returns>
|
||||
public static string GetTemplateAlias(this IPublishedContent content, IFileService fileService)
|
||||
{
|
||||
var user = userService.GetProfileById(content.CreatorId);
|
||||
return user?.Name;
|
||||
if (content.TemplateId.HasValue == false)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var template = fileService.GetTemplate(content.TemplateId.Value);
|
||||
return template == null ? string.Empty : template.Alias;
|
||||
}
|
||||
|
||||
public static string GetWriterName(this IPublishedContent content, IUserService userService)
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, bool disableAlternativeTemplates, bool validateAlternativeTemplates, int templateId)
|
||||
{
|
||||
var user = userService.GetProfileById(content.WriterId);
|
||||
return user?.Name;
|
||||
if (disableAlternativeTemplates)
|
||||
return content.TemplateId == templateId;
|
||||
|
||||
if (content.TemplateId == templateId || !validateAlternativeTemplates)
|
||||
return true;
|
||||
|
||||
var publishedContentContentType = contentTypeService.Get(content.ContentType.Id);
|
||||
if (publishedContentContentType == null)
|
||||
throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')");
|
||||
|
||||
return publishedContentContentType.IsAllowedTemplate(templateId);
|
||||
|
||||
}
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, IFileService fileService, IContentTypeService contentTypeService, bool disableAlternativeTemplates, bool validateAlternativeTemplates, string templateAlias)
|
||||
{
|
||||
var template = fileService.GetTemplate(templateAlias);
|
||||
return template != null && content.IsAllowedTemplate(contentTypeService, disableAlternativeTemplates, validateAlternativeTemplates, template.Id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasValue, Value, Value<T>
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content has a value for a property identified by its alias.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The variation language.</param>
|
||||
/// <param name="segment">The variation segment.</param>
|
||||
/// <param name="fallback">Optional fallback strategy.</param>
|
||||
/// <returns>A value indicating whether the content has a value for the property identified by the alias.</returns>
|
||||
/// <remarks>Returns true if HasValue is true, or a fallback strategy can provide a value.</remarks>
|
||||
public static bool HasValue(this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string culture = null, string segment = null, Fallback fallback = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return true;
|
||||
|
||||
// else let fallback try to get a value
|
||||
return publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, null, out _, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a content's property identified by its alias, if it exists, otherwise a default value.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The variation language.</param>
|
||||
/// <param name="segment">The variation segment.</param>
|
||||
/// <param name="fallback">Optional fallback strategy.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>The value of the content's property identified by the alias, if it exists, otherwise a default value.</returns>
|
||||
public static object Value(this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value, out property))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable)
|
||||
return property?.GetValue(culture, segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a content's property identified by its alias, converted to a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The target property type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The variation language.</param>
|
||||
/// <param name="segment">The variation segment.</param>
|
||||
/// <param name="fallback">Optional fallback strategy.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>The value of the content's property identified by the alias, converted to the specified type.</returns>
|
||||
public static T Value<T>(this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.Value<T>(publishedValueFallback, culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value, out property))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property == null ? default : property.Value<T>(publishedValueFallback, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething: misc.
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified content is a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to determine content type of.</param>
|
||||
/// <param name="docTypeAlias">The alias of the content type to test against.</param>
|
||||
/// <returns>True if the content is of the specified content type; otherwise false.</returns>
|
||||
public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias)
|
||||
{
|
||||
return content.ContentType.Alias.InvariantEquals(docTypeAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified content is a specified content type or it's derived types.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to determine content type of.</param>
|
||||
/// <param name="docTypeAlias">The alias of the content type to test against.</param>
|
||||
/// <param name="recursive">When true, recurses up the content type tree to check inheritance; when false just calls IsDocumentType(this IPublishedContent content, string docTypeAlias).</param>
|
||||
/// <returns>True if the content is of the specified content type or a derived content type; otherwise false.</returns>
|
||||
public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias, bool recursive)
|
||||
{
|
||||
if (content.IsDocumentType(docTypeAlias))
|
||||
return true;
|
||||
|
||||
return recursive && content.IsComposedOf(docTypeAlias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething: equality
|
||||
|
||||
public static bool IsEqual(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Id == other.Id;
|
||||
}
|
||||
|
||||
public static bool IsNotEqual(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.IsEqual(other) == false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething: ancestors and descendants
|
||||
|
||||
public static bool IsDescendant(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return other.Level < content.Level && content.Path.InvariantStartsWith(other.Path.EnsureEndsWith(','));
|
||||
}
|
||||
|
||||
public static bool IsDescendantOrSelf(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Path.InvariantEquals(other.Path) || content.IsDescendant(other);
|
||||
}
|
||||
|
||||
public static bool IsAncestor(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Level < other.Level && other.Path.InvariantStartsWith(content.Path.EnsureEndsWith(','));
|
||||
}
|
||||
|
||||
public static bool IsAncestorOrSelf(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return other.Path.InvariantEquals(content.Path) || content.IsAncestor(other);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -639,6 +806,41 @@ namespace Umbraco.Core
|
||||
|
||||
#region Axes: children
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content item.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <param name="culture">
|
||||
/// The specific culture to get the url children for. Default is null which will use the current culture in <see cref="VariationContext"/>
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// <para>Gets children that are available for the specified culture.</para>
|
||||
/// <para>Children are sorted by their sortOrder.</para>
|
||||
/// <para>
|
||||
/// For culture,
|
||||
/// if null is used the current culture is used.
|
||||
/// If an empty string is used only invariant children are returned.
|
||||
/// If "*" is used all children are returned.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If a variant culture is specified or there is a current culture in the <see cref="VariationContext"/> then the Children returned
|
||||
/// will include both the variant children matching the culture AND the invariant children because the invariant children flow with the current culture.
|
||||
/// However, if an empty string is specified only invariant children are returned.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
// handle context culture for variant
|
||||
if (culture == null)
|
||||
culture = variationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
|
||||
var children = content.ChildrenForAllCultures;
|
||||
return culture == "*"
|
||||
? children
|
||||
: children.Where(x => x.IsInvariantOrHasCulture(culture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content, filtered by a predicate.
|
||||
/// </summary>
|
||||
@@ -741,7 +943,7 @@ namespace Umbraco.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: Siblings
|
||||
#region Axes: siblings
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content.
|
||||
@@ -857,5 +1059,21 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Writer and creator
|
||||
|
||||
public static string GetCreatorName(this IPublishedContent content, IUserService userService)
|
||||
{
|
||||
var user = userService.GetProfileById(content.CreatorId);
|
||||
return user?.Name;
|
||||
}
|
||||
|
||||
public static string GetWriterName(this IPublishedContent content, IUserService userService)
|
||||
{
|
||||
var user = userService.GetProfileById(content.WriterId);
|
||||
return user?.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -23,5 +22,158 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsComposedOf
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content is of a content type composed of the given alias
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The content type alias.</param>
|
||||
/// <returns>A value indicating whether the content is of a content type composed of a content type identified by the alias.</returns>
|
||||
public static bool IsComposedOf(this IPublishedElement content, string alias)
|
||||
{
|
||||
return content.ContentType.CompositionAliases.InvariantContains(alias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasProperty
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content has a property identified by its alias.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <returns>A value indicating whether the content has the property identified by the alias.</returns>
|
||||
/// <remarks>The content may have a property, and that property may not have a value.</remarks>
|
||||
public static bool HasProperty(this IPublishedElement content, string alias)
|
||||
{
|
||||
return content.ContentType.GetPropertyType(alias) != null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasValue
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content has a value for a property identified by its alias.
|
||||
/// </summary>
|
||||
/// <remarks>Returns true if <c>GetProperty(alias)</c> is not <c>null</c> and <c>GetProperty(alias).HasValue</c> is <c>true</c>.</remarks>
|
||||
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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a content's property identified by its alias.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The variation language.</param>
|
||||
/// <param name="segment">The variation segment.</param>
|
||||
/// <param name="fallback">Optional fallback strategy.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>The value of the content's property identified by the alias, if it exists, otherwise a default value.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The value comes from <c>IPublishedProperty</c> field <c>Value</c> ie it is suitable for use when rendering content.</para>
|
||||
/// <para>If no property with the specified alias exists, or if the property has no value, returns <paramref name="defaultValue"/>.</para>
|
||||
/// <para>If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.</para>
|
||||
/// <para>The alias is case-insensitive.</para>
|
||||
/// </remarks>
|
||||
public static object Value(this IPublishedElement content, IPublishedValueFallback publishedValueFallback, string alias, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property?.GetValue(culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value<T>
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a content's property identified by its alias, converted to a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The target property type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The variation language.</param>
|
||||
/// <param name="segment">The variation segment.</param>
|
||||
/// <param name="fallback">Optional fallback strategy.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>The value of the content's property identified by the alias, converted to the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The value comes from <c>IPublishedProperty</c> field <c>Value</c> ie it is suitable for use when rendering content.</para>
|
||||
/// <para>If no property with the specified alias exists, or if the property has no value, or if it could not be converted, returns <c>default(T)</c>.</para>
|
||||
/// <para>If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter.</para>
|
||||
/// <para>The alias is case-insensitive.</para>
|
||||
/// </remarks>
|
||||
public static T Value<T>(this IPublishedElement content, IPublishedValueFallback publishedValueFallback, string alias, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.Value<T>(publishedValueFallback, culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property == null ? default : property.Value<T>(publishedValueFallback, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToIndexedArray
|
||||
|
||||
public static IndexedArrayItem<TContent>[] ToIndexedArray<TContent>(this IEnumerable<TContent> source)
|
||||
where TContent : class, IPublishedElement
|
||||
{
|
||||
var set = source.Select((content, index) => new IndexedArrayItem<TContent>(content, index)).ToArray();
|
||||
foreach (var setItem in set) setItem.TotalCount = set.Length;
|
||||
return set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content is visible.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedValueFallback">The published value fallback implementation.</param>
|
||||
/// <returns>A value indicating whether the content is visible.</returns>
|
||||
/// <remarks>A content is not visible if it has an umbracoNaviHide property with a value of "1". Otherwise,
|
||||
/// the content is visible.</remarks>
|
||||
public static bool IsVisible(this IPublishedElement content, IPublishedValueFallback publishedValueFallback)
|
||||
{
|
||||
// rely on the property converter - will return default bool value, ie false, if property
|
||||
// is not defined, or has no value, else will return its value.
|
||||
return content.Value<bool>(publishedValueFallback, Constants.Conventions.Content.NaviHide) == false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
59
src/Umbraco.Abstractions/PublishedPropertyExtension.cs
Normal file
59
src/Umbraco.Abstractions/PublishedPropertyExtension.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for <c>IPublishedProperty</c>.
|
||||
/// </summary>
|
||||
public static class PublishedPropertyExtension
|
||||
{
|
||||
#region Value
|
||||
|
||||
public static object Value(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
if (property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
return publishedValueFallback.TryGetValue(property, culture, segment, fallback, defaultValue, out var value)
|
||||
? value
|
||||
: property.GetValue(culture, segment); // give converter a chance to return it's own vision of "no value"
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value<T>
|
||||
|
||||
public static T Value<T>(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
if (property.HasValue(culture, segment))
|
||||
{
|
||||
// we have a value
|
||||
// try to cast or convert it
|
||||
var value = property.GetValue(culture, segment);
|
||||
if (value is T valueAsT) return valueAsT;
|
||||
var valueConverted = value.TryConvertTo<T>();
|
||||
if (valueConverted) return valueConverted.Result;
|
||||
|
||||
// cannot cast nor convert the value, nothing we can return but 'default'
|
||||
// note: we don't want to fallback in that case - would make little sense
|
||||
return default;
|
||||
}
|
||||
|
||||
// we don't have a value, try fallback
|
||||
if (publishedValueFallback.TryGetValue(property, culture, segment, fallback, defaultValue, out var fallbackValue))
|
||||
return fallbackValue;
|
||||
|
||||
// we don't have a value - neither direct nor fallback
|
||||
// give a chance to the converter to return something (eg empty enumerable)
|
||||
var noValue = property.GetValue(culture, segment);
|
||||
if (noValue is T noValueAsT) return noValueAsT;
|
||||
var noValueConverted = noValue.TryConvertTo<T>();
|
||||
if (noValueConverted) return noValueConverted.Result;
|
||||
|
||||
// cannot cast noValue nor convert it, nothing we can return but 'default'
|
||||
return default;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,14 @@ using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.Components;
|
||||
using Umbraco.Tests.PublishedContent;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Tests.Published
|
||||
{
|
||||
[TestFixture]
|
||||
public class ConvertersTests
|
||||
public class ConvertersTests : UmbracoTestBase
|
||||
{
|
||||
#region SimpleConverter1
|
||||
|
||||
|
||||
@@ -17,16 +17,15 @@ using Umbraco.Web;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using Umbraco.Web.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Published
|
||||
{
|
||||
[TestFixture]
|
||||
public class NestedContentTests
|
||||
public class NestedContentTests : UmbracoTestBase
|
||||
{
|
||||
private (IPublishedContentType, IPublishedContentType) CreateContentTypes()
|
||||
{
|
||||
Current.Reset();
|
||||
|
||||
var logger = Mock.Of<ILogger>();
|
||||
var profiler = Mock.Of<IProfiler>();
|
||||
var proflog = new ProfilingLogger(logger, profiler);
|
||||
|
||||
@@ -12,13 +12,14 @@ using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Tests.Published
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyCacheLevelTests
|
||||
public class PropertyCacheLevelTests : UmbracoTestBase
|
||||
{
|
||||
[TestCase(PropertyCacheLevel.None, 2)]
|
||||
[TestCase(PropertyCacheLevel.Element, 1)]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
@@ -49,13 +49,11 @@ using Umbraco.Web.Templates;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Net;
|
||||
using Umbraco.Web.Security;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Tests.Testing
|
||||
{
|
||||
/// <summary>
|
||||
@@ -296,7 +294,7 @@ namespace Umbraco.Tests.Testing
|
||||
Composition.RegisterUnique<HtmlUrlParser>();
|
||||
Composition.RegisterUnique<HtmlImageSourceParser>();
|
||||
Composition.RegisterUnique<RichTextEditorPastedImages>();
|
||||
|
||||
Composition.RegisterUnique<IPublishedValueFallback, NoopPublishedValueFallback>();
|
||||
}
|
||||
|
||||
protected virtual void ComposeMisc()
|
||||
|
||||
@@ -31,21 +31,6 @@ namespace Umbraco.Web
|
||||
private static IExamineManager ExamineManager => Current.Factory.GetInstance<IExamineManager>();
|
||||
private static IUserService UserService => Current.Services.UserService;
|
||||
|
||||
#region IsComposedOf
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content is of a content type composed of the given alias
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The content type alias.</param>
|
||||
/// <returns>A value indicating whether the content is of a content type composed of a content type identified by the alias.</returns>
|
||||
public static bool IsComposedOf(this IPublishedContent content, string alias)
|
||||
{
|
||||
return content.ContentType.CompositionAliases.InvariantContains(alias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Template
|
||||
|
||||
/// <summary>
|
||||
@@ -55,34 +40,26 @@ namespace Umbraco.Web
|
||||
/// <returns>Empty string if none is set.</returns>
|
||||
public static string GetTemplateAlias(this IPublishedContent content)
|
||||
{
|
||||
if(content.TemplateId.HasValue == false)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var template = Current.Services.FileService.GetTemplate(content.TemplateId.Value);
|
||||
return template == null ? string.Empty : template.Alias;
|
||||
return content.GetTemplateAlias(Current.Services.FileService);
|
||||
}
|
||||
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, int templateId)
|
||||
{
|
||||
if (Current.Configs.Settings().WebRouting.DisableAlternativeTemplates)
|
||||
return content.TemplateId == templateId;
|
||||
|
||||
if (content.TemplateId == templateId || !Current.Configs.Settings().WebRouting.ValidateAlternativeTemplates)
|
||||
return true;
|
||||
|
||||
var publishedContentContentType = Current.Services.ContentTypeService.Get(content.ContentType.Id);
|
||||
if (publishedContentContentType == null)
|
||||
throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')");
|
||||
|
||||
return publishedContentContentType.IsAllowedTemplate(templateId);
|
||||
return content.IsAllowedTemplate(
|
||||
Current.Services.ContentTypeService,
|
||||
Current.Configs.Settings().WebRouting.DisableAlternativeTemplates,
|
||||
Current.Configs.Settings().WebRouting.ValidateAlternativeTemplates,
|
||||
templateId);
|
||||
|
||||
}
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, string templateAlias)
|
||||
{
|
||||
var template = Current.Services.FileService.GetTemplate(templateAlias);
|
||||
return template != null && content.IsAllowedTemplate(template.Id);
|
||||
return content.IsAllowedTemplate(
|
||||
Current.Services.FileService,
|
||||
Current.Services.ContentTypeService,
|
||||
Current.Configs.Settings().WebRouting.DisableAlternativeTemplates,
|
||||
Current.Configs.Settings().WebRouting.ValidateAlternativeTemplates,
|
||||
templateAlias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -101,14 +78,7 @@ namespace Umbraco.Web
|
||||
/// <remarks>Returns true if HasValue is true, or a fallback strategy can provide a value.</remarks>
|
||||
public static bool HasValue(this IPublishedContent content, string alias, string culture = null, string segment = null, Fallback fallback = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return true;
|
||||
|
||||
// else let fallback try to get a value
|
||||
return PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, null, out _, out _);
|
||||
return content.HasValue(PublishedValueFallback, alias, culture, segment, fallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -123,19 +93,7 @@ namespace Umbraco.Web
|
||||
/// <returns>The value of the content's property identified by the alias, if it exists, otherwise a default value.</returns>
|
||||
public static object Value(this IPublishedContent content, string alias, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value, out property))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable)
|
||||
return property?.GetValue(culture, segment);
|
||||
return content.Value(PublishedValueFallback, alias, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -151,19 +109,7 @@ namespace Umbraco.Web
|
||||
/// <returns>The value of the content's property identified by the alias, converted to the specified type.</returns>
|
||||
public static T Value<T>(this IPublishedContent content, string alias, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.Value<T>(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value, out property))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property == null ? default : property.Value<T>(culture, segment);
|
||||
return content.Value<T>(PublishedValueFallback, alias, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -239,42 +185,7 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething: misc.
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified content is a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to determine content type of.</param>
|
||||
/// <param name="docTypeAlias">The alias of the content type to test against.</param>
|
||||
/// <returns>True if the content is of the specified content type; otherwise false.</returns>
|
||||
public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias)
|
||||
{
|
||||
return content.ContentType.Alias.InvariantEquals(docTypeAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified content is a specified content type or it's derived types.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to determine content type of.</param>
|
||||
/// <param name="docTypeAlias">The alias of the content type to test against.</param>
|
||||
/// <param name="recursive">When true, recurses up the content type tree to check inheritance; when false just calls IsDocumentType(this IPublishedContent content, string docTypeAlias).</param>
|
||||
/// <returns>True if the content is of the specified content type or a derived content type; otherwise false.</returns>
|
||||
public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias, bool recursive)
|
||||
{
|
||||
if (content.IsDocumentType(docTypeAlias))
|
||||
return true;
|
||||
|
||||
return recursive && content.IsComposedOf(docTypeAlias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething: equality
|
||||
|
||||
public static bool IsEqual(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Id == other.Id;
|
||||
}
|
||||
#region IsSomething: equality
|
||||
|
||||
public static HtmlString IsEqual(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
@@ -286,11 +197,6 @@ namespace Umbraco.Web
|
||||
return new HtmlString(content.IsEqual(other) ? valueIfTrue : valueIfFalse);
|
||||
}
|
||||
|
||||
public static bool IsNotEqual(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.IsEqual(other) == false;
|
||||
}
|
||||
|
||||
public static HtmlString IsNotEqual(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
return content.IsNotEqual(other, valueIfTrue, string.Empty);
|
||||
@@ -305,11 +211,6 @@ namespace Umbraco.Web
|
||||
|
||||
#region IsSomething: ancestors and descendants
|
||||
|
||||
public static bool IsDescendant(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return other.Level < content.Level && content.Path.InvariantStartsWith(other.Path.EnsureEndsWith(','));
|
||||
}
|
||||
|
||||
public static HtmlString IsDescendant(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
return content.IsDescendant(other, valueIfTrue, string.Empty);
|
||||
@@ -320,11 +221,6 @@ namespace Umbraco.Web
|
||||
return new HtmlString(content.IsDescendant(other) ? valueIfTrue : valueIfFalse);
|
||||
}
|
||||
|
||||
public static bool IsDescendantOrSelf(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Path.InvariantEquals(other.Path) || content.IsDescendant(other);
|
||||
}
|
||||
|
||||
public static HtmlString IsDescendantOrSelf(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
return content.IsDescendantOrSelf(other, valueIfTrue, string.Empty);
|
||||
@@ -335,11 +231,6 @@ namespace Umbraco.Web
|
||||
return new HtmlString(content.IsDescendantOrSelf(other) ? valueIfTrue : valueIfFalse);
|
||||
}
|
||||
|
||||
public static bool IsAncestor(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return content.Level < other.Level && other.Path.InvariantStartsWith(content.Path.EnsureEndsWith(','));
|
||||
}
|
||||
|
||||
public static HtmlString IsAncestor(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
return content.IsAncestor(other, valueIfTrue, string.Empty);
|
||||
@@ -350,11 +241,6 @@ namespace Umbraco.Web
|
||||
return new HtmlString(content.IsAncestor(other) ? valueIfTrue : valueIfFalse);
|
||||
}
|
||||
|
||||
public static bool IsAncestorOrSelf(this IPublishedContent content, IPublishedContent other)
|
||||
{
|
||||
return other.Path.InvariantEquals(content.Path) || content.IsAncestor(other);
|
||||
}
|
||||
|
||||
public static HtmlString IsAncestorOrSelf(this IPublishedContent content, IPublishedContent other, string valueIfTrue)
|
||||
{
|
||||
return content.IsAncestorOrSelf(other, valueIfTrue, string.Empty);
|
||||
@@ -664,7 +550,7 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: Siblings
|
||||
#region Axes: siblings
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content.
|
||||
|
||||
@@ -23,53 +23,13 @@ namespace Umbraco.Web
|
||||
//
|
||||
// besides, for tests, Current support setting a fallback without even a container
|
||||
//
|
||||
// Update to this comment 8/2/2020: issue as been ameliorated by creating extensions methods in Umbraco.Abstractions
|
||||
// that accept the dependencies as arguments for many of these extension methods, and can be used within the Umbraco code-base.
|
||||
// For site developers, the "friendly" extension methods using service location have been maintained, delegating to the ones that
|
||||
// take the dependencies as parameters.
|
||||
|
||||
private static IPublishedValueFallback PublishedValueFallback => Current.PublishedValueFallback;
|
||||
|
||||
#region IsComposedOf
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content is of a content type composed of the given alias
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The content type alias.</param>
|
||||
/// <returns>A value indicating whether the content is of a content type composed of a content type identified by the alias.</returns>
|
||||
public static bool IsComposedOf(this IPublishedElement content, string alias)
|
||||
{
|
||||
return content.ContentType.CompositionAliases.InvariantContains(alias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasProperty
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content has a property identified by its alias.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <returns>A value indicating whether the content has the property identified by the alias.</returns>
|
||||
/// <remarks>The content may have a property, and that property may not have a value.</remarks>
|
||||
public static bool HasProperty(this IPublishedElement content, string alias)
|
||||
{
|
||||
return content.ContentType.GetPropertyType(alias) != null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasValue
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content has a value for a property identified by its alias.
|
||||
/// </summary>
|
||||
/// <remarks>Returns true if <c>GetProperty(alias)</c> is not <c>null</c> and <c>GetProperty(alias).HasValue</c> is <c>true</c>.</remarks>
|
||||
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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value
|
||||
|
||||
/// <summary>
|
||||
@@ -90,19 +50,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static object Value(this IPublishedElement content, string alias, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property?.GetValue(culture, segment);
|
||||
return content.Value(PublishedValueFallback, alias, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -128,31 +76,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static T Value<T>(this IPublishedElement content, string alias, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
var property = content.GetProperty(alias);
|
||||
|
||||
// if we have a property, and it has a value, return that value
|
||||
if (property != null && property.HasValue(culture, segment))
|
||||
return property.Value<T>(culture, segment);
|
||||
|
||||
// else let fallback try to get a value
|
||||
if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value))
|
||||
return value;
|
||||
|
||||
// else... if we have a property, at least let the converter return its own
|
||||
// vision of 'no value' (could be an empty enumerable) - otherwise, default
|
||||
return property == null ? default : property.Value<T>(culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToIndexedArray
|
||||
|
||||
public static IndexedArrayItem<TContent>[] ToIndexedArray<TContent>(this IEnumerable<TContent> source)
|
||||
where TContent : class, IPublishedElement
|
||||
{
|
||||
var set = source.Select((content, index) => new IndexedArrayItem<TContent>(content, index)).ToArray();
|
||||
foreach (var setItem in set) setItem.TotalCount = set.Length;
|
||||
return set;
|
||||
return content.Value<T>(PublishedValueFallback, alias, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -168,9 +92,7 @@ namespace Umbraco.Web
|
||||
/// the content is visible.</remarks>
|
||||
public static bool IsVisible(this IPublishedElement content)
|
||||
{
|
||||
// rely on the property converter - will return default bool value, ie false, if property
|
||||
// is not defined, or has no value, else will return its value.
|
||||
return content.Value<bool>(Constants.Conventions.Content.NaviHide) == false;
|
||||
return content.IsVisible(PublishedValueFallback);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
@@ -18,12 +17,7 @@ namespace Umbraco.Web
|
||||
|
||||
public static object Value(this IPublishedProperty property, string culture = null, string segment = null, Fallback fallback = default, object defaultValue = default)
|
||||
{
|
||||
if (property.HasValue(culture, segment))
|
||||
return property.GetValue(culture, segment);
|
||||
|
||||
return PublishedValueFallback.TryGetValue(property, culture, segment, fallback, defaultValue, out var value)
|
||||
? value
|
||||
: property.GetValue(culture, segment); // give converter a chance to return it's own vision of "no value"
|
||||
return property.Value(PublishedValueFallback, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -32,33 +26,7 @@ namespace Umbraco.Web
|
||||
|
||||
public static T Value<T>(this IPublishedProperty property, string culture = null, string segment = null, Fallback fallback = default, T defaultValue = default)
|
||||
{
|
||||
if (property.HasValue(culture, segment))
|
||||
{
|
||||
// we have a value
|
||||
// try to cast or convert it
|
||||
var value = property.GetValue(culture, segment);
|
||||
if (value is T valueAsT) return valueAsT;
|
||||
var valueConverted = value.TryConvertTo<T>();
|
||||
if (valueConverted) return valueConverted.Result;
|
||||
|
||||
// cannot cast nor convert the value, nothing we can return but 'default'
|
||||
// note: we don't want to fallback in that case - would make little sense
|
||||
return default;
|
||||
}
|
||||
|
||||
// we don't have a value, try fallback
|
||||
if (PublishedValueFallback.TryGetValue(property, culture, segment, fallback, defaultValue, out var fallbackValue))
|
||||
return fallbackValue;
|
||||
|
||||
// we don't have a value - neither direct nor fallback
|
||||
// give a chance to the converter to return something (eg empty enumerable)
|
||||
var noValue = property.GetValue(culture, segment);
|
||||
if (noValue is T noValueAsT) return noValueAsT;
|
||||
var noValueConverted = noValue.TryConvertTo<T>();
|
||||
if (noValueConverted) return noValueConverted.Result;
|
||||
|
||||
// cannot cast noValue nor convert it, nothing we can return but 'default'
|
||||
return default;
|
||||
return property.Value<T>(PublishedValueFallback, culture, segment, fallback, defaultValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user