Skip to content

Commit

Permalink
Merge pull request #235 from Kentico/rls/v1.2.1
Browse files Browse the repository at this point in the history
Rls/v1.2.1
  • Loading branch information
tkrch authored Sep 2, 2024
2 parents ebd26e5 + 04f0ea5 commit c9cfa8a
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections.Immutable;

using CMS.Base;
using CMS.MediaLibrary;

Expand Down Expand Up @@ -46,27 +44,42 @@ public async Task<CommandResult> Handle(MigrateMediaLibrariesCommand request, Ca
var skippedMediaLibraries = new HashSet<Guid>();
var unsuitableMediaLibraries =
modelFacade.Select("""
SELECT LibraryName, STRING_AGG(CAST(LibraryGUID AS NVARCHAR(max)), '|') as [LibraryGUIDs]
FROM Media_Library
GROUP BY LibraryName
HAVING COUNT(*) > 1
SELECT LibraryName, LibraryGUID FROM Media_Library [ML]
WHERE EXISTS(
SELECT 1
FROM Media_Library [MLI]
WHERE MLI.LibraryName = ML.LibraryName
GROUP BY LibraryName
HAVING COUNT(*) > 1
)
""",
(reader, _) => new { LibraryName = reader.Unbox<string>("LibraryName"), LibraryGuids = reader.Unbox<string?>("LibraryGUIDs")?.Split('|').Select(Guid.Parse).ToImmutableList() ?? [] });
(reader, _) => new
{
LibraryName = reader.Unbox<string>("LibraryName"),
LibraryGuid = reader.Unbox<Guid?>("LibraryGUID")
});

foreach (var mlg in unsuitableMediaLibraries)
var groupedMls = unsuitableMediaLibraries
.GroupBy(x => x.LibraryName)
.Select(x => new { LibraryGuids = x.Select(y => y.LibraryGuid).ToArray(), LibraryName = x.Key });

foreach (var mlg in groupedMls)
{
logger.LogError(
"Media libraries with LibraryGuid ({LibraryGuids}) have same LibraryName '{LibraryName}', due to removal of sites and media library globalization it is required to set unique LibraryName and LibraryFolder",
string.Join(",", mlg.LibraryGuids), mlg.LibraryName);

foreach (var libraryGuid in mlg.LibraryGuids)
{
skippedMediaLibraries.Add(libraryGuid);
if (libraryGuid is { } lg)
{
skippedMediaLibraries.Add(lg);

protocol.Append(HandbookReferences.NotCurrentlySupportedSkip()
.WithMessage($"Media library '{mlg.LibraryName}' with LibraryGuid '{libraryGuid}' doesn't satisfy unique LibraryName and LibraryFolder condition for migration")
.WithData(new { LibraryGuid = libraryGuid, mlg.LibraryName })
);
protocol.Append(HandbookReferences.NotCurrentlySupportedSkip()
.WithMessage($"Media library '{mlg.LibraryName}' with LibraryGuid '{libraryGuid}' doesn't satisfy unique LibraryName and LibraryFolder condition for migration")
.WithData(new { LibraryGuid = libraryGuid, mlg.LibraryName })
);
}
}
}

Expand Down
31 changes: 17 additions & 14 deletions KVA/Migration.Toolkit.Source/Handlers/MigratePagesCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ public async Task<CommandResult> Handle(MigratePagesCommand request, Cancellatio
.SelectWhere<ICmsDocument>("DocumentNodeID = @nodeId", new SqlParameter("nodeId", ksNode.NodeID))
.ToList();

if (nodeLinkedNode != null)
bool isLinkedNode = nodeLinkedNode != null;
if (isLinkedNode)
{
if (nodeLinkedNode.NodeSiteID != ksNode.NodeSiteID)
if (nodeLinkedNode?.NodeSiteID != ksNode.NodeSiteID)
{
// skip & write to protocol
logger.LogWarning("Linked node with NodeGuid {NodeGuid} is linked from different site - unable to migrate", ksTreeOriginal.NodeGUID);
Expand Down Expand Up @@ -153,7 +154,8 @@ public async Task<CommandResult> Handle(MigratePagesCommand request, Cancellatio
CmsTreeK13 node => node with { NodeLinkedNodeID = null, NodeLinkedNodeSiteID = null },
_ => ksNode
};
logger.LogTrace("Linked node with NodeGuid {NodeGuid} was materialized", ksNode.NodeGUID);

logger.LogWarning("Linked node with NodeGuid {NodeGuid} was materialized (Xperience by Kentico doesn't support links), it no longer serves as link to original document. This affect also routing, this document will have own link generated from node alias path", ksNode.NodeGUID);
}
}

Expand Down Expand Up @@ -254,7 +256,8 @@ await MigratePageUrlPaths(
commonDataInfos,
migratedDocument,
ksNode,
migratedDocument.DocumentCulture
migratedDocument.DocumentCulture,
isLinkedNode
);

existingDocumentLanguages.Add(languageGuid);
Expand All @@ -271,7 +274,8 @@ await MigratePageUrlPaths(
commonDataInfos,
null,
ksNode,
culture.ContentLanguageName
culture.ContentLanguageName,
isLinkedNode
);
}

