From 38910a8d5c206934c02d266f88adec726ee83bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 22 Aug 2023 11:27:16 +0200 Subject: [PATCH 1/9] directly render labels without angularJS template code (#14700) --- .../src/common/services/blockeditormodelobject.service.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js index 20661d5d1c..606d16ad2d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js @@ -644,6 +644,12 @@ blockObject.index = 0; if (blockObject.config.label && blockObject.config.label !== "" && blockObject.config.unsupported !== true) { + + // If the label does not contain any AngularJS template, then the MutationObserver wont give us any updates. To ensure labels without angular JS template code, we will just set the label directly for ones without '{{': + if(blockObject.config.label.indexOf("{{") === -1) { + blockObject.label = blockObject.config.label; + } + var labelElement = $('
', { text: blockObject.config.label}); var observer = new MutationObserver(function(mutations) { @@ -673,6 +679,7 @@ this.__labelScope = Object.assign(this.__labelScope, labelVars); $compile(labelElement.contents())(this.__labelScope); + }.bind(blockObject) } else { blockObject.__renderLabel = function() {}; From e1b4aebb0faa0fe479983d5940605f9e5c00296a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 22 Aug 2023 11:27:16 +0200 Subject: [PATCH 2/9] directly render labels without angularJS template code (#14700) --- .../src/common/services/blockeditormodelobject.service.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js index 20661d5d1c..606d16ad2d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js @@ -644,6 +644,12 @@ blockObject.index = 0; if (blockObject.config.label && blockObject.config.label !== "" && blockObject.config.unsupported !== true) { + + // If the label does not contain any AngularJS template, then the MutationObserver wont give us any updates. To ensure labels without angular JS template code, we will just set the label directly for ones without '{{': + if(blockObject.config.label.indexOf("{{") === -1) { + blockObject.label = blockObject.config.label; + } + var labelElement = $('
', { text: blockObject.config.label}); var observer = new MutationObserver(function(mutations) { @@ -673,6 +679,7 @@ this.__labelScope = Object.assign(this.__labelScope, labelVars); $compile(labelElement.contents())(this.__labelScope); + }.bind(blockObject) } else { blockObject.__renderLabel = function() {}; From 80ea5174c6d1e52f798cd892acf243ed8e6ed27d Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 22 Aug 2023 12:28:01 +0100 Subject: [PATCH 3/9] Updated JSON schema reference for Umbraco Forms. (#14701) --- src/JsonSchema/JsonSchema.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonSchema/JsonSchema.csproj b/src/JsonSchema/JsonSchema.csproj index edf62516a5..07a29835de 100644 --- a/src/JsonSchema/JsonSchema.csproj +++ b/src/JsonSchema/JsonSchema.csproj @@ -13,6 +13,6 @@ - + From 9fd0b1986c39344f8f7331b5c8b69cca76d228d4 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 22 Aug 2023 12:28:01 +0100 Subject: [PATCH 4/9] Updated JSON schema reference for Umbraco Forms. (#14701) --- src/JsonSchema/JsonSchema.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonSchema/JsonSchema.csproj b/src/JsonSchema/JsonSchema.csproj index edf62516a5..07a29835de 100644 --- a/src/JsonSchema/JsonSchema.csproj +++ b/src/JsonSchema/JsonSchema.csproj @@ -13,6 +13,6 @@ - + From e5a8d01004c151cbcf91dd0a50344b0b16864dab Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Wed, 23 Aug 2023 10:09:43 +0200 Subject: [PATCH 5/9] Fix exceptions in Slider and Tags property value converters (#13782) * Fix IndexOutOfRangeException when converting single value to range in SliderValueConverter * Fix NullReferenceException while deserializing empty value in TagsValueConverter * Use invariant decimal parsing * Handle converting from slider to single value * Fix parsing range as single value * Make Handle methods autonomous --------- Co-authored-by: nikolajlauridsen --- .../Cache/DataTypeCacheRefresher.cs | 4 - .../ValueConverters/SliderValueConverter.cs | 127 ++++++++++++------ .../ValueConverters/TagsValueConverter.cs | 78 +++++------ 3 files changed, 125 insertions(+), 84 deletions(-) diff --git a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs index ea661c5498..394630fa64 100644 --- a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs @@ -88,10 +88,6 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase _publishedSnapshotService.Notify(payloads)); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs index 76f5b62265..14e80952f4 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Globalization; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services; @@ -6,74 +6,123 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// The slider property value converter. +/// +/// [DefaultPropertyValueConverter] public class SliderValueConverter : PropertyValueConverterBase { - private static readonly ConcurrentDictionary Storages = new(); - private readonly IDataTypeService _dataTypeService; + /// + /// Initializes a new instance of the class. + /// + public SliderValueConverter() + { } - public SliderValueConverter(IDataTypeService dataTypeService) => _dataTypeService = - dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); + /// + /// Initializes a new instance of the class. + /// + /// The data type service. + [Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")] + public SliderValueConverter(IDataTypeService dataTypeService) + { } - public static void ClearCaches() => Storages.Clear(); + /// + /// Clears the data type configuration caches. + /// + [Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")] + public static void ClearCaches() + { } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Slider); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => IsRangeDataType(propertyType.DataType.Id) ? typeof(Range) : typeof(decimal); + => IsRange(propertyType) ? typeof(Range) : typeof(decimal); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) { - if (source == null) + bool isRange = IsRange(propertyType); + + var sourceString = source?.ToString(); + + return isRange + ? HandleRange(sourceString) + : HandleDecimal(sourceString); + } + + private static Range HandleRange(string? sourceString) + { + if (sourceString is null) { - return null; + return new Range(); } - if (IsRangeDataType(propertyType.DataType.Id)) - { - var rangeRawValues = source.ToString()!.Split(Constants.CharArrays.Comma); - Attempt minimumAttempt = rangeRawValues[0].TryConvertTo(); - Attempt maximumAttempt = rangeRawValues[1].TryConvertTo(); + string[] rangeRawValues = sourceString.Split(Constants.CharArrays.Comma); - if (minimumAttempt.Success && maximumAttempt.Success) + if (TryParseDecimal(rangeRawValues[0], out var minimum)) + { + if (rangeRawValues.Length == 1) { - return new Range { Maximum = maximumAttempt.Result, Minimum = minimumAttempt.Result }; + // Configuration is probably changed from single to range, return range with same min/max + return new Range + { + Minimum = minimum, + Maximum = minimum + }; + } + + if (rangeRawValues.Length == 2 && TryParseDecimal(rangeRawValues[1], out var maximum)) + { + return new Range + { + Minimum = minimum, + Maximum = maximum + }; } } - Attempt valueAttempt = source.ToString().TryConvertTo(); - if (valueAttempt.Success) + return new Range(); + } + + private static decimal HandleDecimal(string? sourceString) + { + if (string.IsNullOrEmpty(sourceString)) { - return valueAttempt.Result; + return default; } - // Something failed in the conversion of the strings to decimals - return null; + // This used to be a range slider, so we'll assign the minimum value as the new value + if (sourceString.Contains(',')) + { + var minimumValueRepresentation = sourceString.Split(Constants.CharArrays.Comma)[0]; + + if (TryParseDecimal(minimumValueRepresentation, out var minimum)) + { + return minimum; + } + } + else if (TryParseDecimal(sourceString, out var value)) + { + return value; + } + + return default; } /// - /// Discovers if the slider is set to range mode. + /// Helper method for parsing a double consistently /// - /// - /// The data type id. - /// - /// - /// The . - /// - private bool IsRangeDataType(int dataTypeId) => + private static bool TryParseDecimal(string? representation, out decimal value) + => decimal.TryParse(representation, NumberStyles.Number, CultureInfo.InvariantCulture, out value); - // GetPreValuesCollectionByDataTypeId is cached at repository level; - // still, the collection is deep-cloned so this is kinda expensive, - // better to cache here + trigger refresh in DataTypeCacheRefresher - // TODO: this is cheap now, remove the caching - Storages.GetOrAdd(dataTypeId, id => - { - IDataType? dataType = _dataTypeService.GetDataType(id); - SliderConfiguration? configuration = dataType?.ConfigurationAs(); - return configuration?.EnableRange ?? false; - }); + private static bool IsRange(IPublishedPropertyType propertyType) + => propertyType.DataType.ConfigurationAs()?.EnableRange == true; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs index 3afc5a6596..2dd1c1d56e 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs @@ -1,4 +1,3 @@ -using System.Collections.Concurrent; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Serialization; @@ -7,69 +6,66 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// The tags property value converter. +/// +/// [DefaultPropertyValueConverter] public class TagsValueConverter : PropertyValueConverterBase { - private static readonly ConcurrentDictionary Storages = new(); - private readonly IDataTypeService _dataTypeService; private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. + /// jsonSerializer + public TagsValueConverter(IJsonSerializer jsonSerializer) + => _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); + + /// + /// Initializes a new instance of the class. + /// + /// The data type service. + /// The JSON serializer. + [Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")] public TagsValueConverter(IDataTypeService dataTypeService, IJsonSerializer jsonSerializer) - { - _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); - _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); - } + : this(jsonSerializer) + { } - public static void ClearCaches() => Storages.Clear(); + /// + /// Clears the data type configuration caches. + /// + [Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")] + public static void ClearCaches() + { } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Tags); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { - if (source == null) + string? sourceString = source?.ToString(); + if (string.IsNullOrEmpty(sourceString)) { return Array.Empty(); } - // if Json storage type deserialize and return as string array - if (JsonStorageType(propertyType.DataType.Id)) - { - var array = source.ToString() is not null - ? _jsonSerializer.Deserialize(source.ToString()!) - : null; - return array ?? Array.Empty(); - } - - // Otherwise assume CSV storage type and return as string array - return source.ToString()?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); + return IsJson(propertyType) + ? _jsonSerializer.Deserialize(sourceString) ?? Array.Empty() + : sourceString.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); } - public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) => (string[]?)source; - - /// - /// Discovers if the tags data type is storing its data in a Json format - /// - /// - /// The data type id. - /// - /// - /// The . - /// - private bool JsonStorageType(int dataTypeId) => - - // GetDataType(id) is cached at repository level; still, there is some - // deep-cloning involved (expensive) - better cache here + trigger - // refresh in DataTypeCacheRefresher - Storages.GetOrAdd(dataTypeId, id => - { - TagConfiguration? configuration = _dataTypeService.GetDataType(id)?.ConfigurationAs(); - return configuration?.StorageType == TagsStorageType.Json; - }); + private static bool IsJson(IPublishedPropertyType propertyType) + => propertyType.DataType.ConfigurationAs()?.StorageType == TagsStorageType.Json; } From 3c37653012d1d4e43c74c605cdd5b786c51a5026 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Wed, 23 Aug 2023 10:09:43 +0200 Subject: [PATCH 6/9] Fix exceptions in Slider and Tags property value converters (#13782) * Fix IndexOutOfRangeException when converting single value to range in SliderValueConverter * Fix NullReferenceException while deserializing empty value in TagsValueConverter * Use invariant decimal parsing * Handle converting from slider to single value * Fix parsing range as single value * Make Handle methods autonomous --------- Co-authored-by: nikolajlauridsen --- .../Cache/DataTypeCacheRefresher.cs | 4 - .../ValueConverters/SliderValueConverter.cs | 127 ++++++++++++------ .../ValueConverters/TagsValueConverter.cs | 78 +++++------ 3 files changed, 125 insertions(+), 84 deletions(-) diff --git a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs index ea661c5498..394630fa64 100644 --- a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs @@ -88,10 +88,6 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase _publishedSnapshotService.Notify(payloads)); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs index 76f5b62265..14e80952f4 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Globalization; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services; @@ -6,74 +6,123 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// The slider property value converter. +/// +/// [DefaultPropertyValueConverter] public class SliderValueConverter : PropertyValueConverterBase { - private static readonly ConcurrentDictionary Storages = new(); - private readonly IDataTypeService _dataTypeService; + /// + /// Initializes a new instance of the class. + /// + public SliderValueConverter() + { } - public SliderValueConverter(IDataTypeService dataTypeService) => _dataTypeService = - dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); + /// + /// Initializes a new instance of the class. + /// + /// The data type service. + [Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")] + public SliderValueConverter(IDataTypeService dataTypeService) + { } - public static void ClearCaches() => Storages.Clear(); + /// + /// Clears the data type configuration caches. + /// + [Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")] + public static void ClearCaches() + { } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Slider); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => IsRangeDataType(propertyType.DataType.Id) ? typeof(Range) : typeof(decimal); + => IsRange(propertyType) ? typeof(Range) : typeof(decimal); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) { - if (source == null) + bool isRange = IsRange(propertyType); + + var sourceString = source?.ToString(); + + return isRange + ? HandleRange(sourceString) + : HandleDecimal(sourceString); + } + + private static Range HandleRange(string? sourceString) + { + if (sourceString is null) { - return null; + return new Range(); } - if (IsRangeDataType(propertyType.DataType.Id)) - { - var rangeRawValues = source.ToString()!.Split(Constants.CharArrays.Comma); - Attempt minimumAttempt = rangeRawValues[0].TryConvertTo(); - Attempt maximumAttempt = rangeRawValues[1].TryConvertTo(); + string[] rangeRawValues = sourceString.Split(Constants.CharArrays.Comma); - if (minimumAttempt.Success && maximumAttempt.Success) + if (TryParseDecimal(rangeRawValues[0], out var minimum)) + { + if (rangeRawValues.Length == 1) { - return new Range { Maximum = maximumAttempt.Result, Minimum = minimumAttempt.Result }; + // Configuration is probably changed from single to range, return range with same min/max + return new Range + { + Minimum = minimum, + Maximum = minimum + }; + } + + if (rangeRawValues.Length == 2 && TryParseDecimal(rangeRawValues[1], out var maximum)) + { + return new Range + { + Minimum = minimum, + Maximum = maximum + }; } } - Attempt valueAttempt = source.ToString().TryConvertTo(); - if (valueAttempt.Success) + return new Range(); + } + + private static decimal HandleDecimal(string? sourceString) + { + if (string.IsNullOrEmpty(sourceString)) { - return valueAttempt.Result; + return default; } - // Something failed in the conversion of the strings to decimals - return null; + // This used to be a range slider, so we'll assign the minimum value as the new value + if (sourceString.Contains(',')) + { + var minimumValueRepresentation = sourceString.Split(Constants.CharArrays.Comma)[0]; + + if (TryParseDecimal(minimumValueRepresentation, out var minimum)) + { + return minimum; + } + } + else if (TryParseDecimal(sourceString, out var value)) + { + return value; + } + + return default; } /// - /// Discovers if the slider is set to range mode. + /// Helper method for parsing a double consistently /// - /// - /// The data type id. - /// - /// - /// The . - /// - private bool IsRangeDataType(int dataTypeId) => + private static bool TryParseDecimal(string? representation, out decimal value) + => decimal.TryParse(representation, NumberStyles.Number, CultureInfo.InvariantCulture, out value); - // GetPreValuesCollectionByDataTypeId is cached at repository level; - // still, the collection is deep-cloned so this is kinda expensive, - // better to cache here + trigger refresh in DataTypeCacheRefresher - // TODO: this is cheap now, remove the caching - Storages.GetOrAdd(dataTypeId, id => - { - IDataType? dataType = _dataTypeService.GetDataType(id); - SliderConfiguration? configuration = dataType?.ConfigurationAs(); - return configuration?.EnableRange ?? false; - }); + private static bool IsRange(IPublishedPropertyType propertyType) + => propertyType.DataType.ConfigurationAs()?.EnableRange == true; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs index 3afc5a6596..2dd1c1d56e 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs @@ -1,4 +1,3 @@ -using System.Collections.Concurrent; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Serialization; @@ -7,69 +6,66 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// The tags property value converter. +/// +/// [DefaultPropertyValueConverter] public class TagsValueConverter : PropertyValueConverterBase { - private static readonly ConcurrentDictionary Storages = new(); - private readonly IDataTypeService _dataTypeService; private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. + /// jsonSerializer + public TagsValueConverter(IJsonSerializer jsonSerializer) + => _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); + + /// + /// Initializes a new instance of the class. + /// + /// The data type service. + /// The JSON serializer. + [Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")] public TagsValueConverter(IDataTypeService dataTypeService, IJsonSerializer jsonSerializer) - { - _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); - _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); - } + : this(jsonSerializer) + { } - public static void ClearCaches() => Storages.Clear(); + /// + /// Clears the data type configuration caches. + /// + [Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")] + public static void ClearCaches() + { } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Tags); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { - if (source == null) + string? sourceString = source?.ToString(); + if (string.IsNullOrEmpty(sourceString)) { return Array.Empty(); } - // if Json storage type deserialize and return as string array - if (JsonStorageType(propertyType.DataType.Id)) - { - var array = source.ToString() is not null - ? _jsonSerializer.Deserialize(source.ToString()!) - : null; - return array ?? Array.Empty(); - } - - // Otherwise assume CSV storage type and return as string array - return source.ToString()?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); + return IsJson(propertyType) + ? _jsonSerializer.Deserialize(sourceString) ?? Array.Empty() + : sourceString.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); } - public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) => (string[]?)source; - - /// - /// Discovers if the tags data type is storing its data in a Json format - /// - /// - /// The data type id. - /// - /// - /// The . - /// - private bool JsonStorageType(int dataTypeId) => - - // GetDataType(id) is cached at repository level; still, there is some - // deep-cloning involved (expensive) - better cache here + trigger - // refresh in DataTypeCacheRefresher - Storages.GetOrAdd(dataTypeId, id => - { - TagConfiguration? configuration = _dataTypeService.GetDataType(id)?.ConfigurationAs(); - return configuration?.StorageType == TagsStorageType.Json; - }); + private static bool IsJson(IPublishedPropertyType propertyType) + => propertyType.DataType.ConfigurationAs()?.StorageType == TagsStorageType.Json; } From f2b0c0e8eb9c43d3ad7b0c6dc443c21604685504 Mon Sep 17 00:00:00 2001 From: Nikolaj Date: Thu, 24 Aug 2023 10:44:01 +0200 Subject: [PATCH 7/9] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 6761d6acc5..840819c76b 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "11.5.0-rc", + "version": "11.6.0-rc", "assemblyVersion": { "precision": "build" }, From 869b480dae03345f110a26fc0a5fa08e7f5b2487 Mon Sep 17 00:00:00 2001 From: Nikolaj Date: Thu, 24 Aug 2023 10:49:50 +0200 Subject: [PATCH 8/9] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index f4c3bd0a8a..3c0aeb9872 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "10.7.0-rc", + "version": "10.8.0-rc", "assemblyVersion": { "precision": "build" }, From 1198c76d67e3aa9ef5cebeb54d66708186125165 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 25 Aug 2023 13:07:42 +0200 Subject: [PATCH 9/9] Remove parsing of short into integer (#14721) --- .../Persistence/Factories/UserGroupFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/UserGroupFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/UserGroupFactory.cs index 3c4546da04..44d9cc6790 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/UserGroupFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/UserGroupFactory.cs @@ -78,7 +78,7 @@ internal static class UserGroupFactory if (entity.HasIdentity) { - dto.Id = short.Parse(entity.Id.ToString()); + dto.Id = entity.Id; } return dto;