Details documentation on migration.

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:

  • Drupal 7
  • Configuration

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:

  • Migrate
  • Migrate drupal

 

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:

  • Migrate
  • Migrate drupal

 

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.

  1. 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.


 

  1. 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.


 

  1. 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.


 

  1. 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



 

  1. 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.

  1. 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: