Daniel Medeiros 15 Jun, 2023
Drupal migration challenges: How to import a field collection data from D7 into a content type in D9

It’s not news to anyone that Drupal 7 is at the end of its life. After several postponements, support for Drupal 7 will be discontinued on January 5th, 2025. 

Defining a data migration plan for Drupal 8 and 9 releases can be a big challenge, but this is a crucial time for the development and product team to review and improve the data modeling.

In more basic scenarios like migrating content type to content type, taxonomies to taxonomies, etc. there is an established, well-paved road.

The migration effort involves three steps (see diagram below):

1. Extract data using a source plugin. In our case, the source is a SQL database from Drupal 7.                
2. Map the fields between the versions and transform them using process plugins.                
3. Finally, load data using a destination plugin.

In summary, migration is an ETL process: Extract - Transform - Load.

migration - ETL process


The Problem

Our editorial workflow created many revisions, whereas our content type with field collection generated many new rows in our database. To resolve this issue, we needed to change the data structure.                

Consider this hypothetical scenario:  An educational Drupal 7 website, with a content type called course and with a field called field_course_variation, pointed to a field collection entity. This field collection has a bunch of other fields.                
 

The Requirements

Install and enable the following contrib modules:

https://www.drupal.org/project/migrate_plus                
https://www.drupal.org/project/migrate_tools

Add the following array in your local.settings.php     

To connect your legacy Drupal 7, databases must only add the array above in your local.settings.php. To do things simply, keep the array's name to "migrate."               
 

The Challenge 

Now we import the entity collection into a new content type denominated course_variation. Each field attached to the collection entity will be a field of this new content type. You must import this entity collection into this new content type in Drupal 9.

This is a particular requirement, and there is no out of box solution for it. We have a source plugin to import data from a field collection into a paragraph, but not for a node. So, let's work on coding a new migrate source plugin.                
 

Hands-on

To start, we can create a new class with the following path: /src/Plugin/migrate/source/Course.php        

Now almost everything we need to do is an extension of the primary class  Called: namespace Drupal\paragraphs\Plugin\migrate\source\d7;   

We need to build a query to fetch our field collection data, as we know that any field collection data is attached to a node type.    

This is the most crucial point in this process. The method setSourceProperty defines the field_collection  bundle for us. In our case, the bundle is called field_course.   

The method getFields will run all attached fields in the field collection and bring them into an array. Once we have our source plugin ready, we need to write our yaml file and tell it the name of our custom source plugin. In this example, it is called "field_collection_custom_source".

The file will look like this:

Finally, we need to import this configuration: drush config-import --partial

then run the drush command, which is available in the migrate tools module mentioned above. 

Drush migrate: import awesome_courses

READY! Your new content type is filled out with field collection data at this stage.


References:
https://www.drupal.org/docs/drupal-apis/migrate-api/migrate-api-overview