diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_7_12_0/SetDefaultTagsStorageType.cs b/src/Umbraco.Core/Migrations/Upgrade/V_7_12_0/SetDefaultTagsStorageType.cs index d8f2d37067..c8d65961f4 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_7_12_0/SetDefaultTagsStorageType.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_7_12_0/SetDefaultTagsStorageType.cs @@ -1,47 +1,51 @@ -using System; -using System.Linq; -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Core.Migrations.Upgrade.V_7_12_0 { /// - /// Set the default storageType for the tags datatype to "CSV" to ensure backwards compatibilty since the default is going to be JSON in new versions - /// + /// Set the default storageType for the tags datatype to "CSV" to ensure backwards compatibility since the default is going to be JSON in new versions. + /// public class SetDefaultTagsStorageType : MigrationBase { - public SetDefaultTagsStorageType(IMigrationContext context) : base(context) - { - } + public SetDefaultTagsStorageType(IMigrationContext context) + : base(context) + { } + + // dummy editor for deserialization + private class TagConfigurationEditor : ConfigurationEditor + { } public override void Migrate() { - if (Context?.Database == null) return; + // get all Umbraco.Tags datatypes + var dataTypeDtos = Database.Fetch(Context.SqlContext.Sql() + .Select() + .From() + .Where(x => x.EditorAlias == Constants.PropertyEditors.Aliases.Tags)); - // We need to get all datatypes with an alias of "umbraco.tags" so we can loop over them and set the missing values if needed - var datatypes = Context.Database.Fetch(); - var tagsDataTypes = datatypes.Where(x => string.Equals(x.EditorAlias, Constants.PropertyEditors.Aliases.Tags, StringComparison.InvariantCultureIgnoreCase)); + // get a dummy editor for deserialization + var editor = new TagConfigurationEditor(); - foreach (var datatype in tagsDataTypes) + foreach (var dataTypeDto in dataTypeDtos) { - var dataTypePreValues = JsonConvert.DeserializeObject(datatype.Configuration); + // need to check storageType on raw dictionary, as TagConfiguration would have a default value + var dictionary = JsonConvert.DeserializeObject(dataTypeDto.Configuration); - // We need to check if the node has a "storageType" set - if (!dataTypePreValues.ContainsKey("storageType")) + // if missing, use TagConfiguration to properly update the configuration + // due to ... reasons ... the key can start with a lower or upper 'S' + if (!dictionary.ContainsKey("storageType") && !dictionary.ContainsKey("StorageType")) { - dataTypePreValues["storageType"] = "Csv"; + var configuration = (TagConfiguration)editor.FromDatabase(dataTypeDto.Configuration); + configuration.StorageType = TagsStorageType.Csv; + dataTypeDto.Configuration = ConfigurationEditor.ToDatabase(configuration); + Database.Update(dataTypeDto); } - - Update.Table(Constants.DatabaseSchema.Tables.DataType) - .Set(new { config = JsonConvert.SerializeObject(dataTypePreValues) }) - .Where(new { nodeId = datatype.NodeId }) - .Do(); } } - - } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs index fcf6cef868..9b857c2dff 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Models; @@ -31,7 +30,9 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) { - // if Json storage type deserialzie and return as string array + if (source == null) return Array.Empty(); + + // if Json storage type deserialize and return as string array if (JsonStorageType(propertyType.DataType.Id)) { var jArray = JsonConvert.DeserializeObject(source.ToString()); @@ -39,11 +40,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters } // Otherwise assume CSV storage type and return as string array - var sourceString = source?.ToString() ?? string.Empty; - var csvTags = sourceString - .Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries) - .ToArray(); - return csvTags; + return source.ToString().Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); } public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview) @@ -62,10 +59,9 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters /// private bool JsonStorageType(int dataTypeId) { - // fixme - // 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 + // GetDataType(id) is cached at repository level; still, there is some + // deep-cloning involved (expensive) - better cache here + trigger + // refresh in DataTypeCacheRefresher return Storages.GetOrAdd(dataTypeId, id => {