Skip to content

Commit a23480a

Browse files
Add LegacyReplaceDataTypeArtifactMigratorBase and fix remaining legacy migrators
1 parent d4323e2 commit a23480a

11 files changed

+283
-85
lines changed

src/Umbraco.Deploy.Contrib/Extensions/ArtifactMigratorCollectionBuilderExtensions.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public static ArtifactMigratorCollectionBuilder AddLegacyMigrators(this Artifact
2121
// Allowed at root and child content types to permissions
2222
.Append<ContentTypeArtifactJsonMigrator>()
2323
// Data types
24-
.Append<CheckBoxListDataTypeArtifactMigrator>()
2524
.Append<ColorPickerAliasDataTypeArtifactMigrator>()
2625
.Append<ContentPicker2DataTypeArtifactMigrator>()
2726
.Append<ContentPickerAliasDataTypeArtifactMigrator>()
@@ -32,13 +31,10 @@ public static ArtifactMigratorCollectionBuilder AddLegacyMigrators(this Artifact
3231
.Append<DropdownlistPublishingKeysDataTypeArtifactMigrator>()
3332
.Append<DropDownMultipleDataTypeArtifactMigrator>()
3433
.Append<MediaPicker2DataTypeArtifactMigrator>()
35-
.Append<MediaPickerDataTypeArtifactMigrator>()
3634
.Append<MemberPicker2DataTypeArtifactMigrator>()
3735
.Append<MultiNodeTreePicker2DataTypeArtifactMigrator>()
38-
.Append<MultiNodeTreePickerDataTypeArtifactMigrator>()
3936
.Append<MultipleMediaPickerDataTypeArtifactMigrator>()
4037
.Append<NoEditDataTypeArtifactMigrator>()
41-
.Append<RadioButtonListDataTypeArtifactMigrator>()
4238
.Append<RelatedLinks2DataTypeArtifactMigrator>()
4339
.Append<RelatedLinksDataTypeArtifactMigrator>()
4440
.Append<TextboxDataTypeArtifactMigrator>()

src/Umbraco.Deploy.Contrib/Migrators/Legacy/DataType/CheckBoxListDataTypeArtifactMigrator.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using Umbraco.Cms.Core;
34
using Umbraco.Cms.Core.PropertyEditors;
@@ -11,6 +12,9 @@ namespace Umbraco.Deploy.Contrib.Migrators.Legacy;
1112
/// <summary>
1213
/// Migrates the <see cref="DataTypeArtifact" /> to replace the <see cref="Constants.PropertyEditors.Aliases.CheckBoxList" /> editor configuration from Umbraco 7 to <see cref="ValueListConfiguration" />.
1314
/// </summary>
15+
/// <remarks>
16+
/// </remarks>
17+
[Obsolete("This has been replaced by DefaultLegacyDataTypeConfigurationArtifactMigrator in Deploy 14.1.0.")]
1418
public class CheckBoxListDataTypeArtifactMigrator : DataTypeConfigurationArtifactMigratorBase<ValueListConfiguration>
1519
{
1620
/// <summary>

src/Umbraco.Deploy.Contrib/Migrators/Legacy/DataType/ColorPickerAliasDataTypeArtifactMigrator.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Linq;
23
using Umbraco.Cms.Core;
34
using Umbraco.Cms.Core.PropertyEditors;
45
using Umbraco.Cms.Core.Semver;
@@ -38,10 +39,16 @@ public ColorPickerAliasDataTypeArtifactMigrator(PropertyEditorCollection propert
3839
}
3940
else if (int.TryParse(key, out _) && value is string itemValue)
4041
{
42+
var hex = itemValue.ToLowerInvariant();
43+
if (hex.Length is 3)
44+
{
45+
hex = string.Join(string.Empty, hex.Select(c => $"{c}{c}"));
46+
}
47+
4148
toConfiguration.Items.Add(new ColorPickerConfiguration.ColorPickerItem()
4249
{
43-
Label = itemValue,
44-
Value = itemValue,
50+
Label = hex,
51+
Value = hex,
4552
});
4653
}
4754
}

src/Umbraco.Deploy.Contrib/Migrators/Legacy/DataType/ContentPickerReplaceDataTypeArtifactMigratorBase.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44
using Umbraco.Cms.Core.Semver;
55
using Umbraco.Cms.Core.Serialization;
66
using Umbraco.Deploy.Infrastructure.Artifacts;
7-
using Umbraco.Deploy.Infrastructure.Migrators;
87

98
namespace Umbraco.Deploy.Contrib.Migrators.Legacy;
109

1110
/// <summary>
1211
/// Migrates the <see cref="DataTypeArtifact" /> to replace the editor alias with <see cref="Constants.PropertyEditors.Aliases.ContentPicker" /> and update the configuration.
1312
/// </summary>
14-
public abstract class ContentPickerReplaceDataTypeArtifactMigratorBase : ReplaceDataTypeArtifactMigratorBase
13+
public abstract class ContentPickerReplaceDataTypeArtifactMigratorBase : LegacyReplaceDataTypeArtifactMigratorBase
1514
{
1615
/// <summary>
1716
/// Initializes a new instance of the <see cref="ContentPickerReplaceDataTypeArtifactMigratorBase" /> class.
@@ -26,19 +25,9 @@ protected ContentPickerReplaceDataTypeArtifactMigratorBase(string fromEditorAlia
2625
/// <inheritdoc />
2726
protected override IDictionary<string, object>? MigrateConfiguration(IDictionary<string, object> configuration)
2827
{
29-
if (configuration.TryGetValue("startNodeId", out var startNodeIdValue))
30-
{
31-
if (startNodeIdValue?.ToString() is not string startNodeId || !UdiParser.TryParse(startNodeId, out GuidUdi? udi))
32-
{
33-
// Remove invalid start node ID
34-
configuration.Remove("startNodeId");
35-
}
36-
else
37-
{
38-
// Update start node ID to GUID
39-
configuration["startNodeId"] = udi.Guid;
40-
}
41-
}
28+
ReplaceIntegerWithBoolean(ref configuration, Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes);
29+
ReplaceUdiWithGuid(ref configuration, "startNodeId");
30+
ReplaceIntegerWithBoolean(ref configuration, "showOpenButton");
4231

4332
return configuration;
4433
}

src/Umbraco.Deploy.Contrib/Migrators/Legacy/DataType/DateDataTypeArtifactMigrator.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44
using Umbraco.Cms.Core.Semver;
55
using Umbraco.Cms.Core.Serialization;
66
using Umbraco.Deploy.Infrastructure.Artifacts;
7-
using Umbraco.Deploy.Infrastructure.Migrators;
87

98
namespace Umbraco.Deploy.Contrib.Migrators.Legacy;
109

1110
/// <summary>
1211
/// Migrates the <see cref="DataTypeArtifact" /> to replace the <see cref="FromEditorAlias" /> editor with <see cref="Constants.PropertyEditors.Aliases.DateTime" />.
1312
/// </summary>
14-
public class DateDataTypeArtifactMigrator : ReplaceDataTypeArtifactMigratorBase
13+
public class DateDataTypeArtifactMigrator : LegacyReplaceDataTypeArtifactMigratorBase
1514
{
1615
private const string FromEditorAlias = "Umbraco.Date";
1716

@@ -26,5 +25,10 @@ public DateDataTypeArtifactMigrator(PropertyEditorCollection propertyEditors, IC
2625

2726
/// <inheritdoc />
2827
protected override IDictionary<string, object>? MigrateConfiguration(IDictionary<string, object> configuration)
29-
=> configuration;
28+
{
29+
ReplaceIntegerWithBoolean(ref configuration, "offsetTime");
30+
ReplaceIntegerWithBoolean(ref configuration, "defaultEmpty");
31+
32+
return configuration;
33+
}
3034
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Linq;
5+
using Umbraco.Cms.Core;
6+
using Umbraco.Cms.Core.PropertyEditors;
7+
using Umbraco.Cms.Core.Serialization;
8+
using Umbraco.Deploy.Infrastructure.Migrators;
9+
using Umbraco.Extensions;
10+
11+
namespace Umbraco.Deploy.Contrib.Migrators.Legacy;
12+
13+
/// <inheritdoc />
14+
public abstract class LegacyReplaceDataTypeArtifactMigratorBase : ReplaceDataTypeArtifactMigratorBase
15+
{
16+
private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer;
17+
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="LegacyReplaceDataTypeArtifactMigratorBase" /> class.
20+
/// </summary>
21+
/// <param name="fromEditorAlias">The editor alias to migrate from.</param>
22+
/// <param name="toEditorAlias">The editor alias to migrate to.</param>
23+
/// <param name="propertyEditors">The property editors.</param>
24+
/// <param name="configurationEditorJsonSerializer">The configuration editor JSON serializer.</param>
25+
protected LegacyReplaceDataTypeArtifactMigratorBase(string fromEditorAlias, string toEditorAlias, PropertyEditorCollection propertyEditors, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer)
26+
: base(fromEditorAlias, toEditorAlias, propertyEditors, configurationEditorJsonSerializer)
27+
=> _configurationEditorJsonSerializer = configurationEditorJsonSerializer;
28+
29+
/// <summary>
30+
/// Replaces the old key with a new key.
31+
/// </summary>
32+
/// <param name="configuration">The configuration.</param>
33+
/// <param name="oldKey">The old key.</param>
34+
/// <param name="newKey">The new key.</param>
35+
protected static void ReplaceKey(ref IDictionary<string, object> configuration, string oldKey, string newKey)
36+
{
37+
if (configuration.Remove(oldKey, out var value))
38+
{
39+
configuration[newKey] = value;
40+
}
41+
}
42+
43+
/// <summary>
44+
/// Replaces the UDI value with the GUID.
45+
/// </summary>
46+
/// <param name="configuration">The configuration.</param>
47+
/// <param name="key">The key.</param>
48+
/// <param name="keepInvalid">If set to <c>true</c> keeps the invalid value.</param>
49+
protected static void ReplaceUdiWithGuid(ref IDictionary<string, object> configuration, string key, bool keepInvalid = false)
50+
{
51+
if (configuration.TryGetValue(key, out var value))
52+
{
53+
if (value is string udi && UdiParser.TryParse(udi, out GuidUdi? guidUdi))
54+
{
55+
configuration[key] = guidUdi.Guid;
56+
}
57+
else if (keepInvalid is false && (value is not string guid || Guid.TryParse(guid, out _) is false))
58+
{
59+
configuration.Remove(key);
60+
}
61+
}
62+
}
63+
64+
/// <summary>
65+
/// Replaces the integer value with a boolean (defaults to false).
66+
/// </summary>
67+
/// <param name="configuration">The configuration.</param>
68+
/// <param name="key">The key.</param>
69+
protected static void ReplaceIntegerWithBoolean(ref IDictionary<string, object> configuration, string key)
70+
{
71+
if (configuration.TryGetValue(key, out var value) &&
72+
value is not bool)
73+
{
74+
configuration[key] = value?.ToString()?.ToLowerInvariant() switch
75+
{
76+
"1" or "true" => true,
77+
_ => false,
78+
};
79+
}
80+
}
81+
82+
/// <summary>
83+
/// Replaces the string value with an integer.
84+
/// </summary>
85+
/// <param name="configuration">The configuration.</param>
86+
/// <param name="key">The key.</param>
87+
/// <param name="keepInvalid">If set to <c>true</c> keeps the invalid value.</param>
88+
protected static void ReplaceStringWithInteger(ref IDictionary<string, object> configuration, string key, bool keepInvalid = false)
89+
{
90+
if (configuration.TryGetValue(key, out var value) &&
91+
value is not int)
92+
{
93+
if (value is string stringValue &&
94+
int.TryParse(stringValue, out int intValue))
95+
{
96+
configuration[key] = intValue;
97+
}
98+
else if (keepInvalid is false)
99+
{
100+
configuration.Remove(key);
101+
}
102+
}
103+
}
104+
105+
/// <summary>
106+
/// Replaces the value list array with a string array.
107+
/// </summary>
108+
/// <param name="configuration">The configuration.</param>
109+
/// <param name="key">The key.</param>
110+
protected void ReplaceValueListArrayWithStringArray(ref IDictionary<string, object> configuration, string key)
111+
{
112+
if (TryDeserialize(ref configuration, key, out IEnumerable<LegacyValueListItem>? items))
113+
{
114+
configuration[key] = items.Select(x => x.Value).ToArray();
115+
}
116+
}
117+
118+
/// <summary>
119+
/// Replaces the UDI in the tree source ID value with the GUID.
120+
/// </summary>
121+
/// <param name="configuration">The configuration.</param>
122+
/// <param name="key">The key.</param>
123+
/// <param name="treeSourceType">The entity type of the tree source.</param>
124+
protected void ReplaceTreeSourceIdUdiWithGuid(ref IDictionary<string, object> configuration, string key, out string? treeSourceType)
125+
{
126+
if (TryDeserialize(ref configuration, key, out LegacyTreeSource? treeSource))
127+
{
128+
configuration[key] = new TreeSource()
129+
{
130+
Type = treeSource.Type,
131+
Id = treeSource.Id?.Guid,
132+
DynamicRoot = treeSource.DynamicRoot,
133+
};
134+
}
135+
136+
treeSourceType = treeSource?.Type;
137+
}
138+
139+
/// <summary>
140+
/// Replaces the aliases with keys.
141+
/// </summary>
142+
/// <param name="configuration">The configuration.</param>
143+
/// <param name="key">The key.</param>
144+
/// <param name="getKeyByAlias">The delegate to get the key by alias.</param>
145+
protected static void ReplaceAliasesWithKeys(ref IDictionary<string, object> configuration, string key, Func<string, Guid?> getKeyByAlias)
146+
{
147+
if (configuration.TryGetValue(key, out var value) &&
148+
value is string stringValue)
149+
{
150+
configuration[key] = string.Join(',', stringValue.Split(Constants.CharArrays.Comma).Select(getKeyByAlias).OfType<Guid>());
151+
}
152+
}
153+
154+
/// <summary>
155+
/// Attempts to JSON deserialize the value.
156+
/// </summary>
157+
/// <typeparam name="T">The type to deserialize to.</typeparam>
158+
/// <param name="configuration">The configuration.</param>
159+
/// <param name="key">The key.</param>
160+
/// <param name="value">The value.</param>
161+
/// <returns>
162+
/// <c>true</c> if the value was deserialized; otherwise, <c>false</c>.
163+
/// </returns>
164+
protected bool TryDeserialize<T>(ref IDictionary<string, object> configuration, string key, [NotNullWhen(true)] out T? value)
165+
{
166+
if (configuration.TryGetValue(key, out var configurationValue) &&
167+
configurationValue?.ToString() is string stringValue &&
168+
stringValue.DetectIsJson())
169+
{
170+
value = _configurationEditorJsonSerializer.Deserialize<T>(stringValue);
171+
}
172+
else
173+
{
174+
value = default;
175+
}
176+
177+
return value is not null;
178+
}
179+
180+
private sealed class LegacyValueListItem
181+
{
182+
public required string Value { get; set; }
183+
}
184+
185+
private sealed class LegacyTreeSource
186+
{
187+
public required string Type { get; set; }
188+
public GuidUdi? Id { get; set; }
189+
public object? DynamicRoot { get; set; }
190+
}
191+
192+
private sealed class TreeSource
193+
{
194+
public required string Type { get; set; }
195+
public Guid? Id { get; set; }
196+
public object? DynamicRoot { get; set; }
197+
}
198+
}
Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
using System;
12
using System.Collections.Generic;
2-
using Umbraco.Cms.Core;
33
using Umbraco.Cms.Core.PropertyEditors;
44
using Umbraco.Cms.Core.Semver;
55
using Umbraco.Cms.Core.Serialization;
6+
using Umbraco.Deploy.Core;
67
using Umbraco.Deploy.Infrastructure.Artifacts;
78
using Umbraco.Deploy.Infrastructure.Migrators;
89

@@ -11,9 +12,10 @@ namespace Umbraco.Deploy.Contrib.Migrators.Legacy;
1112
/// <summary>
1213
/// Migrates the <see cref="DataTypeArtifact" /> to update the <see cref="EditorAlias" /> editor configuration.
1314
/// </summary>
15+
[Obsolete("This has been replaced by ReplaceMediaPickerDataTypeArtifactMigrator and DefaultLegacyDataTypeConfigurationArtifactMigrator in Deploy.")]
1416
public class MediaPickerDataTypeArtifactMigrator : DataTypeConfigurationArtifactMigratorBase
1517
{
16-
private const string EditorAlias = "Umbraco.MediaPicker"; // TODO: Use DeployConstants.PropertyEditors.Legacy.Aliases.MediaPicker once made public
18+
private const string EditorAlias = DeployConstants.PropertyEditors.Legacy.Aliases.MediaPicker;
1719

1820
/// <summary>
1921
/// Initializes a new instance of the <see cref="MediaPickerDataTypeArtifactMigrator" /> class.
@@ -26,21 +28,5 @@ public MediaPickerDataTypeArtifactMigrator(PropertyEditorCollection propertyEdit
2628

2729
/// <inheritdoc />
2830
protected override IDictionary<string, object>? MigrateConfiguration(IDictionary<string, object> fromConfiguration)
29-
{
30-
if (fromConfiguration.TryGetValue("startNodeId", out var startNodeIdValue))
31-
{
32-
if (startNodeIdValue?.ToString() is not string startNodeId || !UdiParser.TryParse(startNodeId, out GuidUdi? udi))
33-
{
34-
// Remove invalid start node ID
35-
fromConfiguration.Remove("startNodeId");
36-
}
37-
else
38-
{
39-
// Update start node ID to GUID
40-
fromConfiguration["startNodeId"] = udi.Guid;
41-
}
42-
}
43-
44-
return fromConfiguration;
45-
}
31+
=> fromConfiguration;
4632
}

0 commit comments

Comments
 (0)