Skip to content

Instantly share code, notes, and snippets.

@teglia
Last active December 12, 2023 13:21
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save teglia/09c64dd27c6a953537d291dcf42f7fc5 to your computer and use it in GitHub Desktop.
Save teglia/09c64dd27c6a953537d291dcf42f7fc5 to your computer and use it in GitHub Desktop.
Migrating Field Collections to Paragraphs on an empty Drupal 8 site WITHOUT migrate_tools or migrate_plus

If you are trying to migrate to a NEW EMPTY Drupal 8 site from Drupal 7 and you have field collections that you want to see in Paragraphs, AND you would like to just use core Migrate (possibly with the Migrate Run module) and not have to use Migrate Plus or Migrate Tools, then you might give this setup a try.

These files are all that I required to get a migration of our field collections in Drupal 7 into our Drupal 8 content type with a paragraph field reference (place all of these into your custom migrate module directory, follow the paths outline in each):

  • Custom module info file (migrate_custom.info.yml)
  • Custom module file (migrate_custom.module (remove the .php - added that so gist would give it syntax coloring))
  • Source plugin (src/Plugin/migrate/source/FCEntityMigrate.php)
  • The migration plugin (migrations/custom_paragraph.yml)

This setup assumes the field name of your field collection in Drupal 7 is the same as the field name of the paragraph field in Drupal 8.

Create your custom migration module, place these things in the correct path structure (as listed) and change the following things within to match your paragraph, entity, and field names:

  • "field_custom_paragraph_field" - change all instances of this string (including where it precedes "_value" or follows "field_data_") to the name of your paragraph field reference.
  • "custom_paragraph" - change this in custom_parargraph.yml line 7 to the machine name of your paragraph entity.
  • "custom_paragraph" - all other occurrences of this refer to the plugin name, such as line 12 of custom_paragraph.yml and line 13 of FCEntityMigrate.php.
  • "migrate_custom" - this is the name of your module.
  • "bundle" - change this to your entity type, such as in "drush mi d7_node:bundle"

I have included a start on node revisions, but did not actually test that part. It might work!

Lastly, make sure that any fields you want to migrate in your field collection are included in the migration plugin yml. If they aren't there, they will not migrate.

MANY THANKS to chx (Karoly Negyesi) for helping me stumble through all of the intricacies of this and soooo many other things.

id: custom_paragraph
label: Custom Paragraphs
migration_tags:
- Drupal 7
source:
constants:
type: custom_paragraph
parents:
type: node
name: field_custom_paragraph_field
plugin: custom_paragraph
process:
id: item_id
uuid: uuid
revision_id: revision_id
type: constants/type
field_custom_body: field_custom_body
field_custom_title: field_custom_title
parent_id: field_custom_paragraph_field_value
parent_type: constants/parents/type
parent_field_name: constants/parents/name
destination:
plugin: entity:paragraph
<?php
namespace Drupal\migrate_custom\Plugin\migrate\source;
use Drupal\Core\Database\Query\Condition;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Drupal 7 file source from database.
*
* @MigrateSource(
* id = "custom_paragraph"
* )
*/
class FCEntityMigrate extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('field_collection_item', 'f')
->fields('f')
->orderBy('f.item_id');
$query->leftJoin('field_data_field_custom_paragraph_field', 'fp', 'field_custom_paragraph_field_value = item_id');
$query->addField('fp', 'field_custom_paragraph_field_value');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Get Field API field values.
foreach (array_keys($this->getFields('field_collection_item', 'field_custom_paragraph_field')) as $field) {
$fc_id = $row->getSourceProperty('item_id');
$row->setSourceProperty("$field", $this->getFieldValues('field_collection_item', $field, $fc_id));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'entity_type' => $this->t('The entity type.'),
'bundle' => $this->t('The bundle this is associated with'),
'deleted' => $this->t('Deleted'),
'entity_id' => $this->t('Entity ID'),
'revision_id' => $this->t('Entity revision'),
'delta' => $this->t('The delta'),
'item_id' => $this->t('FC ID'),
'parent_id'
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['item_id']['type'] = 'integer';
return $ids;
}
}
name: Custom Migration
description: Custom migration module for migrating data from a Drupal 7 site.
package: Migrations
type: module
core: 8.x
dependencies:
- migrate
<?php
// NOTE: WARNING: TO_DO: ALARM ALARM! Remove the .php from this filename. It is only there for github gist's syntax coloring.
/**
* @file
* All of our custom code for migrating D7 to D8.
*/
/**
* Implements hook_migration_plugins_alter()
*/
function migrate_custom_migration_plugins_alter(&$definitions) {
// Replace "bundle" below with your content type.
if (isset($definitions['d7_node:bundle'])) {
// field_custom_paragraph_field is your paragraph reference field on your entity
$definitions['d7_node:bundle']['process']['field_custom_paragraph_field'] = array(
'plugin' => 'iterator', // > 8.4 need to change 'iterator' to 'sub_process'
'source' => 'field_custom_paragraph_field', // Field name of FC ref field in D7
'process' => array(
'target_id' => 'value',
'target_revision_id' => 'revision_id',
)
);
}
if (isset($definitions['d7_node_revision:bundle'])) {
$definitions['d7_node_revision:bundle']['process']['field_custom_paragraph_field'] = array(
'plugin' => 'iterator',
'source' => 'field_custom_paragraph_field',
'process' => array(
'target_id' => 'value',
'target_revision_id' => 'revision_id',
)
);
}
}
@cooldrupal
Copy link

It doesn't work for migration from Drupal7 to Drupal10. There are no errors but I got "No migrations found. " message after migration.
I remake query() function also:

public function query() {
   $query = $this->select('field_collection_item', 'f')
     ->fields('f', ['item_id'])
     ->orderBy('f.item_id');
   $query->leftJoin('field_data_field_custom_fields', 'fp', 'field_custom_fields_value = item_id');
   $query->fields('fp');

   return $query;
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment