Added Entity and Entity Reference Revisions which got dropped somewhere along the...
[yaffs-website] / web / modules / contrib / entity_reference_revisions / tests / src / Kernel / Plugin / migrate / destination / EntityReferenceRevisionsDestinationTest.php
1 <?php
2
3 namespace Drupal\Tests\entity_reference_revisions\Kernel\Plugin\migrate\destination;
4
5 use Drupal\field\Entity\FieldConfig;
6 use Drupal\field\Entity\FieldStorageConfig;
7 use Drupal\KernelTests\KernelTestBase;
8 use Drupal\migrate\MigrateExecutable;
9 use Drupal\migrate\MigrateMessageInterface;
10 use Drupal\migrate\Plugin\Migration;
11 use Drupal\node\Entity\NodeType;
12
13 /**
14  * Tests the migration destination plugin.
15  *
16  * @coversDefaultClass \Drupal\entity_reference_revisions\Plugin\migrate\destination\EntityReferenceRevisions
17  * @group entity_reference_revisions
18  */
19 class EntityReferenceRevisionsDestinationTest extends KernelTestBase implements MigrateMessageInterface {
20
21   /**
22    * The migration plugin manager.
23    *
24    * @var \Drupal\migrate\Plugin\MigrationPluginManager
25    */
26   protected $migrationPluginManager;
27
28   /**
29    * {@inheritdoc}
30    */
31   public static $modules = [
32     'migrate',
33     'entity_reference_revisions',
34     'entity_composite_relationship_test',
35     'user',
36     'system',
37     'text',
38   ];
39
40   /**
41    * {@inheritdoc}
42    */
43   protected function setUp() {
44     parent::setUp();
45     $this->installEntitySchema('entity_test_composite');
46     $this->installSchema('system', ['sequences']);
47     $this->installConfig($this->modules);
48
49     $this->migrationPluginManager = \Drupal::service('plugin.manager.migration');
50   }
51
52   /**
53    * Tests get entity type id.
54    *
55    * @dataProvider getEntityTypeIdDataProvider
56    *
57    * @covers ::getEntityTypeId
58    */
59   public function testGetEntityTypeId(array $definition, $expected) {
60     /** @var \Drupal\migrate\Plugin\Migration $migration */
61     $migration = $this->migrationPluginManager->createStubMigration($definition);
62     /** @var \Drupal\entity_reference_revisions\Plugin\migrate\destination\EntityReferenceRevisions $destination */
63     $destination = $migration->getDestinationPlugin();
64
65     /** @var \Drupal\Core\Entity\EntityStorageBase $storage */
66     $storage = $this->readAttribute($destination, 'storage');
67     $actual = $this->readAttribute($storage, 'entityTypeId');
68
69     $this->assertEquals($expected, $actual);
70   }
71
72   /**
73    * Provides multiple migration definitions for "getEntityTypeId" test.
74    */
75   public function getEntityTypeIdDataProvider() {
76     $data = $this->getEntityDataProvider();
77
78     foreach ($data as &$datum) {
79       $datum['expected'] = 'entity_test_composite';
80     }
81
82     return $data;
83   }
84
85   /**
86    * Tests get entity.
87    *
88    * @dataProvider getEntityDataProvider
89    *
90    * @covers ::getEntity
91    * @covers ::rollback
92    * @covers ::rollbackNonTranslation
93    */
94   public function testGetEntity(array $definition, array $expected) {
95     /** @var \Drupal\migrate\Plugin\Migration $migration */
96     $migration = $this->migrationPluginManager->createStubMigration($definition);
97     $migrationExecutable = (new MigrateExecutable($migration, $this));
98     /** @var \Drupal\Core\Entity\EntityStorageBase $storage */
99     $storage = $this->readAttribute($migration->getDestinationPlugin(), 'storage');
100     // Test inserting and updating by looping twice.
101     for ($i = 0; $i < 2; $i++) {
102       $migrationExecutable->import();
103       $migration->getIdMap()->prepareUpdate();
104       foreach ($expected as $data) {
105         $entity = $storage->loadRevision($data['revision_id']);
106         $this->assertEquals($data['label'], $entity->label());
107         $this->assertEquals($data['id'], $entity->id());
108       }
109     }
110     $migrationExecutable->rollback();
111     foreach ($expected as $data) {
112       $entity = $storage->loadRevision($data['id']);
113       $this->assertEmpty($entity);
114     }
115   }
116
117   /**
118    * Provides multiple migration definitions for "getEntity" test.
119    */
120   public function getEntityDataProvider() {
121     return [
122       'without keys' => [
123         'definition' => [
124           'source' => [
125             'plugin' => 'embedded_data',
126             'data_rows' => [
127               ['id' => 1, 'name' => 'content item 1a'],
128               ['id' => 1, 'name' => 'content item 1b'],
129               ['id' => 2, 'name' => 'content item 2'],
130             ],
131             'ids' => [
132               'id' => ['type' => 'integer'],
133               'name' => ['type' => 'text'],
134             ],
135           ],
136           'process' => [
137             'name' => 'name',
138           ],
139           'destination' => [
140             'plugin' => 'entity_reference_revisions:entity_test_composite',
141           ],
142         ],
143         'expected' => [
144           ['id' => 1, 'revision_id' => 1, 'label' => 'content item 1a'],
145           ['id' => 2, 'revision_id' => 2, 'label' => 'content item 1b'],
146           ['id' => 3, 'revision_id' => 3, 'label' => 'content item 2'],
147         ],
148       ],
149       'with ids' => [
150         'definition' => [
151           'source' => [
152             'plugin' => 'embedded_data',
153             'data_rows' => [
154               ['id' => 1, 'name' => 'content item 1a'],
155               ['id' => 1, 'name' => 'content item 1b'],
156               ['id' => 2, 'name' => 'content item 2'],
157               ['id' => 3, 'name' => 'content item 3'],
158             ],
159             'ids' => [
160               'id' => ['type' => 'integer'],
161               'name' => ['type' => 'text'],
162             ],
163           ],
164           'process' => [
165             'name' => 'name',
166             'id' => 'id',
167           ],
168           'destination' => [
169             'plugin' => 'entity_reference_revisions:entity_test_composite',
170           ],
171         ],
172         'expected' => [
173           ['id' => 1, 'revision_id' => 1, 'label' => 'content item 1b'],
174           ['id' => 2, 'revision_id' => 2, 'label' => 'content item 2'],
175           ['id' => 3, 'revision_id' => 3, 'label' => 'content item 3'],
176         ],
177       ],
178       'with ids and new revisions' => [
179         'definition' => [
180           'source' => [
181             'plugin' => 'embedded_data',
182             'data_rows' => [
183               ['id' => 1, 'name' => 'content item 1a'],
184               ['id' => 1, 'name' => 'content item 1b'],
185               ['id' => 2, 'name' => 'content item 2'],
186             ],
187             'ids' => [
188               'id' => ['type' => 'integer'],
189               'name' => ['type' => 'text'],
190             ],
191           ],
192           'process' => [
193             'name' => 'name',
194             'id' => 'id',
195           ],
196           'destination' => [
197             'plugin' => 'entity_reference_revisions:entity_test_composite',
198             'new_revisions' => TRUE,
199           ],
200         ],
201         'expected' => [
202           ['id' => 1, 'revision_id' => 1, 'label' => 'content item 1a'],
203           ['id' => 1, 'revision_id' => 2, 'label' => 'content item 1b'],
204           ['id' => 2, 'revision_id' => 3, 'label' => 'content item 2'],
205         ],
206       ],
207       'with ids and revisions' => [
208         'definition' => [
209           'source' => [
210             'plugin' => 'embedded_data',
211             'data_rows' => [
212               ['id' => 1, 'revision_id' => 1, 'name' => 'content item 1'],
213               ['id' => 2, 'revision_id' => 2, 'name' => 'content item 2'],
214               ['id' => 3, 'revision_id' => 3, 'name' => 'content item 3'],
215             ],
216             'ids' => [
217               'id' => ['type' => 'integer'],
218               'name' => ['type' => 'text'],
219             ],
220           ],
221           'process' => [
222             'id' => 'id',
223             'revision_id' => 'revision_id',
224             'name' => 'name',
225           ],
226           'destination' => [
227             'plugin' => 'entity_reference_revisions:entity_test_composite',
228           ],
229         ],
230         'expected' => [
231           ['id' => 1, 'revision_id' => 1, 'label' => 'content item 1'],
232           ['id' => 2, 'revision_id' => 2, 'label' => 'content item 2'],
233           ['id' => 3, 'revision_id' => 3, 'label' => 'content item 3'],
234         ],
235       ],
236     ];
237   }
238
239   /**
240    * Tests multi-value and single-value destination field linkage.
241    *
242    * @dataProvider destinationFieldMappingDataProvider
243    */
244   public function testDestinationFieldMapping(array $data) {
245     $this->enableModules(['node', 'field']);
246     $this->installEntitySchema('node');
247     $this->installEntitySchema('user');
248     $this->installSchema('node', ['node_access']);
249
250     // Create new content type.
251     $values = ['type' => 'article', 'name' => 'Article'];
252     $node_type = NodeType::create($values);
253     $node_type->save();
254
255     // Add the field_err_single field to the node type.
256     $field_storage = FieldStorageConfig::create([
257       'field_name' => 'field_err_single',
258       'entity_type' => 'node',
259       'type' => 'entity_reference_revisions',
260       'settings' => [
261         'target_type' => 'entity_test_composite',
262       ],
263       'cardinality' => 1,
264     ]);
265     $field_storage->save();
266     $field = FieldConfig::create([
267       'field_storage' => $field_storage,
268       'bundle' => 'article',
269     ]);
270     $field->save();
271
272     // Add the field_err_multiple field to the node type.
273     $field_storage = FieldStorageConfig::create([
274       'field_name' => 'field_err_multiple',
275       'entity_type' => 'node',
276       'type' => 'entity_reference_revisions',
277       'settings' => [
278         'target_type' => 'entity_test_composite',
279       ],
280       'cardinality' => -1,
281     ]);
282     $field_storage->save();
283     $field = FieldConfig::create([
284       'field_storage' => $field_storage,
285       'bundle' => 'article',
286     ]);
287     $field->save();
288
289     $definitions = [];
290     $instances = [];
291     foreach ($data as $datum) {
292       $definitions[$datum['definition']['id']] = $datum['definition'];
293       $instances[$datum['definition']['id']] = $this->migrationPluginManager->createStubMigration($datum['definition']);
294     }
295
296     // Reflection is easier than mocking. We need to use createInstance for
297     // purposes of registering the migration for the migration process plugin.
298     $reflector = new \ReflectionObject($this->migrationPluginManager);
299     $property = $reflector->getProperty('definitions');
300     $property->setAccessible(TRUE);
301     $property->setValue($this->migrationPluginManager, $definitions);
302     $this->container->set('plugin.manager.migration', $this->migrationPluginManager);
303
304     foreach ($data as $datum) {
305       $migration = $this->migrationPluginManager->createInstance($datum['definition']['id']);
306       $migrationExecutable = (new MigrateExecutable($migration, $this));
307       /** @var \Drupal\Core\Entity\EntityStorageBase $storage */
308       $storage = $this->readAttribute($migration->getDestinationPlugin(), 'storage');
309       $migrationExecutable->import();
310       foreach ($datum['expected'] as $expected) {
311         $entity = $storage->loadRevision($expected['id']);
312         $properties = array_diff_key($expected, array_flip(['id']));
313         foreach ($properties as $property => $value) {
314           if (is_array($value)) {
315             foreach ($value as $delta => $text) {
316               $this->assertNotEmpty($entity->{$property}[$delta]->entity, "Entity property $property with $delta is empty");
317               $this->assertEquals($text, $entity->{$property}[$delta]->entity->label());
318             }
319           }
320           else {
321             $this->assertNotEmpty($entity, 'Entity with label ' . $expected[$property] . ' is empty');
322             $this->assertEquals($expected[$property], $entity->label());
323           }
324         }
325       }
326     }
327   }
328
329   /**
330    * Provides multiple migration definitions for "getEntity" test.
331    */
332   public function destinationFieldMappingDataProvider() {
333     return [
334       'scenario 1' => [
335         [
336           'single err' => [
337             'definition' => [
338               'id' => 'single_err',
339               'class' => Migration::class,
340               'source' => [
341                 'plugin' => 'embedded_data',
342                 'data_rows' => [
343                   [
344                     'id' => 1,
345                     'photo' => 'Photo1 here',
346                   ],
347                   [
348                     'id' => 2,
349                     'photo' => 'Photo2 here',
350                   ],
351                 ],
352                 'ids' => [
353                   'id' => ['type' => 'integer'],
354                 ],
355               ],
356               'process' => [
357                 'name' => 'photo',
358               ],
359               'destination' => [
360                 'plugin' => 'entity_reference_revisions:entity_test_composite',
361               ],
362             ],
363             'expected' => [
364               ['id' => 1, 'name' => 'Photo1 here'],
365               ['id' => 2, 'name' => 'Photo2 here'],
366             ],
367           ],
368           'multiple err author1' => [
369             'definition' => [
370               'id' => 'multiple_err_author1',
371               'class' => Migration::class,
372               'source' => [
373                 'plugin' => 'embedded_data',
374                 'data_rows' => [
375                   [
376                     'id' => 1,
377                     'author' => 'Author 1',
378                   ],
379                   [
380                     'id' => 2,
381                     'author' => 'Author 2',
382                   ],
383                 ],
384                 'ids' => [
385                   'author' => ['type' => 'text'],
386                 ],
387               ],
388               'process' => [
389                 'name' => 'author',
390               ],
391               'destination' => [
392                 'plugin' => 'entity_reference_revisions:entity_test_composite',
393               ],
394             ],
395             'expected' => [
396               ['id' => 3, 'name' => 'Author 1'],
397               ['id' => 4, 'name' => 'Author 2'],
398             ],
399           ],
400           'multiple err author 2' => [
401             'definition' => [
402               'id' => 'multiple_err_author2',
403               'class' => Migration::class,
404               'source' => [
405                 'plugin' => 'embedded_data',
406                 'data_rows' => [
407                   [
408                     'id' => 1,
409                     'author' => 'Author 3',
410                   ],
411                   [
412                     'id' => 2,
413                     'author' => 'Author 4',
414                   ],
415                 ],
416                 'ids' => [
417                   'author' => ['type' => 'text'],
418                 ],
419               ],
420               'process' => [
421                 'name' => 'author',
422               ],
423               'destination' => [
424                 'plugin' => 'entity_reference_revisions:entity_test_composite',
425               ],
426             ],
427             'expected' => [
428               ['id' => 5, 'name' => 'Author 3'],
429               ['id' => 6, 'name' => 'Author 4'],
430             ],
431           ],
432           'destination entity' => [
433             'definition' => [
434               'id' => 'node_migration',
435               'class' => Migration::class,
436               'source' => [
437                 'plugin' => 'embedded_data',
438                 'data_rows' => [
439                   [
440                     'id' => 1,
441                     'title' => 'Article 1',
442                     'photo' => 'Photo1 here',
443                     'author' => ['Author 1', 'Author 3'],
444                   ],
445                   [
446                     'id' => 2,
447                     'title' => 'Article 2',
448                     'photo' => 'Photo2 here',
449                     'author' => ['Author 2', 'Author 4'],
450                   ],
451                 ],
452                 'ids' => [
453                   'id' => ['type' => 'integer'],
454                 ],
455               ],
456               'process' => [
457                 'title' => 'title',
458                 'type' => [
459                   'plugin' => 'default_value',
460                   'default_value' => 'article',
461                 ],
462                 'field_err_single/target_id' => [
463                   [
464                     'plugin' => 'migration',
465                     'migration' => ['single_err'],
466                     'no_stub' => TRUE,
467                     'source' => 'id',
468                   ],
469                   [
470                     'plugin' => 'extract',
471                     'index' => [
472                       '0',
473                     ],
474                   ],
475                 ],
476                 'field_err_single/target_revision_id' => [
477                   [
478                     'plugin' => 'migration',
479                     'migration' => ['single_err'],
480                     'no_stub' => TRUE,
481                     'source' => 'id',
482                   ],
483                   [
484                     'plugin' => 'extract',
485                     'index' => [
486                       1,
487                     ],
488                   ],
489                 ],
490                 'field_err_multiple' => [
491                   [
492                     'plugin' => 'migration',
493                     'migration' => [
494                       'multiple_err_author1',
495                       'multiple_err_author2',
496                     ],
497                     'no_stub' => TRUE,
498                     'source' => 'author',
499                   ],
500                   [
501                     'plugin' => 'iterator',
502                     'process' => [
503                       'target_id' => '0',
504                       'target_revision_id' => '1',
505                     ],
506                   ],
507                 ],
508               ],
509               'destination' => [
510                 'plugin' => 'entity:node',
511               ],
512             ],
513             'expected' => [
514               [
515                 'id' => 1,
516                 'title' => 'Article 1',
517                 'field_err_single' => ['Photo1 here'],
518                 'field_err_multiple' => ['Author 1', 'Author 3'],
519               ],
520               [
521                 'id' => 2,
522                 'title' => 'Article 2',
523                 'field_err_single' => ['Photo2 here'],
524                 'field_err_multiple' => ['Author 2', 'Author 4'],
525               ],
526             ],
527           ],
528         ],
529       ],
530     ];
531   }
532
533   /**
534    * {@inheritdoc}
535    */
536   public function display($message, $type = 'status') {
537     $this->assertTrue($type == 'status', $message);
538   }
539
540 }