Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / migrate_drupal / src / Plugin / migrate / EntityReferenceTranslationDeriver.php
diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/EntityReferenceTranslationDeriver.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/EntityReferenceTranslationDeriver.php
new file mode 100644 (file)
index 0000000..bc33695
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+
+namespace Drupal\migrate_drupal\Plugin\migrate;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Deriver for entity reference field translations.
+ *
+ * A migration will be created for every bundle with at least one entity
+ * reference field that is configured to point to one of the supported target
+ * entity types. The migrations will update the entity reference fields with
+ * values found in the mapping tables of the migrations associated with the
+ * target types.
+ *
+ * Example:
+ *
+ * @code
+ * id: d7_entity_reference_translation
+ * label: Entity reference translations
+ * migration_tags:
+ *   - Drupal 7
+ *   - Follow-up migration
+ * deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver
+ * target_types:
+ *   node:
+ *     - d7_node_translation
+ * source:
+ *   plugin: empty
+ *   key: default
+ *   target: default
+ * process: []
+ * destination:
+ *   plugin: null
+ * @endcode
+ *
+ * In this example, the only supported target type is 'node' and the associated
+ * migration for the mapping table lookup is 'd7_node_translation'.
+ */
+class EntityReferenceTranslationDeriver extends DeriverBase implements ContainerDeriverInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The entity field manager.
+   *
+   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * EntityReferenceTranslationDeriver constructor.
+   *
+   * @param string $base_plugin_id
+   *   The base plugin ID.
+   * @param \Drupal\core\Entity\EntityFieldManagerInterface $entity_field_manager
+   *   The entity field manager.
+   * @param \Drupal\core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct($base_plugin_id, EntityFieldManagerInterface $entity_field_manager, EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityFieldManager = $entity_field_manager;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $base_plugin_id,
+      $container->get('entity_field.manager'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    // Get all entity reference fields.
+    $field_map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');
+
+    foreach ($field_map as $entity_type => $fields) {
+      foreach ($fields as $field_name => $field) {
+        foreach ($field['bundles'] as $bundle) {
+          $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
+          $target_type = $field_definitions[$field_name]->getSetting('target_type');
+
+          // If the field's target type is not supported, skip it.
+          if (!array_key_exists($target_type, $base_plugin_definition['target_types'])) {
+            continue;
+          }
+
+          // Key derivatives by entity types and bundles.
+          $derivative_key = $entity_type . '__' . $bundle;
+
+          $derivative = $base_plugin_definition;
+          $entity_type_definition = $this->entityTypeManager->getDefinition($entity_type);
+
+          // Set the migration label.
+          $derivative['label'] = $this->t('@label (@derivative)', [
+            '@label' => $base_plugin_definition['label'],
+            '@derivative' => $derivative_key,
+          ]);
+
+          // Set the source plugin.
+          $derivative['source']['plugin'] = 'content_entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type;
+          if ($entity_type_definition->hasKey('bundle')) {
+            $derivative['source']['bundle'] = $bundle;
+          }
+
+          // Set the process pipeline.
+          $id_key = $entity_type_definition->getKey('id');
+          $derivative['process'][$id_key] = $id_key;
+          if ($entity_type_definition->isRevisionable()) {
+            $revision_key = $entity_type_definition->getKey('revision');
+            $derivative['process'][$revision_key] = $revision_key;
+          }
+          if ($entity_type_definition->isTranslatable()) {
+            $langcode_key = $entity_type_definition->getKey('langcode');
+            $derivative['process'][$langcode_key] = $langcode_key;
+          }
+
+          // Set the destination plugin.
+          $derivative['destination']['plugin'] = 'entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type;
+          if ($entity_type_definition->hasKey('bundle')) {
+            $derivative['destination']['default_bundle'] = $bundle;
+          }
+          if ($entity_type_definition->isTranslatable()) {
+            $derivative['destination']['translations'] = TRUE;
+          }
+
+          // Allow overwriting the entity reference field so we can update its
+          // values with the ones found in the mapping table.
+          $derivative['destination']['overwrite_properties'][$field_name] = $field_name;
+
+          // Add the entity reference field to the process pipeline.
+          $derivative['process'][$field_name] = [
+            'plugin' => 'sub_process',
+            'source' => $field_name,
+            'process' => [
+              'target_id' => [
+                [
+                  'plugin' => 'migration_lookup',
+                  'source' => 'target_id',
+                  'migration' => $base_plugin_definition['target_types'][$target_type],
+                  'no_stub' => TRUE,
+                ],
+                [
+                  'plugin' => 'skip_on_empty',
+                  'method' => 'row',
+                ],
+                [
+                  'plugin' => 'extract',
+                  'index' => [0],
+                ],
+              ],
+            ],
+          ];
+
+          if (!isset($this->derivatives[$derivative_key])) {
+            // If this is a new derivative, add it to the returned derivatives.
+            $this->derivatives[$derivative_key] = $derivative;
+          }
+          else {
+            // If this is an existing derivative, it means this bundle has more
+            // than one entity reference field. In that case, we only want to add
+            // the field to the process pipeline and make it overwritable.
+            $this->derivatives[$derivative_key]['process'] += $derivative['process'];
+            $this->derivatives[$derivative_key]['destination']['overwrite_properties'] += $derivative['destination']['overwrite_properties'];
+          }
+        }
+      }
+    }
+
+    return $this->derivatives;
+  }
+
+}