diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index f43e5c4916..49f679d1f4 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -77,7 +77,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// Gets the published content type containing the property type. - /// + /// public PublishedContentType ContentType { get; internal set; } // internally set by PublishedContentType constructor /// @@ -193,6 +193,20 @@ namespace Umbraco.Core.Models.PublishedContent _modelClrType = _converter == null ? typeof (object) : _converter.GetPropertyValueType(this); } + /// + /// Determines whether a source value is an actual value, or not a value. + /// + /// Used by property.HasValue and, for instance, in fallback scenarios. + public bool IsValue(object value) + { + // if we have a converter, use the converter, + // otherwise use the old magic null & string comparisons + + return _converter == null + ? value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false) + : _converter.IsValue(value); + } + /// /// Gets the property cache level. /// diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs b/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs index 6bd36a8f6f..53851f8653 100644 --- a/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs @@ -17,6 +17,11 @@ namespace Umbraco.Core.PropertyEditors /// A value indicating whether the converter supports a property type. bool IsConverter(PublishedPropertyType propertyType); + /// + /// Determines whether a source value is an actual value, or not a value. + /// + bool IsValue(object value); + /// /// Gets the type of values returned by the converter. /// diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 724d7d0b55..9a82446edd 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -9,33 +9,24 @@ namespace Umbraco.Core.PropertyEditors public abstract class PropertyValueConverterBase : IPropertyValueConverter { public virtual bool IsConverter(PublishedPropertyType propertyType) - { - return false; - } + => false; + + public bool IsValue(object value) + => value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); public virtual Type GetPropertyValueType(PublishedPropertyType propertyType) - { - return typeof (object); - } + => typeof (object); public virtual PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) - { - return PropertyCacheLevel.Snapshot; - } + => PropertyCacheLevel.Snapshot; public virtual object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) - { - return source; - } + => source; public virtual object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - return inter; - } + => inter; public virtual object ConvertIntermediateToXPath(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - return inter?.ToString() ?? string.Empty; - } + => inter?.ToString() ?? string.Empty; } } diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 25933fdd9d..39cb37f160 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -47,6 +47,9 @@ namespace Umbraco.Tests.Published private class SimpleConverter1 : IPropertyValueConverter { + public bool IsValue(object value) + => value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + public bool IsConverter(PublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals("Umbraco.Void"); @@ -117,6 +120,9 @@ namespace Umbraco.Tests.Published _cacheLevel = cacheLevel; } + public bool IsValue(object value) + => value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + public bool IsConverter(PublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals("Umbraco.Void"); diff --git a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs index 950d81ee36..617429d205 100644 --- a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs +++ b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs @@ -210,6 +210,9 @@ namespace Umbraco.Tests.Published public int SourceConverts { get; private set; } public int InterConverts { get; private set; } + public bool IsValue(object value) + => value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + public bool IsConverter(PublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals("Umbraco.Void"); @@ -235,4 +238,4 @@ namespace Umbraco.Tests.Published => ((int) inter).ToString(); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs index 2d24efdd67..73a159cb19 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs @@ -90,11 +90,7 @@ namespace Umbraco.Web.PublishedCache.NuCache public override bool HasValue(string culture = null, string segment = null) { ContextualizeVariation(ref culture, ref segment); - - var sourceValue = GetSourceValue(culture, segment); - - return sourceValue != null && - (!(sourceValue is string) || string.IsNullOrWhiteSpace((string) sourceValue) == false); + return PropertyType.IsValue(GetSourceValue(culture, segment)); } // used to cache the CacheValues of this property