From e0eecd9e526ebd1c39f519358deeaa66ed275f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Krch?= Date: Thu, 19 Sep 2024 03:33:32 +0200 Subject: [PATCH 1/4] #245 implementation of page type custom url pattern migration path --- .../Contexts/SourceInstanceContext.cs | 12 + .../Handlers/MigratePagesCommandHandler.cs | 291 +++++++++--------- KVA/Migration.Toolkit.Source/ModelFacade.cs | 5 + KX13.Extensions/ToolkitApiController.cs | 22 +- .../ToolkitApiController.NET48.cs | 19 +- .../Services/Ipc/Model.cs | 14 + 6 files changed, 219 insertions(+), 144 deletions(-) diff --git a/KVA/Migration.Toolkit.Source/Contexts/SourceInstanceContext.cs b/KVA/Migration.Toolkit.Source/Contexts/SourceInstanceContext.cs index 2173d11c..d38168c0 100644 --- a/KVA/Migration.Toolkit.Source/Contexts/SourceInstanceContext.cs +++ b/KVA/Migration.Toolkit.Source/Contexts/SourceInstanceContext.cs @@ -97,4 +97,16 @@ public async Task RequestSourceInstanceInfo() throw new InvalidOperationException($"No info was loaded for site '{siteName}'"); } + + public IList GetNodeUrls(int nodeId, string siteName) + { + if (cachedInfos.TryGetValue(siteName, out var info) && info?.PageModels is { Count: > 0 } pageModels) + { + return pageModels.Where(pm => pm.NodeId == nodeId).ToList(); + } + else + { + return []; + } + } } diff --git a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs index 1cdfe308..87bd50b0 100644 --- a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs +++ b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs @@ -3,11 +3,12 @@ using CMS.ContentEngine; using CMS.ContentEngine.Internal; +using CMS.Core; using CMS.DataEngine; using CMS.DataEngine.Query; using CMS.Websites; using CMS.Websites.Internal; - +using CMS.Websites.Routing.Internal; using Kentico.Xperience.UMT.Model; using Kentico.Xperience.UMT.Services; @@ -21,6 +22,7 @@ using Migration.Toolkit.Common.Helpers; using Migration.Toolkit.Common.MigrationProtocol; using Migration.Toolkit.KXP.Models; +using Migration.Toolkit.Source.Contexts; using Migration.Toolkit.Source.Helpers; using Migration.Toolkit.Source.Mappers; using Migration.Toolkit.Source.Model; @@ -41,7 +43,8 @@ public class MigratePagesCommandHandler( IUmtMapper mapper, ModelFacade modelFacade, DeferredPathService deferredPathService, - SpoiledGuidContext spoiledGuidContext + SpoiledGuidContext spoiledGuidContext, + SourceInstanceContext sourceInstanceContext ) : IRequestHandler { @@ -250,34 +253,28 @@ public async Task Handle(MigratePagesCommand request, Cancellatio { var languageGuid = cultureCodeToLanguageGuid[migratedDocument.DocumentCulture]; - await MigratePageUrlPaths( - webPageItemInfo.WebPageItemGUID, - webPageItemInfo.WebPageItemID, ksSite.SiteGUID, + await MigratePageUrlPaths(ksSite.SiteGUID, languageGuid, commonDataInfos, migratedDocument, ksNode, migratedDocument.DocumentCulture, - isLinkedNode - ); + isLinkedNode, webPageItemInfo); existingDocumentLanguages.Add(languageGuid); } - var channelCulturesWithoutPage = allTargetLanguages.Where(x => !existingDocumentLanguages.Any(y => y == x.ContentLanguageGUID)); + var channelCulturesWithoutPage = allTargetLanguages.Where(x => existingDocumentLanguages.All(y => y != x.ContentLanguageGUID)); foreach (var culture in channelCulturesWithoutPage) { - await MigratePageUrlPaths( - webPageItemInfo.WebPageItemGUID, - webPageItemInfo.WebPageItemID, ksSite.SiteGUID, + await MigratePageUrlPaths(ksSite.SiteGUID, culture.ContentLanguageGUID, commonDataInfos, null, ksNode, culture.ContentLanguageName, - isLinkedNode - ); + isLinkedNode, webPageItemInfo); } MigrateFormerUrls(ksNode, webPageItemInfo); @@ -339,13 +336,117 @@ private static void AsserVersionStatusRule(List commo } } - private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, Guid webSiteChannelGuid, Guid languageGuid, - List contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture, bool isLinkedNode) + public enum PageRoutingModeEnum // copy of enum from KX13 dll + { + /// + /// Routing based on custom routes of standard MVC support. + /// + Custom = 0, + /// + /// Routing based on system routes driven by content tree structure. + /// + BasedOnContentTree = 1, + } + + private readonly Dictionary cmsClassCache = new(); + private ICmsClass GetCmsClass(int classId) + { + if (cmsClassCache.TryGetValue(classId, out var cmsClass)) + { + return cmsClass; + } + + cmsClass = modelFacade.SelectById(classId); + cmsClassCache[classId] = cmsClass ?? throw new InvalidOperationException($"CMS Class with class id {classId} not found => invalid data"); + return cmsClass; + } + + private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGuid, + List contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture, bool isLinkedNode, WebPageItemInfo webPageItemInfo) { var existingPaths = WebPageUrlPathInfo.Provider.Get() - .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemId) + .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemInfo.WebPageItemID) .ToList(); + + var languageInfo = ContentLanguageInfoProvider.ProviderObject.Get(languageGuid); + var webSiteChannel = WebsiteChannelInfoProvider.ProviderObject.Get(webSiteChannelGuid); + + #region Migration of custom routing model + if (modelFacade.SelectVersion() is { Major: 13 } && KenticoHelper.GetSettingsKey(modelFacade, ksTree.NodeSiteID, "CMSRoutingMode") is (int)PageRoutingModeEnum.Custom) + { + if (modelFacade.SelectById(ksTree.NodeSiteID) is not { } site) + { + logger.LogError("Unable to find source site with ID '{SiteID}', fallback url will be used for node {NodeID}", ksTree.NodeSiteID, ksTree.NodeID); + } + // for ability to resolve macros we query source instance where we can resolve marcos in url pattern for particular page + else if (!sourceInstanceContext.HasInfo) + { + logger.LogWarning("Cannot migrate url for document '{DocumentID}' / node '{NodeID}', source instance context is not available or set-up correctly - default fallback will be used.", ksDocument?.DocumentID, ksTree.NodeID); + } + else if (GetCmsClass(ksTree.NodeClassID) is { } cmsClass && string.IsNullOrWhiteSpace(cmsClass.ClassURLPattern)) + { + logger.LogError("Cannot migrate url for document '{DocumentID}' / node '{NodeID}', class {ClassName} has no url pattern set - default fallback will be used.", ksDocument?.DocumentID, ksTree.NodeID, cmsClass.ClassName); + } + else if (sourceInstanceContext.GetNodeUrls(ksTree.NodeID, site.SiteName) is not { Count: > 0 } pageModels) + { + logger.LogError("No information could be found in source instance about node {NodeID} on site {SiteName}", ksTree.NodeID, site.SiteName); + } + else if (pageModels.FirstOrDefault(pm => pm.DocumentCulture == documentCulture) is not { } pageModel) + { + logger.LogWarning("Page url information for document {DocumentID} / node {NodeID} not found for culture {Culture}", ksDocument?.DocumentID, ksTree.NodeID, documentCulture); + } + else if (string.IsNullOrWhiteSpace(pageModel.CultureUrl)) + { + logger.LogWarning("Page url information for document {DocumentID} / node {NodeID} was found for culture {Culture}, but culture url is empty - unexpected", ksDocument?.DocumentID, ksTree.NodeID, documentCulture); + } + else + { + string patchedUrl = pageModel.CultureUrl.TrimStart(['~']).TrimStart(['/']); + + foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) + { + logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} IPC", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); + + // decision - if change in url occurs in source instance, it is desirable to overwrite migrated one. + var webPageUrlPathGuid = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus == VersionStatus.Draft + ? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT|{ksTree.NodeID}") + : GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|{ksTree.NodeID}"); + + string urlHash = modelFacade.HashPath(patchedUrl); + + var webPageUrlPath = new WebPageUrlPathModel + { + WebPageUrlPathGUID = webPageUrlPathGuid, + WebPageUrlPath = patchedUrl, + WebPageUrlPathHash = urlHash, + WebPageUrlPathWebPageItemGuid = webPageItemInfo.WebPageItemGUID, + WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, + WebPageUrlPathContentLanguageGuid = languageGuid, + WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, + WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch + { + VersionStatus.InitialDraft => false, + VersionStatus.Draft => true, + VersionStatus.Published => false, + VersionStatus.Unpublished => false, + _ => throw new ArgumentOutOfRangeException() + } + }; + + CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); + + var importResult = await importer.ImportAsync(webPageUrlPath); + + LogImportResult(importResult); + } + + return; + } + } + + #endregion + if (modelFacade.IsAvailable()) { var ksPaths = modelFacade.SelectWhere("PageUrlPathNodeId = @nodeId AND PageUrlPathCulture = @culture", @@ -353,12 +454,9 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, new SqlParameter("culture", documentCulture) ).ToList(); - var languageInfo = ContentLanguageInfoProvider.ProviderObject.Get(languageGuid); - var webSiteChannel = WebsiteChannelInfoProvider.ProviderObject.Get(webSiteChannelGuid); - if (ksDocument is null) { - await CreateDefaultPageUrlAsync(webPageItemGuid, webSiteChannelGuid, languageGuid, ksTree, documentCulture, languageInfo, webSiteChannel, existingPaths); + await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); } if (ksPaths.Count > 0) @@ -381,7 +479,7 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, : ksPath.PageUrlPathGUID, WebPageUrlPath = ksPath.PageUrlPathUrlPath.TrimStart('/'), WebPageUrlPathHash = ksPath.PageUrlPathUrlPathHash, - WebPageUrlPathWebPageItemGuid = webPageItemGuid, + WebPageUrlPathWebPageItemGuid = webPageItemInfo.WebPageItemGUID, WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, WebPageUrlPathContentLanguageGuid = languageGuid, WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, @@ -390,7 +488,7 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, VersionStatus.InitialDraft => false, VersionStatus.Draft => true, VersionStatus.Published => false, - VersionStatus.Archived => false, + VersionStatus.Unpublished => false, _ => throw new ArgumentOutOfRangeException() } }; @@ -407,52 +505,23 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, { if (ksDocument is null) { - await CreateDefaultPageUrlAsync(webPageItemGuid, webSiteChannelGuid, languageGuid, ksTree, documentCulture, languageInfo, webSiteChannel, existingPaths); + await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); } foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) { logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} - fallback", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); - - var webPageUrlPath = new WebPageUrlPathModel - { - WebPageUrlPathGUID = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus == VersionStatus.Draft - ? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT|{ksTree.NodeID}") - : GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{ksTree.NodeAliasPath}|{ksTree.NodeID}"), - WebPageUrlPath = ksTree.NodeAliasPath.TrimStart('/'), //ksPath.PageUrlPathUrlPath, - // WebPageUrlPathHash = ksPath.PageUrlPathUrlPathHash, - WebPageUrlPathWebPageItemGuid = webPageItemGuid, - WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, - WebPageUrlPathContentLanguageGuid = languageGuid, - WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, - WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch - { - VersionStatus.InitialDraft => false, - VersionStatus.Draft => true, - VersionStatus.Published => false, - VersionStatus.Unpublished => false, - _ => throw new ArgumentOutOfRangeException() - } - }; - - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); - - var importResult = await importer.ImportAsync(webPageUrlPath); - - LogImportResult(importResult); + + await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, contentItemCommonDataInfo.ContentItemCommonDataVersionStatus, CancellationToken.None); } } } else { - var languageInfo = ContentLanguageInfoProvider.ProviderObject.Get(languageGuid); - - var webSiteChannel = WebsiteChannelInfoProvider.ProviderObject.Get(webSiteChannelGuid); - if (ksDocument is null) { - await CreateDefaultPageUrlAsync(webPageItemGuid, webSiteChannelGuid, languageGuid, ksTree, documentCulture, languageInfo, webSiteChannel, existingPaths); + await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); } foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) @@ -460,62 +529,45 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id}", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); - string urlPath = ((ksDocument switch + string? urlPath = (ksDocument switch { - CmsDocumentK11 doc => isLinkedNode ? $"{languageInfo.ContentLanguageName}{ksTree.NodeAliasPath}" : doc.DocumentUrlPath, - CmsDocumentK12 doc => isLinkedNode ? $"{languageInfo.ContentLanguageName}{ksTree.NodeAliasPath}" : doc.DocumentUrlPath, - null => $"{languageInfo.ContentLanguageName}{ksTree.NodeAliasPath}", + CmsDocumentK11 doc => isLinkedNode ? null : doc.DocumentUrlPath, + CmsDocumentK12 doc => isLinkedNode ? null : doc.DocumentUrlPath, _ => null - }).NullIf(string.Empty) ?? $"{ksTree.NodeAliasPath}").TrimStart('/'); + }).NullIf(string.Empty)?.TrimStart('/'); - var webPageUrlPath = new WebPageUrlPathModel + if (urlPath is null) + { + await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, contentItemCommonDataInfo.ContentItemCommonDataVersionStatus, CancellationToken.None); + } + else { - WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"), - WebPageUrlPath = urlPath, - WebPageUrlPathWebPageItemGuid = webPageItemGuid, - WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, - WebPageUrlPathContentLanguageGuid = languageGuid, - WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, - WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch + var webPageUrlPath = new WebPageUrlPathModel { - VersionStatus.InitialDraft => false, - VersionStatus.Draft => true, - VersionStatus.Published => false, - VersionStatus.Archived => false, - _ => throw new ArgumentOutOfRangeException() - } - }; + WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"), + WebPageUrlPath = urlPath, + WebPageUrlPathWebPageItemGuid = webPageItemInfo.WebPageItemGUID, + WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, + WebPageUrlPathContentLanguageGuid = languageGuid, + WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, + WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch + { + VersionStatus.InitialDraft => false, + VersionStatus.Draft => true, + VersionStatus.Published => false, + VersionStatus.Unpublished => false, + _ => throw new ArgumentOutOfRangeException() + } + }; - var importResult = await importer.ImportAsync(webPageUrlPath); + var importResult = await importer.ImportAsync(webPageUrlPath); - LogImportResult(importResult); + LogImportResult(importResult); + } } } } - private async Task CreateDefaultPageUrlAsync(Guid webPageItemGuid, Guid webSiteChannelGuid, Guid languageGuid, - ICmsTree ksTree, string documentCulture, ContentLanguageInfo languageInfo, WebsiteChannelInfo webSiteChannel, List existingPaths) - { - string urlPath = $"{languageInfo.ContentLanguageName}{ksTree.NodeAliasPath}"; - - var webPageUrlPath = new WebPageUrlPathModel - { - WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"), - WebPageUrlPath = urlPath, - WebPageUrlPathWebPageItemGuid = webPageItemGuid, - WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, - WebPageUrlPathContentLanguageGuid = languageGuid, - WebPageUrlPathIsLatest = true, - WebPageUrlPathIsDraft = false - }; - - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); - - var importResult = await importer.ImportAsync(webPageUrlPath); - - LogDefaultCreationImportResult(importResult); - } - private void CheckPathAlreadyExists(List existingPaths, WebPageUrlPathModel webPageUrlPath, ContentLanguageInfo languageInfo, WebsiteChannelInfo webSiteChannel) @@ -564,35 +616,6 @@ private void LogImportResult(IImportResult importResult) } } - private void LogDefaultCreationImportResult(IImportResult importResult) - { - switch (importResult) - { - case { Success: true, Imported: WebPageUrlPathInfo imported }: - { - logger.LogTrace("Page url default path created '{Path}' '{Guid}'", imported.WebPageUrlPath, imported.WebPageUrlPathGUID); - break; - } - case { Success: false, Exception: { } exception }: - { - logger.LogError("Failed to create default page url path: {Error}", exception.ToString()); - break; - } - case { Success: false, ModelValidationResults: { } validation }: - { - foreach (var validationResult in validation) - { - logger.LogError("Failed to create default url path {Members}: {Error}", string.Join(",", validationResult.MemberNames), validationResult.ErrorMessage); - } - - break; - } - - default: - break; - } - } - private void MigrateFormerUrls(ICmsTree ksNode, WebPageItemInfo targetPage) { if (modelFacade.IsAvailable()) @@ -671,16 +694,6 @@ private void MigrateFormerUrls(ICmsTree ksNode, WebPageItemInfo targetPage) internal static QueryExpression GetWebPageUrlPathHashQueryExpression(string urlPath) => $"CONVERT(VARCHAR(64), HASHBYTES('SHA2_256', LOWER(N'{SqlHelper.EscapeQuotes(urlPath)}')), 2)".AsExpression(); - // private async Task MigrateAlternativeUrls() - // { - // if (modelFacade.IsAvailable()) - // { - // } - // else - // { - // } - // } - #region Deffered patch private async Task ExecDeferredPageBuilderPatch() diff --git a/KVA/Migration.Toolkit.Source/ModelFacade.cs b/KVA/Migration.Toolkit.Source/ModelFacade.cs index 4412ee37..5a2fe51c 100644 --- a/KVA/Migration.Toolkit.Source/ModelFacade.cs +++ b/KVA/Migration.Toolkit.Source/ModelFacade.cs @@ -153,6 +153,11 @@ public bool TrySelectGuid(int? id, out Guid? objectGuid) where T : ISourceMod public SemanticVersion SelectVersion() { + if (semanticVersion != null) + { + return semanticVersion; + } + using var conn = GetConnection(); conn.Open(); diff --git a/KX13.Extensions/ToolkitApiController.cs b/KX13.Extensions/ToolkitApiController.cs index 55a30068..683f255a 100644 --- a/KX13.Extensions/ToolkitApiController.cs +++ b/KX13.Extensions/ToolkitApiController.cs @@ -2,7 +2,10 @@ using System.Linq; using System.Net; using System.Reflection; +using CMS.Core; +using CMS.DocumentEngine; using CMS.SiteProvider; +using Kentico.Content.Web.Mvc; using Kentico.Forms.Web.Mvc; using Kentico.PageBuilder.Web.Mvc; using Kentico.PageBuilder.Web.Mvc.PageTemplates; @@ -12,7 +15,7 @@ public class ToolkitApiController : Controller { // TODO configure your own secret - private const string Secret = ""; + private const string Secret = "secret_used_for_http_posts_to_source_instance_change_to_random_key"; private readonly IHttpContextAccessor _httpContextAccessor; @@ -26,7 +29,7 @@ public class ToolkitInfo public Dictionary> WidgetProperties { get; set; } public Dictionary> PageTemplateProperties { get; set; } public Dictionary> SectionProperties { get; set; } - + public List PageModels { get; set; } public string SiteName { get; set; } } @@ -157,6 +160,19 @@ public IActionResult GetAllDefinitions([FromBody] BodyModel body) } } + var allFormComponents = new ComponentDefinitionProvider().GetAll(); + result.PageModels = Service.Resolve().RetrieveMultiple(q => q.AllCultures()).Select(x => (object)new + { + x.NodeSiteName, + x.DocumentID, + x.DocumentCulture, + x.DocumentGUID, + x.NodeGUID, + x.NodeID, + CultureUrl = DocumentURLProvider.GetUrlForCulture(x, x.DocumentCulture), + Url = DocumentURLProvider.GetUrl(x), + }).ToList(); + return Ok(result); } @@ -227,4 +243,4 @@ public class EditingFormControlModel public string PropertyName { get; set; } } -} \ No newline at end of file +} diff --git a/KX13.NET48.Extensions/ToolkitApiController.NET48.cs b/KX13.NET48.Extensions/ToolkitApiController.NET48.cs index 0cb4609b..d2a6060f 100644 --- a/KX13.NET48.Extensions/ToolkitApiController.NET48.cs +++ b/KX13.NET48.Extensions/ToolkitApiController.NET48.cs @@ -2,7 +2,10 @@ using System.Linq; using System.Reflection; using System.Web.Mvc; +using CMS.Core; +using CMS.DocumentEngine; using CMS.SiteProvider; +using Kentico.Content.Web.Mvc; using Kentico.Forms.Web.Mvc; using Kentico.PageBuilder.Web.Mvc; using Kentico.PageBuilder.Web.Mvc.PageTemplates; @@ -20,7 +23,7 @@ public class ToolkitInfo public Dictionary> WidgetProperties { get; set; } public Dictionary> PageTemplateProperties { get; set; } public Dictionary> SectionProperties { get; set; } - + public List PageModels { get; set; } public string SiteName { get; set; } } @@ -151,6 +154,18 @@ public ActionResult GetAllDefinitions(BodyModel body) } } + result.PageModels = Service.Resolve().RetrieveMultiple(q => q.AllCultures()).Select(x => (object)new + { + x.NodeSiteName, + x.DocumentID, + x.DocumentCulture, + x.DocumentGUID, + x.NodeGUID, + x.NodeID, + CultureUrl = DocumentURLProvider.GetUrlForCulture(x, x.DocumentCulture), + Url = DocumentURLProvider.GetUrl(x), + }).ToList(); + return ToJsonResult(result); } @@ -219,4 +234,4 @@ public class EditingFormControlModel public string PropertyName { get; set; } } -} \ No newline at end of file +} diff --git a/Migration.Toolkit.Common/Services/Ipc/Model.cs b/Migration.Toolkit.Common/Services/Ipc/Model.cs index 32c4fcab..645c1887 100644 --- a/Migration.Toolkit.Common/Services/Ipc/Model.cs +++ b/Migration.Toolkit.Common/Services/Ipc/Model.cs @@ -1,3 +1,4 @@ +// ReSharper disable InconsistentNaming namespace Migration.Toolkit.Common.Services.Ipc; public class SourceInstanceDiscoveredInfo @@ -5,9 +6,22 @@ public class SourceInstanceDiscoveredInfo public Dictionary>? WidgetProperties { get; set; } public Dictionary>? PageTemplateProperties { get; set; } public Dictionary>? SectionProperties { get; set; } + public List PageModels { get; set; } = new(); public string SiteName { get; set; } } +public record PageModel( + int? NodeId, + string NodeSiteName, + int DocumentID, + string DocumentCulture, + Guid DocumentGUID, + Guid NodeGUID, + string CultureUrl, + string Url +); + + public class EditingFormControlModel { /// From 5a763b6c0f4a2d2459bcd077543129af5c37f941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Krch?= Date: Thu, 19 Sep 2024 05:47:07 +0200 Subject: [PATCH 2/4] #245 partial refactor - url manager is used instead of low level api --- .../Handlers/MigratePagesCommandHandler.cs | 117 +++++++----------- KVA/Migration.Toolkit.Source/ModelFacade.cs | 2 +- .../Services/Ipc/Model.cs | 2 +- 3 files changed, 45 insertions(+), 76 deletions(-) diff --git a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs index 87bd50b0..fb60c5d1 100644 --- a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs +++ b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs @@ -44,7 +44,7 @@ public class MigratePagesCommandHandler( ModelFacade modelFacade, DeferredPathService deferredPathService, SpoiledGuidContext spoiledGuidContext, - SourceInstanceContext sourceInstanceContext + SourceInstanceContext sourceInstanceContext ) : IRequestHandler { @@ -61,8 +61,6 @@ public async Task Handle(MigratePagesCommand request, Cancellatio var cultureCodeToLanguageGuid = modelFacade.SelectAll() .ToDictionary(c => c.CultureCode, c => c.CultureGUID, StringComparer.InvariantCultureIgnoreCase); - var allTargetLanguages = ContentLanguageInfoProvider.ProviderObject.Get().ToList(); - var sites = modelFacade.SelectAll(); foreach (var ksSite in sites) { @@ -93,8 +91,8 @@ public async Task Handle(MigratePagesCommand request, Cancellatio .SelectWhere("DocumentNodeID = @nodeId", new SqlParameter("nodeId", ksNode.NodeID)) .ToList(); - bool isLinkedNode = nodeLinkedNode != null; - if (isLinkedNode) + bool wasLinkedNode = nodeLinkedNode != null; + if (wasLinkedNode) { if (nodeLinkedNode?.NodeSiteID != ksNode.NodeSiteID) { @@ -248,7 +246,8 @@ public async Task Handle(MigratePagesCommand request, Cancellatio if (webPageItemInfo != null && targetClass is { ClassWebPageHasUrl: true }) { - var existingDocumentLanguages = new HashSet(); + await GenerateDefaultPageUrlPath(ksNode, webPageItemInfo, wasLinkedNode); + foreach (var migratedDocument in migratedDocuments) { var languageGuid = cultureCodeToLanguageGuid[migratedDocument.DocumentCulture]; @@ -259,22 +258,7 @@ await MigratePageUrlPaths(ksSite.SiteGUID, migratedDocument, ksNode, migratedDocument.DocumentCulture, - isLinkedNode, webPageItemInfo); - - existingDocumentLanguages.Add(languageGuid); - } - - var channelCulturesWithoutPage = allTargetLanguages.Where(x => existingDocumentLanguages.All(y => y != x.ContentLanguageGUID)); - - foreach (var culture in channelCulturesWithoutPage) - { - await MigratePageUrlPaths(ksSite.SiteGUID, - culture.ContentLanguageGUID, - commonDataInfos, - null, - ksNode, - culture.ContentLanguageName, - isLinkedNode, webPageItemInfo); + wasLinkedNode, webPageItemInfo); } MigrateFormerUrls(ksNode, webPageItemInfo); @@ -305,7 +289,7 @@ await MigratePageUrlPaths(ksSite.SiteGUID, } } - await ExecDeferredPageBuilderPatch(); + await ExecDeferredPageBuilderPatch(); return new GenericCommandResult(); } @@ -348,29 +332,25 @@ public enum PageRoutingModeEnum // copy of enum from KX13 dll BasedOnContentTree = 1, } - private readonly Dictionary cmsClassCache = new(); + private readonly Dictionary cmsClassCache = []; private ICmsClass GetCmsClass(int classId) { if (cmsClassCache.TryGetValue(classId, out var cmsClass)) { return cmsClass; } - + cmsClass = modelFacade.SelectById(classId); cmsClassCache[classId] = cmsClass ?? throw new InvalidOperationException($"CMS Class with class id {classId} not found => invalid data"); return cmsClass; } - + private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGuid, - List contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture, bool isLinkedNode, WebPageItemInfo webPageItemInfo) + List contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture, bool wasLinkedNode, WebPageItemInfo webPageItemInfo) { - var existingPaths = WebPageUrlPathInfo.Provider.Get() - .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemInfo.WebPageItemID) - .ToList(); - var languageInfo = ContentLanguageInfoProvider.ProviderObject.Get(languageGuid); var webSiteChannel = WebsiteChannelInfoProvider.ProviderObject.Get(webSiteChannelGuid); - + #region Migration of custom routing model if (modelFacade.SelectVersion() is { Major: 13 } && KenticoHelper.GetSettingsKey(modelFacade, ksTree.NodeSiteID, "CMSRoutingMode") is (int)PageRoutingModeEnum.Custom) @@ -403,11 +383,11 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui else { string patchedUrl = pageModel.CultureUrl.TrimStart(['~']).TrimStart(['/']); - + foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) { logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} IPC", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); - + // decision - if change in url occurs in source instance, it is desirable to overwrite migrated one. var webPageUrlPathGuid = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus == VersionStatus.Draft ? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT|{ksTree.NodeID}") @@ -434,7 +414,7 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } }; - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); + CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); var importResult = await importer.ImportAsync(webPageUrlPath); @@ -446,7 +426,7 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } #endregion - + if (modelFacade.IsAvailable()) { var ksPaths = modelFacade.SelectWhere("PageUrlPathNodeId = @nodeId AND PageUrlPathCulture = @culture", @@ -454,11 +434,6 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui new SqlParameter("culture", documentCulture) ).ToList(); - if (ksDocument is null) - { - await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); - } - if (ksPaths.Count > 0) { foreach (var ksPath in ksPaths) @@ -493,7 +468,7 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } }; - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); + CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); var importResult = await importer.ImportAsync(webPageUrlPath); @@ -501,29 +476,9 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } } } - else - { - if (ksDocument is null) - { - await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); - } - foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) - { - logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} - fallback", - contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, - contentItemCommonDataInfo.ContentItemCommonDataID); - - await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, contentItemCommonDataInfo.ContentItemCommonDataVersionStatus, CancellationToken.None); - } - } } else { - if (ksDocument is null) - { - await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, VersionStatus.InitialDraft, CancellationToken.None); - } - foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) { logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id}", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, @@ -531,16 +486,12 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui string? urlPath = (ksDocument switch { - CmsDocumentK11 doc => isLinkedNode ? null : doc.DocumentUrlPath, - CmsDocumentK12 doc => isLinkedNode ? null : doc.DocumentUrlPath, + CmsDocumentK11 doc => wasLinkedNode ? null : doc.DocumentUrlPath, + CmsDocumentK12 doc => wasLinkedNode ? null : doc.DocumentUrlPath, _ => null }).NullIf(string.Empty)?.TrimStart('/'); - if (urlPath is null) - { - await Service.Resolve().GeneratePageUrlPath(webPageItemInfo, ksTree.NodeAlias, contentItemCommonDataInfo.ContentItemCommonDataVersionStatus, CancellationToken.None); - } - else + if (urlPath is not null) { var webPageUrlPath = new WebPageUrlPathModel { @@ -560,6 +511,8 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } }; + CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); + var importResult = await importer.ImportAsync(webPageUrlPath); LogImportResult(importResult); @@ -568,16 +521,32 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } } - private void CheckPathAlreadyExists(List existingPaths, WebPageUrlPathModel webPageUrlPath, + private async Task GenerateDefaultPageUrlPath(ICmsTree ksTree, WebPageItemInfo webPageItemInfo, bool wasLinkedNode) + { + var man = Service.Resolve(); + string alias = wasLinkedNode ? ksTree.NodeAlias : ksTree.NodeAliasPath; + var collisionData = await man.GeneratePageUrlPath(webPageItemInfo, alias, VersionStatus.InitialDraft, CancellationToken.None); + foreach (var data in collisionData) + { + logger.LogError("WebPageUrlPath collision occured {Path}", data.Path); + } + } + + private void CheckPathAlreadyExists(WebPageUrlPathModel webPageUrlPath, ContentLanguageInfo languageInfo, - WebsiteChannelInfo webSiteChannel) + WebsiteChannelInfo webSiteChannel, int webPageItemId) { + Debug.Assert(webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true },"webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true }"); + + var existingPaths = WebPageUrlPathInfo.Provider.Get() + .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemId) + .ToList(); + var ep = existingPaths.FirstOrDefault(ep => - ep.WebPageUrlPath == webPageUrlPath.WebPageUrlPath && ep.WebPageUrlPathContentLanguageID == languageInfo.ContentLanguageID && ep.WebPageUrlPathIsDraft == webPageUrlPath.WebPageUrlPathIsDraft && - ep.WebPageUrlPathIsLatest == webPageUrlPath.WebPageUrlPathIsLatest && - ep.WebPageUrlPathWebsiteChannelID == webSiteChannel.WebsiteChannelID + ep.WebPageUrlPathWebsiteChannelID == webSiteChannel.WebsiteChannelID && + ep.WebPageUrlPathWebPageItemID == webPageItemId ); if (ep != null) diff --git a/KVA/Migration.Toolkit.Source/ModelFacade.cs b/KVA/Migration.Toolkit.Source/ModelFacade.cs index 5a2fe51c..9cb95ca4 100644 --- a/KVA/Migration.Toolkit.Source/ModelFacade.cs +++ b/KVA/Migration.Toolkit.Source/ModelFacade.cs @@ -157,7 +157,7 @@ public SemanticVersion SelectVersion() { return semanticVersion; } - + using var conn = GetConnection(); conn.Open(); diff --git a/Migration.Toolkit.Common/Services/Ipc/Model.cs b/Migration.Toolkit.Common/Services/Ipc/Model.cs index 645c1887..9a695942 100644 --- a/Migration.Toolkit.Common/Services/Ipc/Model.cs +++ b/Migration.Toolkit.Common/Services/Ipc/Model.cs @@ -6,7 +6,7 @@ public class SourceInstanceDiscoveredInfo public Dictionary>? WidgetProperties { get; set; } public Dictionary>? PageTemplateProperties { get; set; } public Dictionary>? SectionProperties { get; set; } - public List PageModels { get; set; } = new(); + public List PageModels { get; set; } = []; public string SiteName { get; set; } } From 9531e7c49c782586611679ff59b46fee6817b7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Krch?= Date: Thu, 19 Sep 2024 06:16:15 +0200 Subject: [PATCH 3/4] whitespace fix --- .../Handlers/MigratePagesCommandHandler.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs index fb60c5d1..5bf5dbc2 100644 --- a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs +++ b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs @@ -247,7 +247,7 @@ public async Task Handle(MigratePagesCommand request, Cancellatio if (webPageItemInfo != null && targetClass is { ClassWebPageHasUrl: true }) { await GenerateDefaultPageUrlPath(ksNode, webPageItemInfo, wasLinkedNode); - + foreach (var migratedDocument in migratedDocuments) { var languageGuid = cultureCodeToLanguageGuid[migratedDocument.DocumentCulture]; @@ -289,7 +289,7 @@ await MigratePageUrlPaths(ksSite.SiteGUID, } } - await ExecDeferredPageBuilderPatch(); + await ExecDeferredPageBuilderPatch(); return new GenericCommandResult(); } @@ -394,7 +394,7 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui : GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|{ksTree.NodeID}"); string urlHash = modelFacade.HashPath(patchedUrl); - + var webPageUrlPath = new WebPageUrlPathModel { WebPageUrlPathGUID = webPageUrlPathGuid, @@ -536,8 +536,8 @@ private void CheckPathAlreadyExists(WebPageUrlPathModel webPageUrlPath, ContentLanguageInfo languageInfo, WebsiteChannelInfo webSiteChannel, int webPageItemId) { - Debug.Assert(webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true },"webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true }"); - + Debug.Assert(webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true }, "webPageUrlPath is not { WebPageUrlPathIsLatest: false, WebPageUrlPathIsDraft: true }"); + var existingPaths = WebPageUrlPathInfo.Provider.Get() .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemId) .ToList(); From cc712c1844218c45be8888dc9349fc7ad153cdaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Krch?= Date: Thu, 19 Sep 2024 22:46:49 +0200 Subject: [PATCH 4/4] #245 target former urls instead of page urls paths --- .../Handlers/MigratePagesCommandHandler.cs | 51 +++++-------------- .../Helpers/Printer.cs | 3 +- 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs index 5bf5dbc2..eb0b115b 100644 --- a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs +++ b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs @@ -4,6 +4,7 @@ using CMS.ContentEngine; using CMS.ContentEngine.Internal; using CMS.Core; +using CMS.Core.Internal; using CMS.DataEngine; using CMS.DataEngine.Query; using CMS.Websites; @@ -366,7 +367,7 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui } else if (GetCmsClass(ksTree.NodeClassID) is { } cmsClass && string.IsNullOrWhiteSpace(cmsClass.ClassURLPattern)) { - logger.LogError("Cannot migrate url for document '{DocumentID}' / node '{NodeID}', class {ClassName} has no url pattern set - default fallback will be used.", ksDocument?.DocumentID, ksTree.NodeID, cmsClass.ClassName); + logger.LogWarning("Cannot migrate url for document '{DocumentID}' / node '{NodeID}', class {ClassName} has no url pattern set - cannot migrate to former url.", ksDocument?.DocumentID, ksTree.NodeID, cmsClass.ClassName); } else if (sourceInstanceContext.GetNodeUrls(ksTree.NodeID, site.SiteName) is not { Count: > 0 } pageModels) { @@ -383,44 +384,18 @@ private async Task MigratePageUrlPaths(Guid webSiteChannelGuid, Guid languageGui else { string patchedUrl = pageModel.CultureUrl.TrimStart(['~']).TrimStart(['/']); - - foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) + string urlHash = modelFacade.HashPath(patchedUrl); + var webPageFormerUrlPathInfo = new WebPageFormerUrlPathInfo { - logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} IPC", contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); - - // decision - if change in url occurs in source instance, it is desirable to overwrite migrated one. - var webPageUrlPathGuid = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus == VersionStatus.Draft - ? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT|{ksTree.NodeID}") - : GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|{ksTree.NodeID}"); - - string urlHash = modelFacade.HashPath(patchedUrl); - - var webPageUrlPath = new WebPageUrlPathModel - { - WebPageUrlPathGUID = webPageUrlPathGuid, - WebPageUrlPath = patchedUrl, - WebPageUrlPathHash = urlHash, - WebPageUrlPathWebPageItemGuid = webPageItemInfo.WebPageItemGUID, - WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, - WebPageUrlPathContentLanguageGuid = languageGuid, - WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, - WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch - { - VersionStatus.InitialDraft => false, - VersionStatus.Draft => true, - VersionStatus.Published => false, - VersionStatus.Unpublished => false, - _ => throw new ArgumentOutOfRangeException() - } - }; - - CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); - - var importResult = await importer.ImportAsync(webPageUrlPath); - - LogImportResult(importResult); - } - + WebPageFormerUrlPath = patchedUrl, + WebPageFormerUrlPathHash = urlHash, + WebPageFormerUrlPathWebPageItemID = webPageItemInfo.WebPageItemID, + WebPageFormerUrlPathWebsiteChannelID = webSiteChannel.WebsiteChannelID, + WebPageFormerUrlPathContentLanguageID = languageInfo.ContentLanguageID, + WebPageFormerUrlPathLastModified = Service.Resolve().GetDateTimeNow() + }; + WebPageFormerUrlPathInfo.Provider.Set(webPageFormerUrlPathInfo); + logger.LogEntitySetAction(true, webPageItemInfo); return; } } diff --git a/KVA/Migration.Toolkit.Source/Helpers/Printer.cs b/KVA/Migration.Toolkit.Source/Helpers/Printer.cs index be7ed9c5..021efae8 100644 --- a/KVA/Migration.Toolkit.Source/Helpers/Printer.cs +++ b/KVA/Migration.Toolkit.Source/Helpers/Printer.cs @@ -4,7 +4,7 @@ using CMS.MediaLibrary; using CMS.Membership; using CMS.Modules; - +using CMS.Websites; using Migration.Toolkit.Common.Helpers; using Migration.Toolkit.Common.Services; using Migration.Toolkit.KXP.Models; @@ -61,6 +61,7 @@ string FormatModel(string inner) => printType UserInfo item => FormatModel($"ID={item.UserID}, Guid={item.UserGUID} Name={item.UserName}"), RoleInfo item => FormatModel($"ID={item.RoleID}, Guid={item.RoleGUID} Name={item.RoleName}"), MemberInfo item => FormatModel($"ID={item.MemberID}, Guid={item.MemberGuid} Name={item.MemberName}"), + WebPageFormerUrlPathInfo item => FormatModel($"ID={item.WebPageFormerUrlPathID}, Guid=N/A Name={item.WebPageFormerUrlPath}"), CmsForm item => FormatModel($"ID={item.FormId}, GUID={item.FormGuid}, Name={item.FormName}"), CmsUser item => FormatModel($"ID={item.UserId}, GUID={item.UserGuid}, Name={item.UserName}"),