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..eb0b115b 100644 --- a/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs +++ b/KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs @@ -3,11 +3,13 @@ using CMS.ContentEngine; using CMS.ContentEngine.Internal; +using CMS.Core; +using CMS.Core.Internal; 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 +23,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 +44,8 @@ public class MigratePagesCommandHandler( IUmtMapper mapper, ModelFacade modelFacade, DeferredPathService deferredPathService, - SpoiledGuidContext spoiledGuidContext + SpoiledGuidContext spoiledGuidContext, + SourceInstanceContext sourceInstanceContext ) : IRequestHandler { @@ -58,8 +62,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) { @@ -90,8 +92,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) { @@ -245,39 +247,19 @@ 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]; - await MigratePageUrlPaths( - webPageItemInfo.WebPageItemGUID, - webPageItemInfo.WebPageItemID, ksSite.SiteGUID, + await MigratePageUrlPaths(ksSite.SiteGUID, languageGuid, commonDataInfos, migratedDocument, ksNode, migratedDocument.DocumentCulture, - isLinkedNode - ); - - existingDocumentLanguages.Add(languageGuid); - } - - var channelCulturesWithoutPage = allTargetLanguages.Where(x => !existingDocumentLanguages.Any(y => y == x.ContentLanguageGUID)); - - foreach (var culture in channelCulturesWithoutPage) - { - await MigratePageUrlPaths( - webPageItemInfo.WebPageItemGUID, - webPageItemInfo.WebPageItemID, ksSite.SiteGUID, - culture.ContentLanguageGUID, - commonDataInfos, - null, - ksNode, - culture.ContentLanguageName, - isLinkedNode - ); + wasLinkedNode, webPageItemInfo); } MigrateFormerUrls(ksNode, webPageItemInfo); @@ -339,12 +321,86 @@ 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 { - var existingPaths = WebPageUrlPathInfo.Provider.Get() - .WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemId) - .ToList(); + /// + /// 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 = []; + 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 wasLinkedNode, WebPageItemInfo webPageItemInfo) + { + 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.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) + { + 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(['/']); + string urlHash = modelFacade.HashPath(patchedUrl); + var webPageFormerUrlPathInfo = new WebPageFormerUrlPathInfo + { + 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; + } + } + + #endregion if (modelFacade.IsAvailable()) { @@ -353,14 +409,6 @@ 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); - } - if (ksPaths.Count > 0) { foreach (var ksPath in ksPaths) @@ -381,7 +429,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,12 +438,12 @@ 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() } }; - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); + CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); var importResult = await importer.ImportAsync(webPageUrlPath); @@ -403,26 +451,28 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, } } } - else + } + else + { + foreach (var contentItemCommonDataInfo in contentItemCommonDataInfos.Where(x => x.ContentItemCommonDataContentLanguageID == languageInfo.ContentLanguageID)) { - if (ksDocument is null) - { - await CreateDefaultPageUrlAsync(webPageItemGuid, webSiteChannelGuid, languageGuid, ksTree, documentCulture, languageInfo, webSiteChannel, existingPaths); - } - 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, + contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); + + string? urlPath = (ksDocument switch { - logger.LogTrace("Page url path common data info: CIID={ContentItemId} CLID={Language} ID={Id} - fallback", - contentItemCommonDataInfo.ContentItemCommonDataContentItemID, contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, - contentItemCommonDataInfo.ContentItemCommonDataID); + CmsDocumentK11 doc => wasLinkedNode ? null : doc.DocumentUrlPath, + CmsDocumentK12 doc => wasLinkedNode ? null : doc.DocumentUrlPath, + _ => null + }).NullIf(string.Empty)?.TrimStart('/'); + if (urlPath is not null) + { 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, + WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"), + WebPageUrlPath = urlPath, + WebPageUrlPathWebPageItemGuid = webPageItemInfo.WebPageItemGUID, WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, WebPageUrlPathContentLanguageGuid = languageGuid, WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, @@ -436,7 +486,7 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, } }; - CheckPathAlreadyExists(existingPaths, webPageUrlPath, languageInfo, webSiteChannel); + CheckPathAlreadyExists(webPageUrlPath, languageInfo, webSiteChannel, webPageItemInfo.WebPageItemID); var importResult = await importer.ImportAsync(webPageUrlPath); @@ -444,88 +494,34 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, } } } - 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); - } - - 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, - contentItemCommonDataInfo.ContentItemCommonDataContentLanguageID, contentItemCommonDataInfo.ContentItemCommonDataID); - - 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}", - _ => null - }).NullIf(string.Empty) ?? $"{ksTree.NodeAliasPath}").TrimStart('/'); - - var webPageUrlPath = new WebPageUrlPathModel - { - WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"), - WebPageUrlPath = urlPath, - WebPageUrlPathWebPageItemGuid = webPageItemGuid, - WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid, - WebPageUrlPathContentLanguageGuid = languageGuid, - WebPageUrlPathIsLatest = contentItemCommonDataInfo.ContentItemCommonDataIsLatest, - WebPageUrlPathIsDraft = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus switch - { - VersionStatus.InitialDraft => false, - VersionStatus.Draft => true, - VersionStatus.Published => false, - VersionStatus.Archived => false, - _ => throw new ArgumentOutOfRangeException() - } - }; - - var importResult = await importer.ImportAsync(webPageUrlPath); - - LogImportResult(importResult); - } - } } - private async Task CreateDefaultPageUrlAsync(Guid webPageItemGuid, Guid webSiteChannelGuid, Guid languageGuid, - ICmsTree ksTree, string documentCulture, ContentLanguageInfo languageInfo, WebsiteChannelInfo webSiteChannel, List existingPaths) + private async Task GenerateDefaultPageUrlPath(ICmsTree ksTree, WebPageItemInfo webPageItemInfo, bool wasLinkedNode) { - string urlPath = $"{languageInfo.ContentLanguageName}{ksTree.NodeAliasPath}"; - - var webPageUrlPath = new WebPageUrlPathModel + 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) { - 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); + logger.LogError("WebPageUrlPath collision occured {Path}", data.Path); + } } - private void CheckPathAlreadyExists(List existingPaths, WebPageUrlPathModel webPageUrlPath, + 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) @@ -564,35 +560,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 +638,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/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}"), diff --git a/KVA/Migration.Toolkit.Source/ModelFacade.cs b/KVA/Migration.Toolkit.Source/ModelFacade.cs index 4412ee37..9cb95ca4 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..9a695942 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; } = []; 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 { ///