diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index d727770b62..a53833d99e 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -83,5 +83,6 @@ public class UmbracoPlan : MigrationPlan To("{5A2EF07D-37B4-49D5-8E9B-3ED01877263B}"); // we need to re-run this migration, as it was flawed for V14 RC3 (the migration can run twice without any issues) To("{6FB5CA9E-C823-473B-A14C-FE760D75943C}"); + To("{827360CA-0855-42A5-8F86-A51F168CB559}"); } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/CleanUpDataTypeConfigurations.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/CleanUpDataTypeConfigurations.cs new file mode 100644 index 0000000000..9da9b61873 --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/CleanUpDataTypeConfigurations.cs @@ -0,0 +1,66 @@ +using Microsoft.Extensions.Logging; +using NPoco; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_14_0_0; + +public class CleanUpDataTypeConfigurations : MigrationBase +{ + private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; + private readonly ILogger _logger; + + public CleanUpDataTypeConfigurations( + IMigrationContext context, + IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, + ILogger logger) + : base(context) + { + _configurationEditorJsonSerializer = configurationEditorJsonSerializer; + _logger = logger; + } + + protected override void Migrate() + { + Sql sql = Sql() + .Select() + .AndSelect() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.EditorAlias.Contains("Umbraco.")); + + List dataTypeDtos = Database.Fetch(sql); + + foreach (DataTypeDto dataTypeDto in dataTypeDtos) + { + try + { + Dictionary configurationData = dataTypeDto.Configuration.IsNullOrWhiteSpace() + ? new Dictionary() + : _configurationEditorJsonSerializer + .Deserialize>(dataTypeDto.Configuration) + ?? new Dictionary(); + + var configurationDataWithoutNullValues = configurationData + .Where(pair => pair.Value is not null) + .ToDictionary(pair => pair.Key, pair => pair.Value!); + + if (configurationData.Count == configurationDataWithoutNullValues.Count) + { + continue; + } + + dataTypeDto.Configuration = _configurationEditorJsonSerializer.Serialize(configurationDataWithoutNullValues); + Database.Update(dataTypeDto); + _logger.LogInformation("Configuration cleaned up for data type: {dataTypeName} (id: {dataTypeId}, editor alias: {dataTypeEditorAlias})", dataTypeDto.NodeDto?.Text, dataTypeDto.NodeId, dataTypeDto.EditorAlias); + } + catch (Exception ex) + { + _logger.LogError(ex, "Configuration clean-up failed for data type: {dataTypeName} (id: {dataTypeId}, editor alias: {dataTypeEditorAlias})", dataTypeDto.NodeDto?.Text, dataTypeDto.NodeId, dataTypeDto.EditorAlias); + } + } + } +}