Migrando Usuarios desde un archivo CSV a Drupal 8

En un proyecto tuvimos la necesidad de trasladar los usuarios desde la plataforma https://www.ning.com/ hacia un sitio Drupal.


Por suerte la plataforma permite exportar los usuarios registrados en un archivo CSV con la siguiente estructura de columnas:

  • Name
  • Profile Address
  • Email
  • Gender
  • Location
  • Country
  • Zip
  • Age
  • Birthdate
  • Date Joined
  • Receiving Broadcasts?
  • Receiving Any Emails?
  • Last Visit
  • Profesión u Ocupación
  • Institucion o lugar de trabajo

 

Esta información en formato CSV va a ser nuestra fuente (Source) de Migración, es decir, desde donde obtendremos los datos a migrar.

 

Por otro lado los usuarios de nuestro drupal están configurados con los siguientes campos:

  • field_user_city
  • field_user_zip
  • field_user_receive_mail
  • field_user_broadcasts
  • field_user_age
  • field_user_birthdate
  • field_user_gender
  • field_user_name
  • field_user_country
  • field_user_profession

 

La entidad Usuario Drupal va a ser el destino (Destination) de la Migración, es decir, hacia donde pasaran los datos migrados.

 

Para migrar vamos a usar "Migrate API" que está incorporado en el core de Drupal 8, a través del módulo Migrate. Esta API asume tres elementos en una Migración:

  • La Fuente
  • Transformación de datos cuando es necesario
  • El Destino

 

Drupal Migrate Process

La imagen nos indica que toda migración se define en un Plugin de Migración (Migration Plugin). Gracias al módulo "Migrate Plus" este plugin lo podremos definir como un "Entity Configuration", y lo podremos agregar a nuestro proyecto Drupal en un módulo a través de un archivo .yml en el install que nos defina este entity configuration.

 

Notemos además que se menciona tres tipos adicionales de plugin, uno por cada elemento del proceso de migración:

  • Source Plugin
  • Process Plugin
  • Destination Plugin

Estos plugins son aquellos que nos permitirán resolver casos particulares. Por ejemplo, para la migración que vamos a realizar ahora nuestra fuente (Source) es un archivo CSV, entonces vamos a necesitar un "Source Plugin" que obtiene datos desde un archivo CSV, y esto lo encontramos en un módulo contribuido llamado "Migrate Source CSV". Existen otros "Source Plugin" para obtener datos desde otras entidades Drupal, desde tablas de una base de datos relacional y muchos otros. Y podemos construir nuestros propios plugins para nuestras necesidades particulaes.

 

Por otro lado tenemos los plugin de transformación de datos o "Process Plugin". Estos son los encargados de realizar modificaciones en los datos originales, provenientes de la fuente para adoptarlos a lo que se necesita enviar al destino.

 

Finalmente, los "Destination Plugin" son aquellos que se encargan de enviar y almacenar los datos en Drupal, por ejemplo guardarlo en un Nodo, en un Usuario.

 

Módulos Necesarios

  • Migrate (Core). Es el que proporciona el framework de migración.
  • Migrate Tools. Nos brinda varias herramientas de migración, incluyendo varios comandos Drush para ver la lista de migraciones, iniciar una migración, hacer rollback y algunas otras. Inicialmente el UI de Migrate no contenía estas opciones aunque actualmente es posible que ya tenga varias de las opciones acá presentes, tal como indica la documentación de este módulo.
  • Migrate Plus. Brinda varias extensiones, entre ellas la posibilidad de crear un "Migration Plugin" como una entidad de configuración, que en este caso nos servirá para crear nuestro "Migration Plugin".
  • Migrate Source CSV. Es el módulo que nos va a permitir importar desde un archivo CSV.
  • Módulo Personalizado: mexample. Este módulo es el que va a contener el "Migration Plugin", configurando la fuente, el destino, y también vamos a mapear los campos de la fuente con el destino, y en algunos casos indicar como se van a procesar. Incluso crearemos una función para procesar algunos elementos.

Módulo Personalizado

Crearemos un módulo personalizado que tendrá dentro de la carpeta config/install, el archivo migrate_plus.migration.migrate_csv.yml que define nuestro "Migration Plugin".

uuid: 5c12fdab-6767-485e-933c-fd17ed554b27
dependencies:
  enforced:
    module:
      - mexample
id: migrate_csv
migration_group: null
label: 'CSV file migration'
source:
  plugin: csv
  path: public://csv/memberdata.csv
  header_row_count: 1
  keys:
    - id
  column_names:
    -
      id: Identifier
    -
      name: Name
    -
      email: Email
    -
      gender: Gender
    -
      location: Location
    -
      country: Country
    -
      zip: Zip
    -
      age: Age
    -
      birthdate: Birthdate
    -
      date_joined: 'Date Joined'
    -
      broadcasts: 'Receiving Broadcasts'
    -
      receiving_emails: 'Receiving Any Emails'
    -
      last_visit: 'Last Visit'
    -
      profession: Profession
process:
  name: email
  mail: email
  status:
    plugin: default_value
    default_value: 1
  field_user_city: location
  field_user_zip: zip
  field_user_receive_mail:
    plugin: static_map
    source: receiving_emails
    map:
      Yes: 1
      No: 0
  field_user_broadcasts:
    plugin: static_map
    source: broadcasts
    map:
      Yes: 1
      No: 0
  field_user_age: age
  field_user_birthdate: birthdate
  field_user_gender:
    plugin: callback
    callable: strtolower
    source: gender  
  field_user_name: name
  field_user_country:
    plugin: callback
    callable: mexample_iso_country
    source: country
  field_user_profession: profession
destination:
  plugin: 'entity:user'
migration_dependencies:
  required: {  }
