Skip to content

Commit

Permalink
Merge pull request #243 from Kentico/feat/migrate_to_assets
Browse files Browse the repository at this point in the history
Migration of media file and attachments to content items
  • Loading branch information
fialafilip authored Sep 6, 2024
2 parents c9cfa8a + 5d4d7aa commit 56959ea
Show file tree
Hide file tree
Showing 84 changed files with 2,584 additions and 3,754 deletions.
96 changes: 96 additions & 0 deletions KVA/Migration.Toolkit.Source/Auxiliary/EntityIdentityImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.Collections.Frozen;
using CMS.DataEngine;
using Microsoft.Extensions.Logging;
using Migration.Toolkit.Common.Helpers;

namespace Migration.Toolkit.Source.Auxiliary;

public interface ISourceGuidContext
{
int[]? GetSiteIds<T>(Guid entityGuid) where T : ISourceGuidEntity;
}

public class SourceGuidContext(ModelFacade modelFacade, ILogger<ISourceGuidContext> logger) : ISourceGuidContext
{
private static class Cache<T>
{
// ReSharper disable once StaticMemberInGenericType
public static FrozenDictionary<Guid, int[]>? SourceGuidSites;
}

public int[]? GetSiteIds<T>(Guid entityGuid) where T : ISourceGuidEntity
{
var cache = Cache<T>.SourceGuidSites ??= T.Load(modelFacade);
int[]? result = cache.GetValueOrDefault(entityGuid);
switch (result)
{
case { Length: 0 }:
{
logger.LogDebug("Guid {Guid} has no site at all", entityGuid);
return [];
}
case { Length: 1 }:
{
return result;
}
case null:
{
logger.LogDebug("Guid {Guid} is not found at all", entityGuid);
return null;
}
default:
{
logger.LogDebug("Guid {Guid} is present on multiple sites {Sites}", entityGuid, string.Join("|", result));
return result;
}
}
}
}

public record EntityIdentityGuidResult(bool IsFixed, Guid Identity);
public class EntityIdentityFacade(ISourceGuidContext sourceGuidContext)
{
public EntityIdentityGuidResult Translate<T>(Guid guid, int? siteId) where T : ISourceGuidEntity =>
sourceGuidContext.GetSiteIds<T>(guid) switch
{
// not found => leave it as it is or throw
{ Length: 0 } => new EntityIdentityGuidResult(false, guid),
// OK! lets leave guid unchanged
{ Length: 1 } => new EntityIdentityGuidResult(false, guid),
// BAD, guid is not unique, we cannot use it in XbyK
_ => new EntityIdentityGuidResult(true, GuidV5.NewNameBased(T.NewGuidNs, $"{guid}|{siteId ?? -1}"))
};

public EntityIdentityGuidResult Translate<T>(T s) where T : ISourceGuidEntity =>
s.GetIdentity() is var (guid, siteId)
? Translate<T>(guid, siteId)
: throw new InvalidOperationException($"Unable to determine source entity identity: {s}");
}

public class IdentityLocator(EntityIdentityFacade entityIdentityFacade, ILogger<IdentityLocator> logger)
{
public (TTarget target, bool guidIsFixed) LocateTarget<TTarget, TSource>(Guid entityGuid, int? siteId)
where TTarget : AbstractInfoBase<TTarget>, IInfoWithGuid, new()
where TSource : ISourceGuidEntity
{
(bool isFixed, var safeAttachmentGuid) = entityIdentityFacade.Translate<TSource>(entityGuid, siteId);
var target = Provider<TTarget>.Instance.Get(safeAttachmentGuid);

logger.LogTrace("Located {Target} from source {Source}",
new { ID = target.Generalized.ObjectID, CodeName = target.Generalized.ObjectCodeName, type = target.TypeInfo.ObjectClassName },
new { type = typeof(TSource).Name, entityGuid, siteId }
);

return (target, isFixed);
}

public (TTarget target, bool guidIsFixed) LocateTarget<TTarget, TSource>(TSource s)
where TTarget : AbstractInfoBase<TTarget>, IInfoWithGuid, new()
where TSource : ISourceGuidEntity
{
// TODO tomas.krch: 2024-07-23 specialized approach for CMS_USER and CMS_MEMBER

(var entityGuid, int? siteId) = s.GetIdentity();
return LocateTarget<TTarget, TSource>(entityGuid, siteId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public class SourceInstanceContext(
ToolkitConfiguration configuration,
ModelFacade modelFacade)
{
/// <summary>
/// key is SiteName
/// </summary>
private readonly Dictionary<string, SourceInstanceDiscoveredInfo> cachedInfos = new(StringComparer.InvariantCultureIgnoreCase);

private bool sourceInfoLoaded;
Expand Down
12 changes: 3 additions & 9 deletions KVA/Migration.Toolkit.Source/Exceptions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
namespace Migration.Toolkit.Source;

public class MappingFailureException : InvalidOperationException
public class MappingFailureException(string keyName, string reason) : InvalidOperationException($"Key '{keyName}' mapping failed: {reason}")
{
public MappingFailureException(string keyName, string reason) : base($"Key '{keyName}' mapping failed: {reason}")
{
KeyName = keyName;
Reason = reason;
}

public string KeyName { get; }
public string Reason { get; }
public string KeyName { get; } = keyName;
public string Reason { get; } = reason;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ namespace Migration.Toolkit.Source.Handlers;
// ReSharper disable once UnusedMember.Global [implicit use]
public class MigrateAttachmentsCommandHandler(
ModelFacade modelFacade,
AttachmentMigrator attachmentMigrator
IAttachmentMigrator attachmentMigrator
) : IRequestHandler<MigrateAttachmentsCommand, CommandResult>
{
public Task<CommandResult> Handle(MigrateAttachmentsCommand request, CancellationToken cancellationToken)
public async Task<CommandResult> Handle(MigrateAttachmentsCommand request, CancellationToken cancellationToken)
{
var ksCmsAttachments = modelFacade.SelectAll<ICmsAttachment>();

Expand All @@ -25,13 +25,13 @@ public Task<CommandResult> Handle(MigrateAttachmentsCommand request, Cancellatio
continue;
}

(_, bool canContinue, _, _) = attachmentMigrator.MigrateAttachment(ksCmsAttachment);
(_, bool canContinue) = await attachmentMigrator.MigrateAttachment(ksCmsAttachment);
if (!canContinue)
{
break;
}
}

return Task.FromResult<CommandResult>(new GenericCommandResult());
return new GenericCommandResult();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ public async Task<CommandResult> Handle(MigrateFormsCommand request, Cancellatio
.Select(x => x.Attribute("name")?.Value).ToImmutableHashSet();

Debug.Assert(autoIncrementColumns.Count == 1, "autoIncrementColumns.Count == 1");
// TODO tk: 2022-07-08 not true : autoIncrementColumns.First() == csi.IDColumn
// Debug.Assert(autoIncrementColumns.First() == csi.IDColumn, "autoIncrementColumns.First() == csi.IDColumn");

var r = (ksClass.ClassTableName, ksClass.ClassGUID, autoIncrementColumns);
logger.LogTrace("Class '{ClassGuild}' Resolved as: {Result}", ksClass.ClassGUID, r);
Expand Down
Loading

0 comments on commit 56959ea

Please sign in to comment.