Skip to content

Commit 64d174f

Browse files
authored
Release 3.0.0
Release 3.0.0
2 parents df8e8f4 + 71753b5 commit 64d174f

33 files changed

+706
-250
lines changed

KVA/Migration.Tool.Source/Handlers/MigrateCustomModulesCommandHandler.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ private async Task MigrateClasses(EntityConfiguration entityConfiguration, Cance
133133

134134
XNamespace nsSchema = "http://www.w3.org/2001/XMLSchema";
135135
XNamespace msSchema = "urn:schemas-microsoft-com:xml-msdata";
136+
if (string.IsNullOrEmpty(xbkDataClass.ClassXmlSchema))
137+
{
138+
logger.LogError("CmsClass: {ClassName} has no XML schema. Migration incomplete", cmsClass.ClassName);
139+
continue;
140+
}
136141
var xDoc = XDocument.Parse(xbkDataClass.ClassXmlSchema);
137142
var autoIncrementColumns = xDoc.Descendants(nsSchema + "element")
138143
.Where(x => x.Attribute(msSchema + "AutoIncrement")?.Value == "true")

KVA/Migration.Tool.Source/Handlers/MigratePageTypesCommandHandler.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using CMS.ContentEngine;
22
using CMS.DataEngine;
3+
using Kentico.Xperience.UMT.Model;
4+
using Kentico.Xperience.UMT.Services;
35
using MediatR;
46

57
using Microsoft.Data.SqlClient;
@@ -28,7 +30,8 @@ public class MigratePageTypesCommandHandler(
2830
ModelFacade modelFacade,
2931
PageTemplateMigrator pageTemplateMigrator,
3032
ReusableSchemaService reusableSchemaService,
31-
ClassMappingProvider classMappingProvider
33+
ClassMappingProvider classMappingProvider,
34+
IImporter importer
3235
)
3336
: IRequestHandler<MigratePageTypesCommand, CommandResult>
3437
{
@@ -144,9 +147,33 @@ public async Task<CommandResult> Handle(MigratePageTypesCommand request, Cancell
144147

145148
await MigratePageTemplateConfigurations();
146149

150+
await BypassAllowedChildClasses(); // Temporary bypass. Implementation of this features is already planned
151+
147152
return new GenericCommandResult();
148153
}
149154

155+
private async Task BypassAllowedChildClasses()
156+
{
157+
var websiteContentTypes = kxpClassFacade.GetClasses(ClassContentTypeType.WEBSITE);
158+
foreach (var parent in websiteContentTypes)
159+
{
160+
foreach (var child in websiteContentTypes)
161+
{
162+
var model = new AllowedChildContentTypeModel
163+
{
164+
AllowedChildContentTypeParentGuid = parent.ClassGUID,
165+
AllowedChildContentTypeChildGuid = child.ClassGUID
166+
};
167+
168+
var importResult = await importer.ImportAsync(model);
169+
if (importResult is { Success: false })
170+
{
171+
logger.LogError("Failed to define allowed child content type '{ChildClassGuid}' of parent type '{ParentClassGuid}'", model.AllowedChildContentTypeChildGuid, model.AllowedChildContentTypeParentGuid);
172+
}
173+
}
174+
}
175+
}
176+
150177
private async Task MigratePageTemplateConfigurations()
151178
{
152179
if (modelFacade.IsAvailable<ICmsPageTemplateConfiguration>())

KVA/Migration.Tool.Source/Handlers/MigratePagesCommandHandler.cs

Lines changed: 179 additions & 24 deletions
Large diffs are not rendered by default.

KVA/Migration.Tool.Source/KsCoreDiExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public static IServiceCollection UseKsToolCore(this IServiceCollection services,
5151
services.AddSingleton<EntityIdentityFacade>();
5252
services.AddSingleton<IdentityLocator>();
5353
services.AddSingleton<IAssetFacade, AssetFacade>();
54+
services.AddSingleton<ContentFolderService>();
5455
services.AddSingleton<MediaLinkServiceFactory>();
5556
services.AddSingleton<ClassMappingProvider>();
5657
services.AddTransient<VisualBuilderPatcher>();

KVA/Migration.Tool.Source/Mappers/CmsClassMapper.cs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ protected override DataClassInfo MapInternal(ICmsClass source, DataClassInfo tar
142142
target.ClassType = ClassType.OTHER;
143143
target.ClassContentTypeType = null;
144144

145-
target = PatchDataClassInfo(target, existingFieldGUIDs, out string? oldPrimaryKeyName, out string? documentNameField);
145+
target = PatchDataClassInfo(target, existingFieldGUIDs, modelFacade.SelectVersion(), configuration.IncludeExtendedMetadata.GetValueOrDefault(false), out string? oldPrimaryKeyName, out string? documentNameField);
146146

147147
break;
148148
}
@@ -176,7 +176,7 @@ protected override DataClassInfo MapInternal(ICmsClass source, DataClassInfo tar
176176
target.ClassType = ClassType.CONTENT_TYPE;
177177
target.ClassContentTypeType = ClassContentTypeType.REUSABLE;
178178

179-
target = PatchDataClassInfo(target, existingFieldGUIDs, out string? oldPrimaryKeyName, out string? documentNameField);
179+
target = PatchDataClassInfo(target, existingFieldGUIDs, modelFacade.SelectVersion(), configuration.IncludeExtendedMetadata.GetValueOrDefault(false), out string? oldPrimaryKeyName, out string? documentNameField);
180180
break;
181181
}
182182

@@ -194,7 +194,7 @@ protected override DataClassInfo MapInternal(ICmsClass source, DataClassInfo tar
194194
? ClassContentTypeType.REUSABLE
195195
: ClassContentTypeType.WEBSITE;
196196

197-
target = PatchDataClassInfo(target, existingFieldGUIDs, out string? oldPrimaryKeyName, out string? documentNameField);
197+
target = PatchDataClassInfo(target, existingFieldGUIDs, modelFacade.SelectVersion(), configuration.IncludeExtendedMetadata.GetValueOrDefault(false), out string? oldPrimaryKeyName, out string? documentNameField);
198198
break;
199199
}
200200

@@ -230,10 +230,10 @@ private DataClassInfo PatchFormDataClassInfo(DataClassInfo target)
230230
return target;
231231
}
232232

233-
public static DataClassInfo PatchDataClassInfo(DataClassInfo dataClass, Dictionary<string, Guid> existingFieldGUIDs, out string? oldPrimaryKeyName, out string? documentNameField)
233+
public static DataClassInfo PatchDataClassInfo(DataClassInfo dataClass, Dictionary<string, Guid> existingFieldGUIDs, SemanticVersion version, bool includeExtendedMetadata, out string? oldPrimaryKeyName, out string? mappedLegacyField)
234234
{
235235
oldPrimaryKeyName = null;
236-
documentNameField = null;
236+
mappedLegacyField = null;
237237
if (dataClass.ClassType is ClassType.CONTENT_TYPE)
238238
{
239239
var fi = new FormInfo(dataClass.ClassFormDefinition);
@@ -291,8 +291,10 @@ public static DataClassInfo PatchDataClassInfo(DataClassInfo dataClass, Dictiona
291291

292292
Debug.WriteLineIf(oldPrimaryKeyName == null, $"WARN: old PK is null for class '{dataClass.ClassName}'");
293293

294-
AppendDocumentNameField(nfi, dataClass.ClassName, out documentNameField);
295-
294+
foreach (var field in GetLegacyMetadataFields(version, includeExtendedMetadata))
295+
{
296+
AppendLegacyMetadataField(nfi, dataClass.ClassName, field, out mappedLegacyField);
297+
}
296298
dataClass.ClassFormDefinition = nfi.GetXmlDefinition();
297299

298300
return dataClass;
@@ -301,43 +303,55 @@ public static DataClassInfo PatchDataClassInfo(DataClassInfo dataClass, Dictiona
301303
return dataClass;
302304
}
303305

304-
public static string? GetLegacyDocumentName(FormInfo nfi, string className)
306+
public static IEnumerable<LegacyDocumentMetadataFieldMapping> GetLegacyMetadataFields(SemanticVersion version, bool includeExtended)
307+
{
308+
List<LegacyDocumentMetadataFieldMapping> fields = [new("DocumentName", "Page Name", 100, false, x => x.DocumentName)];
309+
if (includeExtended && version is { Major: 12 or 13 })
310+
{
311+
fields.AddRange([
312+
new(nameof(ICmsDocument.DocumentPageTitle), "Page Title", -1, true, x => x.DocumentPageTitle),
313+
new(nameof(ICmsDocument.DocumentPageDescription), "Page Description", -1, true, x => x.DocumentPageDescription),
314+
new(nameof(ICmsDocument.DocumentPageKeyWords), "Page Keywords", -1, true, x => x.DocumentPageKeyWords),
315+
]);
316+
}
317+
return fields;
318+
}
319+
public static string? GetMappedLegacyField(FormInfo nfi, string className, string legacyFieldName)
305320
{
306-
if (nfi.GetFields(true, true).FirstOrDefault(f => GuidHelper.CreateFieldGuid($"documentname|{className}").Equals(f.Guid)) is { } foundField)
321+
if (nfi.GetFields(true, true).FirstOrDefault(f => GuidHelper.CreateFieldGuid($"{legacyFieldName.ToLower()}|{className}").Equals(f.Guid)) is { } foundField)
307322
{
308323
return foundField.Name;
309324
}
310325

311326
return null;
312327
}
313328

314-
private static void AppendDocumentNameField(FormInfo nfi, string newClassName, out string documentNameField)
329+
private static void AppendLegacyMetadataField(FormInfo nfi, string newClassName, LegacyDocumentMetadataFieldMapping mapping, out string targetFieldName)
315330
{
316-
if (GetLegacyDocumentName(nfi, newClassName) is { } fieldName)
331+
if (GetMappedLegacyField(nfi, newClassName, mapping.LegacyFieldName) is { } fieldName)
317332
{
318-
documentNameField = fieldName;
333+
targetFieldName = fieldName;
319334
return;
320335
}
321336

322-
// no DocumentName in v27, we supply one in migration
323-
documentNameField = "DocumentName";
337+
targetFieldName = mapping.LegacyFieldName;
324338
int i = 0;
325-
while (nfi.GetFormField(documentNameField) is not null)
339+
while (nfi.GetFormField(targetFieldName) is not null)
326340
{
327-
documentNameField = $"DocumentName{++i}";
341+
targetFieldName = $"{mapping.LegacyFieldName}{++i}";
328342
}
329343

330344
nfi.AddFormItem(new FormFieldInfo
331345
{
332-
Caption = "Page name", // as in v26.x.x
333-
Name = documentNameField,
334-
AllowEmpty = false,
335-
DataType = "text",
336-
Size = 100,
346+
Caption = mapping.TargetCaption,
347+
Name = targetFieldName,
348+
AllowEmpty = mapping.AllowEmpty,
349+
DataType = mapping.TargetSize switch { -1 => "longtext", _ => "text" },
350+
Size = mapping.TargetSize switch { -1 => 0, _ => mapping.TargetSize },
337351
Precision = 0,
338352
DefaultValue = null,
339-
Guid = GuidHelper.CreateFieldGuid($"documentname|{newClassName}"),
340-
System = false, // no longer system field, system doesn't rely on this field anymore
353+
Guid = GuidHelper.CreateFieldGuid($"{mapping.LegacyFieldName.ToLower()}|{newClassName}"),
354+
System = false,
341355
Settings = { { "controlname", "Kentico.Administration.TextInput" } }
342356
});
343357
}

0 commit comments

Comments
 (0)