Con el trabajo cotidiano de la oficina es natural que en el desarrollo de tareas se presenten desafíos y potenciales temas de investigación. Con la incorporación de nuestro desarrollador Lucas, al grupo de mantenedores del core del sistema de migraciones hemos decidido adentrarnos en este tema poco documentado como es la migración de datos CSV a párrafos.
Párrafos es la nueva forma de creación de contenido. Le permite a los constructores de sitios hacer las cosas más limpias para que pueda dar más poder de edición a sus usuarios finales.
En este blog les explicaré de forma sencilla cómo migrar datos de CSV a párrafos, usando el escenario de un tipo de contenido de Landing Page que tiene un campo de banner (párrafo de valor único) y un campo de Tile (campo de párrafos con varios valores). Asi que el blog abarca los 2 temas muy bien.
Veamos primero nuestros dos archivos CSV. La primer línea de los archivos es la fila del encabezado. Seguido por filas de los valores del CSV. Todo muy normal hasta ahora.
# files.csv
banner
banner.jpg
img1.jpg
img2.jpg
img3.jpg
# landing_pages.csv
id,title,banner_image,banner_link,banner_link_text,desc1,img1,desc2,img2,desc3,img3
1,Services,banner.jpg,http://www.mtech-llc.com,"Go to site",Desc1,img1.jpg,Desc2,img2.jpg,Desc3,img3.jpg
Paragraphs Type: Banner
A continuación debemos construir nuestros tipos de párrafo. El tipo de párrafo banner tiene dos campos. Esto debería parecer muy familiar si alguna vez ha tratado con párrafos o construyendo un sitio de Drupal.
Field Name | Field Type |
Call to Action | Link |
Image | Image |
Paragraphs Type: Tile
Este tipo de párrafo Tile también tiene dos campos y permite imprimir texto con un campo de imagen asociado. El autor de Landing Page va a construir un conjunto bien estructurado de tiles para la región de contenido principal de Landing Page. Por supuesto, puedes intercambiar estos campos y hacer tus párrafos como quieras. Pero esto sólo le da algunos tipos de párrafos muy típicos y enfoques de migración.
Field Name | Field Type |
Description | Text (formatted, long) |
Image | Image |
Y luego creamos el tipo de contenido y sus campos con referencia a párrafos:
Content Type: Landing Page
Field Name | Field Type |
Banner | Entity reference revisions (paragraph field) |
Tile | Entity reference revisions (multi-valor paragraph field) |
En este punto, estamos listos para migrar datos, necesitaremos descargar y habilitar con drush los módulos de contribución Entity Reference Revisions (en este aplicaremos el patch Entity Reference Revisions migrate destination), Migrate Plus, Migrate Source CSV, Migrate Tools y Paragraphs). Con Drupal Console crearemos nuestro módulo personalizado y lo he llamado paragraph_migration( con dependecias migrate_plus, migrate_source_csv y migrate_tools). Para mayor comodidad de este ejemplo, dentro de este módulo estarán los archivos .csv creados (files.csv y landing_pages.csv) con la siguiente ruta paragraph_migration/assets/csv, así mismo las imágenes .jpg dentro de la ruta paragraph_migration/assets/img. Por último, almacenarlos yaml de migración dentro del módulo paragraph_migration en la ruta paragraph_migration/config/install.
Empecemos:
- Migración simple de files.csv: Puede ver mas información en ¿Cómo hacer una migración de csv file con imágenes?
En el sitio, estos archivos se muestran en /admin/content/files.
dependencies:
enforced:
module:
- paragraph_migration
id: files
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/files.csv
header_row_count: 1
keys:
- name
constants:
source_base_path: modules/custom/paragraph_migration/assets/img
destination_base_path: 'public:/'
process:
filename: name
source_full_path:
-
plugin: concat
delimiter: /
source:
- constants/source_base_path
- name
-
plugin: urlencode
destination_full_path:
-
plugin: concat
delimiter: /
source:
- constants/destination_base_path
- name
-
plugin: urlencode
uri:
plugin: file_copy
source:
- '@source_full_path'
- '@destination_full_path'
destination:
plugin: 'entity:file'
migration_dependencies:
required: { }
optional: { }
- Migración de párrafo mulltivalor de -banner, tile_1, tile_2, tile_3-: Usaremos el plugin de destino proveído por el módulo Entity Reference Revisions 'entity_reference_revisions:paragraph' **Es muy importante que dicho plugin sea en singular, diferente al nombre del módulo, para evitar errores a la hora de la migración**
dependencies:
enforced:
module:
- paragraph_migration
id: banner
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/landing_pages.csv
header_row_count: 1
keys:
- id
process:
field_image:
plugin: migration
migration: files
source: banner_image
no_stub: true
field_call_to_action/title: banner_link_text
field_call_to_action/uri: banner_link
destination:
plugin: 'entity_reference_revisions:paragraph'
default_bundle: banner
migration_dependencies:
required:
- files
optional: { }
dependencies:
enforced:
module:
- paragraph_migration
id: tile_1
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/landing_pages.csv
header_row_count: 1
keys:
- id
- img1
process:
field_image:
plugin: migration
migration: files
source: img1
no_stub: true
field_description: desc1
destination:
plugin: 'entity_reference_revisions:paragraph'
default_bundle: tile
migration_dependencies:
required:
- files
optional: { }
dependencies:
enforced:
module:
- paragraph_migration
id: tile_2
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/landing_pages.csv
header_row_count: 1
keys:
- id
- img2
process:
field_image:
plugin: migration
migration: files
source: img2
no_stub: true
field_description: desc2
destination:
plugin: 'entity_reference_revisions:paragraph'
default_bundle: tile
migration_dependencies:
required:
- files
optional: { }
dependencies:
enforced:
module:
- paragraph_migration
id: tile_3
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/landing_pages.csv
header_row_count: 1
keys:
- id
- img3
process:
field_image:
plugin: migration
migration: files
source: img3
no_stub: true
field_description: desc3
destination:
plugin: 'entity_reference_revisions:paragraph'
default_bundle: tile
migration_dependencies:
required:
- files
optional: { }
** Para cada archivo de migración YML de tiles es necesario agregar el id y el nombre de la imagen como id o clave para la migración. **
- Destino de nuestra migración: Por último vamos a revisar el archivo YML que debe reunir nuestras migraciones anteriores en Paragaphs. Hay un enfoque diferente utilizado para los párrafos de múltiples valores en comparación con los párrafos de valor único, así que presta mucha atención a los detalles.
dependencies:
enforced:
module:
- paragraph_migration
id: landing_pages
source:
plugin: csv
path: modules/custom/paragraph_migration/assets/csv/landing_pages.csv
header_row_count: 1
keys:
- id
process:
title: title
field_banner/target_id:
-
plugin: migration
migration: banner
no_stub: true
source: id
-
plugin: extract
index:
- '0'
field_banner/target_revision_id:
-
plugin: migration
migration: banner
no_stub: true
source: id
-
plugin: extract
index:
- 1
combination_1:
plugin: get
source:
- id
- img1
combination_2:
plugin: get
source:
- id
- img2
combination_3:
plugin: get
source:
- id
- img3
combination:
plugin: get
source:
- @combination_1
- @combination_2
- @combination_3
field_tile:
-
plugin: migration
migration:
- tile_1
- tile_2
- tile_3
no_stub: true
source: @combination
-
plugin: iterator
process:
target_id: '0'
target_revision_id: '1'
destination:
plugin: 'entity:node'
default_bundle: landing_page
migration_dependencies:
required:
- banner
- tile_1
- tile_2
- tile_3
optional: { }
**field_banner/target_id y field_banner/target_id : El valor del extract '0' (con comillas simples) es importante y no es un error. Si no lo haces de esta manera,el plugin de proceso extract tratará cero como vacío y omitirá extraer el valor. El valor de 1 (sin comillas) está bien para el plugin de extract. No omite el valor numérico de uno.
**combination: Se trata de un campo temporal o psuedo -campo que se utiliza para recopilar todos los valores fuente juntos, en el formato correcto para insertar posteriormente en el destino real. Se puede decir que es un campo temporal porque tiene un nombre aleatorio que no comienza con el prefijo 'field_' y más tarde se utiliza con un prefijo de signo (@). Utilizamos el campo de combination como intermediario para el destino final 'field_tile'.
En la segunda parte de migración de párrafo multivalor, el plugin iterador sólo acepta valores de strings. No le gustan los números. Las comillas simples alrededor de '0' y '1' no son un error. Esto es diferente a lo que se menciona anteriormente de field_banner/target_id y field_banner/target_id.
Con nuestros yamls de migración totalmente respaldados y nuestros tipos de contenido creados, ahora es el momento de ver cómo funciona. Procedemos a habilitar el módulo paragraphs_migration ya que los archivos están forzados a su dependencia:
$ drush en paragraph_migration -y
Corremos la migración:
$ drush mi --all
LISTO!!!
Puedes obtener el código de este blog en mi repositorio en GitHub.
¿Está buscando ayuda para una migración o actualización de Drupal? Independientemente de la complejidad del sitio o de los datos, MTech puede ayudarle a pasar de un CMS privado o actualizarlo a la última versión: Drupal 8.
Escríbanos sobre su proyecto y nos pondremos en contacto con usted dentro de 48 horas.