diff --git a/core/modules/comment/src/Plugin/migrate/destination/EntityComment.php b/core/modules/comment/src/Plugin/migrate/destination/EntityComment.php index b370015dc6..a433c95704 100644 --- a/core/modules/comment/src/Plugin/migrate/destination/EntityComment.php +++ b/core/modules/comment/src/Plugin/migrate/destination/EntityComment.php @@ -3,6 +3,7 @@ namespace Drupal\comment\Plugin\migrate\destination; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; use Drupal\Core\State\StateInterface; @@ -53,9 +54,11 @@ class EntityComment extends EntityContentBase { * The field type plugin manager service. * @param \Drupal\Core\State\StateInterface $state * The state storage object. + * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager + * The entity field manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, StateInterface $state) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager, $field_type_manager); + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, StateInterface $state, EntityFieldManagerInterface $entity_field_manager = NULL) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager, $field_type_manager, $entity_field_manager); $this->state = $state; } @@ -73,7 +76,8 @@ public static function create(ContainerInterface $container, array $configuratio array_keys($container->get('entity_type.bundle.info')->getBundleInfo($entity_type)), $container->get('entity.manager'), $container->get('plugin.manager.field.field_type'), - $container->get('state') + $container->get('state'), + $container->get('entity_field.manager') ); } diff --git a/core/modules/migrate/src/Plugin/migrate/destination/Entity.php b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php index a3b173f8d0..49fcc4a80d 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/Entity.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php @@ -152,7 +152,7 @@ public function getBundle(Row $row) { * {@inheritdoc} */ public function fields(MigrationInterface $migration = NULL) { - // TODO: Implement fields() method. + return []; } /** diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php index 079eed08e9..f68dbf1ab3 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php @@ -5,7 +5,9 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\Core\TypedData\TypedDataInterface; @@ -94,6 +96,13 @@ class EntityContentBase extends Entity implements HighestIdInterface { */ protected $fieldTypeManager; + /** + * Field type plugin manager. + * + * @var \Drupal\Core\Entity\EntityFieldManagerInterface + */ + protected $entityFieldManager; + /** * Constructs a content entity. * @@ -113,11 +122,14 @@ class EntityContentBase extends Entity implements HighestIdInterface { * The entity manager service. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The field type plugin manager service. + * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager + * The entity field manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, EntityFieldManagerInterface $entity_field_manager = NULL) { parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles); $this->entityManager = $entity_manager; $this->fieldTypeManager = $field_type_manager; + $this->entityFieldManager = $entity_field_manager; } /** @@ -133,7 +145,8 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('entity.manager')->getStorage($entity_type), array_keys($container->get('entity_type.bundle.info')->getBundleInfo($entity_type)), $container->get('entity.manager'), - $container->get('plugin.manager.field.field_type') + $container->get('plugin.manager.field.field_type'), + $container->get('entity_field.manager') ); } @@ -366,4 +379,26 @@ public function getHighestId() { return (int) current($values); } + /** + * {@inheritdoc} + */ + public function fields(MigrationInterface $migration = NULL) { + $entity_type_id = self::getEntityTypeId($this->getPluginId()); + $entity_type = $this->entityManager->getDefinition($entity_type_id); + // Retrieving fields from a non-fieldable content entity will return a + // LogicException. Return an empty list of fields instead. + if (!$entity_type->entityClassImplements(FieldableEntityInterface::class)) { + return []; + } + $field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type->id()); + if (!empty($this->configuration['default_bundle'])) { + $field_definitions += $this->entityFieldManager->getFieldDefinitions($entity_type->id(), $this->configuration['default_bundle']); + } + $fields = []; + foreach ($field_definitions as $field_name => $definition) { + $fields[$field_name] = (string) $definition->getLabel(); + } + return $fields; + } + } diff --git a/core/modules/migrate/tests/modules/migrate_destination_test/migrate_destination_test.info.yml b/core/modules/migrate/tests/modules/migrate_destination_test/migrate_destination_test.info.yml new file mode 100644 index 0000000000..d8f21fb642 --- /dev/null +++ b/core/modules/migrate/tests/modules/migrate_destination_test/migrate_destination_test.info.yml @@ -0,0 +1,6 @@ +name: 'Migrate module destination tests' +type: module +description: 'Support module destination testing.' +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_no_fields.yml b/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_no_fields.yml new file mode 100644 index 0000000000..76fda32c21 --- /dev/null +++ b/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_no_fields.yml @@ -0,0 +1,11 @@ +id: node_no_fields +label: Migrate to no bundle specified destination +source: + plugin: migrate_destination_test + constants: + type: test_node_type_no_fields +process: + type: constants/type + title: title +destination: + plugin: entity:node diff --git a/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_with_fields.yml b/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_with_fields.yml new file mode 100644 index 0000000000..b1ba2fa9ff --- /dev/null +++ b/core/modules/migrate/tests/modules/migrate_destination_test/migrations/node_with_fields.yml @@ -0,0 +1,12 @@ +id: node_with_fields +label: Migrate to bundle specified destination +source: + plugin: migrate_destination_test + constants: + type: test_node_type_with_fields +process: + type: constants/type + title: title +destination: + plugin: entity:node + default_bundle: test_node_type_with_fields diff --git a/core/modules/migrate/tests/modules/migrate_destination_test/src/Plugin/migrate/source/MigrateDestinationTestSource.php b/core/modules/migrate/tests/modules/migrate_destination_test/src/Plugin/migrate/source/MigrateDestinationTestSource.php new file mode 100644 index 0000000000..45c45f631a --- /dev/null +++ b/core/modules/migrate/tests/modules/migrate_destination_test/src/Plugin/migrate/source/MigrateDestinationTestSource.php @@ -0,0 +1,63 @@ + 'Cat'], + ['title' => 'Dog'], + ['title' => 'Monkey'], + ]; + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'title' => $this->t('Title'), + ]; + } + + /** + * {@inheritdoc} + */ + public function __toString() { + return ''; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['title']['type'] = 'string'; + return $ids; + } + + /** + * {@inheritdoc} + */ + protected function initializeIterator() { + $data = []; + foreach ($this->import as $row) { + $data[] = $row; + } + + return new \ArrayIterator($data); + } + +} diff --git a/core/modules/migrate/tests/src/Kernel/MigrateEntityDestinationTest.php b/core/modules/migrate/tests/src/Kernel/MigrateEntityDestinationTest.php new file mode 100644 index 0000000000..a418fabe5b --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateEntityDestinationTest.php @@ -0,0 +1,84 @@ +installSchema('system', ['sequences']); + $this->installSchema('node', ['node_access']); + $this->installEntitySchema('user'); + $this->installEntitySchema('node'); + + NodeType::create([ + 'type' => 'test_node_type_no_field', + 'name' => 'Test node type without fields', + ])->save(); + + NodeType::create([ + 'type' => 'test_node_type_with_fields', + 'name' => 'Test node type with fields', + ])->save(); + } + + /** + * Test destination fields() method. + */ + public function testDestinationField() { + $node_with_fields = $this->getMigration('node_with_fields'); + $destination_fields = $node_with_fields->getDestinationPlugin(); + + $node_no_fields = $this->getMigration('node_no_fields'); + $destination_no_fields = $node_no_fields->getDestinationPlugin(); + + $this->assertTrue(in_array('nid', array_keys($destination_fields->fields()))); + $this->assertFalse(in_array('field_text', array_keys($destination_fields->fields()))); + + $this->assertTrue(in_array('nid', array_keys($destination_no_fields->fields()))); + $this->assertFalse(in_array('field_text', array_keys($destination_no_fields->fields()))); + + // Create a text field attached to 'test_node_type_2' node-type. + FieldStorageConfig::create([ + 'type' => 'string', + 'entity_type' => 'node', + 'field_name' => 'field_text', + ])->save(); + + FieldConfig::create([ + 'entity_type' => 'node', + 'bundle' => 'test_node_type_with_fields', + 'field_name' => 'field_text', + ])->save(); + + $this->assertTrue(in_array('field_text', array_keys($destination_fields->fields()))); + // The destination_bundle_entity migration has default bundle of + // test_node_type so it shouldn't show the fields on other node types. + $this->assertFalse(in_array('field_text', array_keys($destination_no_fields->fields()))); + + } + +} diff --git a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php index da867423ea..277e632532 100644 --- a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php +++ b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php @@ -3,6 +3,7 @@ namespace Drupal\user\Plugin\migrate\destination; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; @@ -95,9 +96,11 @@ class EntityUser extends EntityContentBase { * The field type plugin manager service. * @param \Drupal\Core\Password\PasswordInterface $password * The password service. + * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager + * The entity field manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, PasswordInterface $password) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager, $field_type_manager); + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, PasswordInterface $password, EntityFieldManagerInterface $entity_field_manager = NULL) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager, $field_type_manager, $entity_field_manager); $this->password = $password; } @@ -115,7 +118,8 @@ public static function create(ContainerInterface $container, array $configuratio array_keys($container->get('entity_type.bundle.info')->getBundleInfo($entity_type)), $container->get('entity.manager'), $container->get('plugin.manager.field.field_type'), - $container->get('password') + $container->get('password'), + $container->get('entity_field.manager') ); }