Expand Down Expand Up @@ -335,7 +339,7 @@ private static void AsserVersionStatusRule(List<ContentItemCommonDataInfo> commo
}

private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId, Guid webSiteChannelGuid, Guid languageGuid,
List<ContentItemCommonDataInfo> contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture)
List<ContentItemCommonDataInfo> contentItemCommonDataInfos, ICmsDocument? ksDocument, ICmsTree ksTree, string documentCulture, bool isLinkedNode)
{
var existingPaths = WebPageUrlPathInfo.Provider.Get()
.WhereEquals(nameof(WebPageUrlPathInfo.WebPageUrlPathWebPageItemID), webPageItemId)
Expand Down Expand Up @@ -413,8 +417,8 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId,
var webPageUrlPath = new WebPageUrlPathModel
{
WebPageUrlPathGUID = contentItemCommonDataInfo.ContentItemCommonDataVersionStatus == VersionStatus.Draft
? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT")
: GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{ksTree.NodeAliasPath}"),
? GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{documentCulture}|{ksTree.NodeAliasPath}|DRAFT|{ksTree.NodeID}")
: GuidHelper.CreateWebPageUrlPathGuid($"{ksDocument!.DocumentGUID}|{ksTree.NodeAliasPath}|{ksTree.NodeID}"),
WebPageUrlPath = ksTree.NodeAliasPath, //ksPath.PageUrlPathUrlPath,
// WebPageUrlPathHash = ksPath.PageUrlPathUrlPathHash,
WebPageUrlPathWebPageItemGuid = webPageItemGuid,
Expand Down Expand Up @@ -457,17 +461,16 @@ private async Task MigratePageUrlPaths(Guid webPageItemGuid, int webPageItemId,

string urlPath = (ksDocument switch
{
CmsDocumentK11 doc => doc.DocumentUrlPath,
CmsDocumentK12 doc => doc.DocumentUrlPath,
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;
}).NullIf(string.Empty) ?? $"{ksTree.NodeAliasPath}";

var webPageUrlPath = new WebPageUrlPathModel
{
WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}"),
WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"),
WebPageUrlPath = urlPath,
// WebPageUrlPathHash = kx13PageUrlPath.PageUrlPathUrlPathHash,
WebPageUrlPathWebPageItemGuid = webPageItemGuid,
WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid,
WebPageUrlPathContentLanguageGuid = languageGuid,
Expand Down Expand Up @@ -496,7 +499,7 @@ private async Task CreateDefaultPageUrlAsync(Guid webPageItemGuid, Guid webSiteC

var webPageUrlPath = new WebPageUrlPathModel
{
WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}"),
WebPageUrlPathGUID = GuidHelper.CreateWebPageUrlPathGuid($"{urlPath}|{documentCulture}|{webSiteChannel.WebsiteChannelGUID}|{ksTree.NodeID}"),
WebPageUrlPath = urlPath,
WebPageUrlPathWebPageItemGuid = webPageItemGuid,
WebPageUrlPathWebsiteChannelGuid = webSiteChannelGuid,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text.RegularExpressions;
using CMS.MediaLibrary;

using Microsoft.Extensions.Logging;
Expand All @@ -17,10 +18,11 @@ public class MediaLibraryInfoMapper(ILogger<MediaLibraryInfoMapper> logger, Prim
protected override MediaLibraryInfo? CreateNewInstance(MediaLibraryInfoMapperSource source, MappingHelper mappingHelper, AddFailure addFailure) =>
MediaLibraryInfo.New();

private static readonly Regex allowedCharactersForLibraryName = new(@"[^a-zA-Z0-9_]", RegexOptions.Compiled | RegexOptions.Singleline);
protected override MediaLibraryInfo MapInternal(MediaLibraryInfoMapperSource s, MediaLibraryInfo target, bool newInstance, MappingHelper mappingHelper, AddFailure addFailure)
{
var (ksLibrary, ksSite) = s;

string ksSiteNameSafe = allowedCharactersForLibraryName.Replace(ksSite.SiteName, "_");
// Sets the library properties
target.LibraryDisplayName = ksLibrary.LibraryDisplayName;
target.LibraryName = ksLibrary.LibraryName;
Expand All @@ -30,9 +32,9 @@ protected override MediaLibraryInfo MapInternal(MediaLibraryInfoMapperSource s,
target.LibraryDisplayName = ksLibrary.LibraryDisplayName;
target.LibraryDescription = ksLibrary.LibraryDescription;

if (!target.LibraryFolder.StartsWith($"{ksSite.SiteName}_", StringComparison.InvariantCultureIgnoreCase))
if (!target.LibraryFolder.StartsWith($"{ksSiteNameSafe}_", StringComparison.InvariantCultureIgnoreCase))
{
target.LibraryFolder = $"{ksSite.SiteName}_{ksLibrary.LibraryFolder}";
target.LibraryFolder = $"{ksSiteNameSafe}_{ksLibrary.LibraryFolder}";
}

target.LibraryLastModified = mappingHelper.Require(ksLibrary.LibraryLastModified, nameof(ksLibrary.LibraryLastModified));
Expand Down
55 changes: 33 additions & 22 deletions KVA/Migration.Toolkit.Source/Services/SpoiledGuidContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,49 @@ public class SpoiledGuidContext(ModelFacade modelFacade, ILogger<SpoiledGuidCont

internal IDictionary<Guid, ImmutableList<SpoiledDocumentGuidInfo>> SpoiledDocumentGuids =>
spoiledDocumentGuids ??= modelFacade.Select("""
SELECT DocumentGUID, STRING_AGG(CONCAT(NodeSiteID, '-', NodeID), '|') [SiteID-NodeID]
SELECT DocumentGUID, NodeSiteID, NodeID
FROM View_CMS_Tree_Joined TJ
GROUP BY DocumentGUID
HAVING COUNT(DocumentID) > 1
WHERE EXISTS(
SELECT 1
FROM View_CMS_Tree_Joined TJI
WHERE TJI.DocumentGUID = TJ.DocumentGUID
GROUP BY DocumentGUID
HAVING COUNT(DocumentID) > 1
)
""",
(reader, version) => new { DocumentGUID = reader.Unbox<Guid>("DocumentGuid"), Info = reader.Unbox<string>("SiteID-NodeID") })
.ToFrozenDictionary(
x => x.DocumentGUID,
x => x.Info.Split('|').Select(i =>
(reader, version) => new
{
string[] spl = i.Split('-');

return new SpoiledDocumentGuidInfo(int.Parse(spl[0]), int.Parse(spl[1]));
}).ToImmutableList()
DocumentGUID = reader.Unbox<Guid>("DocumentGUID"),
NodeID = reader.Unbox<int>("NodeID"),
NodeSiteID = reader.Unbox<int>("NodeSiteID"),
})
.GroupBy(x => x.DocumentGUID)
.ToFrozenDictionary(
x => x.Key,
x => x.Select(i => new SpoiledDocumentGuidInfo(i.NodeSiteID, i.NodeID)).ToImmutableList()
);

internal IDictionary<Guid, ImmutableList<SpoiledNodeGuidInfo>> SpoiledNodeGuids =>
spoiledNodeGuids ??= modelFacade.Select("""
SELECT NodeGUID, STRING_AGG(NodeSiteID, '|') [SiteID]
SELECT NodeGUID, NodeSiteID
FROM View_CMS_Tree_Joined TJ
GROUP BY NodeGUID
HAVING COUNT(NodeGUID) > 1
WHERE EXISTS (
SELECT 1
FROM View_CMS_Tree_Joined TJI
WHERE TJI.NodeGUID = TJ.NodeGUID
GROUP BY NodeGUID
HAVING COUNT(NodeGUID) > 1
)
""",
(reader, version) => new { DocumentGUID = reader.Unbox<Guid>("NodeGUID"), Info = reader.Unbox<string>("SiteID") })
.ToFrozenDictionary(
x => x.DocumentGUID,
x => x.Info.Split('|').Select(i =>
(reader, version) => new
{
string[] spl = i.Split('-');

return new SpoiledNodeGuidInfo(int.Parse(spl[0]));
}).ToImmutableList()
NodeGUID = reader.Unbox<Guid>("NodeGUID"),
NodeSiteID = reader.Unbox<int>("NodeSiteID")
})
.GroupBy(x => x.NodeGUID)
.ToFrozenDictionary(
x => x.Key,
x => x.Select(i => new SpoiledNodeGuidInfo(i.NodeSiteID)).ToImmutableList()
);

public Guid EnsureDocumentGuid(Guid documentGuid, int siteId, int nodeId, int documentId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
using Migration.Toolkit.Core.K11.Mappers;
using Migration.Toolkit.K11;
using Migration.Toolkit.K11.Models;
using Migration.Toolkit.KXP.Api.Auxiliary;
using Migration.Toolkit.KXP.Api.Enums;

namespace Migration.Toolkit.Core.K11.Handlers;

Expand All @@ -37,7 +37,7 @@ public async Task<CommandResult> Handle(MigrateMembersCommand request, Cancellat

var k11CmsUsers = k11Context.CmsUsers
.Include(u => u.CmsUserSettingUserSettingsUserNavigation)
.Where(u => UserHelper.PrivilegeLevelsMigratedAsMemberUser.Contains(u.UserPrivilegeLevel))
.Where(u => u.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.None)
;

foreach (var k11User in k11CmsUsers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using Migration.Toolkit.Core.K11.Contexts;
using Migration.Toolkit.K11;
using Migration.Toolkit.K11.Models;
using Migration.Toolkit.KXP.Api.Auxiliary;
using Migration.Toolkit.KXP.Api.Enums;

namespace Migration.Toolkit.Core.K11.Handlers;
Expand All @@ -38,7 +37,7 @@ public async Task<CommandResult> Handle(MigrateUsersCommand request, Cancellatio
await using var k11Context = await k11ContextFactory.CreateDbContextAsync(cancellationToken);

var k11CmsUsers = k11Context.CmsUsers
.Where(u => UserHelper.PrivilegeLevelsMigratedAsAdminUser.Contains(u.UserPrivilegeLevel))
.Where(u => u.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Admin || u.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Editor || u.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.GlobalAdmin)
;

foreach (var k11User in k11CmsUsers)
Expand Down Expand Up @@ -127,7 +126,7 @@ private async Task MigrateUserCmsRoles(K11Context k11Context, CancellationToken
{
var groupedRoles = k11Context.CmsRoles
.Where(r =>
r.CmsUserRoles.Any(ur => UserHelper.PrivilegeLevelsMigratedAsAdminUser.Contains(ur.User.UserPrivilegeLevel))
r.CmsUserRoles.Any(ur => ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Editor || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Admin || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.GlobalAdmin)
)
.GroupBy(x => x.RoleName)
.AsNoTracking();
Expand Down Expand Up @@ -157,7 +156,7 @@ Roles with RoleGuid ({RoleGuids}) have same RoleName '{RoleName}', due to remova

var k11CmsRoles = k11Context.CmsRoles
.Where(r =>
r.CmsUserRoles.Any(ur => UserHelper.PrivilegeLevelsMigratedAsAdminUser.Contains(ur.User.UserPrivilegeLevel))
r.CmsUserRoles.Any(ur => ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Editor || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Admin || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.GlobalAdmin)
)
.AsNoTracking()
.AsAsyncEnumerable();
Expand Down Expand Up @@ -215,8 +214,9 @@ private async Task MigrateUserRole(int k11RoleId)
var k11Context = await k11ContextFactory.CreateDbContextAsync();
var k11UserRoles = k11Context.CmsUserRoles
.Where(ur =>
ur.RoleId == k11RoleId &&
UserHelper.PrivilegeLevelsMigratedAsAdminUser.Contains(ur.User.UserPrivilegeLevel)
ur.RoleId == k11RoleId && (
ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Editor || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.Admin || ur.User.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.GlobalAdmin
)
)
.AsNoTracking()
.AsAsyncEnumerable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using Migration.Toolkit.Core.KX12.Contexts;
using Migration.Toolkit.Core.KX12.Mappers;
using Migration.Toolkit.KX12.Context;
using Migration.Toolkit.KXP.Api.Auxiliary;
using Migration.Toolkit.KXP.Api.Enums;

namespace Migration.Toolkit.Core.KX12.Handlers;
Expand All @@ -39,7 +38,7 @@ public async Task<CommandResult> Handle(MigrateMembersCommand request, Cancellat

var k12CmsUsers = kx12Context.CmsUsers
.Include(u => u.CmsUserSettingUserSettingsUserNavigation)
.Where(u => UserHelper.PrivilegeLevelsMigratedAsMemberUser.Contains(u.UserPrivilegeLevel))
.Where(u => u.UserPrivilegeLevel == (int)UserPrivilegeLevelEnum.None)
;

foreach (var k12User in k12CmsUsers)
Expand Down
Loading

0 comments on commit c9cfa8a

Please sign in to comment.