diff -u b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntity.php --- b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntity.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntity.php @@ -14,8 +14,9 @@ * Drupal content entity source from database. * * @MigrateSource( - * id = "d8_content_entity", - * source_provider = "migrate_drupal" + * id = "entity", + * source_provider = "migrate_drupal", + * deriver = "\Drupal\migrate_drupal\Plugin\migrate\source\d8\ContentEntityDeriver", * ) */ class ContentEntity extends SourcePluginBase implements ContainerFactoryPluginInterface { @@ -59,12 +60,12 @@ * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) { - if (empty($configuration['entity_type'])) { + if (empty($plugin_definition['entity_type'])) { throw new InvalidPluginDefinitionException($plugin_id, 'Missing required entity_type definition'); } $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; - $this->entityType = $configuration['entity_type']; + $this->entityType = $plugin_definition['entity_type']; $entityDefinition = $this->entityTypeManager->getDefinition($this->entityType); $this->bundleKey = $entityDefinition->getKey('bundle'); if (!empty($this->configuration['bundle'])) { diff -u b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntityDeriver.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntityDeriver.php --- b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntityDeriver.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d8/ContentEntityDeriver.php @@ -3,5 +3,64 @@ namespace Drupal\migrate_drupal\Plugin\migrate\source\d8; -class ContentEntityDeriver { +use Drupal\Component\Plugin\Derivative\DeriverBase; +use Drupal\Core\Entity\ContentEntityTypeInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +class ContentEntityDeriver extends DeriverBase implements ContainerDeriverInterface { + + /** + * The base plugin ID this derivative is for. + * + * @var string + */ + protected $basePluginId; + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructs a new ContentEntityDeriver. + * + * @param string $base_plugin_id + * The base plugin ID for the plugin ID. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager + * The entity type manager. + */ + public function __construct($base_plugin_id, EntityTypeManagerInterface $entityTypeManager) { + $this->basePluginId = $base_plugin_id; + $this->entityTypeManager = $entityTypeManager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + // Translations don't make sense unless we have content_translation. + return new static( + $base_plugin_id, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $this->derivatives = []; + foreach ($this->entityTypeManager->getDefinitions() as $definition) { + // The source plugin only supports entities that are a content entity. + if ($definition instanceof ContentEntityTypeInterface) { + $this->derivatives[$definition->id()] = $base_plugin_definition; + $this->derivatives[$definition->id()]['entity_type'] = $definition->id(); + } + } + return parent::getDerivativeDefinitions($base_plugin_definition); + } } diff -u b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d8/ContentEntityTest.php b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d8/ContentEntityTest.php --- b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d8/ContentEntityTest.php +++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d8/ContentEntityTest.php @@ -9,6 +9,8 @@ use Drupal\language\Entity\ConfigurableLanguage; use Drupal\media\Entity\Media; use Drupal\media\Entity\MediaType; +use Drupal\migrate\Plugin\MigrateIdMapInterface; +use Drupal\migrate\Plugin\MigrationInterface; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; use Drupal\taxonomy\Entity\Term; @@ -75,13 +77,20 @@ protected $user; /** - * The migration plugin. + * The mock migration plugin. * - * @var \Drupal\migrate\Plugin\MigrationInterface + * @var \PHPUnit_Framework_MockObject_MockObject */ protected $migration; /** + * The source plugin manager. + * + * @var \Drupal\migrate\Plugin\MigrateSourcePluginManager + */ + protected $sourcePluginManager; + + /** * {@inheritdoc} */ protected function setUp() { @@ -136,9 +145,6 @@ FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED ); - // Create a media type. - $mediaType = $this->createMediaType('test'); - // Create some data. $this->user = User::create([ 'name' => 'user123', @@ -153,13 +159,6 @@ 'uid' => $this->user->id(), ]); $term->save(); - $term2 = Term::create([ - 'vid' => $this->vocabulary, - 'name' => 'Granny Smith', - 'uid' => $this->user->id(), - 'parent' => $term->id(), - ]); - $term2->save(); $this->user->set($this->fieldName, $term->id()); $this->user->save(); $node = Node::create([ @@ -172,127 +171,158 @@ $node->addTranslation('fr', [ 'title' => 'Pommes', ])->save(); - $file = File::create([ - 'filename' => 'foo.txt', - 'uid' => $this->user->id(), - 'uri' => 'public://foo.txt', - ]); - $file->save(); - $media = Media::create([ - 'name' => 'Foo media', - 'uid' => $this->user->id(), - 'bundle' => $mediaType->id(), - ]); - $media->save(); + + + $this->sourcePluginManager = $this->container->get('plugin.manager.migrate.source'); + $this->migration = $this->createMock(MigrationInterface::class); + $idMap = $this->createMock(MigrateIdMapInterface::class); + $idMap->expects(self::any())->method('getRowBySource')->willReturn(NULL); + $this->migration->expects(self::any())->method('getIdMap')->willReturn($idMap); } /** - * Tests table destination. + * Tests user source plugin. */ - public function testEntitySource() { - /** @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migrationPluginManager */ - $migrationPluginManager = \Drupal::service('plugin.manager.migration'); - $definition = $this->migrationDefinition(); - - // User tests. - $definition['source']['entity_type'] = 'user'; - $source = $migrationPluginManager->createStubMigration($definition)->getSourcePlugin(); - $ids = $source->getIds(); + public function testUserSource() { + $userSource = $this->sourcePluginManager->createInstance('entity:user', [], $this->migration); + $this->migration->expects(self::once())->method('getSourcePlugin')->willReturn($userSource); + $this->migration->expects(self::once())->method('getDestinationIds')->willReturn([1]); + $ids = $userSource->getIds(); $this->assertArrayHasKey('langcode', $ids); $this->assertArrayHasKey('uid', $ids); - $fields = $source->fields(); + $fields = $userSource->fields(); $this->assertArrayHasKey('name', $fields); $this->assertArrayHasKey('pass', $fields); $this->assertArrayHasKey('mail', $fields); $this->assertArrayHasKey('uid', $fields); $this->assertArrayHasKey('roles', $fields); - $source->rewind(); - $values = $source->current()->getSource(); + $userSource->rewind(); + $values = $userSource->current()->getSource(); $this->assertEquals('example@example.com', $values['mail'][0]['value']); $this->assertEquals('user123', $values['name'][0]['value']); $this->assertEquals(1, $values['uid']); $this->assertEquals(1, $values['field_entity_reference'][0]['target_id']); + } - // File testing. - $definition['source']['entity_type'] = 'file'; - $source = $migrationPluginManager->createStubMigration($definition)->getSourcePlugin(); - $ids = $source->getIds(); + /** + * Tests file source plugin. + */ + public function testFileSource() { + $file = File::create([ + 'filename' => 'foo.txt', + 'uid' => $this->user->id(), + 'uri' => 'public://foo.txt', + ]); + $file->save(); + + $fileSource = $this->sourcePluginManager->createInstance('entity:file', [], $this->migration); + $this->migration->expects(self::once())->method('getSourcePlugin')->willReturn($fileSource); + $this->migration->expects(self::once())->method('getDestinationIds')->willReturn([1]); + $ids = $fileSource->getIds(); $this->assertArrayHasKey('fid', $ids); - $fields = $source->fields(); + $fields = $fileSource->fields(); $this->assertArrayHasKey('fid', $fields); $this->assertArrayHasKey('filemime', $fields); $this->assertArrayHasKey('filename', $fields); $this->assertArrayHasKey('uid', $fields); $this->assertArrayHasKey('uri', $fields); - $source->rewind(); - $values = $source->current()->getSource(); + $fileSource->rewind(); + $values = $fileSource->current()->getSource(); $this->assertEquals('text/plain', $values['filemime'][0]['value']); $this->assertEquals('public://foo.txt', $values['uri'][0]['value']); $this->assertEquals('foo.txt', $values['filename'][0]['value']); $this->assertEquals(1, $values['fid']); + } - // Node tests. - $definition['source']['entity_type'] = 'node'; - $definition['source']['bundle'] = $this->bundle; - $source = $migrationPluginManager->createStubMigration($definition)->getSourcePlugin(); - $ids = $source->getIds(); + /** + * Tests node source plugin. + */ + public function testNodeSource() { + $nodeSource = $this->sourcePluginManager->createInstance('entity:node', ['bundle' => $this->bundle], $this->migration); + $this->migration->expects(self::once())->method('getSourcePlugin')->willReturn($nodeSource); + $this->migration->expects(self::once())->method('getDestinationIds')->willReturn([1]); + $ids = $nodeSource->getIds(); $this->assertArrayHasKey('langcode', $ids); $this->assertArrayHasKey('nid', $ids); - $fields = $source->fields(); + $fields = $nodeSource->fields(); $this->assertArrayHasKey('nid', $fields); $this->assertArrayHasKey('vid', $fields); $this->assertArrayHasKey('title', $fields); $this->assertArrayHasKey('uid', $fields); $this->assertArrayHasKey('sticky', $fields); - $source->rewind(); - $values = $source->current()->getSource(); + $nodeSource->rewind(); + $values = $nodeSource->current()->getSource(); $this->assertEquals($this->bundle, $values['type'][0]['target_id']); - $this->assertEquals('node', $values['entity_type']); $this->assertEquals(1, $values['nid']); $this->assertEquals(1, $values['status'][0]['value']); $this->assertEquals('Apples', $values['title'][0]['value']); $this->assertEquals(1, $values['field_entity_reference'][0]['target_id']); + } + + /** + * Tests media source plugin. + */ + public function testMediaSource() { + $mediaType = $this->createMediaType('test'); + $media = Media::create([ + 'name' => 'Foo media', + 'uid' => $this->user->id(), + 'bundle' => $mediaType->id(), + ]); + $media->save(); - // Media testing. - $definition['source']['entity_type'] = 'media'; - $definition['source']['bundle'] = 'image'; - $source = $migrationPluginManager->createStubMigration($definition)->getSourcePlugin(); - $ids = $source->getIds(); + $mediaSource = $this->sourcePluginManager->createInstance('entity:media', ['bundle' => 'image'], $this->migration); + $this->migration->expects(self::once())->method('getSourcePlugin')->willReturn($mediaSource); + $this->migration->expects(self::once())->method('getDestinationIds')->willReturn([1]); + $ids = $mediaSource->getIds(); $this->assertArrayHasKey('langcode', $ids); $this->assertArrayHasKey('mid', $ids); - $fields = $source->fields(); + $fields = $mediaSource->fields(); $this->assertArrayHasKey('bundle', $fields); $this->assertArrayHasKey('mid', $fields); $this->assertArrayHasKey('name', $fields); $this->assertArrayHasKey('status', $fields); - $source->rewind(); - $values = $source->current()->getSource(); + $mediaSource->rewind(); + $values = $mediaSource->current()->getSource(); $this->assertEquals(1, $values['mid']); $this->assertEquals('Foo media', $values['name'][0]['value']); $this->assertEquals('Foo media', $values['thumbnail'][0]['title']); $this->assertEquals(1, $values['uid'][0]['target_id']); $this->assertEquals('image', $values['bundle'][0]['target_id']); + } + + /** + * Tests term source plugin. + */ + public function testTermSource() { + $term2 = Term::create([ + 'vid' => $this->vocabulary, + 'name' => 'Granny Smith', + 'uid' => $this->user->id(), + 'parent' => 1, + ]); + $term2->save(); - // Term testing. - $definition['source']['bundle'] = $this->vocabulary; - $definition['source']['entity_type'] = 'taxonomy_term'; - $source = $migrationPluginManager->createStubMigration($definition)->getSourcePlugin(); - $ids = $source->getIds(); + $termSource = $this->sourcePluginManager->createInstance('entity:taxonomy_term', ['bundle' => $this->vocabulary], $this->migration); + $this->migration->expects(self::exactly(2))->method('getSourcePlugin')->willReturn($termSource); + $this->migration->expects(self::at(0))->method('getDestinationIds')->willReturn([1]); + $this->migration->expects(self::at(1))->method('getDestinationIds')->willReturn([2]); + $ids = $termSource->getIds(); $this->assertArrayHasKey('langcode', $ids); $this->assertArrayHasKey('tid', $ids); - $fields = $source->fields(); + $fields = $termSource->fields(); $this->assertArrayHasKey('vid', $fields); $this->assertArrayHasKey('tid', $fields); $this->assertArrayHasKey('name', $fields); - $source->rewind(); - $values = $source->current()->getSource(); + $termSource->rewind(); + $values = $termSource->current()->getSource(); $this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']); $this->assertEquals(1, $values['tid']); // @TODO: add test coverage for parent after // https://www.drupal.org/project/drupal/issues/2543726 $this->assertEquals('Apples', $values['name'][0]['value']); - $source->next(); - $values = $source->current()->getSource(); + $termSource->next(); + $values = $termSource->current()->getSource(); $this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']); $this->assertEquals(2, $values['tid']); // @TODO: add test coverage for parent after @@ -301,24 +331,6 @@ } /** - * Get a migration definition. - * - * @return array - * The definition. - */ - protected function migrationDefinition() { - return [ - 'source' => [ - 'plugin' => 'd8_content_entity', - ], - 'process' => [], - 'destination' => [ - 'plugin' => 'null', - ], - ]; - } - - /** * Create a media type for a source plugin. * * @param string $media_source_name @@ -328,7 +340,6 @@ * A media type. */ protected function createMediaType($media_source_name) { - $id = strtolower($this->randomMachineName()); $media_type = MediaType::create([ 'id' => 'image', 'label' => 'Image',