Serial Field es un campo autoincremental (por tipo de contenido) para drupal. En la última migración que hicimos necesitábamos importar en este campo los ids de la tabla de origen, pero el módulo generaba automáticamente los valores cuando se guardaba el contenido. Además, como el módulo usa tablas temporales para generar los ids y luego los almacena en la tabla del campo, al hacer rollback de una migración los ids no se reseteaban al valor original.

Siempre que nos encontramos con algún problema de este tipo intentamos solucionarlo de forma genérica y publicar la solución. En este caso implementamos un field handler para Migrate y publicamos el parche acá.

Para importar valores directamente en un campo serial hay que definir los mapeos en la migración

$this->addFieldMapping('field_mi_campo_serial', 'src_id');
$this->addFieldMapping('field_mi_campo_serial:is_unique')->defaultValue(TRUE);

La opción is_unique se usa para indicarle al handler que los valores importados ya son únicos y se pueden insertar directamente. Igualmente si el id ya existe lo dejamos vacío para que se genere el id al guardar, asegurando que no haya valores duplicados en la tabla.

Pero que pasa si importamos 10 items, hacemos rollback y los volvemos a importar? Los ids importados originalmente están guardados en la tabla temporal que usa serial para generar los ids, por lo que la segunda vez que importemos los mismos items se generarán nuevos ids en lugar de importarlos. El handler que implementamos provee un método estático para borrar los ids importados de la tabla temporal. Para usarlo hay que implementar prepareRollback en la migración y usar este método para borrar de la tabla temporal las entradas correspondientes a las entidades que se van a eliminar.

public function prepareRollback($entity_ids) {
  MigrateSerialFieldHandler::rollbackSerialIDS($entity_ids, 'field_mi_campo_serial', $this->getDestination()->getBundle());
}

El parche está publicado, si necesitás importar valores a un serial field usalo!

Publicado el 15/09/2013 por ariel