1711436006
2024-03-24 00:00:00
これは一般的に行うことではありませんが、私が行った方法は次のとおりです。 FormContainerBlock
私たちのカスタムに合わせて入力します ExtendedFormContainerBlock
Optimizely Forms for CMS 12 の場合。カスタム プロパティまたは機能を標準に追加する場合は、これを実行する必要がある場合があります。 FormContainerBlock
タイプを選択し、以前に作成したすべてのフォームを再構築または再作成したくない場合。
免責事項
このコードは概念実証として扱ってください。 本番環境に対応していないものとして扱います。 これを基礎として構築するための出発点として使用する必要があります。 データが失われる可能性があります。 データベースをバックアップします。 ローカルで複数回テストします。 ステージング環境でテストします。 もう一度テストしてください。 そしてもう一度テストしてみます。 私のマシンでは動作します。 あなたのものでは機能しないかもしれません。
FormContainerBlock の変換
このアプローチでは、スケジュールされたジョブを使用してコードを実行しました。 こうすることで、ジョブを 1 回実行し、変換が完了したらジョブを削除できます。
コードを見ると、更新していることがわかります。 tblContent
、 tblContentProperty
、 そして tblWorkContentProperty
テーブルに直接アクセスできます。 明らかに、直接 SQL コマンドを実行することはお勧めできませんが、Optimizely が提供する API を使用する以外にこれを実行するより良い方法はありません。
私が作成したスケジュールされたジョブは次のとおりです。
[ScheduledPlugIn(DisplayName = "Convert FormContainerBlocks", GUID = "00000000-0000-0000-0000-000000000000", Description = "Converts all FormContainerBlock instances to ExtendedFormContainerBlock.")]
public class ConvertFormContainerBlocksScheduledJob : ScheduledJobBase
{
private readonly IConfiguration _configuration;
private readonly IContentTypeRepository _contentTypeRepository;
private readonly IContentModelUsage _contentModelUsage;
private readonly IContentVersionRepository _contentVersionRepository;
private readonly IPropertyDefinitionRepository _propertyDefinitionRepository;
private readonly IContentRepository _contentRepository;
private bool _stopSignaled;
public ConvertFormContainerBlocksScheduledJob(
IConfiguration configuration,
IContentTypeRepository contentTypeRepository,
IContentModelUsage contentModelUsage,
IPropertyDefinitionRepository propertyDefinitionRepository,
IContentRepository contentRepository,
IContentVersionRepository contentVersionRepository)
{
_configuration = configuration;
_contentTypeRepository = contentTypeRepository;
_contentModelUsage = contentModelUsage;
_propertyDefinitionRepository = propertyDefinitionRepository;
_contentRepository = contentRepository;
_contentVersionRepository = contentVersionRepository;
IsStoppable = true;
}
public override void Stop()
{
_stopSignaled = true;
}
public override string Execute()
{
OnStatusChanged($"Starting execution of {GetType()}");
throw new Exception("Don't run untested code");
var formContainersContentLinks = GetFormContainerContentLinks();
if (formContainersContentLinks == null || !formContainersContentLinks.Any())
{
return "No FormContainerBlocks found";
}
OnStatusChanged($"Found {formContainersContentLinks.Count()} FormContainerBlocks");
var connectionString = _configuration.GetConnectionString("EPiServerDB");
var extendedFormContainerBlockContentType = _contentTypeRepository.Load<ExtendedFormContainerBlock>();
int total = formContainersContentLinks.Count();
int succeeded = 0;
int failed = 0;
foreach (var contentLink in formContainersContentLinks)
{
OnStatusChanged($"Converting FormContainerBlock with ID {contentLink.ID}");
var fcbInstance = _contentRepository.Get<FormContainerBlock>(contentLink);
var fcbContentType = _contentTypeRepository.Load<FormContainerBlock>();
var efcbContentType = _contentTypeRepository.Load<ExtendedFormContainerBlock>();
var fcbPropertyDefinitionList = _propertyDefinitionRepository.List(fcbContentType.ID);
var efcbPropertyDefinitionList = _propertyDefinitionRepository.List(efcbContentType.ID);
try
{
using var connection = new SqlConnection(connectionString);
connection.Open();
using var updateContentCommand = new SqlCommand("UPDATE tblContent SET fkContentTypeID = @ContentTypeID WHERE pkID = @ContentLinkID", connection);
updateContentCommand.Parameters.AddWithValue("@ContentTypeID", extendedFormContainerBlockContentType.ID);
updateContentCommand.Parameters.AddWithValue("@ContentLinkID", contentLink.ID);
updateContentCommand.ExecuteNonQuery();
updateContentCommand.Dispose();
foreach (var propertyDefinition in fcbPropertyDefinitionList)
{
var newPropertyDefinition = efcbPropertyDefinitionList.FirstOrDefault(pd => pd.Name == propertyDefinition.Name);
if (newPropertyDefinition == null)
{
continue;
}
using var updatePropertyCommand = new SqlCommand("UPDATE tblContentProperty SET fkPropertyDefinitionID = @NewPropertyDefinitionId WHERE fkPropertyDefinitionID = @OldPropertyDefinitionId AND fkContentID = @ContentLinkId", connection);
updatePropertyCommand.Parameters.AddWithValue("@NewPropertyDefinitionId", newPropertyDefinition.ID);
updatePropertyCommand.Parameters.AddWithValue("@OldPropertyDefinitionId", propertyDefinition.ID);
updatePropertyCommand.Parameters.AddWithValue("@ContentLinkID", contentLink.ID);
updatePropertyCommand.ExecuteNonQuery();
updatePropertyCommand.Dispose();
var versions = _contentVersionRepository.List(contentLink);
foreach (var version in versions)
{
using var updateWorkPropertyCommand = new SqlCommand("UPDATE tblWorkContentProperty SET fkPropertyDefinitionID = @NewPropertyDefinitionId WHERE fkPropertyDefinitionID = @OldPropertyDefinitionId AND fkWorkContentID = @WorkContentLinkId", connection);
updateWorkPropertyCommand.Parameters.AddWithValue("@NewPropertyDefinitionId", newPropertyDefinition.ID);
updateWorkPropertyCommand.Parameters.AddWithValue("@OldPropertyDefinitionId", propertyDefinition.ID);
updateWorkPropertyCommand.Parameters.AddWithValue("@WorkContentLinkID", version.ContentLink.WorkID);
updateWorkPropertyCommand.ExecuteNonQuery();
updateWorkPropertyCommand.Dispose();
}
}
OnStatusChanged($"Converted FormContainerBlock with ID {contentLink.ID}");
succeeded++;
}
catch (Exception ex)
{
OnStatusChanged($"Failed to convert FormContainerBlock with ID {contentLink.ID} - {ex.Message}");
failed++;
}
if (_stopSignaled)
{
return $"Stop of job was called. Found {total} FormContainerBlocks. Converting {succeeded} succeeded, {failed} failed.";
}
}
return $"Job completed. Found {total} FormContainerBlocks. Converting {succeeded} succeeded, {failed} failed.";
}
private IEnumerable<ContentReference> GetFormContainerContentLinks()
{
var formContainerBlockContentType = _contentTypeRepository.Load<FormContainerBlock>();
if (formContainerBlockContentType == null)
{
return Enumerable.Empty<ContentReference>();
}
var formContainerBlockUsage = _contentModelUsage.ListContentOfContentType(formContainerBlockContentType);
if (formContainerBlockUsage == null || !formContainerBlockUsage.Any())
{
return Enumerable.Empty<ContentReference>();
}
return formContainerBlockUsage.DistinctBy(usage => usage.ContentLink.ID).Select(usage => usage.ContentLink);
}
}
このコードを実稼働環境で実行する前に複数回テストする必要があると言いましたか? やった? 良い。
#Optimizely #Forms #CMS #での #FormContainerBlock #タイプの変換