From d74c9f9ed9c943dc54111ce763644b6f22816616 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Fri, 19 Jul 2024 17:16:35 +0200 Subject: [PATCH 01/35] Restructure import/export section and add Grid layout migrator classes --- .../deployment-workflow/import-export-v7.md | 228 ++++++++ .../deployment-workflow/import-export.md | 509 +----------------- .../import-with-migrations.md | 288 ++++++++++ 3 files changed, 524 insertions(+), 501 deletions(-) create mode 100644 13/umbraco-deploy/deployment-workflow/import-export-v7.md create mode 100644 13/umbraco-deploy/deployment-workflow/import-with-migrations.md diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md new file mode 100644 index 00000000000..c3629da6a8f --- /dev/null +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -0,0 +1,228 @@ +--- +meta.Title: Migrating from Umbraco 7 +description: How to export content and schema from Umbraco 7 and import into a newer version +--- + +### Migrating from Umbraco 7 + +The import and export feature is available from Deploy 4.9 (which supports Umbraco 8), 10.3, 12.1 and 13.0. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. + +We can use this feature to help migrate from Umbraco 7 to a supported major version using additional logic added to the Deploy Contrib project. + +#### Exporting Umbraco 7 content and schema + +We can generate an export archive in the same format as used by the import/export feature by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. + +This is possible via code, by temporarily applying a composer to an Umbraco 7 project to generate the export archive on start-up: + + +
+DeployExportApplicationHandler.cs (export Umbraco 7 content and schema to ZIP archive) + +```csharp +using System; +using System.Linq; +using System.Web.Hosting; +using Umbraco.Core; +using Umbraco.Deploy; +using UmbracoDeploy.Contrib.Export; + +public class DeployExportApplicationHandler : ApplicationEventHandler +{ + protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + // Set a default value connector that doesn't use object type prefixes + DefaultValueConnector.SetDefault(); + + // Run export after Deploy has started + DeployComponent.Started += (sender, e) => DeployStarted(); + } + + protected void DeployStarted() + { + var udis = new[] + { + // Export all content + Constants.UdiEntityType.Document, + Constants.UdiEntityType.DocumentBlueprint, + Constants.UdiEntityType.Media, + // Export all forms data + Constants.UdiEntityType.FormsForm, + Constants.UdiEntityType.FormsDataSource, + Constants.UdiEntityType.FormsPreValue + }.Select(Udi.Create); + + var dependencyEntityTypes = new[] + { + // Include all related schema + Constants.UdiEntityType.DataType, + Constants.UdiEntityType.DataTypeContainer, + Constants.UdiEntityType.DocumentType, + Constants.UdiEntityType.DocumentTypeContainer, + Constants.UdiEntityType.MediaType, + Constants.UdiEntityType.MediaTypeContainer, + Constants.UdiEntityType.MemberType, + Constants.UdiEntityType.MemberGroup, + Constants.UdiEntityType.Macro, + Constants.UdiEntityType.DictionaryItem, + Constants.UdiEntityType.Template, + Constants.UdiEntityType.Language, + // Include all related files + Constants.UdiEntityType.MediaFile, + Constants.UdiEntityType.MacroScript, + Constants.UdiEntityType.PartialView, + Constants.UdiEntityType.PartialViewMacro, + Constants.UdiEntityType.Script, + Constants.UdiEntityType.Stylesheet, + Constants.UdiEntityType.UserControl, + Constants.UdiEntityType.TemplateFile, + Constants.UdiEntityType.Xslt + }; + + // Create export + var zipArchiveFilePath = HostingEnvironment.MapPath("~/data/" + "export-" + Guid.NewGuid() + ".zip"); + ArtifactExportService.ExportArtifacts(udis, Constants.DeploySelector.ThisAndDescendants, zipArchiveFilePath, dependencyEntityTypes); + } +} +``` + +
+ +#### Importing Umbraco 7 content and schema + +To import this archive into a newer Umbraco project, you need to install either of these packages: + +- `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 +- `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later +Then you need to configure the legacy artifact type resolver and migratory. + +Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: + +- Moving the pre-values of data types to the configuration property; +- Moving the invariant release and expire dates of content to the (culture variant) schedule property; +- Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; +- Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: + - `Umbraco.CheckBoxList` (pre-values to value list) + - `Umbraco.ColorPickerAlias` to `Umbraco.ColorPicker` (pre-values to value list) + - `Umbraco.ContentPicker2` to `Umbraco.ContentPicker` (removes invalid start node ID) + - `Umbraco.ContentPickerAlias` to `Umbraco.ContentPicker` (removes invalid start node ID) + - `Umbraco.Date` to `Umbraco.DateTime` + - `Umbraco.DropDown` to `Umbraco.DropDownListFlexible` (pre-values to value list, single item select) + - `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.DropdownlistMultiplePublishKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.DropdownlistPublishingKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to single item select) + - `Umbraco.DropDownMultiple` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.MediaPicker2` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to single item select) + - `Umbraco.MediaPicker` (removes invalid start node ID) + - `Umbraco.MemberPicker2` to `Umbraco.MemberPicker` + - `Umbraco.MultiNodeTreePicker2` to `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) + - `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) + - `Umbraco.MultipleMediaPicker` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to multiple item select) + - `Umbraco.NoEdit` to `Umbraco.Label` + - `Umbraco.RadioButtonList` (pre-values to value list, change database type from integer to nvarchar) + - `Umbraco.RelatedLinks2` to `Umbraco.MultiUrlPicker` + - `Umbraco.RelatedLinks` to `Umbraco.MultiUrlPicker` + - `Umbraco.Textbox` to `Umbraco.TextBox` + - `Umbraco.TextboxMultiple` to `Umbraco.TextArea` + - `Umbraco.TinyMCEv3` to `Umbraco.TinyMCE` +- Migrating pre-value property values for: + - `Umbraco.CheckBoxList` + - `Umbraco.DropDown.Flexible` + - `Umbraco.RadioButtonList` + +The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified document type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. + +
+LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Contrib.Migrators.Legacy; + +internal class LegacyImportComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactTypeResolvers() + .AddLegacyTypeResolver(); + + builder.DeployArtifactMigrators() + .AddLegacyMigrators() + .Append(); + } + + private class ElementTypeArtifactMigrator : ElementTypeArtifactMigratorBase + { + public ElementTypeArtifactMigrator() + : base("testElement") + { } + } +} +``` + +
+ +{% hint style="info" %} +It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog), followed by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them, so this ensures the schema is completely imported before any content is processed. +{% endhint %} + +#### Obtaining Umbraco Deploy for Umbraco 7 + +Umbraco Deploy for Umbraco 7 is no longer supported and was only available on Umbraco Cloud. It was not released for use on-premise. + +As such if you are looking to migrate from an Umbraco Cloud project running on Umbraco 7, you already have Umbraco Deploy installed. + +If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. + +The export feature can be used without a license. + +{% hint style="info" %} + +A license is required for the Umbraco project you are importing into - whether that's a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. + +{% endhint %} + +Use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. + +1. Download the required `dll` files for Umbraco Deploy for Umbraco 7 from the following links: + +- [Umbraco Deploy v2.1.6](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-release/UmbracoDeploy.v2.1.6.zip): Latest Deploy Version 2 release for Umbraco CMS Version 7 (officially for use on Cloud) +- [Umbraco Deploy Contrib v2.0.0](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-contrib-release/UmbracoDeploy.Contrib.2.0.0.zip): Latest/only Deploy Contrib Version 2 +- [Umbraco Deploy Export v2.0.0](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export): For exporting all content/schema in Version 7 + +2. Install Umbraco Deploy with the Contrib and Export extensions. + +- Install `Umbraco Deploy`, `Deploy.Contrib`, and `Deploy.Export` by copying the downloaded `.dll` files into your Umbraco 7 site. +- When copying the files over from `Umbraco Deploy` you should not overwrite the following files (if you already had Umbraco Deploy installed): + +```csharp + Config/UmbracoDeploy.config + Config/UmbracoDeploy.Settings.config +``` + +- Run the project to make sure it runs without any errors + +3. Update the `web.config` file with the required references for Umbraco Deploy: + +{% code title="web.config" lineNumbers="true" %} + +```xml + + + +
+
+ + + + + + + +``` + +{% endcode %} + +4. Export Content. + +- **Export** your content, schema, and files to zip. \ No newline at end of file diff --git a/13/umbraco-deploy/deployment-workflow/import-export.md b/13/umbraco-deploy/deployment-workflow/import-export.md index 427378a3c14..65d14f29aae 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export.md +++ b/13/umbraco-deploy/deployment-workflow/import-export.md @@ -38,11 +38,11 @@ Umbraco Deploy will then serialize all the selected items to individual files, a After the download, you should also delete the archive file from the server. You can do this immediately via the _Delete_ button available in the dialog. -![Export dialog complete](../../../10/umbraco-deploy/deployment-workflow/images//export-dialog-complete.png) +![Export dialog complete](../../../10/umbraco-deploy/deployment-workflow/images/export-dialog-complete.png) If you miss doing this, you can also clean up archive files from the Umbraco Deploy dashboard in the _Settings_ section. -![Delete exports](../../../10/umbraco-deploy/deployment-workflow/images//delete-exports.png) +![Delete exports](../../../10/umbraco-deploy/deployment-workflow/images/delete-exports.png) {% hint style="info" %} The exported archive files are saved to the Umbraco temp folder in the `Deploy\Export` sub-directory. This is a temporary (non-persistent) location, local to the backoffice server and therefore shouldn't be used for long-term storage of exports. You can also only download the file from the export dialog in the backoffice. @@ -52,7 +52,7 @@ The exported archive files are saved to the Umbraco temp folder in the `Deploy\E Having previously exported content and schema to a zip file, you can import this into a new environment. -![Import dialog](../../../10/umbraco-deploy/deployment-workflow/images//import-dialog.png) +![Import dialog](../../../10/umbraco-deploy/deployment-workflow/images/import-dialog.png) You can upload the file via the browser. @@ -63,518 +63,25 @@ Deploy does not touch the default maximum upload size, but you can [configure th On Umbraco Cloud, the upload size limit is 500 MB. {% endhint %} -![Import dialog step 2](../../../10/umbraco-deploy/deployment-workflow/images//import-dialog-2.png) +![Import dialog step 2](../../../10/umbraco-deploy/deployment-workflow/images/import-dialog-2.png) We validate the file before importing. Schema items that content depends on must either be in the upload itself or already exist on the target environment with the same details. If there are any issues that mean the import cannot proceed, it will be reported. You may also be given warnings for review. You can choose to ignore these and proceed if they aren't relevant to the action you are carrying out. The import then proceeds, processing all the items provided in the zip file. -![Import dialog step 3](../../../10/umbraco-deploy/deployment-workflow/images//import-dialog-3.png) +![Import dialog step 3](../../../10/umbraco-deploy/deployment-workflow/images/import-dialog-3.png) Once complete or on close of the dialog, the imported file will be deleted from the server. If this is missed, perhaps via a closed browser, you can also delete archive files from the Umbraco Deploy dashboard in the _Settings_ section. ## Migrating whilst importing -As well as importing the content and schema directly, we also provide support for modifying the items as part of the process. +It is possible to migrate schema and content whilist importing, e.g. to change Data Type using Nested Content into the Block List and ensure all content data is imported in the correct Block Editor format. -For example, you may have taken an export from an Umbraco 8 site, and are looking to import it into a newer major version. In this situation, most content and schema will carry over without issue. However, you may have some items that are no longer compatible. Usually this is due to a property editor - either a built-in Umbraco one or one provided by a package. These may no longer be available in the new version. - -Often though there is a similar replacement. Using Deploy's import feature we can transform the exported content for the obsolete property into that used by the new one during the import. The migration to a content set compatible with the new versions can then be completed. - -For example, we can migrate from a Nested Content property in Umbraco 8 to a Block List in Umbraco 13. - -We provide the necessary migration hooks for this to happen, divided into two types - **artifact migrators** and **property migrators**. - -### Artifact migrators - -Artifact migrators work by transforming the serialized artifact of any imported artifact, via two interfaces: - -- `IArtifactMigrator` - where the migration occurs at the artifact property level -- `IArtifactJsonMigrator` - where the migration occurs at the lower level of transforming the serialized JSON itself. - -Implementations to handle common migrations of data types from obsoleted property editors are available: - -- `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a datatype from using the legacy media picker to the current version of this property editor -- `ReplaceNestedContentDataTypeArtifactMigrator` - migrated from a datatype based on the obsolete nested content property editor to the block list. - -We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. - -- `ArtifactMigratorBase` - migrates the artifact of the specified type -- `DataTypeArtifactMigratorBase` - migrates Data Type artifacts -- `ReplaceDataTypeArtifactMigratorBase` - migrates a Data Type from one property editor to another -- `ArtifactJsonMigratorBase` - migrates the JSON of the specified artifact type - -### Property migrators - -Property migrators work to transform the content property data itself. They are used in the Deploy content connectors (documents, media and members) when the property editor is changed during an import: - -Again we have an interface: - -- `IPropertyTypeMigrator` - -Implementations for common migrations: - -- `MediaPickerPropertyTypeMigrator` -- `NestedContentPropertyTypeMigrator` - -And a base type to help you build your own migrations: - -- `PropertyTypeMigratorBase` - -{% hint style="info" %} -Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary (containing editor aliases for each content property) stored in the content artifact to the current Content Type/Data Type configuration. -{% endhint %} - -### Registering migrators - -Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. - -You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: - -```csharp -using Umbraco.Cms.Core.Composing; -using Umbraco.Deploy.Core.Migrators; -using Umbraco.Deploy.Infrastructure.Migrators; - -internal class ArtifactMigratorsComposer : IComposer -{ - public void Compose(IUmbracoBuilder builder) - { - builder.DeployArtifactMigrators() - .Append() - .Append(); - - builder.DeployPropertyTypeMigrators() - .Append() - .Append(); - } -} - ``` - -### A custom migration example - Nested Content to Block List - -In order to help writing your own migrations, we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. - -First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: - -
-ReplaceNestedContentDataTypeArtifactMigrator.cs (migrate Nested Content Data Type to Block List) - -```csharp -using System.Globalization; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Core.Serialization; -using Umbraco.Cms.Core.Services; -using Umbraco.Deploy.Infrastructure.Artifacts; - -public class ReplaceNestedContentDataTypeArtifactMigrator : ReplaceDataTypeArtifactMigratorBase -{ - private readonly IContentTypeService _contentTypeService; - - public ReplaceNestedContentDataTypeArtifactMigrator(PropertyEditorCollection propertyEditors, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, IContentTypeService contentTypeService) - : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList, propertyEditors, configurationEditorJsonSerializer) - => _contentTypeService = contentTypeService; - - protected override BlockListConfiguration? MigrateConfiguration(NestedContentConfiguration configuration) - { - var blockListConfiguration = new BlockListConfiguration() - { - UseInlineEditingAsDefault = true // Similar to how Nested Content looks/works - }; - - if (configuration.MinItems > 0) - { - blockListConfiguration.ValidationLimit.Min = configuration.MinItems; - } - - if (configuration.MaxItems > 0) - { - blockListConfiguration.ValidationLimit.Max = configuration.MaxItems; - } - - if (configuration.ContentTypes is not null) - { - var blocks = new List(); - foreach (NestedContentConfiguration.ContentType nestedContentType in configuration.ContentTypes) - { - if (nestedContentType.Alias is not null && - GetContentTypeKey(nestedContentType.Alias) is Guid contentTypeKey) - { - blocks.Add(new BlockListConfiguration.BlockConfiguration() - { - Label = nestedContentType.Template, - ContentElementTypeKey = contentTypeKey - }); - } - } - - blockListConfiguration.Blocks = blocks.ToArray(); - } - - if (blockListConfiguration.ValidationLimit.Min == 1 && - blockListConfiguration.ValidationLimit.Max == 1 && - blockListConfiguration.Blocks.Length == 1) - { - blockListConfiguration.UseSingleBlockMode = true; - } - - return blockListConfiguration; - } - - protected virtual Guid? GetContentTypeKey(string alias) - { - if (_contentTypeService.Get(alias) is IContentType contentTypeByAlias) - { - return contentTypeByAlias.Key; - } - - // New content types are initially saved by Deploy with a custom postfix (to avoid duplicate aliases), so try to get the first matching item - string aliasPrefix = alias + "__"; - foreach (IContentType contentType in _contentTypeService.GetAll()) - { - if (contentType.Alias.StartsWith(aliasPrefix) && - int.TryParse(contentType.Alias[aliasPrefix.Length..], NumberStyles.HexNumber, null, out _)) - { - return contentType.Key; - } - } - - return null; - } -} -``` - -
- -And secondly we have the property migrator that handles restructuring the content property data: - -
-NestedContentPropertyTypeMigrator.cs (migrate Nested Content property data to Block List) - -```csharp -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Deploy; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.Blocks; -using Umbraco.Cms.Core.Services; -using Umbraco.Deploy.Core; -using Umbraco.Deploy.Core.Migrators; -using Umbraco.Deploy.Infrastructure.Extensions; - -public class NestedContentPropertyTypeMigrator : PropertyTypeMigratorBase -{ - private readonly ILogger _logger; - private readonly IContentTypeService _contentTypeService; - - public NestedContentPropertyTypeMigrator(ILogger logger, IContentTypeService contentTypeService) - : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList) - { - _logger = logger; - _contentTypeService = contentTypeService; - } - - public override object? Migrate(IPropertyType propertyType, object? value, IDictionary propertyEditorAliases, IContextCache contextCache) - { - if (value is not string stringValue || !stringValue.TryParseJson(out NestedContentItem[]? nestedContentItems) || nestedContentItems is null) - { - if (value is not null) - { - _logger.LogWarning("Skipping migration of Nested Content items ({PropertyTypeAlias}), because value could not be parsed: {Value}.", propertyType.Alias, value); - } - - return null; - } - - var layoutItems = new List(); - var contentData = new List(); - - foreach (NestedContentItem nestedContentItem in nestedContentItems) - { - IContentType? contentType = contextCache.GetContentTypeByAlias(_contentTypeService, nestedContentItem.ContentTypeAlias); - if (contentType is null) - { - _logger.LogWarning("Skipping migration of Nested Content item ({Id}), because content type does not exist: {ContentTypeAlias}.", nestedContentItem.Id, nestedContentItem.ContentTypeAlias); - continue; - } - - var udi = new GuidUdi(Constants.UdiEntityType.Element, nestedContentItem.Id); - - layoutItems.Add(new BlockListLayoutItem() - { - ContentUdi = udi - }); - - contentData.Add(new BlockItemData() - { - Udi = udi, - ContentTypeKey = contentType.Key, - RawPropertyValues = nestedContentItem.RawPropertyValues - }); - } - - var blockValue = new BlockValue() - { - Layout = new Dictionary() - { - { Constants.PropertyEditors.Aliases.BlockList, JToken.FromObject(layoutItems) } - }, - ContentData = contentData - }; - - return JsonConvert.SerializeObject(blockValue, Formatting.None); - } - - internal class NestedContentItem - { - [JsonProperty("key")] - public Guid Id { get; set; } = Guid.NewGuid(); // Ensure a unique key is set, even if the JSON doesn't have one - - [JsonProperty("name")] - public string? Name { get; set; } - - [JsonIgnore] - public object? PropType { get; set; } // Ensure this property is ignored - - [JsonProperty("ncContentTypeAlias")] - public string ContentTypeAlias { get; set; } = null!; - - [JsonExtensionData] - public Dictionary RawPropertyValues { get; set; } = null!; - } -} -``` - -
- -Moving forward, other migrators may be built by HQ or the community for property editors found in community packages. We'll make them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib) via the `Umbraco.Deploy.Contrib` package. +Deploy contains base classes and implementations to handle common migrations that need to be registered in code, as explained in [Import with migrations](./import-with-migrations.md). ### Migrating from Umbraco 7 -The import and export feature is available from Deploy 4.9 (which supports Umbraco 8), 10.3, 12.1 and 13.0. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. - -We can use this feature to help migrate from Umbraco 7 to a supported major version using additional logic added to the Deploy Contrib project. - -#### Exporting Umbraco 7 content and schema - -We can generate an export archive in the same format as used by the import/export feature by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. - -This is possible via code, by temporarily applying a composer to an Umbraco 7 project to generate the export archive on start-up: - -
-DeployExportApplicationHandler.cs (export Umbraco 7 content and schema to ZIP archive) - -```csharp -using System; -using System.Linq; -using System.Web.Hosting; -using Umbraco.Core; -using Umbraco.Deploy; -using UmbracoDeploy.Contrib.Export; - -public class DeployExportApplicationHandler : ApplicationEventHandler -{ - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - // Set a default value connector that doesn't use object type prefixes - DefaultValueConnector.SetDefault(); - - // Run export after Deploy has started - DeployComponent.Started += (sender, e) => DeployStarted(); - } - - protected void DeployStarted() - { - var udis = new[] - { - // Export all content - Constants.UdiEntityType.Document, - Constants.UdiEntityType.DocumentBlueprint, - Constants.UdiEntityType.Media, - // Export all forms data - Constants.UdiEntityType.FormsForm, - Constants.UdiEntityType.FormsDataSource, - Constants.UdiEntityType.FormsPreValue - }.Select(Udi.Create); - - var dependencyEntityTypes = new[] - { - // Include all related schema - Constants.UdiEntityType.DataType, - Constants.UdiEntityType.DataTypeContainer, - Constants.UdiEntityType.DocumentType, - Constants.UdiEntityType.DocumentTypeContainer, - Constants.UdiEntityType.MediaType, - Constants.UdiEntityType.MediaTypeContainer, - Constants.UdiEntityType.MemberType, - Constants.UdiEntityType.MemberGroup, - Constants.UdiEntityType.Macro, - Constants.UdiEntityType.DictionaryItem, - Constants.UdiEntityType.Template, - Constants.UdiEntityType.Language, - // Include all related files - Constants.UdiEntityType.MediaFile, - Constants.UdiEntityType.MacroScript, - Constants.UdiEntityType.PartialView, - Constants.UdiEntityType.PartialViewMacro, - Constants.UdiEntityType.Script, - Constants.UdiEntityType.Stylesheet, - Constants.UdiEntityType.UserControl, - Constants.UdiEntityType.TemplateFile, - Constants.UdiEntityType.Xslt - }; - - // Create export - var zipArchiveFilePath = HostingEnvironment.MapPath("~/data/" + "export-" + Guid.NewGuid() + ".zip"); - ArtifactExportService.ExportArtifacts(udis, Constants.DeploySelector.ThisAndDescendants, zipArchiveFilePath, dependencyEntityTypes); - } -} -``` - -
- -#### Importing Umbraco 7 content and schema - -To import this archive into a newer Umbraco project, you need to install either of these packages: - -- `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 -- `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later -Then you need to configure the legacy artifact type resolver and migratory. - -Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: - -- Moving the pre-values of data types to the configuration property; -- Moving the invariant release and expire dates of content to the (culture variant) schedule property; -- Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; -- Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: - - `Umbraco.CheckBoxList` (pre-values to value list) - - `Umbraco.ColorPickerAlias` to `Umbraco.ColorPicker` (pre-values to value list) - - `Umbraco.ContentPicker2` to `Umbraco.ContentPicker` (removes invalid start node ID) - - `Umbraco.ContentPickerAlias` to `Umbraco.ContentPicker` (removes invalid start node ID) - - `Umbraco.Date` to `Umbraco.DateTime` - - `Umbraco.DropDown` to `Umbraco.DropDownListFlexible` (pre-values to value list, single item select) - - `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - - `Umbraco.DropdownlistMultiplePublishKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - - `Umbraco.DropdownlistPublishingKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to single item select) - - `Umbraco.DropDownMultiple` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - - `Umbraco.MediaPicker2` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to single item select) - - `Umbraco.MediaPicker` (removes invalid start node ID) - - `Umbraco.MemberPicker2` to `Umbraco.MemberPicker` - - `Umbraco.MultiNodeTreePicker2` to `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) - - `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) - - `Umbraco.MultipleMediaPicker` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to multiple item select) - - `Umbraco.NoEdit` to `Umbraco.Label` - - `Umbraco.RadioButtonList` (pre-values to value list, change database type from integer to nvarchar) - - `Umbraco.RelatedLinks2` to `Umbraco.MultiUrlPicker` - - `Umbraco.RelatedLinks` to `Umbraco.MultiUrlPicker` - - `Umbraco.Textbox` to `Umbraco.TextBox` - - `Umbraco.TextboxMultiple` to `Umbraco.TextArea` - - `Umbraco.TinyMCEv3` to `Umbraco.TinyMCE` -- Migrating pre-value property values for: - - `Umbraco.CheckBoxList` - - `Umbraco.DropDown.Flexible` - - `Umbraco.RadioButtonList` - -The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified document type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. - -
-LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) - -```csharp -using Umbraco.Cms.Core.Composing; -using Umbraco.Deploy.Contrib.Migrators.Legacy; - -internal class LegacyImportComposer : IComposer -{ - public void Compose(IUmbracoBuilder builder) - { - builder.DeployArtifactTypeResolvers() - .AddLegacyTypeResolver(); - - builder.DeployArtifactMigrators() - .AddLegacyMigrators() - .Append(); - } - - private class ElementTypeArtifactMigrator : ElementTypeArtifactMigratorBase - { - public ElementTypeArtifactMigrator() - : base("testElement") - { } - } -} -``` - -
- -{% hint style="info" %} -It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog), followed by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them, so this ensures the schema is completely imported before any content is processed. -{% endhint %} - -#### Obtaining Umbraco Deploy for Umbraco 7 - -Umbraco Deploy for Umbraco 7 is no longer supported and was only available on Umbraco Cloud. It was not released for use on-premise. - -As such if you are looking to migrate from an Umbraco Cloud project running on Umbraco 7, you already have Umbraco Deploy installed. - -If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. - -The export feature can be used without a license. - -{% hint style="info" %} - -A license is required for the Umbraco project you are importing into - whether that's a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. - -{% endhint %} - -Use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. - -1. Download the required `dll` files for Umbraco Deploy for Umbraco 7 from the following links: - -- [Umbraco Deploy v2.1.6](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-release/UmbracoDeploy.v2.1.6.zip): Latest Deploy Version 2 release for Umbraco CMS Version 7 (officially for use on Cloud) -- [Umbraco Deploy Contrib v2.0.0](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-contrib-release/UmbracoDeploy.Contrib.2.0.0.zip): Latest/only Deploy Contrib Version 2 -- [Umbraco Deploy Export v2.0.0](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export): For exporting all content/schema in Version 7 - -2. Install Umbraco Deploy with the Contrib and Export extensions. - -- Install `Umbraco Deploy`, `Deploy.Contrib`, and `Deploy.Export` by copying the downloaded `.dll` files into your Umbraco 7 site. -- When copying the files over from `Umbraco Deploy` you should not overwrite the following files (if you already had Umbraco Deploy installed): - -```csharp - Config/UmbracoDeploy.config - Config/UmbracoDeploy.Settings.config -``` - -- Run the project to make sure it runs without any errors - -3. Update the `web.config` file with the required references for Umbraco Deploy: - -{% code title="web.config" lineNumbers="true" %} - -```xml - - - -
-
- - - - - - - -``` - -{% endcode %} - -4. Export Content. - -- **Export** your content, schema, and files to zip. +Although the import and export feature is not available in Deploy 2 for Umbraco 7, we have released a package to allow creating an export. This needs to be done in code and requires additional legacy migrators to be able to import this into a newer version again, as explained in [Migrating from Umbraco 7](./import-export-v7.md). ## Service details (programmatically importing and exporting) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md new file mode 100644 index 00000000000..509f24fc1cd --- /dev/null +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -0,0 +1,288 @@ +--- +meta.Title: Import with migrations in Umbraco Deploy +description: How to import content and schema while migrating them into newer alternatives +--- + +# Import with migrations + +As well as importing the content and schema directly, we also provide support for modifying the items as part of the process. + +For example, you may have taken an export from an Umbraco 8 site, and are looking to import it into a newer major version. In this situation, most content and schema will carry over without issue. However, you may have some items that are no longer compatible. Usually this is due to a property editor - either a built-in Umbraco one or one provided by a package. These may no longer be available in the new version. + +Often though there is a similar replacement. Using Deploy's import feature we can transform the exported content for the obsolete property into that used by the new one during the import. The migration to a content set compatible with the new versions can then be completed. + +For example, we can migrate from a Nested Content property in Umbraco 8 to a Block List in Umbraco 13. + +We provide the necessary migration hooks for this to happen, divided into two types - **artifact migrators** and **property migrators**. + +### Artifact migrators + +Artifact migrators work by transforming the serialized artifact of any imported artifact, via two interfaces: + +- `IArtifactMigrator` - where the migration occurs at the artifact property level +- `IArtifactJsonMigrator` - where the migration occurs at the lower level of transforming the serialized JSON itself. + +Implementations to handle common migrations of data types from obsoleted property editors are available: + +- `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a Data Type from using the legacy Media Picker to the current version of this property editor +- `ReplaceNestedContentDataTypeArtifactMigrator` - migrates a Data Type based on the obsolete Nested Content property editor to the Block List +- `ReplaceGridDataTypeArtifactMigrator` - migrates a Data Type based on the legacy Grid layout into the Block Grid + +We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. + +- `ArtifactMigratorBase` - migrates the artifact of the specified type +- `DataTypeArtifactMigratorBase` - migrates Data Type artifacts +- `ReplaceDataTypeArtifactMigratorBase` - migrates a Data Type from one property editor to another +- `ArtifactJsonMigratorBase` - migrates the JSON of the specified artifact type +- `ReplaceGridDataTypeArtifactMigratorBase` - migrates a Data Type based on the legacy Grid layout into the Block Grid + +### Property migrators + +Property migrators work to transform the content property data itself. They are used in the Deploy content connectors (documents, media and members) when the property editor is changed during an import: + +Again we have an interface: + +- `IPropertyTypeMigrator` + +Implementations for common migrations: + +- `MediaPickerPropertyTypeMigrator` +- `NestedContentPropertyTypeMigrator` +- `GridPropertyTypeMigrator` + +And a base type to help you build your own migrations: + +- `PropertyTypeMigratorBase` +- `GridPropertyTypeMigratorBase` + +{% hint style="info" %} +Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary (containing editor aliases for each content property) stored in the content artifact to the current Content Type/Data Type configuration. +{% endhint %} + +### Registering migrators + +Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. + +You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Core.Migrators; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal class ArtifactMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append() + .Append(); + } +} + ``` + +### A custom migration example - Nested Content to Block List + +In order to help writing your own migrations, we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. + +First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: + +
+ReplaceNestedContentDataTypeArtifactMigrator.cs (migrate Nested Content Data Type to Block List) + +```csharp +using System.Globalization; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Deploy.Infrastructure.Artifacts; + +public class ReplaceNestedContentDataTypeArtifactMigrator : ReplaceDataTypeArtifactMigratorBase +{ + private readonly IContentTypeService _contentTypeService; + + public ReplaceNestedContentDataTypeArtifactMigrator(PropertyEditorCollection propertyEditors, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, IContentTypeService contentTypeService) + : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList, propertyEditors, configurationEditorJsonSerializer) + => _contentTypeService = contentTypeService; + + protected override BlockListConfiguration? MigrateConfiguration(NestedContentConfiguration configuration) + { + var blockListConfiguration = new BlockListConfiguration() + { + UseInlineEditingAsDefault = true // Similar to how Nested Content looks/works + }; + + if (configuration.MinItems > 0) + { + blockListConfiguration.ValidationLimit.Min = configuration.MinItems; + } + + if (configuration.MaxItems > 0) + { + blockListConfiguration.ValidationLimit.Max = configuration.MaxItems; + } + + if (configuration.ContentTypes is not null) + { + var blocks = new List(); + foreach (NestedContentConfiguration.ContentType nestedContentType in configuration.ContentTypes) + { + if (nestedContentType.Alias is not null && + GetContentTypeKey(nestedContentType.Alias) is Guid contentTypeKey) + { + blocks.Add(new BlockListConfiguration.BlockConfiguration() + { + Label = nestedContentType.Template, + ContentElementTypeKey = contentTypeKey + }); + } + } + + blockListConfiguration.Blocks = blocks.ToArray(); + } + + if (blockListConfiguration.ValidationLimit.Min == 1 && + blockListConfiguration.ValidationLimit.Max == 1 && + blockListConfiguration.Blocks.Length == 1) + { + blockListConfiguration.UseSingleBlockMode = true; + } + + return blockListConfiguration; + } + + protected virtual Guid? GetContentTypeKey(string alias) + { + if (_contentTypeService.Get(alias) is IContentType contentTypeByAlias) + { + return contentTypeByAlias.Key; + } + + // New content types are initially saved by Deploy with a custom postfix (to avoid duplicate aliases), so try to get the first matching item + string aliasPrefix = alias + "__"; + foreach (IContentType contentType in _contentTypeService.GetAll()) + { + if (contentType.Alias.StartsWith(aliasPrefix) && + int.TryParse(contentType.Alias[aliasPrefix.Length..], NumberStyles.HexNumber, null, out _)) + { + return contentType.Key; + } + } + + return null; + } +} +``` + +
+ +And secondly we have the property migrator that handles restructuring the content property data: + +
+NestedContentPropertyTypeMigrator.cs (migrate Nested Content property data to Block List) + +```csharp +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Deploy; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Blocks; +using Umbraco.Cms.Core.Services; +using Umbraco.Deploy.Core; +using Umbraco.Deploy.Core.Migrators; +using Umbraco.Deploy.Infrastructure.Extensions; + +public class NestedContentPropertyTypeMigrator : PropertyTypeMigratorBase +{ + private readonly ILogger _logger; + private readonly IContentTypeService _contentTypeService; + + public NestedContentPropertyTypeMigrator(ILogger logger, IContentTypeService contentTypeService) + : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList) + { + _logger = logger; + _contentTypeService = contentTypeService; + } + + public override object? Migrate(IPropertyType propertyType, object? value, IDictionary propertyEditorAliases, IContextCache contextCache) + { + if (value is not string stringValue || !stringValue.TryParseJson(out NestedContentItem[]? nestedContentItems) || nestedContentItems is null) + { + if (value is not null) + { + _logger.LogWarning("Skipping migration of Nested Content items ({PropertyTypeAlias}), because value could not be parsed: {Value}.", propertyType.Alias, value); + } + + return null; + } + + var layoutItems = new List(); + var contentData = new List(); + + foreach (NestedContentItem nestedContentItem in nestedContentItems) + { + IContentType? contentType = contextCache.GetContentTypeByAlias(_contentTypeService, nestedContentItem.ContentTypeAlias); + if (contentType is null) + { + _logger.LogWarning("Skipping migration of Nested Content item ({Id}), because content type does not exist: {ContentTypeAlias}.", nestedContentItem.Id, nestedContentItem.ContentTypeAlias); + continue; + } + + var udi = new GuidUdi(Constants.UdiEntityType.Element, nestedContentItem.Id); + + layoutItems.Add(new BlockListLayoutItem() + { + ContentUdi = udi + }); + + contentData.Add(new BlockItemData() + { + Udi = udi, + ContentTypeKey = contentType.Key, + RawPropertyValues = nestedContentItem.RawPropertyValues + }); + } + + var blockValue = new BlockValue() + { + Layout = new Dictionary() + { + { Constants.PropertyEditors.Aliases.BlockList, JToken.FromObject(layoutItems) } + }, + ContentData = contentData + }; + + return JsonConvert.SerializeObject(blockValue, Formatting.None); + } + + internal class NestedContentItem + { + [JsonProperty("key")] + public Guid Id { get; set; } = Guid.NewGuid(); // Ensure a unique key is set, even if the JSON doesn't have one + + [JsonProperty("name")] + public string? Name { get; set; } + + [JsonIgnore] + public object? PropType { get; set; } // Ensure this property is ignored + + [JsonProperty("ncContentTypeAlias")] + public string ContentTypeAlias { get; set; } = null!; + + [JsonExtensionData] + public Dictionary RawPropertyValues { get; set; } = null!; + } +} +``` + +
+ +Moving forward, other migrators may be built by HQ or the community for property editors found in community packages. We'll make them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib) via the `Umbraco.Deploy.Contrib` package. \ No newline at end of file From 9f075e3195ce1a78b5fb2f3e1dfb592ea55b8494 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 07:17:42 +0100 Subject: [PATCH 02/35] Fixed linting issues and added summary page. --- 13/umbraco-deploy/SUMMARY.md | 2 ++ .../deployment-workflow/import-export-v7.md | 10 +++++----- 13/umbraco-deploy/deployment-workflow/import-export.md | 4 ++-- .../deployment-workflow/import-with-migrations.md | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/13/umbraco-deploy/SUMMARY.md b/13/umbraco-deploy/SUMMARY.md index 78de0c974f8..9b93004598d 100644 --- a/13/umbraco-deploy/SUMMARY.md +++ b/13/umbraco-deploy/SUMMARY.md @@ -31,6 +31,8 @@ * [Deployment](deployment-workflow/README.md) * [Transferring Content, Media and Forms](deployment-workflow/content-transfer.md) * [Import and Export](deployment-workflow/import-export.md) + * [Import and Export with Migrations](deployment-workflow/import-with-migrations.md) + * [Import and Export from V7](deployment-workflow/import-export-v7.md) * [Deploying Changes](deployment-workflow/deploying-changes.md) * [Deploying deletions](deployment-workflow/deploying-deletions.md) * [Restoring content](deployment-workflow/restoring-content/README.md) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index c3629da6a8f..95b33ffcd18 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -7,11 +7,11 @@ description: How to export content and schema from Umbraco 7 and import into a n The import and export feature is available from Deploy 4.9 (which supports Umbraco 8), 10.3, 12.1 and 13.0. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. -We can use this feature to help migrate from Umbraco 7 to a supported major version using additional logic added to the Deploy Contrib project. +We can use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. #### Exporting Umbraco 7 content and schema -We can generate an export archive in the same format as used by the import/export feature by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. +We can generate an export archive in the same format as used by the import/export feature. This is done by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. This is possible via code, by temporarily applying a composer to an Umbraco 7 project to generate the export archive on start-up: @@ -130,7 +130,7 @@ Artifact type resolvers allow resolving changes in the type that's stored in the - `Umbraco.DropDown.Flexible` - `Umbraco.RadioButtonList` -The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified document type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. +The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content.
LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) @@ -163,7 +163,7 @@ internal class LegacyImportComposer : IComposer
{% hint style="info" %} -It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog), followed by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them, so this ensures the schema is completely imported before any content is processed. +It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). You can follow that by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them. By importing schema first we ensure the schema is updated before any content is processed. {% endhint %} #### Obtaining Umbraco Deploy for Umbraco 7 @@ -207,7 +207,7 @@ Use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a ne {% code title="web.config" lineNumbers="true" %} ```xml - +
diff --git a/13/umbraco-deploy/deployment-workflow/import-export.md b/13/umbraco-deploy/deployment-workflow/import-export.md index 65d14f29aae..bacc4c334b5 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export.md +++ b/13/umbraco-deploy/deployment-workflow/import-export.md @@ -75,13 +75,13 @@ Once complete or on close of the dialog, the imported file will be deleted from ## Migrating whilst importing -It is possible to migrate schema and content whilist importing, e.g. to change Data Type using Nested Content into the Block List and ensure all content data is imported in the correct Block Editor format. +It is possible to migrate schema and content whilst importing. For example, to change Data Type using Nested Content to Block List and ensure content data is imported to the correct Block Editor format. Deploy contains base classes and implementations to handle common migrations that need to be registered in code, as explained in [Import with migrations](./import-with-migrations.md). ### Migrating from Umbraco 7 -Although the import and export feature is not available in Deploy 2 for Umbraco 7, we have released a package to allow creating an export. This needs to be done in code and requires additional legacy migrators to be able to import this into a newer version again, as explained in [Migrating from Umbraco 7](./import-export-v7.md). +The import and export feature is not available in Deploy 2 for Umbraco 7. We have though released a package to allow creating an export. This needs to be done in code and requires additional legacy migrators to be able to import into a newer version. This is explained in [Migrating from Umbraco 7](./import-export-v7.md). ## Service details (programmatically importing and exporting) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index 509f24fc1cd..d4cce71bb71 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -48,7 +48,7 @@ Implementations for common migrations: - `MediaPickerPropertyTypeMigrator` - `NestedContentPropertyTypeMigrator` -- `GridPropertyTypeMigrator` +- `GridPropertyTypeMigrator` And a base type to help you build your own migrations: @@ -56,7 +56,7 @@ And a base type to help you build your own migrations: - `GridPropertyTypeMigratorBase` {% hint style="info" %} -Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary (containing editor aliases for each content property) stored in the content artifact to the current Content Type/Data Type configuration. +Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary stored in the content artifact to the current Content Type/Data Type configuration. The dictionary contains editor aliases for each content property. {% endhint %} ### Registering migrators From 8171200e653109de3cf0703241ffc7542a1e017a Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 08:04:12 +0100 Subject: [PATCH 03/35] Added details of migrating the grid and community packages. --- .../import-with-migrations.md | 146 +++++++++++++++++- 1 file changed, 143 insertions(+), 3 deletions(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index d4cce71bb71..edf4e7fb6d9 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -27,6 +27,7 @@ Implementations to handle common migrations of data types from obsoleted propert - `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a Data Type from using the legacy Media Picker to the current version of this property editor - `ReplaceNestedContentDataTypeArtifactMigrator` - migrates a Data Type based on the obsolete Nested Content property editor to the Block List - `ReplaceGridDataTypeArtifactMigrator` - migrates a Data Type based on the legacy Grid layout into the Block Grid +- `ReplaceUnknownEditorDataTypeArtifactMigrator` - replaces any unknown editor alias with a label We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. @@ -85,9 +86,149 @@ internal class ArtifactMigratorsComposer : IComposer } ``` -### A custom migration example - Nested Content to Block List +### Details of Specific Migrations -In order to help writing your own migrations, we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. +Umbraco Deploy ships with migrators to handle the conversion of core property editors as they have changed, been removed or replaced between versions. + +Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. + +#### Grid to Block Grid + +The grid editor introduced in Umbraco 7 has been removed from Umbraco 14. It's functionality is replaced with the Block Grid. + +With Deploy migrators we have support for migrating data type configuration and property data between these property editors. + +You can configure the default migration with the following composer: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append(); + } +} +``` + +Thee implementations make use of the following conventions to migrate the data: + +- `ReplaceGridDataTypeArtifactMigrator`: + - Grid layouts are migrated to an existing or new element type with an alias based on the layout name, prefixed with `gridLayout_` (this can be customized by overriding `MigrateGridTemplate()`); + - Row configurations are migrated to an existing or new element type with an alias based on the row name, prefixed with `gridRow_` (this can be customized by overriding `MigrateGridLayout()`); + - Similarly, grid editors are migrated to an existing or new element type with an alias based on the editor alias, prefixed with `gridEditor_` (this can be customized by overriding `MigrateGridEditor()`). The available editors are retrieved from the `grid.editors.config.js` files (can be overridden in `GetGridEditors()`). Each migrated grid editor will have the following property types added to the element type: + - The `media` grid editor is migrated to multiple properties: the `value` property contains the selected media item (using Media Picker v3), `altText` the alternate text (using a Textbox) and `caption` the caption (also using a Textbox); + - The remaining grid editors create a single `value` property that uses the following editors: + - `rte` - the default 'Rich Text Editor', falling back to the first `Umbraco.TinyMCE` editor. + - `headline` - the default 'Textstring', falling back to the first `Umbraco.TextBox` editor. + - `macro` and `embed` grid editors are converted into rich text editors. + - `quote` or any other - use falling back to the first `Umbraco.TextArea` editor. + - The block label is also updated for the built-in grid editors, ensuring a nice preview is available (the WYSIWYG style previews are incompatible between these editors, so the custom views are not migrated); + - Grid settings config and styles are migrated to a new element type with a random alias, prefixed with `gridSettings_` (this can be customized by overriding `MigrateGridSettings()`). This is because the migration only has context about the data type configuration (not the actual data type) and multiple data type can potentially use the same configuration (for config and styles), so there's no predictable way to create a unique alias. The migrated settings element type will have the property types added for the config and styles: + - Each config setting is migrated to a property with an alias based on the key, prefixed with `setting_` and added below a 'Settings' property group; + - Similarly, each style is migrated to a property with an alias based on the key, prefixed with `style_` and added below a 'Styles' property group; + - The following property editors are used for these properties based on the config/style view: + - `radiobuttonlist` - a new 'Radio Button List' data type that uses the pre-values; + - `multivalues` - a new 'Checkbox List' data type that uses the pre-values; + - `textstring` - the default 'Textstring', falling back to the first `Umbraco.TextBox` editor. + - `mediapicker` and `imagepicker` - the default 'Media Picker' (v3, single image), falling back to the first `Umbraco.MediaPicker3` editor. + - `boolean` - the default 'Checkbox', falling back to the first `Umbraco.TrueFalse` editor. + - `number` - the default 'Numeric', falling back to the first `Umbraco.Integer` editor. + - `treepicker`, `treesource`, `textarea` or any other - the default 'Textarea', falling back to the first `Umbraco.TextArea` editor. +- `GridPropertyTypeMigrator`: + - Gets the grid layout and row configuration element types based on the alias prefix/name convention used by the data type artifact migrator; + - The grid editor values are migrated to the respective properties: + - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the data type), alternate text and caption; + - All other values are converted to a simple value or otherwise to a JSON string; + - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: + - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. + - All other values are returned as-is. + +Given the flexibility of the grid editor and Block Grid you may want to take further control over the migration. You can do that by creating your own migrator classes, that make use of our provided base classes. You would then register your own migrators instead of the ones shipped with Umbraco Deploy in your composer. + +The base classes provide the following functionality. Methods you should look to override to amend the default behavior have been noted above. + +- `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` data type editor alias with `Umbraco.BlockGrid` and migrates the configuration: + - The amount of columns is copied over. + - Grid layouts, row configurations and grid editors are migrated to blocks: + - If multiple grid layouts are configured or if at least one contains multiple sections or isn't the full width, each grid layout will be migrated to a 'layout block' (an element type without properties). + - If multiple row configurations are configured or if at least one contains areas that don't allow all grid editors or has a maximum amount of items set, each row configuration is migrated to a block (this is also always done when there are multiple grid layouts, as each layout can configure allowed row configurations). + - All grid editors are migrated to blocks (allowing a single grid editor to be migrated to multiple blocks to support DocTypeGridEditor, as that allows selecting different element types). + - The settings config and styles are migrated to a single element type (even though each setting can define whether it's supported for rows and/or cells) and used on the blocks that are allowed. + - Block groups are added for Layout and Content and used on the corresponding block types. +- `GridPropertyTypeMigratorBase` - migrates the property data from the `GridValue` into the `BlockValue` (using the `Umbraco.BlockGrid` layout): + - The related data type is retrieved to get the configured blocks. + - All grid control values are first migrated into their content blocks. + - Settings config and styles for 'grid cells' are stored on the area within a row, but areas in the Block Grid can't have settings, so this is migrated into the first migrated grid control content block instead. + - If a layout block can be found for the row configuration name, all grid controls are wrapped into that block. + - Similarly, if a layout block can be found for the grid layout name, all items are wrapped into that block. + - The JSON serialized `BlockValue` is returned. + +#### Migrating From Doc Type Grid Editor + +[Doc Type Grid Editor](https://our.umbraco.com/packages/backoffice-extensions/doc-type-grid-editor/) was a community package commonly used with the legacy grid editor. If you are using this with Umbraco 7 and up, you can export and migrate into the Block Grid on Umbraco 13 or above. + +Ensure you are running the latest version of `Umbraco.Deploy.Contrib` compatible with your Umbraco major version. + +In your new project, register the following migrators to add support for the import from Doc Type Grid Editor grids: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append(); + } +} +``` + +The migrators add the following behavior: + +- `ReplaceDocTypeGridEditorDataTypeArtifactMigrator` extends `ReplaceGridDataTypeArtifactMigrator` and ensures any DocTypeGridEditor is migrated to blocks using the allowed element types. If the element types aren't found the default implementation will migrate to new element types. +- `DocTypeGridEditorPropertyTypeMigrator` extends `GridPropertyTypeMigrator` and ensures the Doc Type Grid Editor values are mapped one-to-one to the block item data. + +#### Migrating from Matryoshka + +[Matryoshka](https://our.umbraco.com/packages/backoffice-extensions/matryoshka-tabs-for-umbraco-8/) was an Umbraco package that added tab support for document types in Umbraco. The feature was subsequently added to the product itself. + +We provide a migrator for this package in `Umbraco.Deploy.Contrib`. + +This adds support for migrating Matryoshka Group Separators into native property groups. It removes the Matryoshka data types during import and migrates the document, media and member types. Native property groups are also changed into tabs, similarly to how they were displayed with Matryoshka installed. + +To use, you register the migrators: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + } +} +``` + +### Source Code Example - Nested Content to Block List + +As described above, the nested content to block list migration will occur register the corresponding migrator with your application. + +In order to help writing your own migrations. we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: @@ -285,4 +426,3 @@ public class NestedContentPropertyTypeMigrator : PropertyTypeMigratorBase -Moving forward, other migrators may be built by HQ or the community for property editors found in community packages. We'll make them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib) via the `Umbraco.Deploy.Contrib` package. \ No newline at end of file From 6ebd03ac6d1d746802a71615caaf6d3163787e67 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 08:09:25 +0100 Subject: [PATCH 04/35] Linting. --- .../import-with-migrations.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index edf4e7fb6d9..df368e5e39e 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -22,7 +22,7 @@ Artifact migrators work by transforming the serialized artifact of any imported - `IArtifactMigrator` - where the migration occurs at the artifact property level - `IArtifactJsonMigrator` - where the migration occurs at the lower level of transforming the serialized JSON itself. -Implementations to handle common migrations of data types from obsoleted property editors are available: +Implementations to handle common migrations of Data Types from obsoleted property editors are available: - `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a Data Type from using the legacy Media Picker to the current version of this property editor - `ReplaceNestedContentDataTypeArtifactMigrator` - migrates a Data Type based on the obsolete Nested Content property editor to the Block List @@ -96,7 +96,7 @@ Open source migrators may be built by HQ or the community for property editors f The grid editor introduced in Umbraco 7 has been removed from Umbraco 14. It's functionality is replaced with the Block Grid. -With Deploy migrators we have support for migrating data type configuration and property data between these property editors. +With Deploy migrators we have support for migrating Data Type configuration and property data between these property editors. You can configure the default migration with the following composer: @@ -130,21 +130,21 @@ Thee implementations make use of the following conventions to migrate the data: - `macro` and `embed` grid editors are converted into rich text editors. - `quote` or any other - use falling back to the first `Umbraco.TextArea` editor. - The block label is also updated for the built-in grid editors, ensuring a nice preview is available (the WYSIWYG style previews are incompatible between these editors, so the custom views are not migrated); - - Grid settings config and styles are migrated to a new element type with a random alias, prefixed with `gridSettings_` (this can be customized by overriding `MigrateGridSettings()`). This is because the migration only has context about the data type configuration (not the actual data type) and multiple data type can potentially use the same configuration (for config and styles), so there's no predictable way to create a unique alias. The migrated settings element type will have the property types added for the config and styles: + - Grid settings config and styles are migrated to a new element type with a random alias, prefixed with `gridSettings_` (this can be customized by overriding `MigrateGridSettings()`). This is because the migration only has context about the Data Type configuration (not the actual Data Type) and multiple Data Type can potentially use the same configuration (for config and styles), so there's no predictable way to create a unique alias. The migrated settings element type will have the property types added for the config and styles: - Each config setting is migrated to a property with an alias based on the key, prefixed with `setting_` and added below a 'Settings' property group; - Similarly, each style is migrated to a property with an alias based on the key, prefixed with `style_` and added below a 'Styles' property group; - The following property editors are used for these properties based on the config/style view: - - `radiobuttonlist` - a new 'Radio Button List' data type that uses the pre-values; - - `multivalues` - a new 'Checkbox List' data type that uses the pre-values; + - `radiobuttonlist` - a new 'Radio Button List' Data Type that uses the pre-values; + - `multivalues` - a new 'Checkbox List' Data Type that uses the pre-values; - `textstring` - the default 'Textstring', falling back to the first `Umbraco.TextBox` editor. - `mediapicker` and `imagepicker` - the default 'Media Picker' (v3, single image), falling back to the first `Umbraco.MediaPicker3` editor. - `boolean` - the default 'Checkbox', falling back to the first `Umbraco.TrueFalse` editor. - `number` - the default 'Numeric', falling back to the first `Umbraco.Integer` editor. - `treepicker`, `treesource`, `textarea` or any other - the default 'Textarea', falling back to the first `Umbraco.TextArea` editor. - `GridPropertyTypeMigrator`: - - Gets the grid layout and row configuration element types based on the alias prefix/name convention used by the data type artifact migrator; + - Gets the grid layout and row configuration element types based on the alias prefix/name convention used by the Data Type artifact migrator; - The grid editor values are migrated to the respective properties: - - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the data type), alternate text and caption; + - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the Data Type), alternate text and caption; - All other values are converted to a simple value or otherwise to a JSON string; - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. @@ -154,7 +154,7 @@ Given the flexibility of the grid editor and Block Grid you may want to take fur The base classes provide the following functionality. Methods you should look to override to amend the default behavior have been noted above. -- `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` data type editor alias with `Umbraco.BlockGrid` and migrates the configuration: +- `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` Data Type editor alias with `Umbraco.BlockGrid` and migrates the configuration: - The amount of columns is copied over. - Grid layouts, row configurations and grid editors are migrated to blocks: - If multiple grid layouts are configured or if at least one contains multiple sections or isn't the full width, each grid layout will be migrated to a 'layout block' (an element type without properties). @@ -163,7 +163,7 @@ The base classes provide the following functionality. Methods you should look to - The settings config and styles are migrated to a single element type (even though each setting can define whether it's supported for rows and/or cells) and used on the blocks that are allowed. - Block groups are added for Layout and Content and used on the corresponding block types. - `GridPropertyTypeMigratorBase` - migrates the property data from the `GridValue` into the `BlockValue` (using the `Umbraco.BlockGrid` layout): - - The related data type is retrieved to get the configured blocks. + - The related Data Type is retrieved to get the configured blocks. - All grid control values are first migrated into their content blocks. - Settings config and styles for 'grid cells' are stored on the area within a row, but areas in the Block Grid can't have settings, so this is migrated into the first migrated grid control content block instead. - If a layout block can be found for the row configuration name, all grid controls are wrapped into that block. @@ -206,7 +206,7 @@ The migrators add the following behavior: We provide a migrator for this package in `Umbraco.Deploy.Contrib`. -This adds support for migrating Matryoshka Group Separators into native property groups. It removes the Matryoshka data types during import and migrates the document, media and member types. Native property groups are also changed into tabs, similarly to how they were displayed with Matryoshka installed. +This adds support for migrating Matryoshka Group Separators into native property groups. It removes the Matryoshka Data Types during import and migrates the document, media and member types. Native property groups are also changed into tabs, similarly to how they were displayed with Matryoshka installed. To use, you register the migrators: From 364a00c3c233508310c538754672e4d3e3944e2b Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 08:13:43 +0100 Subject: [PATCH 05/35] Linting. --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 4 ++-- .../deployment-workflow/import-with-migrations.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 95b33ffcd18..f8242b7d34f 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -172,13 +172,13 @@ Umbraco Deploy for Umbraco 7 is no longer supported and was only available on Um As such if you are looking to migrate from an Umbraco Cloud project running on Umbraco 7, you already have Umbraco Deploy installed. -If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. +If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud. Or to upgrade to a newer Deploy on-premise version. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. The export feature can be used without a license. {% hint style="info" %} -A license is required for the Umbraco project you are importing into - whether that's a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. +A license is required for the Umbraco project you are importing into. This can be a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. {% endhint %} diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index df368e5e39e..26040c90c2b 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -145,7 +145,7 @@ Thee implementations make use of the following conventions to migrate the data: - Gets the grid layout and row configuration element types based on the alias prefix/name convention used by the Data Type artifact migrator; - The grid editor values are migrated to the respective properties: - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the Data Type), alternate text and caption; - - All other values are converted to a simple value or otherwise to a JSON string; + - All other values are converted to a text value or otherwise to a JSON string; - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. - All other values are returned as-is. From 9a24afa6eef668ac6236774f67eb1a53dfab59bb Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 08:24:47 +0100 Subject: [PATCH 06/35] Linting. --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index f8242b7d34f..83850d27862 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -5,9 +5,9 @@ description: How to export content and schema from Umbraco 7 and import into a n ### Migrating from Umbraco 7 -The import and export feature is available from Deploy 4.9 (which supports Umbraco 8), 10.3, 12.1 and 13.0. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. +The import and export feature is available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. -We can use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. +We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. #### Exporting Umbraco 7 content and schema From 84c444242fe4cd650820f0d520aa0ea8c0faa663 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 22 Jul 2024 08:34:54 +0100 Subject: [PATCH 07/35] Copied import/export docs to 14. --- .../deployment-workflow/import-export-v7.md | 228 +++++++ .../deployment-workflow/import-export.md | 607 +----------------- .../import-with-migrations.md | 428 ++++++++++++ 3 files changed, 683 insertions(+), 580 deletions(-) create mode 100644 14/umbraco-deploy/deployment-workflow/import-export-v7.md create mode 100644 14/umbraco-deploy/deployment-workflow/import-with-migrations.md diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md new file mode 100644 index 00000000000..83850d27862 --- /dev/null +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -0,0 +1,228 @@ +--- +meta.Title: Migrating from Umbraco 7 +description: How to export content and schema from Umbraco 7 and import into a newer version +--- + +### Migrating from Umbraco 7 + +The import and export feature is available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. + +We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. + +#### Exporting Umbraco 7 content and schema + +We can generate an export archive in the same format as used by the import/export feature. This is done by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. + +This is possible via code, by temporarily applying a composer to an Umbraco 7 project to generate the export archive on start-up: + + +
+DeployExportApplicationHandler.cs (export Umbraco 7 content and schema to ZIP archive) + +```csharp +using System; +using System.Linq; +using System.Web.Hosting; +using Umbraco.Core; +using Umbraco.Deploy; +using UmbracoDeploy.Contrib.Export; + +public class DeployExportApplicationHandler : ApplicationEventHandler +{ + protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + // Set a default value connector that doesn't use object type prefixes + DefaultValueConnector.SetDefault(); + + // Run export after Deploy has started + DeployComponent.Started += (sender, e) => DeployStarted(); + } + + protected void DeployStarted() + { + var udis = new[] + { + // Export all content + Constants.UdiEntityType.Document, + Constants.UdiEntityType.DocumentBlueprint, + Constants.UdiEntityType.Media, + // Export all forms data + Constants.UdiEntityType.FormsForm, + Constants.UdiEntityType.FormsDataSource, + Constants.UdiEntityType.FormsPreValue + }.Select(Udi.Create); + + var dependencyEntityTypes = new[] + { + // Include all related schema + Constants.UdiEntityType.DataType, + Constants.UdiEntityType.DataTypeContainer, + Constants.UdiEntityType.DocumentType, + Constants.UdiEntityType.DocumentTypeContainer, + Constants.UdiEntityType.MediaType, + Constants.UdiEntityType.MediaTypeContainer, + Constants.UdiEntityType.MemberType, + Constants.UdiEntityType.MemberGroup, + Constants.UdiEntityType.Macro, + Constants.UdiEntityType.DictionaryItem, + Constants.UdiEntityType.Template, + Constants.UdiEntityType.Language, + // Include all related files + Constants.UdiEntityType.MediaFile, + Constants.UdiEntityType.MacroScript, + Constants.UdiEntityType.PartialView, + Constants.UdiEntityType.PartialViewMacro, + Constants.UdiEntityType.Script, + Constants.UdiEntityType.Stylesheet, + Constants.UdiEntityType.UserControl, + Constants.UdiEntityType.TemplateFile, + Constants.UdiEntityType.Xslt + }; + + // Create export + var zipArchiveFilePath = HostingEnvironment.MapPath("~/data/" + "export-" + Guid.NewGuid() + ".zip"); + ArtifactExportService.ExportArtifacts(udis, Constants.DeploySelector.ThisAndDescendants, zipArchiveFilePath, dependencyEntityTypes); + } +} +``` + +
+ +#### Importing Umbraco 7 content and schema + +To import this archive into a newer Umbraco project, you need to install either of these packages: + +- `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 +- `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later +Then you need to configure the legacy artifact type resolver and migratory. + +Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: + +- Moving the pre-values of data types to the configuration property; +- Moving the invariant release and expire dates of content to the (culture variant) schedule property; +- Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; +- Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: + - `Umbraco.CheckBoxList` (pre-values to value list) + - `Umbraco.ColorPickerAlias` to `Umbraco.ColorPicker` (pre-values to value list) + - `Umbraco.ContentPicker2` to `Umbraco.ContentPicker` (removes invalid start node ID) + - `Umbraco.ContentPickerAlias` to `Umbraco.ContentPicker` (removes invalid start node ID) + - `Umbraco.Date` to `Umbraco.DateTime` + - `Umbraco.DropDown` to `Umbraco.DropDownListFlexible` (pre-values to value list, single item select) + - `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.DropdownlistMultiplePublishKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.DropdownlistPublishingKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to single item select) + - `Umbraco.DropDownMultiple` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) + - `Umbraco.MediaPicker2` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to single item select) + - `Umbraco.MediaPicker` (removes invalid start node ID) + - `Umbraco.MemberPicker2` to `Umbraco.MemberPicker` + - `Umbraco.MultiNodeTreePicker2` to `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) + - `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) + - `Umbraco.MultipleMediaPicker` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to multiple item select) + - `Umbraco.NoEdit` to `Umbraco.Label` + - `Umbraco.RadioButtonList` (pre-values to value list, change database type from integer to nvarchar) + - `Umbraco.RelatedLinks2` to `Umbraco.MultiUrlPicker` + - `Umbraco.RelatedLinks` to `Umbraco.MultiUrlPicker` + - `Umbraco.Textbox` to `Umbraco.TextBox` + - `Umbraco.TextboxMultiple` to `Umbraco.TextArea` + - `Umbraco.TinyMCEv3` to `Umbraco.TinyMCE` +- Migrating pre-value property values for: + - `Umbraco.CheckBoxList` + - `Umbraco.DropDown.Flexible` + - `Umbraco.RadioButtonList` + +The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. + +
+LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Contrib.Migrators.Legacy; + +internal class LegacyImportComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactTypeResolvers() + .AddLegacyTypeResolver(); + + builder.DeployArtifactMigrators() + .AddLegacyMigrators() + .Append(); + } + + private class ElementTypeArtifactMigrator : ElementTypeArtifactMigratorBase + { + public ElementTypeArtifactMigrator() + : base("testElement") + { } + } +} +``` + +
+ +{% hint style="info" %} +It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). You can follow that by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them. By importing schema first we ensure the schema is updated before any content is processed. +{% endhint %} + +#### Obtaining Umbraco Deploy for Umbraco 7 + +Umbraco Deploy for Umbraco 7 is no longer supported and was only available on Umbraco Cloud. It was not released for use on-premise. + +As such if you are looking to migrate from an Umbraco Cloud project running on Umbraco 7, you already have Umbraco Deploy installed. + +If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud. Or to upgrade to a newer Deploy on-premise version. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. + +The export feature can be used without a license. + +{% hint style="info" %} + +A license is required for the Umbraco project you are importing into. This can be a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. + +{% endhint %} + +Use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. + +1. Download the required `dll` files for Umbraco Deploy for Umbraco 7 from the following links: + +- [Umbraco Deploy v2.1.6](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-release/UmbracoDeploy.v2.1.6.zip): Latest Deploy Version 2 release for Umbraco CMS Version 7 (officially for use on Cloud) +- [Umbraco Deploy Contrib v2.0.0](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-contrib-release/UmbracoDeploy.Contrib.2.0.0.zip): Latest/only Deploy Contrib Version 2 +- [Umbraco Deploy Export v2.0.0](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export): For exporting all content/schema in Version 7 + +2. Install Umbraco Deploy with the Contrib and Export extensions. + +- Install `Umbraco Deploy`, `Deploy.Contrib`, and `Deploy.Export` by copying the downloaded `.dll` files into your Umbraco 7 site. +- When copying the files over from `Umbraco Deploy` you should not overwrite the following files (if you already had Umbraco Deploy installed): + +```csharp + Config/UmbracoDeploy.config + Config/UmbracoDeploy.Settings.config +``` + +- Run the project to make sure it runs without any errors + +3. Update the `web.config` file with the required references for Umbraco Deploy: + +{% code title="web.config" lineNumbers="true" %} + +```xml + + + +
+
+ + + + + + + +``` + +{% endcode %} + +4. Export Content. + +- **Export** your content, schema, and files to zip. \ No newline at end of file diff --git a/14/umbraco-deploy/deployment-workflow/import-export.md b/14/umbraco-deploy/deployment-workflow/import-export.md index 41517566050..bacc4c334b5 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export.md +++ b/14/umbraco-deploy/deployment-workflow/import-export.md @@ -1,72 +1,69 @@ --- meta.Title: Import and export with Umbraco Deploy -description: >- - How to import and export content and schema between Umbraco environments and - projects +description: How to import and export content and schema between Umbraco environments and projects --- # Import and Export ## What is import and export? -The import and export feature of Umbraco Deploy allows you to transfer content and schema between Umbraco environments. Exports are made from one environment to a `.zip` file. This file is imported into another environment to update the Umbraco data there. +The import and export feature of Umbraco Deploy allows you to transfer content and schema between Umbraco environments. Exports are made from one environment to a `.zip` file. And this file is imported into another environment to update the Umbraco data there. ## When to use import and export Umbraco Deploy provides two primary workflows for managing different types of Umbraco data: -* Umbraco schema (such as document types and data types) are transferred [as `.uda` files serialized to disk](deploying-changes.md). They are deployed to refresh the schema information in a destination environment along with code and template updates. -* Umbraco content (such as content and media) is [transferred by editors using backoffice operations](content-transfer.md). +- Umbraco schema (such as document types and data types) are transferred [as `.uda` files serialized to disk](./deploying-changes.md). They are deployed to refresh the schema information in a destination environment along with code and template updates. +- Umbraco content (such as content and media) are [transferred by editors using backoffice operations](./content-transfer.md). We recommend using these approaches for day-to-day editorial and developer activities. -Import and export are intended more for larger transfer options, project upgrades, or one-off tasks when setting up new environments. +Import and export is intended more for larger transfer options, project upgrades, or one-off tasks when setting up new environments. As import and export is a two-step process, it doesn't require inter-environment communication. This allows us to process much larger batches of information without running into hard limits imposed by Cloud hosting platforms. -We can also provide hooks to allow for migrations of artifacts (such as data types) and property data when importing. This should allow you to migrate your Umbraco data from one Umbraco major version to a newer one. +We are also able provide hooks to allow for migrations of artifacts (such as data types) and property data when importing. This should allow you to migrate your Umbraco data from one Umbraco major version to a newer one. ## Exporting content and schema -To export content and schema, you can select either a specific item of content or a whole tree or workspace. +To export content and schema, you can select either a specific item of content, or a whole tree or workspace. -When exporting, you can choose to include associated media files. Bear in mind that including media files for a large site can lead to a big zip file. So even with this option, you might want to consider a different method for transferring large amounts of media. For example, using direct transfer between Cloud storage accounts or File Transfer Protocol (FTP). +When exporting, you can choose to include associated media files. Bear in mind that including media files for a large site can lead to a big zip file. So even with this option, you might want to consider a different method for transferring large amounts of media. For example using direct transfer between Cloud storage accounts or File Transfer Protocol (FTP). If your account has access to the Settings section, you can also choose to include the schema information and related files as well. -
Export dialog

Export dialog

+![Export dialog](../../../10/umbraco-deploy/deployment-workflow/images/export-dialog.png) -Umbraco Deploy will then serialize all the selected items to individual files, archive them into a zip file, and make that available for download. You can download the file using the **Download** button. +Umbraco Deploy will then serialize all the selected items to individual files, archive them into a zip file and make that available for download. You can download the file using the _Download_ button. -After the download, you should also delete the archive file from the server. You can do this immediately via the **Delete** button available in the dialog. - -
+After the download, you should also delete the archive file from the server. You can do this immediately via the _Delete_ button available in the dialog. ![Export dialog complete](../../../10/umbraco-deploy/deployment-workflow/images/export-dialog-complete.png) -If you miss doing this, you can also clean up archive files from the Umbraco Deploy dashboard in the **Settings** section. +If you miss doing this, you can also clean up archive files from the Umbraco Deploy dashboard in the _Settings_ section. ![Delete exports](../../../10/umbraco-deploy/deployment-workflow/images/delete-exports.png) {% hint style="info" %} -The exported archive files are saved to the Umbraco **temp** folder in the `Deploy\Export` sub-directory. This is a temporary (non-persistent) location, local to the backoffice server, and therefore shouldn't be used for long-term storage of exports. You can also only download the file from the export dialog in the backoffice. +The exported archive files are saved to the Umbraco temp folder in the `Deploy\Export` sub-directory. This is a temporary (non-persistent) location, local to the backoffice server and therefore shouldn't be used for long-term storage of exports. You can also only download the file from the export dialog in the backoffice. {% endhint %} ## Importing content and schema Having previously exported content and schema to a zip file, you can import this into a new environment. -
Import dialog

Import dialog

+![Import dialog](../../../10/umbraco-deploy/deployment-workflow/images/import-dialog.png) You can upload the file via the browser. Similar to when exporting, you can choose to import everything from the archive file, or only content, schema or files. {% hint style="info" %} -Deploy does not touch the default maximum upload size, but you can [configure this yourself by following the CMS documentation](https://docs.umbraco.com/umbraco-cms/reference/configuration/maximumuploadsizesettings). On Umbraco Cloud, the upload size limit is 500 MB. +Deploy does not touch the default maximum upload size, but you can [configure this yourself by following the CMS documentation](https://docs.umbraco.com/umbraco-cms/reference/configuration/maximumuploadsizesettings). + On Umbraco Cloud, the upload size limit is 500 MB. {% endhint %} -
Import dialog step 2

Import dialog step 2

+![Import dialog step 2](../../../10/umbraco-deploy/deployment-workflow/images/import-dialog-2.png) We validate the file before importing. Schema items that content depends on must either be in the upload itself or already exist on the target environment with the same details. If there are any issues that mean the import cannot proceed, it will be reported. You may also be given warnings for review. You can choose to ignore these and proceed if they aren't relevant to the action you are carrying out. @@ -78,562 +75,13 @@ Once complete or on close of the dialog, the imported file will be deleted from ## Migrating whilst importing -As well as importing the content and schema directly, we also provide support for modifying the items as part of the process. - -For example, you may have taken an export from an Umbraco 8 site, and are looking to import it into a newer major version. In this situation, most content and schema will carry over without issue. However, you may have some items that are no longer compatible. Usually this is due to a property editor - either a built-in Umbraco one or one provided by a package. These may no longer be available in the new version. - -Often though there is a similar replacement. Using Deploy's import feature we can transform the exported content for the obsolete property into that used by the new one during the import. The migration to a content set compatible with the new versions can then be completed. - -For example, we can migrate from a Nested Content property in Umbraco 8 to a Block List in Umbraco 13. - -We provide the necessary migration hooks for this to happen, divided into two types - **artifact migrators** and **property migrators**. - -### Artifact migrators - -Artifact migrators work by transforming the serialized artifact of any imported artifact, via two interfaces: - -* `IArtifactMigrator` - where the migration occurs at the artifact property level -* `IArtifactJsonMigrator` - where the migration occurs at the lower level of transforming the serialized JSON itself. - -Implementations to handle common migrations of data types from obsoleted property editors are available: - -* `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a datatype from using the legacy media picker to the current version of this property editor -* `ReplaceNestedContentDataTypeArtifactMigrator` - migrated from a datatype based on the obsolete nested content property editor to the block list. - -We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. - -* `ArtifactMigratorBase` - migrates the artifact of the specified type -* `DataTypeArtifactMigratorBase` - migrates Data Type artifacts -* `ReplaceDataTypeArtifactMigratorBase` - migrates a Data Type from one property editor to another -* `ArtifactJsonMigratorBase` - migrates the JSON of the specified artifact type - -### Property migrators - -Property migrators work to transform the content property data itself. They are used in the Deploy content connectors (documents, media and members) when the property editor is changed during an import: - -Again we have an interface: - -* `IPropertyTypeMigrator` - -Implementations for common migrations: - -* `MediaPickerPropertyTypeMigrator` -* `NestedContentPropertyTypeMigrator` - -And a base type to help you build your own migrations: - -* `PropertyTypeMigratorBase` - -{% hint style="info" %} -Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary (containing editor aliases for each content property) stored in the content artifact to the current Content Type/Data Type configuration. -{% endhint %} - -### Registering migrators - -Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. - -You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: - -```csharp -using Umbraco.Cms.Core.Composing; -using Umbraco.Deploy.Core.Migrators; -using Umbraco.Deploy.Infrastructure.Migrators; - -internal class ArtifactMigratorsComposer : IComposer -{ - public void Compose(IUmbracoBuilder builder) - { - builder.DeployArtifactMigrators() - .Append() - .Append(); - - builder.DeployPropertyTypeMigrators() - .Append() - .Append(); - } -} -``` - -### A custom migration example - Nested Content to Block List - -In order to help writing your own migrations, we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. - -First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: - -
- -ReplaceNestedContentDataTypeArtifactMigrator.cs (migrate Nested Content Data Type to Block List) - -```csharp -using System.Globalization; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Core.Serialization; -using Umbraco.Cms.Core.Services; -using Umbraco.Deploy.Infrastructure.Artifacts; - -public class ReplaceNestedContentDataTypeArtifactMigrator : ReplaceDataTypeArtifactMigratorBase -{ - private readonly IContentTypeService _contentTypeService; - - public ReplaceNestedContentDataTypeArtifactMigrator(PropertyEditorCollection propertyEditors, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, IContentTypeService contentTypeService) - : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList, propertyEditors, configurationEditorJsonSerializer) - => _contentTypeService = contentTypeService; - - protected override BlockListConfiguration? MigrateConfiguration(NestedContentConfiguration configuration) - { - var blockListConfiguration = new BlockListConfiguration() - { - UseInlineEditingAsDefault = true // Similar to how Nested Content looks/works - }; - - if (configuration.MinItems > 0) - { - blockListConfiguration.ValidationLimit.Min = configuration.MinItems; - } - - if (configuration.MaxItems > 0) - { - blockListConfiguration.ValidationLimit.Max = configuration.MaxItems; - } - - if (configuration.ContentTypes is not null) - { - var blocks = new List(); - foreach (NestedContentConfiguration.ContentType nestedContentType in configuration.ContentTypes) - { - if (nestedContentType.Alias is not null && - GetContentTypeKey(nestedContentType.Alias) is Guid contentTypeKey) - { - blocks.Add(new BlockListConfiguration.BlockConfiguration() - { - Label = nestedContentType.Template, - ContentElementTypeKey = contentTypeKey - }); - } - } - - blockListConfiguration.Blocks = blocks.ToArray(); - } - - if (blockListConfiguration.ValidationLimit.Min == 1 && - blockListConfiguration.ValidationLimit.Max == 1 && - blockListConfiguration.Blocks.Length == 1) - { - blockListConfiguration.UseSingleBlockMode = true; - } - - return blockListConfiguration; - } - - protected virtual Guid? GetContentTypeKey(string alias) - { - if (_contentTypeService.Get(alias) is IContentType contentTypeByAlias) - { - return contentTypeByAlias.Key; - } - - // New content types are initially saved by Deploy with a custom postfix (to avoid duplicate aliases), so try to get the first matching item - string aliasPrefix = alias + "__"; - foreach (IContentType contentType in _contentTypeService.GetAll()) - { - if (contentType.Alias.StartsWith(aliasPrefix) && - int.TryParse(contentType.Alias[aliasPrefix.Length..], NumberStyles.HexNumber, null, out _)) - { - return contentType.Key; - } - } - - return null; - } -} -``` - -
- -,And secondly we have the property migrator that handles restructuring the content property data: - -
- -NestedContentPropertyTypeMigrator.cs (migrate Nested Content property data to Block List) - -```csharp -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Deploy; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.Blocks; -using Umbraco.Cms.Core.Services; -using Umbraco.Deploy.Core; -using Umbraco.Deploy.Core.Migrators; -using Umbraco.Deploy.Infrastructure.Extensions; - -public class NestedContentPropertyTypeMigrator : PropertyTypeMigratorBase -{ - private readonly ILogger _logger; - private readonly IContentTypeService _contentTypeService; - - public NestedContentPropertyTypeMigrator(ILogger logger, IContentTypeService contentTypeService) - : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList) - { - _logger = logger; - _contentTypeService = contentTypeService; - } - - public override object? Migrate(IPropertyType propertyType, object? value, IDictionary propertyEditorAliases, IContextCache contextCache) - { - if (value is not string stringValue || !stringValue.TryParseJson(out NestedContentItem[]? nestedContentItems) || nestedContentItems is null) - { - if (value is not null) - { - _logger.LogWarning("Skipping migration of Nested Content items ({PropertyTypeAlias}), because value could not be parsed: {Value}.", propertyType.Alias, value); - } - - return null; - } - - var layoutItems = new List(); - var contentData = new List(); - - foreach (NestedContentItem nestedContentItem in nestedContentItems) - { - IContentType? contentType = contextCache.GetContentTypeByAlias(_contentTypeService, nestedContentItem.ContentTypeAlias); - if (contentType is null) - { - _logger.LogWarning("Skipping migration of Nested Content item ({Id}), because content type does not exist: {ContentTypeAlias}.", nestedContentItem.Id, nestedContentItem.ContentTypeAlias); - continue; - } +It is possible to migrate schema and content whilst importing. For example, to change Data Type using Nested Content to Block List and ensure content data is imported to the correct Block Editor format. - var udi = new GuidUdi(Constants.UdiEntityType.Element, nestedContentItem.Id); - - layoutItems.Add(new BlockListLayoutItem() - { - ContentUdi = udi - }); - - contentData.Add(new BlockItemData() - { - Udi = udi, - ContentTypeKey = contentType.Key, - RawPropertyValues = nestedContentItem.RawPropertyValues - }); - } - - var blockValue = new BlockValue() - { - Layout = new Dictionary() - { - { Constants.PropertyEditors.Aliases.BlockList, JToken.FromObject(layoutItems) } - }, - ContentData = contentData - }; - - return JsonConvert.SerializeObject(blockValue, Formatting.None); - } - - internal class NestedContentItem - { - [JsonProperty("key")] - public Guid Id { get; set; } = Guid.NewGuid(); // Ensure a unique key is set, even if the JSON doesn't have one - - [JsonProperty("name")] - public string? Name { get; set; } - - [JsonIgnore] - public object? PropType { get; set; } // Ensure this property is ignored - - [JsonProperty("ncContentTypeAlias")] - public string ContentTypeAlias { get; set; } = null!; - - [JsonExtensionData] - public Dictionary RawPropertyValues { get; set; } = null!; - } -} -``` - -
- -Moving forward, other migrators may be built by HQ or the community for property editors found in community packages. We'll make them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib) via the `Umbraco.Deploy.Contrib` package. +Deploy contains base classes and implementations to handle common migrations that need to be registered in code, as explained in [Import with migrations](./import-with-migrations.md). ### Migrating from Umbraco 7 -The import and export feature is available from Deploy 4.9 (which supports Umbraco 8), 10.3, 12.1 and 13.0. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. - -We can use this feature to help migrate from Umbraco 7 to a supported major version using additional logic added to the Deploy Contrib project. - -#### Exporting Umbraco 7 content and schema - -We can generate an export archive in the same format as used by the import/export feature by adding the [`Umbraco.Deploy.Contrib.Export` assembly](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export) to your Umbraco 7 project. This archive can then be imported into a newer Umbraco version by configuring the legacy import migrators. You can also apply additional migrators to update obsolete data types and property data into newer equivalents. - -This is possible via code, by temporarily applying a composer to an Umbraco 7 project to generate the export archive on start-up: - -
- -DeployExportApplicationHandler.cs (export Umbraco 7 content and schema to ZIP archive) - -```csharp -using System; -using System.Linq; -using System.Web.Hosting; -using Umbraco.Core; -using Umbraco.Deploy; -using UmbracoDeploy.Contrib.Export; - -public class DeployExportApplicationHandler : ApplicationEventHandler -{ - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - // Set a default value connector that doesn't use object type prefixes - DefaultValueConnector.SetDefault(); - - // Run export after Deploy has started - DeployComponent.Started += (sender, e) => DeployStarted(); - } - - protected void DeployStarted() - { - var udis = new[] - { - // Export all content - Constants.UdiEntityType.Document, - Constants.UdiEntityType.DocumentBlueprint, - Constants.UdiEntityType.Media, - // Export all forms data - Constants.UdiEntityType.FormsForm, - Constants.UdiEntityType.FormsDataSource, - Constants.UdiEntityType.FormsPreValue - }.Select(Udi.Create); - - var dependencyEntityTypes = new[] - { - // Include all related schema - Constants.UdiEntityType.DataType, - Constants.UdiEntityType.DataTypeContainer, - Constants.UdiEntityType.DocumentType, - Constants.UdiEntityType.DocumentTypeContainer, - Constants.UdiEntityType.MediaType, - Constants.UdiEntityType.MediaTypeContainer, - Constants.UdiEntityType.MemberType, - Constants.UdiEntityType.MemberGroup, - Constants.UdiEntityType.Macro, - Constants.UdiEntityType.DictionaryItem, - Constants.UdiEntityType.Template, - Constants.UdiEntityType.Language, - // Include all related files - Constants.UdiEntityType.MediaFile, - Constants.UdiEntityType.MacroScript, - Constants.UdiEntityType.PartialView, - Constants.UdiEntityType.PartialViewMacro, - Constants.UdiEntityType.Script, - Constants.UdiEntityType.Stylesheet, - Constants.UdiEntityType.UserControl, - Constants.UdiEntityType.TemplateFile, - Constants.UdiEntityType.Xslt - }; - - // Create export - var zipArchiveFilePath = HostingEnvironment.MapPath("~/data/" + "export-" + Guid.NewGuid() + ".zip"); - ArtifactExportService.ExportArtifacts(udis, Constants.DeploySelector.ThisAndDescendants, zipArchiveFilePath, dependencyEntityTypes); - } -} -``` - -
- -#### Importing Umbraco 7 content and schema - -To import this archive into a newer Umbraco project, you need to install either of these packages: - -* `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 -* `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later Then you need to configure the legacy artifact type resolver and migratory. - -Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: - -* Moving the pre-values of data types to the configuration property; -* Moving the invariant release and expire dates of content to the (culture variant) schedule property; -* Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; -* Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: - * `Umbraco.CheckBoxList` (pre-values to value list) - * `Umbraco.ColorPickerAlias` to `Umbraco.ColorPicker` (pre-values to value list) - * `Umbraco.ContentPicker2` to `Umbraco.ContentPicker` (removes invalid start node ID) - * `Umbraco.ContentPickerAlias` to `Umbraco.ContentPicker` (removes invalid start node ID) - * `Umbraco.Date` to `Umbraco.DateTime` - * `Umbraco.DropDown` to `Umbraco.DropDownListFlexible` (pre-values to value list, single item select) - * `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - * `Umbraco.DropdownlistMultiplePublishKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - * `Umbraco.DropdownlistPublishingKeys` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to single item select) - * `Umbraco.DropDownMultiple` to `Umbraco.DropDownListFlexible` (pre-values to value list, defaults to multiple item select) - * `Umbraco.MediaPicker2` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to single item select) - * `Umbraco.MediaPicker` (removes invalid start node ID) - * `Umbraco.MemberPicker2` to `Umbraco.MemberPicker` - * `Umbraco.MultiNodeTreePicker2` to `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) - * `Umbraco.MultiNodeTreePicker` (removes invalid start node ID) - * `Umbraco.MultipleMediaPicker` to `Umbraco.MediaPicker` (removes invalid start node ID, defaults to multiple item select) - * `Umbraco.NoEdit` to `Umbraco.Label` - * `Umbraco.RadioButtonList` (pre-values to value list, change database type from integer to nvarchar) - * `Umbraco.RelatedLinks2` to `Umbraco.MultiUrlPicker` - * `Umbraco.RelatedLinks` to `Umbraco.MultiUrlPicker` - * `Umbraco.Textbox` to `Umbraco.TextBox` - * `Umbraco.TextboxMultiple` to `Umbraco.TextArea` - * `Umbraco.TinyMCEv3` to `Umbraco.TinyMCE` -* Migrating pre-value property values for: - * `Umbraco.CheckBoxList` - * `Umbraco.DropDown.Flexible` - * `Umbraco.RadioButtonList` - -The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified document type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. - -
- -LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) - -```csharp -using Umbraco.Cms.Core.Composing; -using Umbraco.Deploy.Contrib.Migrators.Legacy; - -internal class LegacyImportComposer : IComposer -{ - public void Compose(IUmbracoBuilder builder) - { - builder.DeployArtifactTypeResolvers() - .AddLegacyTypeResolver(); - - builder.DeployArtifactMigrators() - .AddLegacyMigrators() - .Append(); - } - - private class ElementTypeArtifactMigrator : ElementTypeArtifactMigratorBase - { - public ElementTypeArtifactMigrator() - : base("testElement") - { } - } -} -``` - -
- -{% hint style="info" %} -It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog), followed by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them, so this ensures the schema is completely imported before any content is processed. -{% endhint %} - -#### Obtaining Umbraco Deploy for Umbraco 7 - -Umbraco Deploy for Umbraco 7 is no longer supported and was only available on Umbraco Cloud. It was not released for use on-premise. - -As such if you are looking to migrate from an Umbraco Cloud project running on Umbraco 7, you already have Umbraco Deploy installed. - -If you have an Umbraco 7 on-premise website, you can use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. You will need to obtain and install Umbraco Deploy for Umbraco 7 into your project, solely to use the export feature. - -The export feature can be used without a license. - -{% hint style="info" %} -A license is required for the Umbraco project you are importing into - whether that's a license that comes as part of an Umbraco Cloud subscription, or an on-premise one. -{% endhint %} - -Use this guide to migrate from on-premise to Umbraco Cloud or to upgrade to a newer Deploy version on-premise. - -1. Download the required `dll` files for Umbraco Deploy for Umbraco 7 from the following links: - -* [Umbraco Deploy v2.1.6](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-release/UmbracoDeploy.v2.1.6.zip): Latest Deploy Version 2 release for Umbraco CMS Version 7 (officially for use on Cloud) -* [Umbraco Deploy Contrib v2.0.0](https://umbraconightlies.blob.core.windows.net/umbraco-deploy-contrib-release/UmbracoDeploy.Contrib.2.0.0.zip): Latest/only Deploy Contrib Version 2 -* [Umbraco Deploy Export v2.0.0](https://github.com/umbraco/Umbraco.Deploy.Contrib/releases/tag/release-2.0.0-export): For exporting all content/schema in Version 7 - -2. Install Umbraco Deploy with the Contrib and Export extensions. - -* Install `Umbraco Deploy`, `Deploy.Contrib`, and `Deploy.Export` by copying the downloaded `.dll` files into your Umbraco 7 site. -* When copying the files over from `Umbraco Deploy` you should not overwrite the following files (if you already had Umbraco Deploy installed): - -```csharp - Config/UmbracoDeploy.config - Config/UmbracoDeploy.Settings.config -``` - -* Run the project to make sure it runs without any errors - -3. Update the `web.config` file with the required references for Umbraco Deploy: - -{% code title="web.config" lineNumbers="true" %} -```xml - - - -
-
- - - - - - - -``` -{% endcode %} - -4. Export Content. - -* **Export** your content, schema, and files to zip. - -
- -Upload to Large error when migrating from Umbraco 7 to Umbraco 13+ - -When migrating an Umbraco 7 project to Umbraco 13+, you might encounter an upload error regarding size limits (_upload too large_). - -To overcome this error, you must configure the size limits on both projects. - -Below are the steps on how to configure the size limits on Umbraco 7 and Umbraco 13+. - -\ -**Umbraco 7** - -1. Go to your [Web.config ](https://docs.umbraco.com/umbraco-cms/reference/configuration/maximumuploadsizesettings#using-iis)file on your Umbraco 7 project. -2. Add the following code to configure the size limits: - -{% code title="web.config" %} -```xml - - - - - - - - - -``` -{% endcode %} - -3. Add the `maxAllowedContentLength` size value. The size should be in Bytes. - -Once this has been added, you can configure the size limit on the project you are migrating to. - -**Umbraco 13+** - -1. Go to the `appSettings.json` file in your project. -2. Add the following code in your [appSettings.json](https://docs.umbraco.com/umbraco-cms/reference/configuration/runtimesettings) file under `Umbraco > CMS`: - -{% code title="appSettings.json" overflow="wrap" %} -```json - "Runtime": { - "MaxQueryStringLength": AddSizeHere, - } -``` -{% endcode %} - -3. Add the `MaxQueryStringLength` value you want to transfer. The size should be in Kilobytes. - -You need to ensure the size between the two projects is the same. - -The web.config uses bytes, you must ensure the number of bytes you set for Umbraco 7 matches the kilobytes set in the Umbraco 13+ project. - -You can use this [website](https://www.gbmb.org/bytes-to-kb) to convert bytes into kilobytes. - -
+The import and export feature is not available in Deploy 2 for Umbraco 7. We have though released a package to allow creating an export. This needs to be done in code and requires additional legacy migrators to be able to import into a newer version. This is explained in [Migrating from Umbraco 7](./import-export-v7.md). ## Service details (programmatically importing and exporting) @@ -643,23 +91,22 @@ You may have need to make use of this service directly if building something cus The service interface defines two methods: -* `ExportArtifactsAsync` - takes a collection of artifacts and a storage provider defined by the `IArtifactExportProvider` interface. The artifacts are serialized and exported to storage. - * `IArtifactExportProvider` defines methods for creating streams for writing serialized artifacts or files handled by Deploy (media, templates, stylesheets etc.). -* `ImportArtifactsAsync` - takes storage provider containing an import defined by the `IArtifactImportProvider` interface. The artifacts from storage are imported into Umbraco. - * `IArtifactImportProvider` defines methods for creating streams for reading serialized artifacts or files handled by Deploy (media, templates, stylesheets etc.). +- `ExportArtifactsAsync` - takes a collection of artifacts and a storage provider defined by the `IArtifactExportProvider` interface. The artifacts are serialized and exported to storage. + - `IArtifactExportProvider` defines methods for creating streams for writing serialized artifacts or files handled by Deploy (media, templates, stylesheets etc.). +- `ImportArtifactsAsync` - takes storage provider containing an import defined by the `IArtifactImportProvider` interface. The artifacts from storage are imported into Umbraco. + - `IArtifactImportProvider` defines methods for creating streams for reading serialized artifacts or files handled by Deploy (media, templates, stylesheets etc.). Implementations for `IArtifactExportProvider` and `IArtifactImportProvider` are provided for: -* A physical directory. -* An Umbraco file system. -* A zip file. +- A physical directory. +- An Umbraco file system. +- A zip file. These are all accessible for use via extension methods available on `IArtifactImportExportService` found in the `Umbraco.Deploy.Infrastructure.Extensions` namespace. The following example shows this service in use, importing and exporting from a zip file on startup:
- ArtifactImportExportComposer.cs (import and export on startup) ```csharp diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md new file mode 100644 index 00000000000..26040c90c2b --- /dev/null +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -0,0 +1,428 @@ +--- +meta.Title: Import with migrations in Umbraco Deploy +description: How to import content and schema while migrating them into newer alternatives +--- + +# Import with migrations + +As well as importing the content and schema directly, we also provide support for modifying the items as part of the process. + +For example, you may have taken an export from an Umbraco 8 site, and are looking to import it into a newer major version. In this situation, most content and schema will carry over without issue. However, you may have some items that are no longer compatible. Usually this is due to a property editor - either a built-in Umbraco one or one provided by a package. These may no longer be available in the new version. + +Often though there is a similar replacement. Using Deploy's import feature we can transform the exported content for the obsolete property into that used by the new one during the import. The migration to a content set compatible with the new versions can then be completed. + +For example, we can migrate from a Nested Content property in Umbraco 8 to a Block List in Umbraco 13. + +We provide the necessary migration hooks for this to happen, divided into two types - **artifact migrators** and **property migrators**. + +### Artifact migrators + +Artifact migrators work by transforming the serialized artifact of any imported artifact, via two interfaces: + +- `IArtifactMigrator` - where the migration occurs at the artifact property level +- `IArtifactJsonMigrator` - where the migration occurs at the lower level of transforming the serialized JSON itself. + +Implementations to handle common migrations of Data Types from obsoleted property editors are available: + +- `ReplaceMediaPickerDataTypeArtifactMigrator` - migrates a Data Type from using the legacy Media Picker to the current version of this property editor +- `ReplaceNestedContentDataTypeArtifactMigrator` - migrates a Data Type based on the obsolete Nested Content property editor to the Block List +- `ReplaceGridDataTypeArtifactMigrator` - migrates a Data Type based on the legacy Grid layout into the Block Grid +- `ReplaceUnknownEditorDataTypeArtifactMigrator` - replaces any unknown editor alias with a label + +We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. + +- `ArtifactMigratorBase` - migrates the artifact of the specified type +- `DataTypeArtifactMigratorBase` - migrates Data Type artifacts +- `ReplaceDataTypeArtifactMigratorBase` - migrates a Data Type from one property editor to another +- `ArtifactJsonMigratorBase` - migrates the JSON of the specified artifact type +- `ReplaceGridDataTypeArtifactMigratorBase` - migrates a Data Type based on the legacy Grid layout into the Block Grid + +### Property migrators + +Property migrators work to transform the content property data itself. They are used in the Deploy content connectors (documents, media and members) when the property editor is changed during an import: + +Again we have an interface: + +- `IPropertyTypeMigrator` + +Implementations for common migrations: + +- `MediaPickerPropertyTypeMigrator` +- `NestedContentPropertyTypeMigrator` +- `GridPropertyTypeMigrator` + +And a base type to help you build your own migrations: + +- `PropertyTypeMigratorBase` +- `GridPropertyTypeMigratorBase` + +{% hint style="info" %} +Property editor changes are determined by comparing the `PropertyEditorAliases` dictionary stored in the content artifact to the current Content Type/Data Type configuration. The dictionary contains editor aliases for each content property. +{% endhint %} + +### Registering migrators + +Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. + +You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Core.Migrators; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal class ArtifactMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append() + .Append(); + } +} + ``` + +### Details of Specific Migrations + +Umbraco Deploy ships with migrators to handle the conversion of core property editors as they have changed, been removed or replaced between versions. + +Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. + +#### Grid to Block Grid + +The grid editor introduced in Umbraco 7 has been removed from Umbraco 14. It's functionality is replaced with the Block Grid. + +With Deploy migrators we have support for migrating Data Type configuration and property data between these property editors. + +You can configure the default migration with the following composer: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append(); + } +} +``` + +Thee implementations make use of the following conventions to migrate the data: + +- `ReplaceGridDataTypeArtifactMigrator`: + - Grid layouts are migrated to an existing or new element type with an alias based on the layout name, prefixed with `gridLayout_` (this can be customized by overriding `MigrateGridTemplate()`); + - Row configurations are migrated to an existing or new element type with an alias based on the row name, prefixed with `gridRow_` (this can be customized by overriding `MigrateGridLayout()`); + - Similarly, grid editors are migrated to an existing or new element type with an alias based on the editor alias, prefixed with `gridEditor_` (this can be customized by overriding `MigrateGridEditor()`). The available editors are retrieved from the `grid.editors.config.js` files (can be overridden in `GetGridEditors()`). Each migrated grid editor will have the following property types added to the element type: + - The `media` grid editor is migrated to multiple properties: the `value` property contains the selected media item (using Media Picker v3), `altText` the alternate text (using a Textbox) and `caption` the caption (also using a Textbox); + - The remaining grid editors create a single `value` property that uses the following editors: + - `rte` - the default 'Rich Text Editor', falling back to the first `Umbraco.TinyMCE` editor. + - `headline` - the default 'Textstring', falling back to the first `Umbraco.TextBox` editor. + - `macro` and `embed` grid editors are converted into rich text editors. + - `quote` or any other - use falling back to the first `Umbraco.TextArea` editor. + - The block label is also updated for the built-in grid editors, ensuring a nice preview is available (the WYSIWYG style previews are incompatible between these editors, so the custom views are not migrated); + - Grid settings config and styles are migrated to a new element type with a random alias, prefixed with `gridSettings_` (this can be customized by overriding `MigrateGridSettings()`). This is because the migration only has context about the Data Type configuration (not the actual Data Type) and multiple Data Type can potentially use the same configuration (for config and styles), so there's no predictable way to create a unique alias. The migrated settings element type will have the property types added for the config and styles: + - Each config setting is migrated to a property with an alias based on the key, prefixed with `setting_` and added below a 'Settings' property group; + - Similarly, each style is migrated to a property with an alias based on the key, prefixed with `style_` and added below a 'Styles' property group; + - The following property editors are used for these properties based on the config/style view: + - `radiobuttonlist` - a new 'Radio Button List' Data Type that uses the pre-values; + - `multivalues` - a new 'Checkbox List' Data Type that uses the pre-values; + - `textstring` - the default 'Textstring', falling back to the first `Umbraco.TextBox` editor. + - `mediapicker` and `imagepicker` - the default 'Media Picker' (v3, single image), falling back to the first `Umbraco.MediaPicker3` editor. + - `boolean` - the default 'Checkbox', falling back to the first `Umbraco.TrueFalse` editor. + - `number` - the default 'Numeric', falling back to the first `Umbraco.Integer` editor. + - `treepicker`, `treesource`, `textarea` or any other - the default 'Textarea', falling back to the first `Umbraco.TextArea` editor. +- `GridPropertyTypeMigrator`: + - Gets the grid layout and row configuration element types based on the alias prefix/name convention used by the Data Type artifact migrator; + - The grid editor values are migrated to the respective properties: + - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the Data Type), alternate text and caption; + - All other values are converted to a text value or otherwise to a JSON string; + - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: + - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. + - All other values are returned as-is. + +Given the flexibility of the grid editor and Block Grid you may want to take further control over the migration. You can do that by creating your own migrator classes, that make use of our provided base classes. You would then register your own migrators instead of the ones shipped with Umbraco Deploy in your composer. + +The base classes provide the following functionality. Methods you should look to override to amend the default behavior have been noted above. + +- `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` Data Type editor alias with `Umbraco.BlockGrid` and migrates the configuration: + - The amount of columns is copied over. + - Grid layouts, row configurations and grid editors are migrated to blocks: + - If multiple grid layouts are configured or if at least one contains multiple sections or isn't the full width, each grid layout will be migrated to a 'layout block' (an element type without properties). + - If multiple row configurations are configured or if at least one contains areas that don't allow all grid editors or has a maximum amount of items set, each row configuration is migrated to a block (this is also always done when there are multiple grid layouts, as each layout can configure allowed row configurations). + - All grid editors are migrated to blocks (allowing a single grid editor to be migrated to multiple blocks to support DocTypeGridEditor, as that allows selecting different element types). + - The settings config and styles are migrated to a single element type (even though each setting can define whether it's supported for rows and/or cells) and used on the blocks that are allowed. + - Block groups are added for Layout and Content and used on the corresponding block types. +- `GridPropertyTypeMigratorBase` - migrates the property data from the `GridValue` into the `BlockValue` (using the `Umbraco.BlockGrid` layout): + - The related Data Type is retrieved to get the configured blocks. + - All grid control values are first migrated into their content blocks. + - Settings config and styles for 'grid cells' are stored on the area within a row, but areas in the Block Grid can't have settings, so this is migrated into the first migrated grid control content block instead. + - If a layout block can be found for the row configuration name, all grid controls are wrapped into that block. + - Similarly, if a layout block can be found for the grid layout name, all items are wrapped into that block. + - The JSON serialized `BlockValue` is returned. + +#### Migrating From Doc Type Grid Editor + +[Doc Type Grid Editor](https://our.umbraco.com/packages/backoffice-extensions/doc-type-grid-editor/) was a community package commonly used with the legacy grid editor. If you are using this with Umbraco 7 and up, you can export and migrate into the Block Grid on Umbraco 13 or above. + +Ensure you are running the latest version of `Umbraco.Deploy.Contrib` compatible with your Umbraco major version. + +In your new project, register the following migrators to add support for the import from Doc Type Grid Editor grids: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + + builder.DeployPropertyTypeMigrators() + .Append(); + } +} +``` + +The migrators add the following behavior: + +- `ReplaceDocTypeGridEditorDataTypeArtifactMigrator` extends `ReplaceGridDataTypeArtifactMigrator` and ensures any DocTypeGridEditor is migrated to blocks using the allowed element types. If the element types aren't found the default implementation will migrate to new element types. +- `DocTypeGridEditorPropertyTypeMigrator` extends `GridPropertyTypeMigrator` and ensures the Doc Type Grid Editor values are mapped one-to-one to the block item data. + +#### Migrating from Matryoshka + +[Matryoshka](https://our.umbraco.com/packages/backoffice-extensions/matryoshka-tabs-for-umbraco-8/) was an Umbraco package that added tab support for document types in Umbraco. The feature was subsequently added to the product itself. + +We provide a migrator for this package in `Umbraco.Deploy.Contrib`. + +This adds support for migrating Matryoshka Group Separators into native property groups. It removes the Matryoshka Data Types during import and migrates the document, media and member types. Native property groups are also changed into tabs, similarly to how they were displayed with Matryoshka installed. + +To use, you register the migrators: + +```csharp +using Umbraco.Cms.Core.Composing; +using Umbraco.Deploy.Infrastructure.Migrators; + +internal sealed class DeployMigratorsComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.DeployArtifactMigrators() + .Append(); + } +} +``` + +### Source Code Example - Nested Content to Block List + +As described above, the nested content to block list migration will occur register the corresponding migrator with your application. + +In order to help writing your own migrations. we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. + +First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: + +
+ReplaceNestedContentDataTypeArtifactMigrator.cs (migrate Nested Content Data Type to Block List) + +```csharp +using System.Globalization; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Deploy.Infrastructure.Artifacts; + +public class ReplaceNestedContentDataTypeArtifactMigrator : ReplaceDataTypeArtifactMigratorBase +{ + private readonly IContentTypeService _contentTypeService; + + public ReplaceNestedContentDataTypeArtifactMigrator(PropertyEditorCollection propertyEditors, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, IContentTypeService contentTypeService) + : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList, propertyEditors, configurationEditorJsonSerializer) + => _contentTypeService = contentTypeService; + + protected override BlockListConfiguration? MigrateConfiguration(NestedContentConfiguration configuration) + { + var blockListConfiguration = new BlockListConfiguration() + { + UseInlineEditingAsDefault = true // Similar to how Nested Content looks/works + }; + + if (configuration.MinItems > 0) + { + blockListConfiguration.ValidationLimit.Min = configuration.MinItems; + } + + if (configuration.MaxItems > 0) + { + blockListConfiguration.ValidationLimit.Max = configuration.MaxItems; + } + + if (configuration.ContentTypes is not null) + { + var blocks = new List(); + foreach (NestedContentConfiguration.ContentType nestedContentType in configuration.ContentTypes) + { + if (nestedContentType.Alias is not null && + GetContentTypeKey(nestedContentType.Alias) is Guid contentTypeKey) + { + blocks.Add(new BlockListConfiguration.BlockConfiguration() + { + Label = nestedContentType.Template, + ContentElementTypeKey = contentTypeKey + }); + } + } + + blockListConfiguration.Blocks = blocks.ToArray(); + } + + if (blockListConfiguration.ValidationLimit.Min == 1 && + blockListConfiguration.ValidationLimit.Max == 1 && + blockListConfiguration.Blocks.Length == 1) + { + blockListConfiguration.UseSingleBlockMode = true; + } + + return blockListConfiguration; + } + + protected virtual Guid? GetContentTypeKey(string alias) + { + if (_contentTypeService.Get(alias) is IContentType contentTypeByAlias) + { + return contentTypeByAlias.Key; + } + + // New content types are initially saved by Deploy with a custom postfix (to avoid duplicate aliases), so try to get the first matching item + string aliasPrefix = alias + "__"; + foreach (IContentType contentType in _contentTypeService.GetAll()) + { + if (contentType.Alias.StartsWith(aliasPrefix) && + int.TryParse(contentType.Alias[aliasPrefix.Length..], NumberStyles.HexNumber, null, out _)) + { + return contentType.Key; + } + } + + return null; + } +} +``` + +
+ +And secondly we have the property migrator that handles restructuring the content property data: + +
+NestedContentPropertyTypeMigrator.cs (migrate Nested Content property data to Block List) + +```csharp +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Deploy; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Blocks; +using Umbraco.Cms.Core.Services; +using Umbraco.Deploy.Core; +using Umbraco.Deploy.Core.Migrators; +using Umbraco.Deploy.Infrastructure.Extensions; + +public class NestedContentPropertyTypeMigrator : PropertyTypeMigratorBase +{ + private readonly ILogger _logger; + private readonly IContentTypeService _contentTypeService; + + public NestedContentPropertyTypeMigrator(ILogger logger, IContentTypeService contentTypeService) + : base(Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.BlockList) + { + _logger = logger; + _contentTypeService = contentTypeService; + } + + public override object? Migrate(IPropertyType propertyType, object? value, IDictionary propertyEditorAliases, IContextCache contextCache) + { + if (value is not string stringValue || !stringValue.TryParseJson(out NestedContentItem[]? nestedContentItems) || nestedContentItems is null) + { + if (value is not null) + { + _logger.LogWarning("Skipping migration of Nested Content items ({PropertyTypeAlias}), because value could not be parsed: {Value}.", propertyType.Alias, value); + } + + return null; + } + + var layoutItems = new List(); + var contentData = new List(); + + foreach (NestedContentItem nestedContentItem in nestedContentItems) + { + IContentType? contentType = contextCache.GetContentTypeByAlias(_contentTypeService, nestedContentItem.ContentTypeAlias); + if (contentType is null) + { + _logger.LogWarning("Skipping migration of Nested Content item ({Id}), because content type does not exist: {ContentTypeAlias}.", nestedContentItem.Id, nestedContentItem.ContentTypeAlias); + continue; + } + + var udi = new GuidUdi(Constants.UdiEntityType.Element, nestedContentItem.Id); + + layoutItems.Add(new BlockListLayoutItem() + { + ContentUdi = udi + }); + + contentData.Add(new BlockItemData() + { + Udi = udi, + ContentTypeKey = contentType.Key, + RawPropertyValues = nestedContentItem.RawPropertyValues + }); + } + + var blockValue = new BlockValue() + { + Layout = new Dictionary() + { + { Constants.PropertyEditors.Aliases.BlockList, JToken.FromObject(layoutItems) } + }, + ContentData = contentData + }; + + return JsonConvert.SerializeObject(blockValue, Formatting.None); + } + + internal class NestedContentItem + { + [JsonProperty("key")] + public Guid Id { get; set; } = Guid.NewGuid(); // Ensure a unique key is set, even if the JSON doesn't have one + + [JsonProperty("name")] + public string? Name { get; set; } + + [JsonIgnore] + public object? PropType { get; set; } // Ensure this property is ignored + + [JsonProperty("ncContentTypeAlias")] + public string ContentTypeAlias { get; set; } = null!; + + [JsonExtensionData] + public Dictionary RawPropertyValues { get; set; } = null!; + } +} +``` + +
+ From 895b24aa3d124634859a62d8acd4d81ebcfabb0d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:29:25 +0200 Subject: [PATCH 08/35] Update 13/umbraco-deploy/SUMMARY.md --- 13/umbraco-deploy/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/SUMMARY.md b/13/umbraco-deploy/SUMMARY.md index 9b93004598d..22252b3475e 100644 --- a/13/umbraco-deploy/SUMMARY.md +++ b/13/umbraco-deploy/SUMMARY.md @@ -32,7 +32,7 @@ * [Transferring Content, Media and Forms](deployment-workflow/content-transfer.md) * [Import and Export](deployment-workflow/import-export.md) * [Import and Export with Migrations](deployment-workflow/import-with-migrations.md) - * [Import and Export from V7](deployment-workflow/import-export-v7.md) + * [Import and Export from version 7](deployment-workflow/import-export-v7.md) * [Deploying Changes](deployment-workflow/deploying-changes.md) * [Deploying deletions](deployment-workflow/deploying-deletions.md) * [Restoring content](deployment-workflow/restoring-content/README.md) From 0d02aae47ff737216455616bc830001c6f54a6e3 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:29:33 +0200 Subject: [PATCH 09/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 83850d27862..f36d0c078d0 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -5,7 +5,7 @@ description: How to export content and schema from Umbraco 7 and import into a n ### Migrating from Umbraco 7 -The import and export feature is available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. +The import and export features are available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you cannot trigger an export from there in the same way. We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. From dd60669b8fad23bb809572fb52fed3383ec2905f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:29:40 +0200 Subject: [PATCH 10/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index f36d0c078d0..5a6e9a1602c 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -7,7 +7,7 @@ description: How to export content and schema from Umbraco 7 and import into a n The import and export features are available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you cannot trigger an export from there in the same way. -We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. +We can use this feature to help migrate from Umbraco 7 to a supported major version. However, it requires additional logic to be added to the Deploy Contrib project. #### Exporting Umbraco 7 content and schema From 1a582c4926535ad07928d2bd1b324e60765b3cbc Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:29:48 +0200 Subject: [PATCH 11/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 5a6e9a1602c..757927ca9ba 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -99,7 +99,7 @@ Then you need to configure the legacy artifact type resolver and migratory. Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: - Moving the pre-values of data types to the configuration property; -- Moving the invariant release and expire dates of content to the (culture variant) schedule property; +- Moving the invariant release and expiration dates of content to the (culture variant) schedule property; - Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; - Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: - `Umbraco.CheckBoxList` (pre-values to value list) From 0b5e3375886f6bb6e6cb4a8d53a91fb89eed0fb0 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:29:58 +0200 Subject: [PATCH 12/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 1 + 1 file changed, 1 insertion(+) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 757927ca9ba..68d3ebec6c1 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -94,6 +94,7 @@ To import this archive into a newer Umbraco project, you need to install either - `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 - `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later + Then you need to configure the legacy artifact type resolver and migratory. Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: From 93b84d9d7ae5c044fffa1d067fa22204235e213a Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:06 +0200 Subject: [PATCH 13/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index 26040c90c2b..124b027666f 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -90,7 +90,7 @@ internal class ArtifactMigratorsComposer : IComposer Umbraco Deploy ships with migrators to handle the conversion of core property editors as they have changed, been removed or replaced between versions. -Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. +Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. #### Grid to Block Grid From b1541ec286bef3e656a767ad52d925253141e281 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:13 +0200 Subject: [PATCH 14/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index 124b027666f..c5a59f1ef10 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -117,7 +117,7 @@ internal sealed class DeployMigratorsComposer : IComposer } ``` -Thee implementations make use of the following conventions to migrate the data: +These implementations make use of the following conventions to migrate the data: - `ReplaceGridDataTypeArtifactMigrator`: - Grid layouts are migrated to an existing or new element type with an alias based on the layout name, prefixed with `gridLayout_` (this can be customized by overriding `MigrateGridTemplate()`); From a1451462e413a0f3bb35a8b8bb0c914e0e2b245f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:22 +0200 Subject: [PATCH 15/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index c5a59f1ef10..04509735d0f 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -147,7 +147,7 @@ These implementations make use of the following conventions to migrate the data: - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the Data Type), alternate text and caption; - All other values are converted to a text value or otherwise to a JSON string; - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: - - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. + - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as a modifier and added to the stored value), before trying to get the media item by a path. - All other values are returned as-is. Given the flexibility of the grid editor and Block Grid you may want to take further control over the migration. You can do that by creating your own migrator classes, that make use of our provided base classes. You would then register your own migrators instead of the ones shipped with Umbraco Deploy in your composer. From 618985869a2ce7a44ec86dd05183812d2669dad8 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:29 +0200 Subject: [PATCH 16/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index 04509735d0f..fc146d2a94f 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -155,7 +155,7 @@ Given the flexibility of the grid editor and Block Grid you may want to take fur The base classes provide the following functionality. Methods you should look to override to amend the default behavior have been noted above. - `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` Data Type editor alias with `Umbraco.BlockGrid` and migrates the configuration: - - The amount of columns is copied over. + - The number of columns is copied over. - Grid layouts, row configurations and grid editors are migrated to blocks: - If multiple grid layouts are configured or if at least one contains multiple sections or isn't the full width, each grid layout will be migrated to a 'layout block' (an element type without properties). - If multiple row configurations are configured or if at least one contains areas that don't allow all grid editors or has a maximum amount of items set, each row configuration is migrated to a block (this is also always done when there are multiple grid layouts, as each layout can configure allowed row configurations). From 6eff8d4e1adba6bddea9a7bc216cd6d1c3d2614f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:36 +0200 Subject: [PATCH 17/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index fc146d2a94f..1a05c6896e1 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -228,7 +228,7 @@ internal sealed class DeployMigratorsComposer : IComposer As described above, the nested content to block list migration will occur register the corresponding migrator with your application. -In order to help writing your own migrations. we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. +To help write your own migrations, we share the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: From 585f77f177288b58e125aba99788f375e43af7b0 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:30:52 +0200 Subject: [PATCH 18/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 68d3ebec6c1..2742191c5f8 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -131,7 +131,7 @@ Artifact type resolvers allow resolving changes in the type that's stored in the - `Umbraco.DropDown.Flexible` - `Umbraco.RadioButtonList` -The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. +The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as the element type. Element types are a concept added in Umbraco 8 and are required for Document Types that are used in Nested Content.
LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) From 470dc9e8fcff4368ef3334b41f85db9ebc1d84b5 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:31:05 +0200 Subject: [PATCH 19/35] Update 13/umbraco-deploy/deployment-workflow/import-export-v7.md --- 13/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-export-v7.md b/13/umbraco-deploy/deployment-workflow/import-export-v7.md index 2742191c5f8..8bd1da497c5 100644 --- a/13/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/13/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -164,7 +164,7 @@ internal class LegacyImportComposer : IComposer
{% hint style="info" %} -It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). You can follow that by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them. By importing schema first we ensure the schema is updated before any content is processed. +It is recommended to start by importing only the schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). Then, you can proceed with importing all content and schema together. The order in which the artifacts are imported depends on their dependencies. By importing the schema first, we ensure that the schema is updated before any content is processed. {% endhint %} #### Obtaining Umbraco Deploy for Umbraco 7 From ab41756719bf2d2b62bc695c032186adb02945eb Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:31:16 +0200 Subject: [PATCH 20/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index 26040c90c2b..956f0b9a7b2 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -29,7 +29,7 @@ Implementations to handle common migrations of Data Types from obsoleted propert - `ReplaceGridDataTypeArtifactMigrator` - migrates a Data Type based on the legacy Grid layout into the Block Grid - `ReplaceUnknownEditorDataTypeArtifactMigrator` - replaces any unknown editor alias with a label -We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. +We've also made available base implementations that you can use to build your own migrations. You may need to handle the transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. - `ArtifactMigratorBase` - migrates the artifact of the specified type - `DataTypeArtifactMigratorBase` - migrates Data Type artifacts From 9f016f8de3dbbb77bc9393306ca6eea8ca7d586e Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:31:27 +0200 Subject: [PATCH 21/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index 956f0b9a7b2..f3fef30f46b 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -62,7 +62,7 @@ Property editor changes are determined by comparing the `PropertyEditorAliases` ### Registering migrators -Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. +Migrators will run if you have registered them, so you can enable only the ones needed for your solution. You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: From 36ab1d4a8aa0091d6e9af752a0f0f56a4ad31e6d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:31:39 +0200 Subject: [PATCH 22/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index f3fef30f46b..38f0583079e 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -90,7 +90,7 @@ internal class ArtifactMigratorsComposer : IComposer Umbraco Deploy ships with migrators to handle the conversion of core property editors as they have changed, been removed or replaced between versions. -Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made them available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. +Open source migrators may be built by HQ or the community for property editors found in community packages. They will be made available for [use](https://www.nuget.org/packages/Umbraco.Deploy.Contrib) and [review](https://github.com/umbraco/Umbraco.Deploy.Contrib/tree/v13/dev/src/Umbraco.Deploy.Contrib/Migrators) via the `Umbraco.Deploy.Contrib` package. #### Grid to Block Grid From df59b1b60f28a259c1642cce35cd89bfa5178137 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:32:23 +0200 Subject: [PATCH 23/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index 38f0583079e..a15d9c55c91 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -117,7 +117,7 @@ internal sealed class DeployMigratorsComposer : IComposer } ``` -Thee implementations make use of the following conventions to migrate the data: +These implementations make use of the following conventions to migrate the data: - `ReplaceGridDataTypeArtifactMigrator`: - Grid layouts are migrated to an existing or new element type with an alias based on the layout name, prefixed with `gridLayout_` (this can be customized by overriding `MigrateGridTemplate()`); From 4cdd4decc6b53efb517a58746fca5957a31ac0eb Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:32:35 +0200 Subject: [PATCH 24/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index a15d9c55c91..de9e99ea73f 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -147,7 +147,7 @@ These implementations make use of the following conventions to migrate the data: - The `media` grid editor converts the value to a media item with crops (based on the UDI or media path), including the focal point (although this needs to be enabled on the Data Type), alternate text and caption; - All other values are converted to a text value or otherwise to a JSON string; - If a row or cell contains settings config or styles and the corresponding block has a settings element type configured, the settings config and styles are migrated to their respective properties in a similar way, based on the property editor alias: - - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as modifier and added to the stored value), before trying to get the media item by path. + - `Umbraco.MediaPicker3` - removes `url('` from the beginning and `')` from the end of the value (commonly used as a modifier and added to the stored value), before trying to get the media item by a path. - All other values are returned as-is. Given the flexibility of the grid editor and Block Grid you may want to take further control over the migration. You can do that by creating your own migrator classes, that make use of our provided base classes. You would then register your own migrators instead of the ones shipped with Umbraco Deploy in your composer. From f2f7f617be346bf263e84db4acf3b6d2bf329d25 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:32:47 +0200 Subject: [PATCH 25/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index 1a05c6896e1..c2fb04f3734 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -62,7 +62,7 @@ Property editor changes are determined by comparing the `PropertyEditorAliases` ### Registering migrators -Migrators will run if you've registered them to, hence you can enable only the ones needed for your solution. +Migrators will run if you have registered them, so you can enable only the ones needed for your solution. You can do this via a composer, as in the following example. Here we register two of the migrators shipped with Umbraco Deploy: From 7974483998866f1ec59c4c7f1a220b08dad2a972 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:00 +0200 Subject: [PATCH 26/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index de9e99ea73f..1c88119c0cb 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -155,7 +155,7 @@ Given the flexibility of the grid editor and Block Grid you may want to take fur The base classes provide the following functionality. Methods you should look to override to amend the default behavior have been noted above. - `ReplaceGridDataTypeArtifactMigratorBase` - replaces the `Umbraco.Grid` Data Type editor alias with `Umbraco.BlockGrid` and migrates the configuration: - - The amount of columns is copied over. + - The number of columns is copied over. - Grid layouts, row configurations and grid editors are migrated to blocks: - If multiple grid layouts are configured or if at least one contains multiple sections or isn't the full width, each grid layout will be migrated to a 'layout block' (an element type without properties). - If multiple row configurations are configured or if at least one contains areas that don't allow all grid editors or has a maximum amount of items set, each row configuration is migrated to a block (this is also always done when there are multiple grid layouts, as each layout can configure allowed row configurations). From 7f32af520394d2f1983085a66b08f8cc562fa471 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:10 +0200 Subject: [PATCH 27/35] Update 13/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 13/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md index 1c88119c0cb..65dd946af4d 100644 --- a/13/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/13/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -228,7 +228,7 @@ internal sealed class DeployMigratorsComposer : IComposer As described above, the nested content to block list migration will occur register the corresponding migrator with your application. -In order to help writing your own migrations. we share here the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. +To help write your own migrations, we share the source code of an example that ships with Umbraco Deploy. This migration converts Nested Content to Block List. First we have the artifact migrator that handles the conversion of the configuration stored with a datatype: From 0e297a1cce009c437729bca15f3bf932fff07557 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:20 +0200 Subject: [PATCH 28/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index 83850d27862..f36d0c078d0 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -5,7 +5,7 @@ description: How to export content and schema from Umbraco 7 and import into a n ### Migrating from Umbraco 7 -The import and export feature is available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you can't trigger an export from there in the same way. +The import and export features are available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you cannot trigger an export from there in the same way. We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. From 19412d833f70084a5f9468d6f1351aebdc343f54 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:31 +0200 Subject: [PATCH 29/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index f36d0c078d0..5a6e9a1602c 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -7,7 +7,7 @@ description: How to export content and schema from Umbraco 7 and import into a n The import and export features are available for Umbraco Deploy supporting Umbraco 8 and above. It's not been ported back to Umbraco 7, hence you cannot trigger an export from there in the same way. -We can however use this feature to help migrate from Umbraco 7 to a supported major version. It requires additional logic added to the Deploy Contrib project. +We can use this feature to help migrate from Umbraco 7 to a supported major version. However, it requires additional logic to be added to the Deploy Contrib project. #### Exporting Umbraco 7 content and schema From 1a5e37153ace23b965b4a5e0880b3fcbcdc0c4e6 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:44 +0200 Subject: [PATCH 30/35] Update 14/umbraco-deploy/deployment-workflow/import-with-migrations.md --- 14/umbraco-deploy/deployment-workflow/import-with-migrations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md index c2fb04f3734..65dd946af4d 100644 --- a/14/umbraco-deploy/deployment-workflow/import-with-migrations.md +++ b/14/umbraco-deploy/deployment-workflow/import-with-migrations.md @@ -29,7 +29,7 @@ Implementations to handle common migrations of Data Types from obsoleted propert - `ReplaceGridDataTypeArtifactMigrator` - migrates a Data Type based on the legacy Grid layout into the Block Grid - `ReplaceUnknownEditorDataTypeArtifactMigrator` - replaces any unknown editor alias with a label -We've also made available base implementations that you can use to build your own migrations. You may have a need to handle transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. +We've also made available base implementations that you can use to build your own migrations. You may need to handle the transfer of information between other obsolete and replacement property editors that you have in your Umbraco application. - `ArtifactMigratorBase` - migrates the artifact of the specified type - `DataTypeArtifactMigratorBase` - migrates Data Type artifacts From a8000be54f4c6d46e9fc483ca57256e0e46f2acd Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:57 +0200 Subject: [PATCH 31/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 1 + 1 file changed, 1 insertion(+) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index 5a6e9a1602c..48501d09af8 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -94,6 +94,7 @@ To import this archive into a newer Umbraco project, you need to install either - `UmbracoDeploy.Contrib` 4.3 for Umbraco 8 - `Umbraco.Deploy.Contrib` for Umbraco 10.2, 12.1, 13.1 or later + Then you need to configure the legacy artifact type resolver and migratory. Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: From 8bd7e88d92e837c054bba83760c09698cec4a61c Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:34:06 +0200 Subject: [PATCH 32/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index 48501d09af8..68d3ebec6c1 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -100,7 +100,7 @@ Then you need to configure the legacy artifact type resolver and migratory. Artifact type resolvers allow resolving changes in the type that's stored in the `__type` JSON property of the artifact. This is in case it moved to a different assembly or namespace (or got renamed) in a newer version. The legacy migrators handle the following changes: - Moving the pre-values of data types to the configuration property; -- Moving the invariant release and expire dates of content to the (culture variant) schedule property; +- Moving the invariant release and expiration dates of content to the (culture variant) schedule property; - Moving the 'allowed at root' and 'allowed child content types' of content/media/member types to the permissions property; - Migrating the Data Type configuration from pre-values to the correct configuration objects and new editor aliases for: - `Umbraco.CheckBoxList` (pre-values to value list) From 5342912b6b38e9a9ec7eb3458ac3f9bf350cf1ac Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:34:16 +0200 Subject: [PATCH 33/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index 68d3ebec6c1..2742191c5f8 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -131,7 +131,7 @@ Artifact type resolvers allow resolving changes in the type that's stored in the - `Umbraco.DropDown.Flexible` - `Umbraco.RadioButtonList` -The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as element type. Element types are a concept added in Umbraco 8 and are required for document types that are used in Nested Content. +The following composer adds the required legacy artifact type resolver and migrators. It also adds a custom resolver that marks the specified Document Type alias `testElement` as the element type. Element types are a concept added in Umbraco 8 and are required for Document Types that are used in Nested Content.
LegacyImportComposer.cs (configure artifact type resolver and artifact migrators) From 4bf6594c08fd838f6d0b6c92701a046f974b537c Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:34:25 +0200 Subject: [PATCH 34/35] Update 14/umbraco-deploy/deployment-workflow/import-export-v7.md --- 14/umbraco-deploy/deployment-workflow/import-export-v7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/umbraco-deploy/deployment-workflow/import-export-v7.md b/14/umbraco-deploy/deployment-workflow/import-export-v7.md index 2742191c5f8..8bd1da497c5 100644 --- a/14/umbraco-deploy/deployment-workflow/import-export-v7.md +++ b/14/umbraco-deploy/deployment-workflow/import-export-v7.md @@ -164,7 +164,7 @@ internal class LegacyImportComposer : IComposer
{% hint style="info" %} -It is recommended to first only import schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). You can follow that by a complete import of all content and schema. The order in which the artifacts are imported depends on the dependencies between them. By importing schema first we ensure the schema is updated before any content is processed. +It is recommended to start by importing only the schema and schema files (by deselecting 'Content' and 'Content files' in the dialog). Then, you can proceed with importing all content and schema together. The order in which the artifacts are imported depends on their dependencies. By importing the schema first, we ensure that the schema is updated before any content is processed. {% endhint %} #### Obtaining Umbraco Deploy for Umbraco 7 From f09aac1a1e0387df58f9691cc152edd23c619134 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 23 Jul 2024 09:56:16 +0100 Subject: [PATCH 35/35] Updated summary file for Forms 14 --- 14/umbraco-deploy/SUMMARY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/14/umbraco-deploy/SUMMARY.md b/14/umbraco-deploy/SUMMARY.md index 78de0c974f8..22252b3475e 100644 --- a/14/umbraco-deploy/SUMMARY.md +++ b/14/umbraco-deploy/SUMMARY.md @@ -31,6 +31,8 @@ * [Deployment](deployment-workflow/README.md) * [Transferring Content, Media and Forms](deployment-workflow/content-transfer.md) * [Import and Export](deployment-workflow/import-export.md) + * [Import and Export with Migrations](deployment-workflow/import-with-migrations.md) + * [Import and Export from version 7](deployment-workflow/import-export-v7.md) * [Deploying Changes](deployment-workflow/deploying-changes.md) * [Deploying deletions](deployment-workflow/deploying-deletions.md) * [Restoring content](deployment-workflow/restoring-content/README.md)