diff -u b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php --- b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/Entity.php @@ -170,7 +170,11 @@ $entity_id = reset($old_destination_id_values) ?: $this->getEntityId($row); if (!empty($entity_id) && ($entity = $this->storage->load($entity_id))) { // Allow updateEntity() to change the entity. - $this->updateEntity($entity, $row); + $result = $this->updateEntity($entity, $row); + if ($result !== NULL) { + trigger_error(__CLASS__ . '::updateEntity() should not return an entity. See https://www.drupal.org/project/drupal/issues/2921661'); + $entity = $result; + } } else { // Attempt to ensure we always have a bundle. diff -u b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php --- b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php @@ -208,7 +208,8 @@ * The row object to update from. * * @return \Drupal\Core\Entity\EntityInterface - * An updated entity from row values. + * An updated entity from row values. This deprecated in Drupal 8.6.0 and + * will be removed in Drupal 9. See tbd. */ protected function updateEntity(EntityInterface &$entity, Row $row) { $empty_destinations = $row->getEmptyDestinationProperties(); diff -u b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php --- b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php @@ -162,7 +162,11 @@ } // We need to update the entity, so that the destination row IDs are // correct. - $this->updateEntity($entity, $row); + $result = $this->updateEntity($entity, $row); + if ($result !== NULL) { + trigger_error(__CLASS__ . '::updateEntity() should not return an entity. See https://www.drupal.org/project/drupal/issues/2921661'); + $entity = $result; + } $entity->isDefaultRevision(FALSE); return $entity; } interdiff impossible; taking evasive action reverted: --- b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php +++ /dev/null @@ -1,162 +0,0 @@ -migration = $this->prophesize(MigrationInterface::class); - $this->storage = $this->prophesize(EntityStorageInterface::class); - - $this->entityType = $this->prophesize(EntityTypeInterface::class); - $this->entityType->getSingularLabel()->willReturn('foo'); - $this->entityType->getPluralLabel()->willReturn('bar'); - $this->storage->getEntityType()->willReturn($this->entityType->reveal()); - $this->storage->getEntityTypeId()->willReturn('foo'); - - $this->entityManager = $this->prophesize(EntityManagerInterface::class); - } - - /** - * Tests that revision destination fails for unrevisionable entities. - */ - public function testUnrevisionable() { - $this->entityType->getKey('id')->willReturn('id'); - $this->entityType->getKey('revision')->willReturn(''); - $this->entityManager->getBaseFieldDefinitions('foo') - ->willReturn([ - 'id' => BaseFieldDefinitionTest::create('integer'), - ]); - - $destination = new EntityRevisionTestDestination( - [], - '', - [], - $this->migration->reveal(), - $this->storage->reveal(), - [], - $this->entityManager->reveal(), - $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() - ); - $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support revisions.'); - $destination->getIds(); - } - - /** - * Tests that translation destination fails for untranslatable entities. - */ - public function testUntranslatable() { - $this->entityType->getKey('id')->willReturn('id'); - $this->entityType->getKey('revision')->willReturn('vid'); - $this->entityType->getKey('langcode')->willReturn(''); - $this->entityManager->getBaseFieldDefinitions('foo') - ->willReturn([ - 'id' => BaseFieldDefinitionTest::create('integer'), - 'vid' => BaseFieldDefinitionTest::create('integer'), - ]); - - $destination = new EntityRevisionTestDestination( - ['translations' => TRUE], - '', - [], - $this->migration->reveal(), - $this->storage->reveal(), - [], - $this->entityManager->reveal(), - $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() - ); - $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.'); - $destination->getIds(); - } - -} - -/** - * Stub class for testing EntityRevision methods. - */ -class EntityRevisionTestDestination extends EntityRevision { - - private $entity = NULL; - - public function setEntity($entity) { - $this->entity = $entity; - } - - protected function getEntity(Row $row, array $old_destination_id_values) { - return $this->entity; - } - - public static function getEntityTypeId($plugin_id) { - return 'foo'; - } - -} - -/** - * Stub class for BaseFieldDefinition. - */ -class BaseFieldDefinitionTest extends BaseFieldDefinition { - - public static function create($type) { - return new static([]); - } - - public function getSettings() { - return []; - } - - public function getType() { - return 'integer'; - } - -} unchanged: --- a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php +++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php @@ -1,13 +1,7 @@ storage = $this->prophesize(EntityStorageInterface::class); $this->entityType = $this->prophesize(EntityTypeInterface::class); - $this->entityType->getPluralLabel()->willReturn('wonkiness'); + $this->entityType->getSingularLabel()->willReturn('foo'); + $this->entityType->getPluralLabel()->willReturn('bar'); $this->storage->getEntityType()->willReturn($this->entityType->reveal()); + $this->storage->getEntityTypeId()->willReturn('foo'); $this->entityManager = $this->prophesize(EntityManagerInterface::class); } /** - * Test basic entity save. - * - * @covers ::import + * Tests that revision destination fails for unrevisionable entities. */ - public function testImport() { - $bundles = []; - $destination = new EntityTestDestination([], '', [], - $this->migration->reveal(), - $this->storage->reveal(), - $bundles, - $this->entityManager->reveal(), - $this->prophesize(FieldTypePluginManagerInterface::class)->reveal()); - $entity = $this->prophesize(ContentEntityInterface::class); - // Assert that save is called. - $entity->save() - ->shouldBeCalledTimes(1); - // Set an id for the entity - $entity->id() - ->willReturn(5); - $destination->setEntity($entity->reveal()); - // Ensure the id is saved entity id is returned from import. - $this->assertEquals([5], $destination->import(new Row())); - // Assert that import set the rollback action. - $this->assertEquals(MigrateIdMapInterface::ROLLBACK_DELETE, $destination->rollbackAction()); - } + public function testUnrevisionable() { + $this->entityType->getKey('id')->willReturn('id'); + $this->entityType->getKey('revision')->willReturn(''); + $this->entityManager->getBaseFieldDefinitions('foo') + ->willReturn([ + 'id' => BaseFieldDefinitionTest::create('integer'), + ]); - /** - * Test row skipping when we can't get an entity to save. - * - * @covers ::import - */ - public function testImportEntityLoadFailure() { - $bundles = []; - $destination = new EntityTestDestination([], '', [], + $destination = new EntityRevisionTestDestination( + [], + '', + [], $this->migration->reveal(), $this->storage->reveal(), - $bundles, + [], $this->entityManager->reveal(), - $this->prophesize(FieldTypePluginManagerInterface::class)->reveal()); - $destination->setEntity(FALSE); - $this->setExpectedException(MigrateException::class, 'Unable to get entity'); - $destination->import(new Row()); + $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() + ); + $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support revisions.'); + $destination->getIds(); } /** - * Test that translation destination fails for untranslatable entities. + * Tests that translation destination fails for untranslatable entities. */ public function testUntranslatable() { - // An entity type without a language. - $this->entityType->getKey('langcode')->willReturn(''); $this->entityType->getKey('id')->willReturn('id'); + $this->entityType->getKey('revision')->willReturn('vid'); + $this->entityType->getKey('langcode')->willReturn(''); $this->entityManager->getBaseFieldDefinitions('foo') - ->willReturn(['id' => BaseFieldDefinitionTest::create('integer')]); + ->willReturn([ + 'id' => BaseFieldDefinitionTest::create('integer'), + 'vid' => BaseFieldDefinitionTest::create('integer'), + ]); - $destination = new EntityTestDestination( + $destination = new EntityRevisionTestDestination( ['translations' => TRUE], '', [], @@ -129,18 +115,16 @@ public function testUntranslatable() { $this->entityManager->reveal(), $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() ); - $this->setExpectedException(MigrateException::class, 'This entity type does not support translation'); + $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.'); $destination->getIds(); } } /** - * Stub class for testing EntityContentBase methods. - * - * We want to test things without testing the base class implementations. + * Stub class for testing EntityRevision methods. */ -class EntityTestDestination extends EntityContentBase { +class EntityRevisionTestDestination extends EntityRevision { private $entity = NULL; diff -u b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php --- b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php +++ b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php @@ -231,7 +231,5 @@ * empty implementation avoids this. */ - protected function updateEntity(EntityInterface &$entity, Row $row) { - return $entity; - } + protected function updateEntity(EntityInterface &$entity, Row $row) {} } only in patch2: unchanged: --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php @@ -186,12 +186,14 @@ public function getIds() { /** * Updates an entity with the contents of a row. * + * Note that the entity passed in is updated. + * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to update. * @param \Drupal\migrate\Row $row * The row object to update from. */ - protected function updateEntity(EntityInterface $entity, Row $row) { + protected function updateEntity(EntityInterface &$entity, Row $row) { // This is a translation if the language in the active config does not // match the language of this row. $translation = FALSE; only in patch2: unchanged: --- a/core/modules/search/src/Plugin/migrate/destination/EntitySearchPage.php +++ b/core/modules/search/src/Plugin/migrate/destination/EntitySearchPage.php @@ -21,7 +21,7 @@ class EntitySearchPage extends EntityConfigBase { * @param \Drupal\migrate\Row $row * The row object to update from. */ - protected function updateEntity(EntityInterface $entity, Row $row) { + protected function updateEntity(EntityInterface &$entity, Row $row) { $entity->setPlugin($row->getDestinationProperty('plugin')); $entity->getPlugin()->setConfiguration($row->getDestinationProperty('configuration')); }