This article is feedback on my first use of Migrate, a module that allows you to import content from just about any data source into a Drupal site.
By the way, I've contributed some documentation on this module here, because although it's already very detailed, I couldn't find a point dedicated to translations.
Modules used:
- Migrate : 7.x-2.6-RC1
- Migrate_extras : 7.x-2.5, for custom entities.
In the article, I assume you have a structure like in the documentation: https://drupal.org/node/2218843
From entityreference to entityreference
Content types and data provided
| Content type 1 en | -> | Content type 1 en | Title, content type code 1 |
| ^ | ^ | ||
| Content type 2 en | <--> | Content type 2 en | Title, content type code 1, content type code 2 |
| ^ | |||
| Content type 3 en | -> | Content type 3 en | Title, title content type 2 |
Content type 2 to content type 1
In the case of the reference from content type 2 to content type 1, as in the data provided there is the code identifying the node of content type 1, we can find its id thanks to a callback function during mapping. This function will be based on an EntityFieldQuery that can filter on the language and the value of the code.
$this->addFieldMapping('field_contenttype1', 'contenttype1_code')
->callbacks(array($this, 'getcontenttype1nid'));
protected function getcontenttype1nid($value) {
$query = new EntityFieldQuery();
$node_list = $query->entityCondition('entity_type', 'node')
->propertyCondition('type', 'contenttype1')
->propertyCondition('language', str_replace('_', '-', $this->arguments['language_prefix']))
->fieldCondition('field_contenttype11_code', 'value', $value, '=')
->execute();
if (isset($node_list['node'])) {
$node_nid_list = array_keys($node_list['node']);
$value = $node_nid_list['0'];
}
return $value;
}Content type 3 to content type 2
Here as there is a risk of uncertainty due to the fact that we only have the title of content type 2 that is given and with translations there are risks of problems due to non-accurate translations. It's better to rely on the management of content type 2 translations as explained on this documentation page.
As translations at the level of the same content type are mastered and as the management of references at the level of the main language (in this case English) between different content types is also mastered. So we're going to take a diversion via this reference to find the right references in the other languages.
Importing custom entities
Migrate works very well with kernel entities, such as nodes, users, taxonomy terms, etc. On the other hand for custom entities there it's a bit more complicated. For everything commerce, there's Migrate commerce, for entities created from entity API it should pass but I haven't tested it yet, for entities created from ECK there on the other hand it's not perfected yet.
Even if the import can be done, Migrate cannot determine the id of the entity created and therefore (apart from error messages during the import) it cannot rollback and for it the entities will not have been imported. This means that the import must be done in one go.
Here are the changes you need to make to create custom entities:
$this->destination = new MigrateDestinationEntityAPI('my_entity', 'bundle_of_my_entity'); $this->map = new MigrateSQLMap($this->machineName, array( 'csv_id' => array( 'type' => 'int', unsigned' => TRUE, not null' => TRUE, ) ), MigrateDestinationEntityAPI::getKeySchema() );
Miscellaneous comments
Data pre-processing
In the prepareRow function, it is possible to modify the data, which is handy for concatenating several pieces of data and for example adding HTML tags.
$row->description = '
' . $row->description. '
' . $row->description_2 . '
';
Adjusting values
It is possible to modify values on the fly, with a callback function on a particular mapping, which comes in handy when the data provided is not complete and is on the site, so you can go and get it to adjust.
$this->addFieldMapping('field_drupal', 'data')
->callbacks(array($this, 'change_donnee'));Then we need to implement a change_donnee function that will take care of the adjustment.
Combining data
In the prepareRow function, it is possible to create new data from other data. For example:
$row->new_data = $row->data_1 . ' - ' . $row->data_2;
Then in field mapping, we can use:
$this->addFieldMapping('field_drupal', 'new_data');Conclusion
I really found this module excellent, because you can really do what you want with the data, start from any source (and even several simultaneously, but I haven't had that need yet), do processing before, during, after the import. Manage content that doesn't yet exist, but that hasn't been tested yet either. And manage a whole host of other more or less complicated cases.
There's a reason it's in the core of Drupal 8.