0

I've got a node type in Drupal 8 that uses field collections (from the module of the same name). The Field Collections module doesn't yet have a working migration destination plugin, so what I'd like to do is use some kind of post-processing to (ugh) brute-force the field collection data into the nodes (note that I've tried the -dev version of Field Collection, and the destination plugin doesn't appear to be functional). Note that my source is an SQL database and not a Drupal instance.

Here are the relevant files:

The migration definition file:

id: fm_quiz
label: FM Quiz
migration_group: quizzes
source:
  plugin: fm_quiz
  key: source
destination:
  plugin: fm_quiz
process:
  type:
    plugin: default_value
    default_value: quiz
  title: title
  uid:
    plugin: default_value
    default_value: 1
  sticky:
    plugin: default_value
    default_value: 0

The destination plugin:

<?php

/**
 * @file
 * Contains \Drupal\fm_quiz\Plugin\migrate\destination\FMQuiz.
 */

namespace Drupal\fm_quiz\Plugin\migrate\destination;

use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
use Drupal\migrate\Row;


/**
 * @MigrateDestination(
 *   id = "fm_quiz"
 * )
 */
class FMQuiz extends EntityContentBase {

  /**
     * {@inheritdoc}
     */
  public function import(Row $row, array $old_destination_id_values = array()) {
    $node = $this->getEntity($row, $old_destination_id_values);
    print_r($node);

    return [$node->id()];
  }

}

At the moment, Drupal doesn't seem to want to recognize that this migration exists as written.

If I change the destination to "entity:node", then it imports the nodes as expected. If I change the destination in both files to "entity:node:fm_quiz", then Drupal says that "Migration fm_quiz did not meet the requirements" (and provides no other information).

Am I doing something wrong, or is what I'm trying to do just not possible right now? Do I need to just make an end run around the migration system?

2

It's my understanding that your migration problem lies in the fact that you can't add a custom destination plugin for nodes. Your exact migration strategy is not entirely understood from your question, so I'm going to address only the part related to destination migration plugin, which might help you addressing the problem with adding custom logic to a migration process.

Destination plugins for entity migrations are indeed created by a deriver (see MigrateEntity::getDerivativeDefinitions()) and adding custom destination plugins is not as straightforward as creating, for example, a custom source plugin which extends an existing source plugin, because destination entity type is determined from the ID of destination plugin (entity:[name]).

You can still can create custom destination plugins for entity migrations in the following way:

Migration definition file:

id: fm_quiz
label: FM Quiz
migration_group: quizzes
source:
  plugin: fm_quiz
  key: source
destination:
  plugin: fm_quiz
process:
  type:
    plugin: default_value
    default_value: quiz
  title: title
  uid:
    plugin: default_value
    default_value: 1
  sticky:
    plugin: default_value
    default_value: 0

Custom migration destination plugin:

<?php

namespace Drupal\fm_quiz\Plugin\migrate\destination;

use Drupal\Core\Entity\Entity;
use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @MigrateDestination(
 *   id = "fm_quiz"
 * )
 */
class FmQuizNodeDestination extends EntityContentBase {

  /** @var string $entityType */
  public static $entityType = 'node';

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
    return parent::create($container, $configuration, 'entity:' . static::$entityType, $plugin_definition, $migration);
  }

  /**
   * {@inheritdoc}
   */
  public function import(Row $row, array $old_destination_id_values = array()) {
    // Add custom code here, if needed.
    return parent::import($row, $old_destination_id_values);
  }

}

Technically, it's the same class that entity:node destination plugin would use, but create() method of the custom class tricks parent class to use storage of node entity type.

| improve this answer | |
  • @Smartsheeteng My comment was about extending destination plugins. Core already provides entity:node plugin by means or deriver, so if you add your own @MigrateDestination(id = "entity:node") destination plugin, it will not extend the existing plugin. – maijs Apr 28 '17 at 14:31
0

Field Collection is deprecated in Drupal 8. From the project page:

Paragraphs is likely to replace field collection for Drupal 8. Field collection is on its way to being deprecated. It is recommended to use paragraphs instead of field collection for Drupal 8 projects.

You should replace your Field Collections with Paragraphs, and migrate Field Collection data into those. Assuming that you're migrating from a Drupal 7 site, this process is mostly working as per [META] Migrate support for importing field collections as paragraphs. The only remaining task still open (at the time of this writing) is Field collections deriver and base migration, which is awaiting feedback from additional reviewers.

So it shouldn't be necessary for you to write a custom migration.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.