optional: {  }

 

Algunos comentarios sobre el archivo:

  • uuid es el Identificador Único Universal de esta entidad. Todas las entidades en Drupal requieren un uuid. Si no le colocamos uno en este archivo que vamos a importar, Drupal le generará uno. De tal manera que podríamos obviar este valor. Usualmente se le coloca uno ya existente cuando queremos que copias del mismo proyecto puedan identificar la configuración única, al exportar configuraciones, por ejemplo.
  • Colocamos en dependencies -> enforced -> module el nombre de nuestro módulo para que esta entidad dependa de nuestro módulo, de tal manera que cuando lo desinstalemos, lo retire de la configuración de Drupal.
  • id, es el valor con el que se identificará nuestra migración, por ejemplo al enviar el comando con drush.
  • migration_group, si es que queremos organizar varias migraciones en grupo.
  • source, es como decíamos las fuente de migración y acá configuramos varios detalles, como por ejemplo que será un csv, en donde estará ubicado el archivo (o url si es que fuera el caso) y otros detalles.
  • En process, vamos a ir mapeando los campos del origen con el destino. E indicando si en ese camino se va a realizar alguna transformación. Vemos que hay varias transformaciones que estamos realizando, como cuando usamos el plugin "static_map", que significa que los valores que llegan se reemplazan por otros pre-establecidos, por ejemplo "yes" por 1, y "no" por 0 en el campo "field_user_receive_mail". También podemos asignar un valor por defecto con el plugin "default_value". Otro process plugin muy útil es el que llama a una función para que realice la transformación, ya sea una función propia de PHP o una personalizada que nosotros podemos haber desarrollado, es el plugin "callback".
  • En el archivo también vemos que se define el destination. En este caso usa el plugin "entity:user" para hacer que los datos se graben en el usuario.

Adaptar el archivo CSV

Para que nuestra migración funcione sin inconvenientes es necesario realizar algunos cambios a nuestro archivo CSV.

  • Crear un campo identificador único. Como migrate hace un mapeo entre los registros que va leyendo y lo que almacena en Drupal, requiere tener una forma de identificar cada elemento de manera única. Esto también servirá para hacer rollback en caso necesario. Para generar el campo único podemos abrir el archivo CSV en una hoja de cálculo, crear una columna y utilizar las opciones para rellenar números correlativos.
  • Cambiar de orden a los campos. Los "column_names" los hemos colocado como lista, por lo que "Migrate Source CSV" identifica los campos por el orden que hemos definido en el archivo YML. Otra opción sería indicar en el archivo YML el índice del campo que nos interesa (comenzando desde 0). Es necesario por tanto modificar este orden para que coincidan entre ellos.
  • Finalmente cambiar el nombre de los campos del archivo CSV. Aunque como hemos visto no influye en la migración, nos ayuda a identificar sin errores la correspondencia entre los campos.

 

Ejecutar la Migración

  1. Instalamos todos los módulos requeridos.
  2. Instalamos nuestro módulo personalizado. De esta manera la entidad de configuración "Migration Plugin" que estamos creando pasa a nuestro sitio Drupal.
  3. Mediante comandos de Drush podemos:
    1. Ver la migración
    2. Ejecutarla
    3. Ver los resultados
    4. Hacer rollback

 

Comandos más frecuentes:
migrate-status (ms)     List all migrations with current status.
migrate-import (mi)     Perform one or more migration processes
migrate-rollback (mr)     Roll back the destination objects from a given migration

Ejemplos:

Haciendo migrate status antes de importar. Muestra todos los "Migration Plugins" existentes.  Indicando cuantos registros hay para importar, cuantos han sido importados y cuantos faltan procesar.

Migrate Status

Haciendo una importación. Necesitamos indicar el id del "Migration Plugin" como parámetro.

Migrate Import

Haciendo un migrate status luego de importar.

Datos Migrados

Haciendo un migrate rollback. También es necesario indicar el id del "Migration Plugin" como parámetro.

Migrate Rollback

 

Otros comandos drush:
migrate-analyze (maz)     Analyze the source fields for a migration.
migrate-audit (ma)     View information on problems in a migration.
migrate-register (mreg)     Register or re-register any statically defined migrations.
migrate-deregister     Remove all tracking of a migration
migrate-fields-destination (mfd)     List the fields available for mapping in a destination.
migrate-fields-source (mfs)     List the fields available for mapping from a source.
migrate-import (mi)     Perform one or more migration processes
migrate-mappings (mm)     View information on all field mappings in a migration.
migrate-messages (mmsg)     View any messages associated with a migration.
migrate-reset-status (mrs)     Reset a active migration's status to idle
migrate-rollback (mr)     Roll back the destination objects from a given migration
migrate-status (ms)     List all migrations with current status.
migrate-stop (mst)     Stop an active migration operation
migrate-wipe (mw)     Delete all nodes from specified content types.

 

Finalmente verificamos que los usuarios hallan migrado correctamente. Pueden existir algunos warnings al momento de migrar. Por ejemplo si alguno de los campos de texto contiene más caracteres permitidos por el tamaño de campo definido en Drupal, nos puede mostrar un mensaje que se "truncará" la cadena, es decir que solo se almacenará la parte de contenido que alcance en el campo y el resto se perderá.

 

Referencias

  1. https://www.drupal.org/docs/8/api/migrate-api/migrate-source-plugins/migrating-data-from-a-csv-source

Añadir nuevo comentario

Texto sin formato

  • No se permiten etiquetas HTML.
  • Saltos automáticos de líneas y de párrafos.
  • Las direcciones de correos electrónicos y páginas web se convierten en enlaces automáticamente.
CAPTCHA
Esta pregunta para comprobar que eres una persona real e impedir el envío de SPAM.