Introduction:
The Drupal 7 websites will face the lack of community support from drupal.org after November 2022. So every website running on drupal 7 will need to be moved on to Drupal 8 or Drupal 9.
The content migration from drupal 7 to drupal 9 is an easy piece to manage by drupal migration modules. By the drupal’s inbuilt migrate and migrate_drupal module, it is possible to migrate all types of entities easily with a few database configurations and drush commands.
What migrate modules offer:
The migrate modules allow us to migrate all content types, taxonomy vocabularies and terms, users, menus, etc. We just need to run a drush command with following migration tag:
The migrate drupal ui module enables us to migrate the content from drupal UI also.
We can see one migrations folder in all core modules in drupal 8 and drupal 9. These configurable files are used for migration of such entities.
Challenges:
It is not everytime required that the website owners will need the same content or structure in a new website in Drupal 8/9 from drupal 7.
It may be a requirement to migrate or skip a content type, change the destination (Drupal 9) content type fields, use a specific content type to migrate in particular content type entities etc.
Sometimes the website owner wants to split up one content type entity into a few more content types in drupal 9. For example a tag with article one in article content type needs to migrate in article extend content type or contents having tag name as news need to be migrated in news content type. This brings up some more ways to think and research for these kinds of migrations.
Overall the website owners want to improve the visibility and functionality of the new website.
Such kind of requirements lead the content migration to be managed in a custom way for developers. There developers need to think and do analysis of source and destination content types and create some custom plugins, add some more configurable migration files etc.
About this Case Study :
This case study is done on the various types of content and files or media migration cases.
In this, I have placed a few example configurable files with proper configured fields for various types of field migrations. Also it includes the database structure for migration and how migrate gets happen in drupal.
This document consist of migrations of few custom plugins also like migrate only published nodes, migrate one specific reference taxonomy term contents in specific content type, how content types splitting will handle the content in destination website, what are the possible area of mistakes and how we can debug these etc.
What approach I will use for content migration:
In this content migration case study, we will first migrate the files/media and other dependency migrations to use migration_lookup in content migration.
We will create several configurable migration scripts for specific content type migrations for different use cases.
We will use a custom plugin for migration of specific tagged content in reference fields.
Implementation:
In content migration, the files have some difference in migration from drupal 6 or 7 as in drupal 8/9 the files are referenced to the media entities. In drupal 8 or 9, the contents will consider all files as media and these are related to the file ids used in drupal 8/9 nodes.
I am creating this document as per my experience in migration from drupal 7 to drupal 9.
In this, we will migrate the files as the first step and content in the next steps.
Required modules:
Migration of files from drupal 7 to drupal 9:
Files migration will include the fid, filename, filemime, filesize, status. If you want to migrate the files in auto incremented fids, then you can remove fid from the migration file.
The file migration uses the source site base path to identify the file locations.
Step 1: Create a custom module for migrating the custom content rather than migrating whole content using a drupal migrate module.
Let’s say the module name is custom_migrate. It will contain the following file structure.
- custom_module.info.yml
- module/custom/custom_module/config/install
- module/custom/custom_module/src/Plugin
The install folder will contain all migration files and Plugin will contain custom plugins in case you want any modification while migration.
Step 2: Create a migrate plus group for migration.
Migrate plus group:
Migrate plus group is a file having the source database identification while migration.
The file will be as below:
Put the following code into the custom_module/config/install/migrate_plusmigrate_plus.migration_group.migrate_group.yml file.
# A "migration group" is - surprise! - a group of migrations. It is used to # group migrations for display by our tools, and to perform operations on a # specific set of migrations. It can also be used to hold any configuration # common to those migrations, so it doesn't have to be duplicated in each one.
# The machine name of the group, by which it is referenced in individual # migrations. id: migrate_plus_group
# A human-friendly label for the group. label: Migrate Plus group
# More information about the group. description: Migrate plus group contain database informations
# Short description of the type of source, e.g. "Drupal 6" or "WordPress". source_type: Drupal 7
# Here we add any default configuration settings to be shared among all # migrations in the group. For this example, the source tables are in the # Drupal (default) database, but usually if your source data is in a # database it will be external. shared_configuration: # Specifying 'source' here means that this configuration will be merged into # the 'source' configuration of each migration. source: # A better practice for real-world migrations would be to add a database # connection to your external database in settings.php and reference its # key here. key: migrate
# dependency so the migration_group configuration will be removed on module # uninstall.
|
Details of above file :
- Id: The id of the migration group file is a unique configuration id.
- source_type: Select the drupal version in source type.
- key: The key is important in this file which has the database key name and identifies this key from the settings.php file from the destination site (Drupal 8/9).
This will be added in settings.php as below.
$databases['migrate']['default'] = array ( 'database' => drupal7_databasename, 'username' => 'dbusername', 'password' => 'dbpassword', 'prefix' => '', 'host' => 'dbhost', 'port' => 'port_number', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );
|
The migrate array could be added below the database information of the drupal 8/9 site. Make sure this information is correct with the username, password and hostname of the source site database.
Step 3: Migrate the files from drupal 7 to drupal 9.
Create a migrate file for migrating the files from drupal 7 to drupal 9.
The below file will migrate all types of files in one attempt using the d7_file plugin.
The following code will be placed in custom_module/config/install/migrate_plus.migration.migrate_files.yml
# Every migration that references a file by Drupal 7 fid should specify this # migration as an optional dependency. id: migrate_files label: Public files audit: true migration_tags: - drupal7_file_migration migration_group: migrate_plus_group source: plugin: d7_file constants: # The tool configuring this migration must set source_base_path. It # represents the fully qualified path relative to which URIs in the files # table are specified, and must end with a /. See source_full_path # configuration in this migration's process pipeline as an example. source_base_path: 'https://emaple.com/' process: # If you are using this file to build a custom migration consider removing # the fid field to allow incremental migrations. fid: fid
filename: filename source_full_path: - plugin: concat delimiter: / source: - constants/source_base_path - filepath - plugin: urlencode uri: plugin: file_copy source: - '@source_full_path' - uri filemime: filemime # No need to migrate filesize, it is computed when file entities are saved. # filesize: filesize status: status # Drupal 7 didn't keep track of the file's creation or update time -- all it # had was the vague "timestamp" column. So we'll use it for both. created: timestamp changed: timestamp uid: uid destination: plugin: entity:file
|
The source base path will concat the file path and use the file to migrate from source to destination with all file configurations.
The mapping with source and destination will migrate the information in the database to the database. The file_copy plugin will be to download and upload the files from source to destination.
Step 4: Migrate the files to media from drupal 7 to drupal 9.
The files to media is a process of mapping the referenced fields of media to the file entities in any media type.
We can migrate the files to media by specific file types to particular media types where we can map the files to media type fields in drupal 9. In this, we identify the types of files by the filemime property.
Below is an example of files to media migration.
Images to media migration:
Place below content in this file custom_module/config/install/migrate_plus.migration.migrate_images_media.yml
id: images_media label: Files migration_tags: - images_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - image/jpeg - image/jpeg - image/gif - image/png - image/tiff - image/ief - image/pcx - image/svg+xml - image/vnd.djvu - image/vnd.microsoft.icon - image/vnd.wap.wbmp - image/x-cmu-raster - image/x-coreldraw - image/x-coreldrawpattern - image/x-coreldrawtemplate - image/x-corelphotopaint - image/x-jg - image/x-jng - image/x-ms-bmp - image/x-photoshop - image/x-portable-anymap - image/x-portable-bitmap - image/x-portable-graymap - image/x-portable-pixmap - image/x-rgb - image/x-xbitmap - image/x-xpixmap - image/x-xwindowdump - image/webp - image/* source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_image/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_image/alt: field_file_image_alt_text/0/value field_media_image/title: field_file_image_title_text/0/value Field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: image migration_dependencies: required: - migrate_files
|
The file to media migration can happen after file migration as it will depend upon the file information that will take from the database.
skip_on_value plugin is very useful in this kind of situation where you can migrate specific types of files based on condition. This plugin has three useful parameters: method (optional), not_equal/equal (optional) and value.
There may be two types of method it can use are row and process. Row method will Skips the entire row when an empty value is encountered and the process method will prevents further processing of the input property when the value is empty.
not_equals parameter, If set, skipping occurs when values are not equal. By default this value is equal and true
The value parameter is a single value or array of values against which the source value
should be compared.
Next we used migration_lookup plugin for mapping the files to media fields. migration_lookup is a migration process plugin that gets a value from a previous migration. It is particularly useful for reference fields because it can look up the ID of an entity created by a previous migration.
Similarly we can migrate the documents and audio files to media types easily.
Documents file migration to document media type:
id: documents_media label: Files migration_tags: - documents_to_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - text/html - text/plain - application/acad - application/msword - application/vnd.ms-excel - application/pdf - application/vnd.ms-powerpoint - application/vnd.oasis.opendocument.text - application/vnd.oasis.opendocument.spreadsheet - application/vnd.oasis.opendocument.presentation - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - application/vnd.openxmlformats-officedocument.presentationml.presentation - application/vnd.openxmlformats-officedocument.wordprocessingml.document - application/zip - application/x-7z-compressed - application/x-tar - application/gzip source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_file/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: document migration_dependencies: required: - migrate_files
|
Audio file migration to audio media type:
id: audio_media label: Files migration_tags: - audio_to_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - audio/mpeg - audio/ogg - audio/x-ms-wma - audio/basic - audio/midi - audio/mp4 - audio/prs.sid - audio/x-aiff - audio/x-gsm - audio/x-mpegurl - audio/x-ms-wax - audio/x-pn-realaudio - audio/x-realaudio - audio/x-scpls - audio/x-sd2 - audio/x-wav - audio/x-matroska - audio/webm - audio/* source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_audio_file/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: audio_file migration_dependencies: required: - migrate_files
|
Drush commands for migration of files and media :
We have included migration tags in migration files to use for tagging particular migrations in the drush command. In this, the same tags may be used for multiple files in case someone wants to migrate from several migration files in a single attempt.
We can use drush commands as below for migration using tags.
File migrations:
drush migrate:import --tag="drupal7_file_migration"
|
Files to media migrations:
drush migrate:import --tag="images_media_migration"
|
drush migrate:import --tag="documents_to_media_migration"
|
drush migrate:import --tag="audio_to_media_migration"
|
---------------------------------------------------------------------------------------------------------------------------
Migration of contents from drupal 7 to drupal 9:
MigratIn content migration, the files have some difference in migration from drupal 6 or 7 as in drupal 8/9 the files are referenced to the media entities. In drupal 8 or 9, the contents will consider all files as media and these are related to the file ids used in drupal 8/9 nodes.
I am creating this document as per my experience in migration from drupal 7 to drupal 9.
In this, we will migrate the files as the first step and content in the next steps.
Required modules:
Migration of files from drupal 7 to drupal 9:
Files migration will include the fid, filename, filemime, filesize, status. If you want to migrate the files in auto incremented fids, then you can remove fid from the migration file.
The file migration uses the source site base path to identify the file locations.
Step 1: Create a custom module for migrating the custom content rather than migrating whole content using a drupal migrate module.
Let’s say the module name is custom_migrate. It will contain the following file structure.
- custom_module.info.yml
- module/custom/custom_module/config/install
- module/custom/custom_module/src/Plugin
The install folder will contain all migration files and Plugin will contain custom plugins in case you want any modification while migration.
Step 2: Create a migrate plus group for migration.
Migrate plus group:
Migrate plus group is a file having the source database identification while migration.
The file will be as below:
Put the following code into the custom_module/config/install/migrate_plusmigrate_plus.migration_group.migrate_group.yml file.
# A "migration group" is - surprise! - a group of migrations. It is used to # group migrations for display by our tools, and to perform operations on a # specific set of migrations. It can also be used to hold any configuration # common to those migrations, so it doesn't have to be duplicated in each one.
# The machine name of the group, by which it is referenced in individual # migrations. id: migrate_plus_group
# A human-friendly label for the group. label: Migrate Plus group
# More information about the group. description: Migrate plus group contain database informations
# Short description of the type of source, e.g. "Drupal 6" or "WordPress". source_type: Drupal 7
# Here we add any default configuration settings to be shared among all # migrations in the group. For this example, the source tables are in the # Drupal (default) database, but usually if your source data is in a # database it will be external. shared_configuration: # Specifying 'source' here means that this configuration will be merged into # the 'source' configuration of each migration. source: # A better practice for real-world migrations would be to add a database # connection to your external database in settings.php and reference its # key here. key: migrate
# dependency so the migration_group configuration will be removed on module # uninstall.
|
Details of above file :
- Id: The id of the migration group file is a unique configuration id.
- source_type: Select the drupal version in source type.
- key: The key is important in this file which has the database key name and identifies this key from the settings.php file from the destination site (Drupal 8/9).
This will be added in settings.php as below.
$databases['migrate']['default'] = array ( 'database' => drupal7_databasename, 'username' => 'dbusername', 'password' => 'dbpassword', 'prefix' => '', 'host' => 'dbhost', 'port' => 'port_number', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );
|
The migrate array could be added below the database information of the drupal 8/9 site. Make sure this information is correct with the username, password and hostname of the source site database.
Step 3: Migrate the files from drupal 7 to drupal 9.
Create a migrate file for migrating the files from drupal 7 to drupal 9.
The below file will migrate all types of files in one attempt using the d7_file plugin.
The following code will be placed in custom_module/config/install/migrate_plus.migration.migrate_files.yml
# Every migration that references a file by Drupal 7 fid should specify this # migration as an optional dependency. id: migrate_files label: Public files audit: true migration_tags: - drupal7_file_migration migration_group: migrate_plus_group source: plugin: d7_file constants: # The tool configuring this migration must set source_base_path. It # represents the fully qualified path relative to which URIs in the files # table are specified, and must end with a /. See source_full_path # configuration in this migration's process pipeline as an example. source_base_path: 'https://emaple.com/' process: # If you are using this file to build a custom migration consider removing # the fid field to allow incremental migrations. fid: fid
filename: filename source_full_path: - plugin: concat delimiter: / source: - constants/source_base_path - filepath - plugin: urlencode uri: plugin: file_copy source: - '@source_full_path' - uri filemime: filemime # No need to migrate filesize, it is computed when file entities are saved. # filesize: filesize status: status # Drupal 7 didn't keep track of the file's creation or update time -- all it # had was the vague "timestamp" column. So we'll use it for both. created: timestamp changed: timestamp uid: uid destination: plugin: entity:file
|
The source base path will concat the file path and use the file to migrate from source to destination with all file configurations.
The mapping with source and destination will migrate the information in the database to the database. The file_copy plugin will be to download and upload the files from source to destination.
Step 4: Migrate the files to media from drupal 7 to drupal 9.
The files to media is a process of mapping the referenced fields of media to the file entities in any media type.
We can migrate the files to media by specific file types to particular media types where we can map the files to media type fields in drupal 9. In this, we identify the types of files by the filemime property.
Below is an example of files to media migration.
Images to media migration:
Place below content in this file custom_module/config/install/migrate_plus.migration.migrate_images_media.yml
id: images_media label: Files migration_tags: - images_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - image/jpeg - image/jpeg - image/gif - image/png - image/tiff - image/ief - image/pcx - image/svg+xml - image/vnd.djvu - image/vnd.microsoft.icon - image/vnd.wap.wbmp - image/x-cmu-raster - image/x-coreldraw - image/x-coreldrawpattern - image/x-coreldrawtemplate - image/x-corelphotopaint - image/x-jg - image/x-jng - image/x-ms-bmp - image/x-photoshop - image/x-portable-anymap - image/x-portable-bitmap - image/x-portable-graymap - image/x-portable-pixmap - image/x-rgb - image/x-xbitmap - image/x-xpixmap - image/x-xwindowdump - image/webp - image/* source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_image/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_image/alt: field_file_image_alt_text/0/value field_media_image/title: field_file_image_title_text/0/value Field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: image migration_dependencies: required: - migrate_files
|
The file to media migration can happen after file migration as it will depend upon the file information that will take from the database.
skip_on_value plugin is very useful in this kind of situation where you can migrate specific types of files based on condition. This plugin has three useful parameters: method (optional), not_equal/equal (optional) and value.
There may be two types of method it can use are row and process. Row method will Skips the entire row when an empty value is encountered and the process method will prevents further processing of the input property when the value is empty.
not_equals parameter, If set, skipping occurs when values are not equal. By default this value is equal and true
The value parameter is a single value or array of values against which the source value
should be compared.
Next we used migration_lookup plugin for mapping the files to media fields. migration_lookup is a migration process plugin that gets a value from a previous migration. It is particularly useful for reference fields because it can look up the ID of an entity created by a previous migration.
Similarly we can migrate the documents and audio files to media types easily.
Documents file migration to document media type:
id: documents_media label: Files migration_tags: - documents_to_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - text/html - text/plain - application/acad - application/msword - application/vnd.ms-excel - application/pdf - application/vnd.ms-powerpoint - application/vnd.oasis.opendocument.text - application/vnd.oasis.opendocument.spreadsheet - application/vnd.oasis.opendocument.presentation - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - application/vnd.openxmlformats-officedocument.presentationml.presentation - application/vnd.openxmlformats-officedocument.wordprocessingml.document - application/zip - application/x-7z-compressed - application/x-tar - application/gzip source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_file/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: document migration_dependencies: required: - migrate_files
|
Audio file migration to audio media type:
id: audio_media label: Files migration_tags: - audio_to_media_migration migration_group: migrate_plus_group source: plugin: d7_file scheme: public process: temp1: - plugin: skip_on_value method: row not_equals: true value: - audio/mpeg - audio/ogg - audio/x-ms-wma - audio/basic - audio/midi - audio/mp4 - audio/prs.sid - audio/x-aiff - audio/x-gsm - audio/x-mpegurl - audio/x-ms-wax - audio/x-pn-realaudio - audio/x-realaudio - audio/x-scpls - audio/x-sd2 - audio/x-wav - audio/x-matroska - audio/webm - audio/* source: filemime name: filename uid: node_uid status: status created: timestamp changed: timestamp field_media_audio_file/target_id: - plugin: migration_lookup migration: migrate_files source: fid field_media_in_library: plugin: default_value default_value: true destination: plugin: entity:media default_bundle: audio_file migration_dependencies: required: - migrate_files
|
Drush commands for migration of files and media :
We have included migration tags in migration files to use for tagging particular migrations in the drush command. In this, the same tags may be used for multiple files in case someone wants to migrate from several migration files in a single attempt.
We can use drush commands as below for migration using tags.
File migrations:
drush migrate:import --tag="drupal7_file_migration"
|
Files to media migrations:
drush migrate:import --tag="images_media_migration"
|
drush migrate:import --tag="documents_to_media_migration"
|
drush migrate:import --tag="audio_to_media_migration"
|
---------------------------------------------------------------------------------------------------------------------------
Migration of contents from drupal 7 to drupal 9:
Migration of the contents of a specific content type from drupal 7 to a particular content type in drupal 9:
In the content content migration, we will use the same Migrate Plus group yml file that has database key information.
# A "migration group" is - surprise! - a group of migrations. It is used to # group migrations for display by our tools, and to perform operations on a # specific set of migrations. It can also be used to hold any configuration # common to those migrations, so it doesn't have to be duplicated in each one.
# The machine name of the group, by which it is referenced in individual # migrations. id: migrate_plus_group
# A human-friendly label for the group. label: Migrate Plus group
# More information about the group. description: Migrate plus group contain database informations
# Short description of the type of source, e.g. "Drupal 6" or "WordPress". source_type: Drupal 7
# Here we add any default configuration settings to be shared among all # migrations in the group. For this example, the source tables are in the # Drupal (default) database, but usually if your source data is in a # database it will be external. shared_configuration: # Specifying 'source' here means that this configuration will be merged into # the 'source' configuration of each migration. source: # A better practice for real-world migrations would be to add a database # connection to your external database in settings.php and reference its # key here. key: migrate
# dependency so the migration_group configuration will be removed on module # uninstall.
|
And the same database configurations.
$databases['migrate']['default'] = array ( 'database' => drupal7_databasename, 'username' => 'dbusername', 'password' => 'dbpassword', 'prefix' => '', 'host' => 'dbhost', 'port' => 'port_number', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );
|
Now we will identify and do some analysis on the fields of source and destination content type and decide the fields to map the source fields to destination fields.
Here we will consider a few content type cases for fields in source and destination.
- Two basic text fields and one Text (formatted, long, with summary) field.
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: d7_node node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html uid: node_uid title: title Moderation_state: #If you want to add the Moderation status of content. - plugin: default_value default_value: published created: created changed: changed promote: promote sticky: sticky revision_uid: revision_uid revision_log: log revision_timestamp: timestamp langcode: - plugin: default_value source: language default_value: nl destination: plugin: 'entity:node' default_bundle: destination_content_type_name
|
Here in the above migration file, we could see a few plugins used according to fields. Default_value plugin is used for mapping the source and destination basic text fields values.
sub_process plugin enables an inherited process for one field of other types like formatted, reference entity fields, date fields etc.
- Content types have media/file fields.
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: d7_node node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html
field_destination_attachment:
-
plugin: sub_process
source: source_attachment_field_name
process:
target_id:
plugin: migration_lookup
source: fid
migration: documents_media uid: node_uid title: title Moderation_state: #If you want to add the Moderation status of content. - plugin: default_value default_value: published created: created changed: changed promote: promote sticky: sticky revision_uid: revision_uid revision_log: log revision_timestamp: timestamp langcode: - plugin: default_value source: language default_value: nl destination: plugin: 'entity:node' default_bundle: destination_content_type_name
migration_dependencies:
required:
- documents_media
|
field_destination_attachment field in the above migration file is a reference field. In this, we have used migration look_up to map the file ids of document media migration results. The target id will be updated as per migration map table in the database database look like the image below.

The documents_media migration also added as dependency migration in this file. So this condition will migrate the files from D7 to the media entity in D9.
- Content types have a taxonomy reference field.
In taxonomy reference fields, we have to do analysis on the contents of this content type to get an idea about terms used in contents. If source contents have terms that do not exist on d9, then we first migrate the taxonomy terms or create those manually in d9 then after we will migrate contents.
Now we will migrate the taxonomy vocabularies and terms.
id: taxonomy_vocabulary label: Taxonomy vocabularies Migration_tags: taxonomy_vocabularies_tag
migration_group: migrate_plus_group source: plugin: d7_taxonomy_vocabulary process: vid: - plugin: make_unique_entity_field source: machine_name entity_type: taxonomy_vocabulary field: vid length: 30 migrated: true - # This plugin checks if the vocabulary being migrated is the one used by # Forum. If so, we use the machine name that Forum expects. Otherwise, we # leave it unchanged. plugin: forum_vocabulary machine_name: forums label: name name: name description: description weight: weight destination: plugin: entity:taxonomy_vocabulary
|
Taxonomy terms migration file.
id: taxonomy_term label: Taxonomy terms audit: true Migration_tags: taxonomy_terms_tag
migration_group: migrate_plus_group deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver source: plugin: d7_taxonomy_term process: # If you are using this file to build a custom migration consider removing # the field to allow incremental migrations. tid: tid vid: plugin: migration_lookup migration: taxonomy_vocabulary source: vid name: name 'description/value': description 'description/format': format weight: weight # Only attempt to stub real (non-zero) parents. parent_id: - plugin: skip_on_empty method: process source: parent - plugin: migration_lookup migration: d7_taxonomy_term parent: plugin: default_value default_value: 0 source: '@parent_id' forum_container: is_container changed: timestamp langcode: language destination: plugin: entity:taxonomy_term migration_dependencies: required: - taxonomy_vocabulary
|
Now we will do mapping of reference fields based on taxonomy migration files.
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: d7_node node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html field_reference_name: - plugin: sub_process source: source_field_reference_name process: target_id: plugin: migration_lookup source: tid migration: taxonomy_term uid: node_uid title: title Moderation_state: #If you want to add the Moderation status of content. - plugin: default_value default_value: published created: created changed: changed promote: promote sticky: sticky revision_uid: revision_uid revision_log: log revision_timestamp: timestamp langcode: - plugin: default_value source: language default_value: nl destination: plugin: 'entity:node' default_bundle: destination_content_type_name migration_dependencies: required: - taxonomy_term
|
If the destination taxonomy term is the same for all contents, then we can use the default_value plugin and the default value will be the destination tid.
- Content types have a date field.
For date fields migration, we can migrate the date in different date formats and timezone.
The source date fields have date value in array format. So we need to extract the array then map the values from array keys to destination fields. This array will include the date and time values.
The date field has field_value and field_end_value as date and time in the database. So one date field will be mapped in two fields in a migration file.
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: d7_node node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html field_date_name/value:
-
plugin: extract
source: source_date_field_name
index:
- '0'
- value
-
plugin: format_date
from_format: 'Y-m-d H:i:s'
to_format: 'Y-m-d\TH:i:s'
field_meeting_time/end_value:
-
plugin: extract
source: source_date_field_name
index:
- '0'
- value2
-
plugin: format_date
from_format: 'Y-m-d H:i:s'
to_format: 'Y-m-d\TH:i:s' uid: node_uid title: title Moderation_state: #If you want to add the Moderation status of content. - plugin: default_value default_value: published created: created changed: changed promote: promote sticky: sticky revision_uid: revision_uid revision_log: log revision_timestamp: timestamp langcode: - plugin: default_value source: language default_value: nl destination: plugin: 'entity:node' default_bundle: destination_content_type_name
|
- Migrate the contents that have a specific taxonomy term referenced (For example, migrate articles or basic pages that have specific tag)
To migrate such contents, we need to extend the source plugin query method and add one condition there for a particular taxonomy term.
We will add one file in src/Plugin/migrate/source/extend_source_plugin in our custom_module to alter the query before it filters the contents from source to migrate.
Add namespace and use statement in this class like below:
namespace Drupal\az_migration\Plugin\migrate\source;
use Drupal\migrate\Row; use Drupal\node\Plugin\migrate\source\d7\Node as d7_node; use Drupal\migrate\Plugin\migrate\source\SqlBase; use Drupal\migrate\Plugin\MigrateSourceInterface;
|
This class will extend the d7_node alias and implement the MigrateSourceInterface class.
class MigratePublishedNodes extends d7_node implements MigrateSourceInterface {
/**
* Published specific nodes from the d7 database.
*
* @MigrateSource(
* id = "migrate_specific_nodes",
* source_module = "node"
* )
*/
class MigratePublishedNodes extends d7_node implements MigrateSourceInterface { /** * {@inheritdoc} */ public function query() { $query = parent::query(); $migration_id = $this->migration->id(); // Only migrate published records. Remove the below line if you want to migrate the unpublished node also. $query->condition('n.status', 1); // Only migrate contents having specific taxonomy terms switch ($migration_id) { case 'migrate_conten'’: // Add source taxonomy id in $tids variable, this can be multiple in case you want to migrate contents which have multiple taxonomy ids. $tids = [101]; $query-> join('field_data_field_reference_fields', 'frf', 'n.nid = frf.entity_id'); $query->condition('fbt.field_terms_tid', $tids, 'IN'); break; default: } return $query; } }
|
The altered source plugin will be used as a new source plugin migrate_specific_nodes now for migration. This plugin will migrate contents that have 101 taxonomy terms as reference.
The updated migration file for content will be as below:
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: migrate_specific_nodes node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html field_date_name/value: - plugin: extract source: source_date_field_name index: - '0' - value - plugin: format_date from_format: 'Y-m-d H:i:s' to_format: 'Y-m-d\TH:i:s' field_meeting_time/end_value: - plugin: extract source: source_date_field_name index: - '0' - value2 - plugin: format_date from_format: 'Y-m-d H:i:s' to_format: 'Y-m-d\TH:i:s' uid: node_uid title: title Moderation_state: #If you want to add the Moderation status of content. - plugin: default_value default_value: published created: created changed: changed promote: promote sticky: sticky revision_uid: revision_uid revision_log: log revision_timestamp: timestamp langcode: - plugin: default_value source: language default_value: nl destination: plugin: 'entity:node' default_bundle: destination_content_type_name
|
If we want to map these all specific contents to a particular taxonomy in destination then we can use the default_value plugin and default_value will be taxonomy term id.
field_detination_reference: - plugin: default_value default_value: 102
|
ion of the contents of a specific content type from drupal 7 to a particular content type in drupal 9:
In the content content migration, we will use the same Migrate Plus group yml file that has database key information.
# A "migration group" is - surprise! - a group of migrations. It is used to # group migrations for display by our tools, and to perform operations on a # specific set of migrations. It can also be used to hold any configuration # common to those migrations, so it doesn't have to be duplicated in each one.
# The machine name of the group, by which it is referenced in individual # migrations. id: migrate_plus_group
# A human-friendly label for the group. label: Migrate Plus group
# More information about the group. description: Migrate plus group contain database informations
# Short description of the type of source, e.g. "Drupal 6" or "WordPress". source_type: Drupal 7
# Here we add any default configuration settings to be shared among all # migrations in the group. For this example, the source tables are in the # Drupal (default) database, but usually if your source data is in a # database it will be external. shared_configuration: # Specifying 'source' here means that this configuration will be merged into # the 'source' configuration of each migration. source: # A better practice for real-world migrations would be to add a database # connection to your external database in settings.php and reference its # key here. key: migrate
# dependency so the migration_group configuration will be removed on module # uninstall.
|
And the same database configurations.
$databases['migrate']['default'] = array ( 'database' => drupal7_databasename, 'username' => 'dbusername', 'password' => 'dbpassword', 'prefix' => '', 'host' => 'dbhost', 'port' => 'port_number', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );
|
Now we will identify and do some analysis on the fields of source and destination content type and decide the fields to map the source fields to destination fields.
Here we will consider a few content type cases for fields in source and destination.
- Two basic text fields and one Text (formatted, long, with summary) field.
id: migrate_content label: Nodes To Migrate deriver: Drupal\node\Plugin\migrate\D7NodeDeriver field_plugin_method: alterFieldInstanceMigration cck_plugin_method: null migration_tags: - migrate_content_tag migration_group: migrate_plus_group source: plugin: d7_node node_type: source_node_type process: Field_text_field_1: #this is destination field name - plugin: default_value default_value: source_fieldname_1 Field_text_field_2: - plugin: default_value default_value: source_fieldname_2 body: plugin: sub_process source: body process: value: value format: - plugin: default_value default_value: basic_html/full_html uid: node_uid
|