Migrate es genial, a resumidas cuentas te permite importar información desde varias fuentes. Así de simple.
En este post voy tocar dos cosas muy por encima. Qué puede importar y como implementar Migrate (este modulo no importa nada por si mismo)
Primero lo primero:
¿Desde donde te deja importar información?
- SQL (Cualquier DB que Drupal sea capaz de leer)
- XML
- List
- CSV
- JSON
- MSSQL (Microsoft SQL Server)
- Oracle
- Multi items
Y esas son las fuentes que provee Migrate, pero cualquier módulo puede añadir nuevas fuentes sin mayor problema. pueden ver en detalle cada una de las clases que implementa los sources en https://drupal.org/node/1006986
¿Que puede crear con la información que importa?
- Nodos
- Comentarios
- Archivos
- Menus
- Items de menu
- Roles
- Tablas en la DB
- Terminos
- Usuarios
Y una vez mas esas son las fuentes que provee Migrate, pero cualquier módulo puede añadir nuevos destinos. por ejemplo algun modulo puede proveer la implementación para crear profiles de Profile2. La información en detalle de cada una de las clases que implementan estos “destinos” la pueden ver en https://drupal.org/node/1006988
Ok ahora vamos a implementar Migrate en un módulo. Para hacerlo no puede ser más fácil. Solo necesitas 2 cosas: un hook y extender de una clase
Nuestro módulo de ejemplo se llama “migrate_posts” que va a copiar todos los posts que hay en mi blog (WordPress) usando como fuente la DB (El source es SQL en este caso)
La onda en la siguiente:
Primero tenemos que crear un archivo migrate_posts.migrate.inc y dentro de él definir el hook_migrate_api() que es el que le da la información necesaria a Migrate sobre nuestra implementación:
<?php
/**
* Implements hook_migrate_api().
*/
function migrate_posts_migrate_api() {
$api = array(
'api' => 2,
'groups' => array(
'wordpress' => array(
'title' => t('Importación de posts desde WordPress'),
),
),
'migrations' => array(
'WPFromDB' => array(
'class_name' => 'WPMigrationFromDB',
'group_name' => 'wordpress',
),
),
);
return $api;
}
El HOOK necesita 3 cosas:
Que le digas que API vas a usar (Siempre es la 2 salvo que cuando leas este artículo hayan sacado la versión 3.x del módulo). Que le indiques un grupo y por ultimo que le indiques cual es tu migrator
Desglosemos esto:
Un grupo es simplemente un “tag” donde vas a agrupar todos los migrators que vos créas conveniente. Por ejemplo, si quisieras crear un importador de posts y otro importador a parte para los comentarios, entonces meterías los dos migrators dentro del grupo de “wordpress”.
En “migrations” definimos el nombre máquina de nuestro importador (WPFromDB), el nombre de la clase que va a realizar la acción (WPMigrationFromDB) y el grupo al que pertenece.
Lo último que queda por aclarar es que “migrate_posts.migrate.inc” es la convención que usa Migrate, por lo que no hace falta hacer un require/include en tu .module
Ya hemos terminado con el primer paso, vamos al segundo. La clase de importacion.
Creamos un archivo .inc que es el que va a contener la clase. por ejemplo “posts-migrator-from-db.inc” y en el .info de tu modulo lo agregas (files[] = posts-migrator-from-db.inc)
Y dentro de él ponemos la clase:
<?php
class WPMigrationFromDB extends Migration {
public function __construct($arguments) {
parent::__construct($arguments);
// #############################################
// Definición del source (desde donde vamos a obtener la información)
Database::addConnectionInfo('temporal', 'MI_DB', array(
'driver' => 'mysql',
'database' => 'MI_DB',
'username' => 'USUARIO',
'password' => 'CONTRASEÑA',
'host' => 'localhost',
));
$query = Database::getConnection('MI_DB', 'temporal')
->select('wp_posts', 'posts')
->fields('posts', array(
'id',
'post_date',
'post_modified',
'post_title',
'post_content',
))
->condition("post_type", "post", "=")
->condition("post_status", "publish", "=");
$this->source = new MigrateSourceSQL($query);
// #############################################
// Definición del destino (lo que se va a crear con los datos conseguidos)
$this->destination = new MigrateDestinationNode('page');
// #############################################
// Indicamos cual es el identificador UNICO de cada elemento que se consiga desde la fuente
$this->map = new MigrateSQLMap($this->machineName,
array(
'id' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
)
),
MigrateDestinationNode::getKeySchema()
);
// #############################################
// Mapeo de los valores del origen y destino
$this->addFieldMapping('uid')->defaultValue(1);
$this->addFieldMapping('created', 'post_date');
$this->addFieldMapping('changed', 'post_modified');
$this->addFieldMapping('title', 'post_title');
$this->addFieldMapping('body', 'post_content');
}
}
No voy a profundizar en la implementación de la clase porque este post es solo para demostrar lo fácil que es implementar Migrate. Ya vendrán post hablando de las clases.
Y básicamente te eso es todo lo que necesitas para implementar Migrate.
Bueno, ahora usamos drush
Limpiamos el cache para que Drupal lea el .info de nuestro módulo y sepa que “posts-migrator-from-db.inc” existe
drush cc all
Registramos nuestro migrator:
drush migrate-register
Revisamos que el migrator se haya registrado:
drush migrate-status
Que deberia devolver:
Group: wordpress Total Imported Unprocessed Status Last imported
WPFromDB 169 0 169 Idle 2013-06-12 17:59:17
Y si todo está ok, podemos importar nuestros posts:
drush migrate-import WPFromDB
Y para deshacer la importación:
drush migrate-rollback WPFromDB
Chau!