"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
Data migration to Drupal using Migrate Module
1. Data migration to Drupal - Using the migrate module
Ishan Mahajan
DrupalCamp Delhi
April, 2011
2. Agenda
● Migrate module
●
Steps to work with migrate module
● Hooks
● Building classes
– Description
– Adding source
– Mapping
– Process data
● Walk through an example migration – TYPO3 to Drupal
● Code Heavy! - you may fall asleep
3. Migrate Module
● Provides a flexible framework for migrating content into Drupal
● Supports core Drupal objects such as nodes, users, taxonomy
terms and comments.
● Can define your own import handler
● Can define your own field handler
● Supports migration from XML, JSON, CSV, Databases
Cont...
4. Migrate Module (cont..)
● Incremental migrations
● Drush commands for import, listing, status, rollback etc
● Only status UI – all mappings must to be done in code
5. Migration example
● Migrate 'tt_news' from TYPO3 to Drupal
● Talk about a small aspect of the migrate module (migrating
nodes of type news)
● Not talking about creating own DestinationHandlers and
FieldHandlers
● Migrating from a MySQL database
● Both the database are on the same machine
7. Step 1: implement hook
● Define your own module and let the migrate module know about
it
● Implement hook_migrate_api
function mymodule_migrate_api() {
return array(
'api' => 2,
);
}
8. Step 2: define migration class
● Give description
● Let migrate know about the source of your content
● Let migrate know about the destination type
● Map the source and destination fields
● Massage the data before being migrated.
9. Step 2(contd)
class Typo3NewsMigration extends Migration {
public function __construct() {
parent::__construct();
...
}
public function prepare(stdClass $node, stdClass $row) {
...
}
}
10. Functions
● public function __construct() {..}
● Define the destination type(node, user, comment etc)
● Describe the source(databse, xml etc.)
● Field mappings
● (optional) public function prepare(stdClass $node,
stdClass $row) {..}
● Massage the data that was pulled in – clean up text,
links etc.
11. Step 2a: Give Description
● Class description
$this->description = t('News migration from TYPO3');
● Dependencies
$this->dependencies = array('Typo3NewsCategory');
● Create map object - tracking the relationships between source row and Drupal object
$this->map = new MigrateSQLMap($this->machineName,
array(
'uid' => array(
'type' => 'int',
'alias' => 'tn',
)
),
MigrateDestinationNode::getKeySchema()
);
13. Incremental Migrations
● Import items which have been added/edited since the last
migration
● “high-water” mark for each migration class
$this->highwaterField = array(
'name' => 'last_changed', // Column to be used as highwater
mark
'alias' => 'tn', // Table alias containing that column
);
$query->orderBy('last_changed');
14. Step 2c: Map the Data
● Let the migrate module know the type of source
$this->source = new MigrateSourceSQL($query);
● Similarly provide the destination handler
$this->destination = new MigrateDestinationNode('news');
15. Step 2d: Map the fields
● Field mapings take the form
● $this->addFieldMapping(‘destination_field_name’,
‘source_field_name’);
● Can define default values
● $this->addFieldMapping('language')
->defaultValue('en');
● File fields require additional arguments
16. Step 2d(contd.)Fields
// Mapped fields
$this->addFieldMapping('title', 'title')
->description(t('Title of the node'));
$this->addFieldMapping('field_news_author_email', 'author_email');
...
// Image field
$arguments = MigrateFileFieldHandler::arguments(drupal_get_path('module', 'news') . '/pics', 'file_copy', FILE_EXISTS_RENAME);
$this->addFieldMapping('field_news_images', 'image')
->arguments($arguments)
->separator(',');
// just pass the taxonomy name
$this->addFieldMapping('News Category', 'newstags')
->separator(',');
// node reference field
$this->addFieldMapping('field_news_related_articles', 'related_list')
->sourceMigration('Typo3News')
->separator(',');
17. Step 3: Massage the data
● On its way to Drupal!
public function prepare(stdClass $node, stdClass $row) {
$node->status = ($row->hidden) ? '0' : '1';
$node->body = $this->processLinkTag($node->body);
}