Si usted necesita migrar campos field_collection de D7 a un nuevo sitio en D8, puede echar un vistazo a este blog y espero le sea de utilidad.
Antes de continuar dejaré este enlace:
[META] Migrate support for importing field collections as paragraphs: Parent Issue
Éste issue y sus hijos fueron creados en la comunidad de Drupal para que el módulo Paragraphs pueda soportar las migraciones de Field Colecction y generar sus plantillas cuando hagamos migrate-upgrade.
Ahora mientras se resuelven estos issues, le mostraré cómo hemos hecho nuestras migraciones ahora.
Como no tenemos una plantilla aún para generar los paragraphs de field_collections en D7, entonces debemos hacer todo esto manual.
Mi ejemplo consiste en crear un paragraph llamado Contact con 3 campos luego migrarlo a un nodo llamado Organization:
Campos Contact: Email (Email), Phone(Telephone number), Website(Link)
Campo Organization: Contact (Entity reference revisions).
En un custom módulo (en nuestro caso migrate_drupal): en src/Plugin/migrate/source nos creamos una clase llamada FieldColection.php con los siguientes datos:
<?php
namespace Drupal\custom_migrate\Plugin\migrate\source;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* d7_field_collection_item source.
*
* @MigrateSource(
* id = "d7_field_collection_item"
* )
*/
class FieldCollection extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
// Select node in its last revision.
$query = $this->select('field_collection_item', 'fci')
->fields('fci', [
'item_id',
'field_name',
'revision_id'
]);
if (isset($this->configuration['field_name'])) {
$query->innerJoin('field_data_' . $this->configuration['field_name'], 'fd', 'fd.' . $this->configuration['field_name'] . '_value = fci.item_id');
$query->fields('fd', ['entity_type', 'bundle', 'entity_id', $this->configuration['field_name'] . '_revision_id']);
$query->condition('fci.field_name', $this->configuration['field_name']);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// If field specified, get field revision ID so there aren't issues mapping.
if(isset($this->configuration['field_name'])) {
$row->setSourceProperty('revision_id', $row->getSourceProperty($this->configuration['field_name'] . '_revision_id'));
}
// Get field API field values.
foreach (array_keys($this->getFields('field_collection_item', $row->getSourceProperty('field_name'))) as $field) {
$item_id = $row->getSourceProperty('item_id');
$revision_id = $row->getSourceProperty('revision_id');
$row->setSourceProperty($field, $this->getFieldValues('field_collection_item', $field, $item_id, $revision_id));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'item_id' => $this->t('Item ID'),
'revision_id' => $this->t('Revision ID'),
'field_name' => $this->t('Name of field')
];
return $fields;
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['item_id']['type'] = 'integer';
$ids['item_id']['alias'] = 'fci';
return $ids;
}
}
Luego creamos nuestra plantilla yml de migración en nuestra carpeta config/sync:
migrate_plus.migration.d7_field_collection_contacts.yml con los siguientes datos:
langcode: en
status: true
dependencies: { }
id: d7_field_collection_contacts
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
- 'Drupal 7'
migration_group: migrate_drupal_7
label: Contacts
source:
plugin: d7_field_collection_item
key: migrate
# field_name is used in our custom plugin to get data about this field_collection_item.
field_name: field_contact
process:
field_email:
plugin: iterator
source: field_email
process:
value: email
revision_id: revision_id
field_phone:
plugin: iterator
source: field_phone
process:
value: value
revision_id: revision_id
field_website:
plugin: iterator
source: field_website
process:
uri: value
revision_id: revision_id
destination:
plugin: 'entity_reference_revisions:paragraph'
default_bundle: contact
migration_dependencies:
required: { }
optional: { }
Luego de crearla debemos hacer limpiar caché (drush cr) luego exportar nuestras configuraciones (drush cex -y) entonces podremos usar o probar nuestra migración, debemos asegurarnos de revisar los process de los campos, por ejemplo en d7 un link era field_website_uri ahora en d8 es remapeado como field_website_value y así sucesivamente. Una vez más, todo esto finalmente se hará para usted con el sistema de plugin de campo. Pero por ahora tenemos que hacerlo manualmente
Ahora procedemos a la migración de paragraph a nuestro nodo Organization; tenemos nuestra plantilla generada y modificamos nuestro campo Contact porque anteriormente era un field_collection_item:
langcode: en
status: true
dependencies: { }
id: d7_node_organization
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
- 'Drupal 7'
- Content
migration_group: migrate_drupal_7
label: 'Nodes (Organization)'
source:
plugin: d7_node
node_type: organization
process:
nid: tnid
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
body:
plugin: iterator
source: body
process:
value: value
format:
-
plugin: static_map
bypass: true
source: format
map:
- null
-
plugin: skip_on_empty
method: process
-
plugin: migration
migration:
- d6_filter_format
- d7_filter_format
source: format
field_contacts:
-
plugin: skip_on_empty
method: process
source: field_contact_new
-
plugin: migration_lookup
migration: d7_field_collection_contacts
no_stub: true
-
plugin: iterator
process:
target_id: '0'
target_revision_id: '1'
destination:
plugin: 'entity:node'
default_bundle: organization
migration_dependencies:
required:
- d7_user
- d7_node_type
optional:
- d7_field_instance
- d6_filter_format
- d7_filter_format
Necesitamos cambiar el valor del source de field_contact y lo he hecho en un hook_migrate_MIGRATION_ID_prepare_row en nuestro archivo .module; esto es debido a que necesitamos enviarle la clave item_id al plugin migration_lookup.
/**
* Implements hook_migrate_MIGRATION_ID_prepare_row().
*/
function custom_migrate_migrate_d7_node_organization_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
$values = $row->getSourceProperty('field_contact');
$value_new = [];
if ($values) {
foreach ($values as $value) {
$value_new[] = ['item_id' => $value['value']];
}
$row->setSourceProperty('field_contact_new', $value_new);
}
Y de esta manera podemos ahora migrar los field_collection_item a Paragraph y tenerlo en nuestro nodo; le invito a que deje su contribución en los issues que se han creado para automatizar estas migraciones en el módulo de Paragraphs. Muchas Gracias a todos.
¿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.