Hero

Que son y como funcionan los plugins de migracion en Drupal 8

Noviembre 16, 2016

langelhc
Drupal
Desarrollo de Modulos

En este artículo explicaremos algunos detalles de los plugins de migracion en Drupal 8, esta publicación es la continuación de éste artículo donde encontraremos información de como preparar una migración con la Drupal Console.

El sistema de migración que viene en el núcleo (core) de Drupal 8, permite migrar tipos de contenido, campos (excepto aquellos campos de módulos contribuidos), usuarios, roles, contenido, archivos, taxonomías y otros. Desde una instalación de Drupal 6/7.

Las plantillas de migración las encontraremos en la carpeta “migration_templates” y los plugins en la carpeta “src/Plugin/migrate”.

Analizemos el plugin de migración de nodos de Drupal 7, que viene en el núcleo de Drupal 8:

Migration templates:

Son archivos YAML donde se definen algunas propiedades como el identificador de la migracion, un etiqueta, tags para saber si el script puede ser usado por otras versiones de drupal, dependencias de migracion donde se especifica si la migración tiene dependencias obligatorias u opciones. A continuación veremos el archivo YAML de la migración de nodos desde D7:

Ruta del archivo: core/modules/node/migration_templates/d7_node.yml

id: d7_node
label: Nodes
migration_tags:
  - Drupal 7
deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
source:
  plugin: d7_node
process:
  nid: nid
  vid: vid
  langcode:
    plugin: default_value
    source: language
    default_value: "und"
  title: title
  uid: node_uid
  status: status
  created: created
  changed: changed
  promote: promote
  sticky: sticky
  revision_uid: revision_uid
  revision_log: log
  revision_timestamp: timestamp
destination:
  plugin: entity:node
migration_dependencies:
  required:
    - d7_user
    - d7_node_type
  optional:
    - d7_field_instance
  • La opción ‘deriver’ hace posible que el plugin de migración esté disponible para cada tipo de contenido existente en D7, al momento de especificar un id de migración desde la Drupal Console se verá algo como el siguiente ejemplo:

Migration ids in Drupal Console

  • En la opción ‘process’, se especifican las propiedades y los valores que tomarán, en un próximo articulo hablaremos de los Process plugins que se pueden usar.
  • En la opción ‘migration_dependencies’ se especifica los Ids de migracion que son obligatorios u opcionales para la ejecución del plugin ‘d7_node’.

Plugin de migración:

Se encarga de procesar la migración de nodos a D8, veremos como ejemplo el plugin de migración de nodos desde D7:

El Id de la migración se define en la Anotación @MigrateSource() en este ejemplo es ‘d7_node’.

En la función query definimos la consulta SQL que obtendrá los datos a migrar.

En la función prepareRow, asignamos con el método setSourceProperty los valores que tendrán las propiedades o campos, también podemos realizar algunas operaciones con los datos antes de que sean migrados.

La variable $row es un objeto que contiene datos del sitio de D7, aquí se pueden hacer algunas modificaciones antes que se procese la fila que devuelve el resultado de la consulta definida en la función ‘query’.

Se debe tener en cuenta el uso de algunos métodos:

Método getFields:

Recibe dos parametros $entity_type (por ejemplo: node) y $bundle (por ejemplo: article).

$this->getFields('node', $row->getSourceProperty('type'))

Devuelve un arreglo con los campos de un tipo de entidad especifico.

Método getFieldValues:

Recibe cuatro parametros: $entity_type (node), $field (nombre maquina del campo), $entity_id (id del nodo), $revision_id.

$this->getFieldValues('node', $field, $nid, $vid);

Devuelve un arreglo con los valores del campo indicado en la variable $field, donde la clave del arreglo es un Delta (en caso de que el campo sea del tipo multi-valor). Aquí se puede tener más información.

Método getSourceProperty:

Recibe una cadena que es el nombre de la propiedad de origen (fuente) de la fila que se esta procesando.

$row->getSourceProperty('nid');

Devuelve el valor de la propiedad especificada de la fila que se está procesando en ese momento (por ejemplo: El id del nodo). Aquí puede encontrar más información.

Método setSourceProperty:

Recibe dos parámetros $property (nombre de la propiedad/campo) y $data (valores de la propiedad que se asignaran)

$row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid);

Más información del método.

Ruta del archivo: core/modules/node/src/Plugin/migrate/source/d7/Node.php

<?php


namespace Drupal\node\Plugin\migrate\source\d7;


use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;


/**
 * Drupal 7 node source from database.
 *
 * @MigrateSource(
 *   id = "d7_node",
 *   source_provider = "node"
 * )
 */
class Node extends FieldableEntity {


  /**
   * The join options between the node and the node_revisions table.
   */
  const JOIN = 'n.vid = nr.vid';


  /**
   * {@inheritdoc}
   */
  public function query() {
    // Select node in its last revision.
    $query = $this->select('node_revision', 'nr')
      ->fields('n', array(
        'nid',
        'type',
        'language',
        'status',
        'created',
        'changed',
        'comment',
        'promote',
        'sticky',
        'tnid',
        'translate',
      ))
      ->fields('nr', array(
        'vid',
        'title',
        'log',
        'timestamp',
      ));
    $query->addField('n', 'uid', 'node_uid');
    $query->addField('nr', 'uid', 'revision_uid');
    $query->innerJoin('node', 'n', static::JOIN);


    if (isset($this->configuration['node_type'])) {
      $query->condition('n.type', $this->configuration['node_type']);
    }
    return $query;
  }


  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    // Get Field API field values.
    foreach (array_keys($this->getFields('node', $row->getSourceProperty('type'))) as $field) {
      $nid = $row->getSourceProperty('nid');
      $vid = $row->getSourceProperty('vid');
      $row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid));
    }
    return parent::prepareRow($row);
  }


  /**
   * {@inheritdoc}
   */
  public function fields() {
    $fields = array(
      'nid' => $this->t('Node ID'),
      'type' => $this->t('Type'),
      'title' => $this->t('Title'),
      'node_uid' => $this->t('Node authored by (uid)'),
      'revision_uid' => $this->t('Revision authored by (uid)'),
      'created' => $this->t('Created timestamp'),
      'changed' => $this->t('Modified timestamp'),
      'status' => $this->t('Published'),
      'promote' => $this->t('Promoted to front page'),
      'sticky' => $this->t('Sticky at top of lists'),
      'revision' => $this->t('Create new revision'),
      'language' => $this->t('Language (fr, en, ...)'),
      'tnid' => $this->t('The translation set id for this node'),
      'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
    );
    return $fields;
  }


  /**
   * {@inheritdoc}
   */
  public function getIds() {
    $ids['nid']['type'] = 'integer';
    $ids['nid']['alias'] = 'n';
    return $ids;
  }
}

En el plugin ‘d7_node’ tiene un bucle donde asigna los valores de cada campo del tipo de contenido asumiendo que los nombres máquina de los campos son los mismos en D7 y D8.

Para mayor información acerca de este proceso automatizado de Upgrate puede consultar Upgrade a Drupal 8.

Para consultar algunos errores conocidos al ejecutar migraciones se puede ver aquí.

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.