From c4e9a22730adfc0504fd931797a41920fd6ed84e Mon Sep 17 00:00:00 2001 From: "MASTER\\DominikaG2" Date: Wed, 21 Jan 2026 18:45:03 -0500 Subject: [PATCH 1/3] Update (non-permanent) links to Learn portal guides. Remove Migration protocol (obsolete) form example configuration Change order of sections in Extensions README for better flow (+ add one small note based on feedback) --- Migration.Tool.CLI/README.md | 5 +- Migration.Tool.Common/README.md | 1 - Migration.Tool.Extensions/README.md | 346 ++++++++++++++-------------- README.md | 4 +- 4 files changed, 175 insertions(+), 181 deletions(-) diff --git a/Migration.Tool.CLI/README.md b/Migration.Tool.CLI/README.md index 9ec56bce..ddd30507 100644 --- a/Migration.Tool.CLI/README.md +++ b/Migration.Tool.CLI/README.md @@ -10,7 +10,7 @@ This document describes how to configure and run the Migration CLI, the main exe The source instance must **not** use a [separated contact management database](https://docs.kentico.com/x/4giRBg), it is recommended that you [rejoin the contact management database](https://docs.kentico.com/x/5giRBg) before proceeding with the migration. -If you are migrating from Kentico Xperience 13, remember to [update your source instance to Refresh 5 or higher](https://docs.kentico.com/guides/architecture/upgrade-from-kx13/upgrade-faq#do-i-have-to-update-my-kx13-site-before-migration). +If you are migrating from Kentico Xperience 13, remember to [update your source instance to Refresh 5 or higher](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-from-kx13/upgrade-faq#do-i-have-to-update-my-kx13-site-before-migration). ## Set up the target instance @@ -83,7 +83,7 @@ Migration.Tool.CLI.exe migrate --sites --custom-modules --custom-tables --catego successfully. > [!TIP] -> Refer to our [FAQ page](https://docs.kentico.com/guides/architecture/upgrade-from-kx13/upgrade-faq#can-i-run-the-kentico-migration-tool-against-my-project-multiple-times) for best practices of performing repeated (iterative) data migration. +> Refer to our [FAQ page](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-from-kx13/upgrade-faq#can-i-run-the-kentico-migration-tool-against-my-project-multiple-times) for best practices of performing repeated (iterative) data migration. ### Migration Details for Specific Object Types @@ -588,7 +588,6 @@ Add the options under the `Settings` section in the configuration file. "CMSConnectionString": "Data Source=myserver;Initial Catalog=XperienceByKentico;Integrated Security=True;Persist Security Info=False;Connect Timeout=120;Encrypt=False;Current Language=English;" } }, - "MigrationProtocolPath": "C:\\_Development\\xperience-migration-toolkit-master\\Migration.Tool.Protocol.log", "MemberIncludeUserSystemFields": "FirstName|MiddleName|LastName|FullName|UserPrivilegeLevel|UserIsExternal|LastLogon|UserLastModified|UserGender|UserDateOfBirth", "ConvertClassesToContentHub": "Acme.Article,Acme.Product,Acme.CustomClass", "CustomModuleClassDisplayNamePatterns": { diff --git a/Migration.Tool.Common/README.md b/Migration.Tool.Common/README.md index 1e2afc6d..ff8022e3 100644 --- a/Migration.Tool.Common/README.md +++ b/Migration.Tool.Common/README.md @@ -17,7 +17,6 @@ Provides shared infrastructure used by all other migration projects: - `Commands.cs` - All MediatR commands (MigrateSitesCommand, MigratePagesCommand, etc.) - `ToolConfiguration.cs` - Configuration model with validation - `IPrinter.cs` / `IPrimaryKeyMappingContext.cs` - Core service abstractions -- `MigrationProtocol/` - Structured migration result reporting - `Abstractions/` - Interfaces for custom migrations and mappers - `Services/` - Command line interface parsing and execution logic diff --git a/Migration.Tool.Extensions/README.md b/Migration.Tool.Extensions/README.md index a476fd0a..5bda7afe 100644 --- a/Migration.Tool.Extensions/README.md +++ b/Migration.Tool.Extensions/README.md @@ -20,15 +20,15 @@ The project enables you to: - [Available Customization Types](#available-customization-types) - [When Custom Migrations Execute](#when-custom-migrations-execute) - [Implementation Guides](#implementation-guides) - - [Customize Field Migrations](#customize-field-migrations) - - [Customize Linked Page Handling](#customize-linked-page-handling) - - [Customize Widget Migrations](#customize-widget-migrations) - - [Customize Widget Property Migrations](#customize-widget-property-migrations) - - [Migrate Pages to Widgets](#migrate-pages-to-widgets) - [Custom Class Mappings](#custom-class-mappings) - [Remodel Page Types as Reusable Field Schemas Guide](#remodel-page-types-as-reusable-field-schemas-guide) - [Sample Class Mappings](#sample-class-mappings) + - [Customize Linked Page Handling](#customize-linked-page-handling) + - [Migrate Pages to Widgets](#migrate-pages-to-widgets) - [Custom Child Links](#custom-child-links) + - [Customize Field Migrations](#customize-field-migrations) + - [Customize Widget Migrations](#customize-widget-migrations) + - [Customize Widget Property Migrations](#customize-widget-property-migrations) - [Registration](#registration) - [Working with Source and Target APIs](#working-with-source-and-target-apis) @@ -65,16 +65,6 @@ Controls migration behavior and relationships of individual content items during - Link child pages as content item references (e.g., link child `Book` pages in a `Books` field when migrating `Author` pages to reusable content) - Apply conditional logic based on content structure or hierarchy -### Field Migrations (`IFieldMigration`) - -Transforms individual field values during data migration. - -**Use cases:** - -- Handle custom form controls -- Convert data formats (date formats, URL structures) -- Transform content (HTML cleanup, path updates) - ### Widget Migrations (`IWidgetMigration`) Changes widget types or restructures widget data. @@ -95,6 +85,16 @@ Transforms individual widget property values. - Convert property value formats - Transform paths or URLs in widget data +### Field Migrations (`IFieldMigration`) + +Transforms individual field values during data migration. + +**Use cases:** + +- Handle custom form controls +- Convert data formats (date formats, URL structures) +- Transform content (HTML cleanup, path updates) + ## When Custom Migrations Execute When registered, customizations execute based on CLI migration parameters. The order depends on parameter dependencies (e.g., `--pages` requires `--page-types` to run first): @@ -113,6 +113,22 @@ For detailed information about all available CLI parameters, their dependencies, | **Widget Migrations** | `--pages` | | **Widget Property Migrations** | `--pages` | +> [!NOTE] +> Class mappings run before page data migration. Field value transformations defined in class mappings (using `ConvertFrom`) are applied during content type structure migration, not during individual page processing. + +**Execution during page migration:** + +As multiple custom migrations run during the `--pages` migration, custom migrations execute in the following order for each page: + +1. Content item directors control overall behavior (e.g., dropping pages, converting to widgets, handling linked pages) +2. Widget migrations and widget property migrations transform Page Builder content +3. Field migrations transform page field values + +> [!TIP] +> Widget migrations execute before content items are saved to the database. To query migrated content items from the database during widget migration (e.g., to modify their property value), run the migration tool twice. + +After all pages are migrated, the tool performs a final pass to update `TreePath` properties (converting `NodeAliasPath` references). This happens automatically and doesn't require custom migration logic. + ### Criteria for Custom Migration Execution The Kentico Migration Tool uses a handler-based architecture where handlers automatically call your custom migrations during data transformation. Typically, you do not interact with handlers directly—simply register your migrations and the migration tool will invoke them automatically. @@ -123,50 +139,108 @@ Custom migrations are called during transformation: 2. **Ranking** - If multiple migrations match, the one with the lowest `Rank` value is selected and applied 3. **Execution** - Once selected, the tool invokes your transformation method to migrate the data (e.g., `MigrateValue()`, `MigrateWidget()`, or `Direct()`) -**Execution during page migration:** +## Implementation Guides -As multiple custom migrations run during the `--pages` migration, custom migrations execute in the following order for each page: +The following sections provide detailed instructions for implementing each type of custom migration. -1. Content item directors control overall behavior (e.g., dropping pages, converting to widgets, handling linked pages) -2. Widget migrations and widget property migrations transform Page Builder content -3. Field migrations transform page field values +### Custom Class Mappings -After all pages are migrated, the tool performs a final pass to update `TreePath` properties (converting `NodeAliasPath` references). This happens automatically and doesn't require custom migration logic. +You can customize class mappings to adjust the content model between the source instance and the target Xperience by Kentico instance. For example, you can merge multiple page types into a single content type, remodel page types as [reusable field scehams](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides), or migrate them to the [content hub](https://docs.kentico.com/x/barWCQ) as reusable content. -**Overall migration order:** +1. Create a new class. +2. Add an `IServiceCollection` extension method. Use a separate method for every class mapping that you wish to configure. +3. Within the extension method, define a new `MultiClassMapping` object: -When running a complete migration with multiple parameters, custom migrations execute in this sequence: + ```csharp + var m = new MultiClassMapping(targetClassName, target => + { + // Target content type name + target.ClassName = "Acme.Article"; + // Database table name of the new type + target.ClassTableName = "Acme_Article"; + // Display name of the content type + target.ClassDisplayName = "Article"; + // Type of the class (specifies that the class is a content type) + target.ClassType = ClassType.CONTENT_TYPE; + // What the content type is used for (reusable content, pages, email, or headless) + target.ClassContentTypeType = ClassContentTypeType.WEBSITE; + }); + ``` -1. **Class mappings** (with `--page-types` or `--custom-modules`) - Define content type structure and field definitions, including value conversions via `ConvertFrom` -2. **Content item directors, widget migrations, and field migrations** (with `--pages`) - Transform individual page data in the order described above +4. Define a new primary key: -Note that class mappings run before page data migration, so any field value transformations defined in class mappings (e.g., using `ConvertFrom`) are applied during the content type structure migration, not during individual page processing. + ```csharp + m.BuildField("ArticleID").AsPrimaryKey(); + ``` -## Implementation Guides +5. Define individual fields of the new content type: -The following sections provide detailed instructions for implementing each type of custom migration. + ```csharp + // Builds a new title field + var title = m.BuildField("Title"); -### Customize Field Migrations + // You can map any number of source fields. The migration creates items of the target data class for every item from a mapped source data class. + // The default migration is skipped for any data class / page type where you map at least one source field -You can customize field migrations to control how fields are mapped for page types, modules, system objects, and forms. In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IFieldMigration` interface. Implement the following properties and methods required by the interface: + // Maps the "ArticleTitle" field from the source data class "Article.BlogPost" + // Sets the isTemplate parameter to true, which makes the new field inherit the source field definition as a template + // The field definition is migrated according to the migration tool's data type and form control/component mappings + title.SetFrom("Article.BlogPost", "ArticleTitle", true); + // Maps the "ArticleTitle" field from a second source data class "Article.NewsArticle" + // The isTemplate parameter is not set, so only the value is taken from this source field + title.SetFrom("Article.NewsArticle", "ArticleTitle"); -- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. -- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current field. Use properties of the `FieldMigrationContext` object passed as an argument to the method to evaluate the condition. For each field, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. - - `SourceDataType` - A string property that specifies the [data type](https://docs.kentico.com/x/coJwCg) of the source field. - - `SourceFormControl` - A string property that specifies the [form control](https://docs.kentico.com/x/lAyRBg) used by the source field. - - `FieldName` - A string property that specifies the code name of the field. - - `SourceObjectContext` - An interface that can be used to check the context of the source object (e.g. page vs. form). -- `MigrateFieldDefinition` - Migrate the definition of the field. Use the `XElement` attribute to transform the field. -- `MigrateValue` - Migrate the value of the field. Use the source value and the `FieldMigrationContext` with the same parameters as described in `ShallMigrate`. + // You can modify the field definition, e.g., change the caption of the field + title.WithFieldPatch(f => f.Caption = "Article title"); + ``` -You can see samples: +6. (*Optional*) You can add custom value conversions: -- [SampleTextMigration.cs](./CommunityMigrations/SampleTextMigration.cs) - - A sample migration with further explanations -- [AssetMigration.cs](./DefaultMigrations/AssetMigration.cs) - - An example of a usable migration + ```csharp + var publishDate = m.BuildField("PublishDate"); + publishDate.SetFrom("Article.BlogPost", "BlogPostDate", true); + + // Uses value conversion to modify the field value + publishDate.ConvertFrom("Article.NewsArticle", "ArticleDateAsText", false, + (v, context) => + { + switch (context) + { + case ConvertorTreeNodeContext treeNodeContext: + // You can use the available TreeNode context here + // (var nodeGuid, int nodeSiteId, int? documentId, bool migratingFromVersionHistory) = treeNodeContext; + break; + default: + // No context is available (possibly when the tool is extended with other conversion possibilities) + break; + } -After implementing the migration, you need to [register the migration](#registration) in the system. + return v?.ToString() is { } av && !string.IsNullOrWhiteSpace(av) ? DateTime.Parse(av) : null; + }); + startDate.WithFieldPatch(f => f.Caption = "Event start date"); + ``` + +7. Complete the implementation by [registering the class mapping](#registration) in the dependency injection container. + +8. Ensure that your class mapping extension methods run during the startup of the migration tool. Call the methods from `UseCustomizations` in the [ServiceCollectionExtensions](/Migration.Tool.Extensions/ServiceCollectionExtensions.cs) class. + +**Note**: Your mappings now replace the default migration functionality for all data classes (page types, custom tables or custom module classes) that you use as a source. Any class where you set at least one source field is affected. If you map only some fields from a source class, the remaining fields are not migrated at all. + +If you need class mappings to alter several data classes in Kentico Xperience 13, consider [using AI tools to help you generate mappings quickly](https://docs.kentico.com/x/speed_up_remodeling_with_ai_guides). + +#### Remodel Page Types as Reusable Field Schemas Guide + +For an end-to-end example of how to extract common fields from two page types from Kentico Xperience 13 and move them to a [reusable field schema](https://docs.kentico.com/x/D4_OD) shared by both web page content types in Xperience by Kentico follow this [migration guide](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides) in the documentation. + +Note that any usage of `ReusableSchemaBuilder` in custom class mappings cannot be combined together with the `Settings.CreateReusableFieldSchemaForClasses` configuration option. + +#### Sample Class Mappings + +You can find sample class mappings in the [ClassMappingSample.cs](/Migration.Tool.Extensions/ClassMappings/ClassMappingSample.cs) file. + +- `AddSimpleRemodelingSample` showcases how to change the mapping of a single page type +- `AddClassMergeSample` showcases how to merge two page types into a single content type +- `AddReusableRemodelingSample` showcases how to migrate a page type as reusable content ### Customize Linked Page Handling @@ -265,51 +339,6 @@ After implementing your linked page director, you need to [register the director - Use logging to track which strategy is applied to each linked page - Verify that ancestor pages exist and have the expected structure -### Customize Widget Migrations - -You can customize widget migration to change the widget to which source widgets are migrated in the target instance. In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IWidgetMigration` interface. Implement the following properties and methods required by the interface: - -- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. -- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current widget. Use properties of the `WidgetMigrationContext` and `WidgetIdentifier` objects passed as an argument to the method to evaluate the condition. For each widget, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. - - `WidgetMigrationContext.SiteId` - An integer property that specifies the ID of the site on which the widget was used in the source instance. - - `WidgetIdentifier.TypeIdentifier` - A string property that specifies the identifier of the widget. -- `MigrateWidget`- Migrate the widget data using the following properties: - - `identifier` - A `WidgetIdentifier` object, see `ShallMigrate` to see properties. - - `value` - A `JToken` object containing the deserialized value of the property. - - `context` - A `WidgetMigrationContext` object, see `ShallMigrate` to see properties. - -You can see a sample: [SampleWidgetMigration.cs](./CommunityMigrations/SampleWidgetMigration.cs) - -After implementing the migration, you need to [register the migration](#registration) in the system. - -> [!TIP] -> For a complete end-to-end example, see our guide on [how to migrate widget data as reusable content](https://docs.kentico.com/x/migrate_widget_data_as_reusable_content_guides) in the Kentico documentation. - -### Customize Widget Property Migrations - -In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IWidgetPropertyMigration` interface. Implement the following properties and methods required by the interface: - -- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. -- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current widget. Use properties of the `WidgetPropertyMigrationContext` and `propertyName` objects passed as an argument to the method to evaluate the condition. For each widget property, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. - - `WidgetPropertyMigrationContext.SiteId` - An integer property that specifies the ID of the site on which the widget was used in the source instance. - - `WidgetPropertyMigrationContext.EditingFormControlModel` - An object representing the [form control](https://docs.kentico.com/x/lAyRBg) of the property. - - `propertyName` - A string property that specifies the identifier of the property. -- `MigrateWidgetProperty`- Migrate the widget property data using the following properties: - - `key` - Name of the property. - - `value` - A `JToken` object containing the deserialized value of the property. - - `context` - A `WidgetPropertyMigrationContext`. See `ShallMigrate` method to see the properties. - -You can see samples: - -- [Path selector migration](./DefaultMigrations/WidgetPathSelectorMigration.cs) -- [Page selector migration](./DefaultMigrations/WidgetPageSelectorMigration.cs) -- [File selector migration](./DefaultMigrations/WidgetFileMigration.cs) - -After implementing the migration, you need to [register the migration](#registration) in the system. - -> [!TIP] -> For common widget property transformation scenarios, see [our technical deep-dive guide](https://docs.kentico.com/x/transform_widget_properties_guides) in the Kentico documentation. - ### Migrate Pages to Widgets This migration allows you to migrate pages from the source instance as [widgets](https://docs.kentico.com/x/7gWiCQ) in the target instance. This migration can be used in the following ways: @@ -375,115 +404,82 @@ After implementing the content item director, you need to [register the director > [!TIP] > You can see a sample implementation in [SamplePageToWidgetDirector.cs](./CommunityMigrations/SamplePageToWidgetDirector.cs) or follow along with our complete practical example on [how to convert child pages to widgets](https://docs.kentico.com/x/convert_child_pages_to_widgets_guides) in the Kentico documentation. -### Custom Class Mappings - -You can customize class mappings to adjust the content model between the source instance and the target Xperience by Kentico instance. For example, you can merge multiple page types into a single content type, remodel page types as [reusable field scehams](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides), or migrate them to the [content hub](https://docs.kentico.com/x/barWCQ) as reusable content. - -1. Create a new class. -2. Add an `IServiceCollection` extension method. Use a separate method for every class mapping that you wish to configure. -3. Within the extension method, define a new `MultiClassMapping` object: - - ```csharp - var m = new MultiClassMapping(targetClassName, target => - { - // Target content type name - target.ClassName = "Acme.Article"; - // Database table name of the new type - target.ClassTableName = "Acme_Article"; - // Display name of the content type - target.ClassDisplayName = "Article"; - // Type of the class (specifies that the class is a content type) - target.ClassType = ClassType.CONTENT_TYPE; - // What the content type is used for (reusable content, pages, email, or headless) - target.ClassContentTypeType = ClassContentTypeType.WEBSITE; - }); - ``` - -4. Define a new primary key: - - ```csharp - m.BuildField("ArticleID").AsPrimaryKey(); - ``` - -5. Define individual fields of the new content type: +### Custom Child Links - ```csharp - // Builds a new title field - var title = m.BuildField("Title"); +This feature allows you to link child pages as referenced content items of a page converted to reusable content item. - // You can map any number of source fields. The migration creates items of the target data class for every item from a mapped source data class. - // The default migration is skipped for any data class / page type where you map at least one source field +This feature is available by means of content item director. - // Maps the "ArticleTitle" field from the source data class "Article.BlogPost" - // Sets the isTemplate parameter to true, which makes the new field inherit the source field definition as a template - // The field definition is migrated according to the migration tool's data type and form control/component mappings - title.SetFrom("Article.BlogPost", "ArticleTitle", true); - // Maps the "ArticleTitle" field from a second source data class "Article.NewsArticle" - // The isTemplate parameter is not set, so only the value is taken from this source field - title.SetFrom("Article.NewsArticle", "ArticleTitle"); +You can apply a simple general rule to link child pages e.g. in `Children` field or you can apply more elaborate rules. You can see samples of both approaches in [SampleChildLinkDirector.cs](./CommunityMigrations/SampleChildLinkDirector.cs) or follow along with our [guide to transfer page hierarchy to the Content hub](https://docs.kentico.com/x/transfer_page_hierarchy_to_content_hub_guides). - // You can modify the field definition, e.g., change the caption of the field - title.WithFieldPatch(f => f.Caption = "Article title"); - ``` +After implementing the content item director, you need to [register the director](#registration) in the system. -6. (*Optional*) You can add custom value conversions: +### Customize Field Migrations - ```csharp - var publishDate = m.BuildField("PublishDate"); - publishDate.SetFrom("Article.BlogPost", "BlogPostDate", true); - - // Uses value conversion to modify the field value - publishDate.ConvertFrom("Article.NewsArticle", "ArticleDateAsText", false, - (v, context) => - { - switch (context) - { - case ConvertorTreeNodeContext treeNodeContext: - // You can use the available TreeNode context here - // (var nodeGuid, int nodeSiteId, int? documentId, bool migratingFromVersionHistory) = treeNodeContext; - break; - default: - // No context is available (possibly when the tool is extended with other conversion possibilities) - break; - } +You can customize field migrations to control how fields are mapped for page types, modules, system objects, and forms. In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IFieldMigration` interface. Implement the following properties and methods required by the interface: - return v?.ToString() is { } av && !string.IsNullOrWhiteSpace(av) ? DateTime.Parse(av) : null; - }); - startDate.WithFieldPatch(f => f.Caption = "Event start date"); - ``` +- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. +- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current field. Use properties of the `FieldMigrationContext` object passed as an argument to the method to evaluate the condition. For each field, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. + - `SourceDataType` - A string property that specifies the [data type](https://docs.kentico.com/x/coJwCg) of the source field. + - `SourceFormControl` - A string property that specifies the [form control](https://docs.kentico.com/x/lAyRBg) used by the source field. + - `FieldName` - A string property that specifies the code name of the field. + - `SourceObjectContext` - An interface that can be used to check the context of the source object (e.g. page vs. form). +- `MigrateFieldDefinition` - Migrate the definition of the field. Use the `XElement` attribute to transform the field. +- `MigrateValue` - Migrate the value of the field. Use the source value and the `FieldMigrationContext` with the same parameters as described in `ShallMigrate`. -7. Complete the implementation by [registering the class mapping](#registration) in the dependency injection container. +You can see samples: -8. Ensure that your class mapping extension methods run during the startup of the migration tool. Call the methods from `UseCustomizations` in the [ServiceCollectionExtensions](/Migration.Tool.Extensions/ServiceCollectionExtensions.cs) class. +- [SampleTextMigration.cs](./CommunityMigrations/SampleTextMigration.cs) + - A sample migration with further explanations +- [AssetMigration.cs](./DefaultMigrations/AssetMigration.cs) + - An example of a usable migration -**Note**: Your mappings now replace the default migration functionality for all data classes (page types, custom tables or custom module classes) that you use as a source. Any class where you set at least one source field is affected. If you map only some fields from a source class, the remaining fields are not migrated at all. +After implementing the migration, you need to [register the migration](#registration) in the system. -If you need class mappings to alter several data classes in Kentico Xperience 13, consider [using AI tools to help you generate mappings quickly](https://docs.kentico.com/x/speed_up_remodeling_with_ai_guides). +### Customize Widget Migrations -#### Remodel Page Types as Reusable Field Schemas Guide +You can customize widget migration to change the widget to which source widgets are migrated in the target instance. In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IWidgetMigration` interface. Implement the following properties and methods required by the interface: -For an end-to-end example of how to extract common fields from two page types from Kentico Xperience 13 and move them to a [reusable field schema](https://docs.kentico.com/x/D4_OD) shared by both web page content types in Xperience by Kentico follow this [migration guide](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides) in the documentation. +- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. +- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current widget. Use properties of the `WidgetMigrationContext` and `WidgetIdentifier` objects passed as an argument to the method to evaluate the condition. For each widget, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. + - `WidgetMigrationContext.SiteId` - An integer property that specifies the ID of the site on which the widget was used in the source instance. + - `WidgetIdentifier.TypeIdentifier` - A string property that specifies the identifier of the widget. +- `MigrateWidget`- Migrate the widget data using the following properties: + - `identifier` - A `WidgetIdentifier` object, see `ShallMigrate` to see properties. + - `value` - A `JToken` object containing the deserialized value of the property. + - `context` - A `WidgetMigrationContext` object, see `ShallMigrate` to see properties. -Note that any usage of `ReusableSchemaBuilder` in custom class mappings cannot be combined together with the `Settings.CreateReusableFieldSchemaForClasses` configuration option. +You can see a sample: [SampleWidgetMigration.cs](./CommunityMigrations/SampleWidgetMigration.cs) -#### Sample Class Mappings +After implementing the migration, you need to [register the migration](#registration) in the system. -You can find sample class mappings in the [ClassMappingSample.cs](/Migration.Tool.Extensions/ClassMappings/ClassMappingSample.cs) file. +> [!TIP] +> For a complete end-to-end example, see our guide on [how to migrate widget data as reusable content](https://docs.kentico.com/x/migrate_widget_data_as_reusable_content_guides) in the Kentico documentation. -- `AddSimpleRemodelingSample` showcases how to change the mapping of a single page type -- `AddClassMergeSample` showcases how to merge two page types into a single content type -- `AddReusableRemodelingSample` showcases how to migrate a page type as reusable content +### Customize Widget Property Migrations +In the `Migration.Tool.Extensions/CommunityMigrations` folder, create a new file with a class that implements the `IWidgetPropertyMigration` interface. Implement the following properties and methods required by the interface: -### Custom Child Links +- `Rank` - An integer property that determines the order in which migrations are applied. Use a value lower than *100000*, as that is the value for system migrations. +- `ShallMigrate` - A boolean method that specifies whether the migration shall be applied for the current widget. Use properties of the `WidgetPropertyMigrationContext` and `propertyName` objects passed as an argument to the method to evaluate the condition. For each widget property, the migration with the lowest rank that returns `true` from the `ShallMigrate` method is used. + - `WidgetPropertyMigrationContext.SiteId` - An integer property that specifies the ID of the site on which the widget was used in the source instance. + - `WidgetPropertyMigrationContext.EditingFormControlModel` - An object representing the [form control](https://docs.kentico.com/x/lAyRBg) of the property. + - `propertyName` - A string property that specifies the identifier of the property. +- `MigrateWidgetProperty`- Migrate the widget property data using the following properties: + - `key` - Name of the property. + - `value` - A `JToken` object containing the deserialized value of the property. + - `context` - A `WidgetPropertyMigrationContext`. See `ShallMigrate` method to see the properties. -This feature allows you to link child pages as referenced content items of a page converted to reusable content item. +You can see samples: -This feature is available by means of content item director. +- [Path selector migration](./DefaultMigrations/WidgetPathSelectorMigration.cs) +- [Page selector migration](./DefaultMigrations/WidgetPageSelectorMigration.cs) +- [File selector migration](./DefaultMigrations/WidgetFileMigration.cs) -You can apply a simple general rule to link child pages e.g. in `Children` field or you can apply more elaborate rules. You can see samples of both approaches in [SampleChildLinkDirector.cs](./CommunityMigrations/SampleChildLinkDirector.cs) or follow along with our [guide to transfer page hierarchy to the Content hub](https://docs.kentico.com/x/transfer_page_hierarchy_to_content_hub_guides). +After implementing the migration, you need to [register the migration](#registration) in the system. -After implementing the content item director, you need to [register the director](#registration) in the system. +> [!TIP] +> For common widget property transformation scenarios, see [our technical deep-dive guide](https://docs.kentico.com/x/transform_widget_properties_guides) in the Kentico documentation. ## Registration diff --git a/README.md b/README.md index 02599083..9e3eb315 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ This repository contains the data migration tool and its technical reference doc - [Advanced upgrade deep dives](https://docs.kentico.com/x/upgrade_deep_dives_guides) - Developer-focused guides for customizing migrations and handling complex scenarios > [!IMPORTANT] -> When planning an upgrade, note special considerations for [deploying to production](https://docs.kentico.com/guides/architecture/upgrade-from-kx13/upgrade-faq#are-there-special-considerations-when-deploying-an-upgraded-project-to-production-for-the-first-time) and [deploying to SaaS](https://docs.kentico.com/guides/architecture/upgrade-from-kx13/upgrade-faq#are-there-special-considerations-when-performing-an-upgrade-using-xperience-by-kentico-saas). +> When planning an upgrade, note special considerations for [deploying to production](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-from-kx13/upgrade-faq#are-there-special-considerations-when-deploying-an-upgraded-project-to-production-for-the-first-time) and [deploying to SaaS](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-from-kx13/upgrade-faq#are-there-special-considerations-when-performing-an-upgrade-using-xperience-by-kentico-saas). ## Technical Documentation (This Repository) @@ -182,7 +182,7 @@ To report bugs, upgrade to the latest Migration Tool version before submitting i See [`SUPPORT.md`](https://github.com/Kentico/.github/blob/main/SUPPORT.md#full-support) for more information. > [!IMPORTANT] -> Before submitting a support ticket, please read about the [best practices on reporting Kentico Migration Tool and upgrade issues](https://docs.kentico.com/guides/architecture/upgrade-from-kx13/upgrade-faq#what-is-the-difference-between-the-documentation-in-the-github-repo-and-on-the-docs.kentico.com-site). +> Before submitting a support ticket, please read about the [best practices on reporting Kentico Migration Tool and upgrade issues](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-from-kx13/upgrade-faq#what-is-the-difference-between-the-documentation-in-the-github-repo-and-on-the-docs.kentico.com-site). ## Security From bf5233323992999bd278b5d0b83ece51c6d884b2 Mon Sep 17 00:00:00 2001 From: "MASTER\\DominikaG2" Date: Thu, 22 Jan 2026 15:03:55 -0500 Subject: [PATCH 2/3] Remove migration protocol path from the appsettings.json config --- Migration.Tool.CLI/appsettings.json | 1 - 1 file changed, 1 deletion(-) diff --git a/Migration.Tool.CLI/appsettings.json b/Migration.Tool.CLI/appsettings.json index a1f8604c..cbf0d3fc 100644 --- a/Migration.Tool.CLI/appsettings.json +++ b/Migration.Tool.CLI/appsettings.json @@ -16,7 +16,6 @@ } }, "Settings": { - "MigrationProtocolPath": "C:\\Logs\\protocol.txt", "KxConnectionString": "[TODO]", "KxCmsDirPath": "[TODO]", "XbyKDirPath": "[TODO]", From 51fe22d80173580636deaaa370c986fbc007ccff Mon Sep 17 00:00:00 2001 From: "MASTER\\DominikaG2" Date: Fri, 23 Jan 2026 21:41:45 -0500 Subject: [PATCH 3/3] Implement review suggestions --- Migration.Tool.CLI/README.md | 19 +++++++++++++++++++ Migration.Tool.Extensions/README.md | 17 +++++++---------- README.md | 2 +- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Migration.Tool.CLI/README.md b/Migration.Tool.CLI/README.md index ddd30507..8aa056d6 100644 --- a/Migration.Tool.CLI/README.md +++ b/Migration.Tool.CLI/README.md @@ -661,6 +661,25 @@ Add the options under the `Settings` section in the configuration file. } ``` +## Logging + +The migration tool uses [.NET logging](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging) with console and file output. Configure log levels and file path in the `Logging` section of `appsettings.json`: + +```json +"Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning" + }, + "pathFormat": "logs/log.txt" +} +``` + +- **Console** - Real-time progress with timestamps +- **Files** - Detailed logs at the specified path (default: `logs/log-.txt`) + +To use logging in custom migrations, inject `ILogger` into your class constructor. + ## Source instance API discovery > :warning: **Warning** – source instance API discovery is only available when migrating from Kentico Xperience 13. diff --git a/Migration.Tool.Extensions/README.md b/Migration.Tool.Extensions/README.md index 5bda7afe..d9f17011 100644 --- a/Migration.Tool.Extensions/README.md +++ b/Migration.Tool.Extensions/README.md @@ -145,7 +145,7 @@ The following sections provide detailed instructions for implementing each type ### Custom Class Mappings -You can customize class mappings to adjust the content model between the source instance and the target Xperience by Kentico instance. For example, you can merge multiple page types into a single content type, remodel page types as [reusable field scehams](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides), or migrate them to the [content hub](https://docs.kentico.com/x/barWCQ) as reusable content. +You can customize class mappings to adjust the content model between the source instance and the target Xperience by Kentico instance. For example, you can merge multiple page types into a single content type, remodel page types as [reusable field schemas](https://docs.kentico.com/x/remodel_page_types_as_reusable_field_schemas_guides), or migrate them to the [content hub](https://docs.kentico.com/x/barWCQ) as reusable content. 1. Create a new class. 2. Add an `IServiceCollection` extension method. Use a separate method for every class mapping that you wish to configure. @@ -287,7 +287,7 @@ Implement your decision logic based on available node properties (`NodeClassID`, #### Available Actions -##### `options.Drop()` +#### `options.Drop()` Skips migration of the linked page entirely. Use for temporary content, archived pages, or content that should be handled manually. #### `options.Materialize()` @@ -302,13 +302,10 @@ Creates a content item reference field in an ancestor page that points to the or #### Common Strategies -**Content Type-Based**: Use `NodeClassID` to look up the content type and apply different strategies based on page type. - -**Path-Based**: Filter by `NodeAliasPath` to handle different sections of your site (e.g., archive pages, temporary content). - -**Site-Specific**: Use `source.SourceSite.SiteName` to apply different rules for different sites in multi-site scenarios. - -**Contextual**: Combine node properties with ancestor analysis to make intelligent decisions about reference placement. +- **Content Type-Based**: Use `NodeClassID` to look up the content type and apply different strategies based on page type. +- **Path-Based**: Filter by `NodeAliasPath` to handle different sections of your site (e.g., archive pages, temporary content). +- **Site-Specific**: Use `source.SourceSite.SiteName` to apply different rules for different sites in multi-site scenarios. +- **Contextual**: Combine node properties with ancestor analysis to make intelligent decisions about reference placement. #### Important Considerations @@ -336,7 +333,7 @@ After implementing your linked page director, you need to [register the director - **Deferred processing**: Some linked pages may be processed in a second pass if their dependencies aren't ready **Debugging Tips:** -- Use logging to track which strategy is applied to each linked page +- Use [logging](../Migration.Tool.CLI/README.md#logging) to track which strategy is applied to each linked page - Verify that ancestor pages exist and have the expected structure ### Migrate Pages to Widgets diff --git a/README.md b/README.md index 9e3eb315..ac7cdd9f 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ For a lift-and-shift migration, use the migration tool's default configuration: --sites --custom-modules --users --settings-keys --page-types --pages --type-restrictions --contact-management --forms --media-libraries --data-protection --custom-tables --members --categories ``` -5. **Review results** - Check console output and log files for issues or manual steps: +5. **Review results** - Check console [output and log files](./Migration.Tool.CLI/README.md#logging) for issues or manual steps: - **Console** shows real-time progress and results - **Log files** capture detailed execution logs (`logs\log-.txt`)