3 namespace Drupal\Tests\migrate\Kernel;
5 use Drupal\entity_test\Entity\EntityTestMul;
6 use Drupal\KernelTests\KernelTestBase;
7 use Drupal\language\Entity\ConfigurableLanguage;
8 use Drupal\migrate\MigrateExecutable;
9 use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
10 use Drupal\migrate\Plugin\MigrateIdMapInterface;
11 use Drupal\migrate\Plugin\MigrationInterface;
12 use Drupal\migrate\Row;
13 use Drupal\migrate_entity_test\Entity\StringIdEntityTest;
16 * Tests the EntityContentBase destination.
20 class MigrateEntityContentBaseTest extends KernelTestBase {
27 public static $modules = ['migrate', 'user', 'language', 'entity_test'];
30 * The storage for entity_test_mul.
32 * @var \Drupal\Core\Entity\ContentEntityStorageInterface
37 * A content migrate destination.
39 * @var \Drupal\migrate\Plugin\MigrateDestinationInterface
41 protected $destination;
46 protected function setUp() {
49 // Enable two required fields with default values: a single-value field and
50 // a multi-value field.
51 \Drupal::state()->set('entity_test.required_default_field', TRUE);
52 \Drupal::state()->set('entity_test.required_multi_default_field', TRUE);
53 $this->installEntitySchema('entity_test_mul');
55 ConfigurableLanguage::createFromLangcode('en')->save();
56 ConfigurableLanguage::createFromLangcode('fr')->save();
58 $this->storage = $this->container->get('entity.manager')->getStorage('entity_test_mul');
62 * Check the existing translations of an entity.
66 * @param string $default
67 * The expected default translation language code.
68 * @param string[] $others
69 * The expected other translation language codes.
71 protected function assertTranslations($id, $default, $others = []) {
72 $entity = $this->storage->load($id);
73 $this->assertTrue($entity, "Entity exists");
74 $this->assertEquals($default, $entity->language()->getId(), "Entity default translation");
75 $translations = array_keys($entity->getTranslationLanguages(FALSE));
78 $this->assertEquals($others, $translations, "Entity translations");
82 * Create the destination plugin to test.
84 * @param array $configuration
85 * The plugin configuration.
87 protected function createDestination(array $configuration) {
88 $this->destination = new EntityContentBase(
92 $this->getMock(MigrationInterface::class),
95 $this->container->get('entity.manager'),
96 $this->container->get('plugin.manager.field.field_type')
101 * Test importing and rolling back translated entities.
103 public function testTranslated() {
104 // Create a destination.
105 $this->createDestination(['translations' => TRUE]);
107 // Create some pre-existing entities.
108 $this->storage->create(['id' => 1, 'langcode' => 'en'])->save();
109 $this->storage->create(['id' => 2, 'langcode' => 'fr'])->save();
110 $translated = $this->storage->create(['id' => 3, 'langcode' => 'en']);
112 $translated->addTranslation('fr')->save();
114 // Pre-assert that things are as expected.
115 $this->assertTranslations(1, 'en');
116 $this->assertTranslations(2, 'fr');
117 $this->assertTranslations(3, 'en', ['fr']);
118 $this->assertFalse($this->storage->load(4));
120 $destination_rows = [
121 // Existing default translation.
122 ['id' => 1, 'langcode' => 'en', 'action' => MigrateIdMapInterface::ROLLBACK_PRESERVE],
124 ['id' => 2, 'langcode' => 'en', 'action' => MigrateIdMapInterface::ROLLBACK_DELETE],
125 // Existing non-default translation.
126 ['id' => 3, 'langcode' => 'fr', 'action' => MigrateIdMapInterface::ROLLBACK_PRESERVE],
128 ['id' => 4, 'langcode' => 'fr', 'action' => MigrateIdMapInterface::ROLLBACK_DELETE],
130 $rollback_actions = [];
133 foreach ($destination_rows as $idx => $destination_row) {
135 foreach ($destination_row as $key => $value) {
136 $row->setDestinationProperty($key, $value);
138 $this->destination->import($row);
140 // Check that the rollback action is correct, and save it.
141 $this->assertEquals($destination_row['action'], $this->destination->rollbackAction());
142 $rollback_actions[$idx] = $this->destination->rollbackAction();
145 $this->assertTranslations(1, 'en');
146 $this->assertTranslations(2, 'fr', ['en']);
147 $this->assertTranslations(3, 'en', ['fr']);
148 $this->assertTranslations(4, 'fr');
150 // Rollback the rows.
151 foreach ($destination_rows as $idx => $destination_row) {
152 if ($rollback_actions[$idx] == MigrateIdMapInterface::ROLLBACK_DELETE) {
153 $this->destination->rollback($destination_row);
157 // No change, update of existing translation.
158 $this->assertTranslations(1, 'en');
159 // Remove added translation.
160 $this->assertTranslations(2, 'fr');
161 // No change, update of existing translation.
162 $this->assertTranslations(3, 'en', ['fr']);
163 // No change, can't remove default translation.
164 $this->assertTranslations(4, 'fr');
168 * Tests creation of ID columns table with definitions taken from entity type.
170 public function testEntityWithStringId() {
171 $this->enableModules(['migrate_entity_test']);
172 $this->installEntitySchema('migrate_string_id_entity_test');
176 'plugin' => 'embedded_data',
178 ['id' => 123, 'version' => 'foo'],
179 // This integer needs an 'int' schema with 'big' size. If 'destid1'
180 // is not correctly taking the definition from the destination entity
181 // type, the import will fail with a SQL exception.
182 ['id' => 123456789012, 'version' => 'bar'],
185 'id' => ['type' => 'integer', 'size' => 'big'],
186 'version' => ['type' => 'string'],
191 'version' => 'version',
194 'plugin' => 'entity:migrate_string_id_entity_test',
198 $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
199 $executable = new MigrateExecutable($migration);
200 $result = $executable->import();
201 $this->assertEquals(MigrationInterface::RESULT_COMPLETED, $result);
203 /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map_plugin */
204 $id_map_plugin = $migration->getIdMap();
206 // Check that the destination has been stored.
207 $map_row = $id_map_plugin->getRowBySource(['id' => 123, 'version' => 'foo']);
208 $this->assertEquals(123, $map_row['destid1']);
209 $map_row = $id_map_plugin->getRowBySource(['id' => 123456789012, 'version' => 'bar']);
210 $this->assertEquals(123456789012, $map_row['destid1']);
214 * Tests empty destinations.
216 public function testEmptyDestinations() {
217 $this->enableModules(['migrate_entity_test']);
218 $this->installEntitySchema('migrate_string_id_entity_test');
222 'plugin' => 'embedded_data',
224 ['id' => 123, 'version' => 'foo'],
225 // This integer needs an 'int' schema with 'big' size. If 'destid1'
226 // is not correctly taking the definition from the destination entity
227 // type, the import will fail with an SQL exception.
228 ['id' => 123456789012, 'version' => 'bar'],
231 'id' => ['type' => 'integer', 'size' => 'big'],
232 'version' => ['type' => 'string'],
234 'constants' => ['null' => NULL],
238 'version' => 'version',
241 'plugin' => 'entity:migrate_string_id_entity_test',
245 $migration = \Drupal::service('plugin.manager.migration')
246 ->createStubMigration($definition);
247 $executable = new MigrateExecutable($migration);
248 $executable->import();
250 /** @var \Drupal\migrate_entity_test\Entity\StringIdEntityTest $entity */
251 $entity = StringIdEntityTest::load('123');
252 $this->assertSame('foo', $entity->version->value);
253 $entity = StringIdEntityTest::load('123456789012');
254 $this->assertSame('bar', $entity->version->value);
256 // Rerun the migration forcing the version to NULL.
257 $definition['process'] = [
259 'version' => 'constants/null',
262 $migration = \Drupal::service('plugin.manager.migration')
263 ->createStubMigration($definition);
264 $executable = new MigrateExecutable($migration);
265 $executable->import();
267 /** @var \Drupal\migrate_entity_test\Entity\StringIdEntityTest $entity */
268 $entity = StringIdEntityTest::load('123');
269 $this->assertNull($entity->version->value);
270 $entity = StringIdEntityTest::load('123456789012');
271 $this->assertNull($entity->version->value);
277 public function testStubRows() {
278 // Create a destination.
279 $this->createDestination([]);
281 // Import a stub row.
282 $row = new Row([], [], TRUE);
283 $row->setDestinationProperty('type', 'test');
284 $ids = $this->destination->import($row);
285 $this->assertCount(1, $ids);
287 // Make sure the entity was saved.
288 $entity = EntityTestMul::load(reset($ids));
289 $this->assertInstanceOf(EntityTestMul::class, $entity);
290 // Make sure the default value was applied to the required fields.
291 $single_field_name = 'required_default_field';
292 $single_default_value = $entity->getFieldDefinition($single_field_name)->getDefaultValueLiteral();
293 $this->assertSame($single_default_value, $entity->get($single_field_name)->getValue());
295 $multi_field_name = 'required_multi_default_field';
296 $multi_default_value = $entity->getFieldDefinition($multi_field_name)->getDefaultValueLiteral();
298 $this->assertCount($count, $multi_default_value);
299 for ($i = 0; $i < $count; ++$i) {
300 $this->assertSame($multi_default_value[$i], $entity->get($multi_field_name)->get($i)->getValue());