Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / migrate / tests / src / Kernel / MigrateEntityContentBaseTest.php
1 <?php
2
3 namespace Drupal\Tests\migrate\Kernel;
4
5 use Drupal\KernelTests\KernelTestBase;
6 use Drupal\language\Entity\ConfigurableLanguage;
7 use Drupal\migrate\MigrateExecutable;
8 use Drupal\migrate\MigrateMessage;
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;
14
15 /**
16  * Tests the EntityContentBase destination.
17  *
18  * @group migrate
19  */
20 class MigrateEntityContentBaseTest extends KernelTestBase {
21
22   /**
23    * Modules to enable.
24    *
25    * @var array
26    */
27   public static $modules = ['migrate', 'user', 'language', 'entity_test'];
28
29   /**
30    * The storage for entity_test_mul.
31    *
32    * @var \Drupal\Core\Entity\ContentEntityStorageInterface
33    */
34   protected $storage;
35
36   /**
37    * A content migrate destination.
38    *
39    * @var \Drupal\migrate\Plugin\MigrateDestinationInterface
40    */
41   protected $destination;
42
43   /**
44    * {@inheritdoc}
45    */
46   protected function setUp() {
47     parent::setUp();
48     $this->installEntitySchema('entity_test_mul');
49
50     ConfigurableLanguage::createFromLangcode('en')->save();
51     ConfigurableLanguage::createFromLangcode('fr')->save();
52
53     $this->storage = $this->container->get('entity.manager')->getStorage('entity_test_mul');
54   }
55
56   /**
57    * Check the existing translations of an entity.
58    *
59    * @param int $id
60    *   The entity ID.
61    * @param string $default
62    *   The expected default translation language code.
63    * @param string[] $others
64    *   The expected other translation language codes.
65    */
66   protected function assertTranslations($id, $default, $others = []) {
67     $entity = $this->storage->load($id);
68     $this->assertTrue($entity, "Entity exists");
69     $this->assertEquals($default, $entity->language()->getId(), "Entity default translation");
70     $translations = array_keys($entity->getTranslationLanguages(FALSE));
71     sort($others);
72     sort($translations);
73     $this->assertEquals($others, $translations, "Entity translations");
74   }
75
76   /**
77    * Create the destination plugin to test.
78    *
79    * @param array $configuration
80    *   The plugin configuration.
81    */
82   protected function createDestination(array $configuration) {
83     $this->destination = new EntityContentBase(
84       $configuration,
85       'fake_plugin_id',
86       [],
87       $this->getMock(MigrationInterface::class),
88       $this->storage,
89       [],
90       $this->container->get('entity.manager'),
91       $this->container->get('plugin.manager.field.field_type')
92     );
93   }
94
95   /**
96    * Test importing and rolling back translated entities.
97    */
98   public function testTranslated() {
99     // Create a destination.
100     $this->createDestination(['translations' => TRUE]);
101
102     // Create some pre-existing entities.
103     $this->storage->create(['id' => 1, 'langcode' => 'en'])->save();
104     $this->storage->create(['id' => 2, 'langcode' => 'fr'])->save();
105     $translated = $this->storage->create(['id' => 3, 'langcode' => 'en']);
106     $translated->save();
107     $translated->addTranslation('fr')->save();
108
109     // Pre-assert that things are as expected.
110     $this->assertTranslations(1, 'en');
111     $this->assertTranslations(2, 'fr');
112     $this->assertTranslations(3, 'en', ['fr']);
113     $this->assertFalse($this->storage->load(4));
114
115     $destination_rows = [
116       // Existing default translation.
117       ['id' => 1, 'langcode' => 'en', 'action' => MigrateIdMapInterface::ROLLBACK_PRESERVE],
118       // New translation.
119       ['id' => 2, 'langcode' => 'en', 'action' => MigrateIdMapInterface::ROLLBACK_DELETE],
120       // Existing non-default translation.
121       ['id' => 3, 'langcode' => 'fr', 'action' => MigrateIdMapInterface::ROLLBACK_PRESERVE],
122       // Brand new row.
123       ['id' => 4, 'langcode' => 'fr', 'action' => MigrateIdMapInterface::ROLLBACK_DELETE],
124     ];
125     $rollback_actions = [];
126
127     // Import some rows.
128     foreach ($destination_rows as $idx => $destination_row) {
129       $row = new Row();
130       foreach ($destination_row as $key => $value) {
131         $row->setDestinationProperty($key, $value);
132       }
133       $this->destination->import($row);
134
135       // Check that the rollback action is correct, and save it.
136       $this->assertEquals($destination_row['action'], $this->destination->rollbackAction());
137       $rollback_actions[$idx] = $this->destination->rollbackAction();
138     }
139
140     $this->assertTranslations(1, 'en');
141     $this->assertTranslations(2, 'fr', ['en']);
142     $this->assertTranslations(3, 'en', ['fr']);
143     $this->assertTranslations(4, 'fr');
144
145     // Rollback the rows.
146     foreach ($destination_rows as $idx => $destination_row) {
147       if ($rollback_actions[$idx] == MigrateIdMapInterface::ROLLBACK_DELETE) {
148         $this->destination->rollback($destination_row);
149       }
150     }
151
152     // No change, update of existing translation.
153     $this->assertTranslations(1, 'en');
154     // Remove added translation.
155     $this->assertTranslations(2, 'fr');
156     // No change, update of existing translation.
157     $this->assertTranslations(3, 'en', ['fr']);
158     // No change, can't remove default translation.
159     $this->assertTranslations(4, 'fr');
160   }
161
162   /**
163    * Tests creation of ID columns table with definitions taken from entity type.
164    */
165   public function testEntityWithStringId() {
166     $this->enableModules(['migrate_entity_test']);
167     $this->installEntitySchema('migrate_string_id_entity_test');
168
169     $definition = [
170       'source' => [
171         'plugin' => 'embedded_data',
172         'data_rows' => [
173           ['id' => 123, 'version' => 'foo'],
174           // This integer needs an 'int' schema with 'big' size. If 'destid1'
175           // is not correctly taking the definition from the destination entity
176           // type, the import will fail with a SQL exception.
177           ['id' => 123456789012, 'version' => 'bar'],
178         ],
179         'ids' => [
180           'id' => ['type' => 'integer', 'size' => 'big'],
181           'version' => ['type' => 'string'],
182         ],
183       ],
184       'process' => [
185         'id' => 'id',
186         'version' => 'version',
187       ],
188       'destination' => [
189         'plugin' => 'entity:migrate_string_id_entity_test',
190       ],
191     ];
192
193     $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
194     $executable = new MigrateExecutable($migration, new MigrateMessage());
195     $result = $executable->import();
196     $this->assertEquals(MigrationInterface::RESULT_COMPLETED, $result);
197
198     /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map_plugin */
199     $id_map_plugin = $migration->getIdMap();
200
201     // Check that the destination has been stored.
202     $map_row = $id_map_plugin->getRowBySource(['id' => 123, 'version' => 'foo']);
203     $this->assertEquals(123, $map_row['destid1']);
204     $map_row = $id_map_plugin->getRowBySource(['id' => 123456789012, 'version' => 'bar']);
205     $this->assertEquals(123456789012, $map_row['destid1']);
206   }
207
208   /**
209    * Tests empty destinations.
210    */
211   public function testEmptyDestinations() {
212     $this->enableModules(['migrate_entity_test']);
213     $this->installEntitySchema('migrate_string_id_entity_test');
214
215     $definition = [
216       'source' => [
217         'plugin' => 'embedded_data',
218         'data_rows' => [
219           ['id' => 123, 'version' => 'foo'],
220           // This integer needs an 'int' schema with 'big' size. If 'destid1'
221           // is not correctly taking the definition from the destination entity
222           // type, the import will fail with an SQL exception.
223           ['id' => 123456789012, 'version' => 'bar'],
224         ],
225         'ids' => [
226           'id' => ['type' => 'integer', 'size' => 'big'],
227           'version' => ['type' => 'string'],
228         ],
229         'constants' => ['null' => NULL],
230       ],
231       'process' => [
232         'id' => 'id',
233         'version' => 'version',
234       ],
235       'destination' => [
236         'plugin' => 'entity:migrate_string_id_entity_test',
237       ],
238     ];
239
240     $migration = \Drupal::service('plugin.manager.migration')
241       ->createStubMigration($definition);
242     $executable = new MigrateExecutable($migration, new MigrateMessage());
243     $executable->import();
244
245     /** @var \Drupal\migrate_entity_test\Entity\StringIdEntityTest $entity */
246     $entity = StringIdEntityTest::load('123');
247     $this->assertSame('foo', $entity->version->value);
248     $entity = StringIdEntityTest::load('123456789012');
249     $this->assertSame('bar', $entity->version->value);
250
251     // Rerun the migration forcing the version to NULL.
252     $definition['process'] = [
253       'id' => 'id',
254       'version' => 'constants/null',
255     ];
256
257     $migration = \Drupal::service('plugin.manager.migration')
258       ->createStubMigration($definition);
259     $executable = new MigrateExecutable($migration, new MigrateMessage());
260     $executable->import();
261
262     /** @var \Drupal\migrate_entity_test\Entity\StringIdEntityTest $entity */
263     $entity = StringIdEntityTest::load('123');
264     $this->assertNull($entity->version->value);
265     $entity = StringIdEntityTest::load('123456789012');
266     $this->assertNull($entity->version->value);
267   }
268
269 }