Pull merge.
[yaffs-website] / web / core / modules / migrate_drupal / tests / src / Kernel / Plugin / migrate / source / ContentEntityTest.php
1 <?php
2
3 namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source;
4
5 use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
6 use Drupal\Core\Field\FieldStorageDefinitionInterface;
7 use Drupal\Core\Language\LanguageInterface;
8 use Drupal\file\Entity\File;
9 use Drupal\KernelTests\KernelTestBase;
10 use Drupal\language\Entity\ConfigurableLanguage;
11 use Drupal\media\Entity\Media;
12 use Drupal\migrate\Plugin\MigrationInterface;
13 use Drupal\migrate_drupal\Plugin\migrate\source\ContentEntity;
14 use Drupal\node\Entity\Node;
15 use Drupal\node\Entity\NodeType;
16 use Drupal\taxonomy\Entity\Term;
17 use Drupal\taxonomy\Entity\Vocabulary;
18 use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
19 use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
20 use Drupal\user\Entity\User;
21
22 /**
23  * Tests the entity content source plugin.
24  *
25  * @group migrate_drupal
26  */
27 class ContentEntityTest extends KernelTestBase {
28
29   use EntityReferenceTestTrait;
30   use MediaTypeCreationTrait;
31
32   /**
33    * {@inheritdoc}
34    */
35   public static $modules = [
36     'user',
37     'migrate',
38     'migrate_drupal',
39     'system',
40     'node',
41     'taxonomy',
42     'field',
43     'file',
44     'image',
45     'media',
46     'media_test_source',
47     'text',
48     'filter',
49     'language',
50     'content_translation',
51   ];
52
53   /**
54    * The bundle used in this test.
55    *
56    * @var string
57    */
58   protected $bundle = 'article';
59
60   /**
61    * The name of the field used in this test.
62    *
63    * @var string
64    */
65   protected $fieldName = 'field_entity_reference';
66
67   /**
68    * The vocabulary ID.
69    *
70    * @var string
71    */
72   protected $vocabulary = 'fruit';
73
74   /**
75    * The test user.
76    *
77    * @var \Drupal\user\Entity\User
78    */
79   protected $user;
80
81   /**
82    * The migration plugin manager.
83    *
84    * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
85    */
86   protected $migrationPluginManager;
87
88   /**
89    * The source plugin manager.
90    *
91    * @var \Drupal\migrate\Plugin\MigrateSourcePluginManager
92    */
93   protected $sourcePluginManager;
94
95   /**
96    * {@inheritdoc}
97    */
98   protected function setUp() {
99     parent::setUp();
100     $this->installEntitySchema('node');
101     $this->installEntitySchema('file');
102     $this->installEntitySchema('media');
103     $this->installEntitySchema('taxonomy_term');
104     $this->installEntitySchema('taxonomy_vocabulary');
105     $this->installEntitySchema('user');
106     $this->installSchema('system', ['sequences']);
107     $this->installSchema('user', 'users_data');
108     $this->installSchema('file', 'file_usage');
109     $this->installSchema('node', ['node_access']);
110     $this->installConfig($this->modules);
111
112     ConfigurableLanguage::createFromLangcode('fr')->save();
113
114     // Create article content type.
115     $node_type = NodeType::create(['type' => $this->bundle, 'name' => 'Article']);
116     $node_type->save();
117
118     // Create a vocabulary.
119     $vocabulary = Vocabulary::create([
120       'name' => $this->vocabulary,
121       'description' => $this->vocabulary,
122       'vid' => $this->vocabulary,
123       'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
124     ]);
125     $vocabulary->save();
126
127     // Create a term reference field on node.
128     $this->createEntityReferenceField(
129       'node',
130       $this->bundle,
131       $this->fieldName,
132       'Term reference',
133       'taxonomy_term',
134       'default',
135       ['target_bundles' => [$this->vocabulary]],
136       FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
137     );
138     // Create a term reference field on user.
139     $this->createEntityReferenceField(
140       'user',
141       'user',
142       $this->fieldName,
143       'Term reference',
144       'taxonomy_term',
145       'default',
146       ['target_bundles' => [$this->vocabulary]],
147       FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
148     );
149
150     // Create some data.
151     $this->user = User::create([
152       'name' => 'user123',
153       'uid' => 1,
154       'mail' => 'example@example.com',
155     ]);
156     $this->user->save();
157
158     $term = Term::create([
159       'vid' => $this->vocabulary,
160       'name' => 'Apples',
161       'uid' => $this->user->id(),
162     ]);
163     $term->save();
164     $this->user->set($this->fieldName, $term->id());
165     $this->user->save();
166     $node = Node::create([
167       'type' => $this->bundle,
168       'title' => 'Apples',
169       $this->fieldName => $term->id(),
170       'uid' => $this->user->id(),
171     ]);
172     $node->save();
173     $node->addTranslation('fr', [
174       'title' => 'Pommes',
175       $this->fieldName => $term->id(),
176     ])->save();
177
178     $this->sourcePluginManager = $this->container->get('plugin.manager.migrate.source');
179     $this->migrationPluginManager = $this->container->get('plugin.manager.migration');
180   }
181
182   /**
183    * Tests the constructor for missing entity_type.
184    */
185   public function testConstructorEntityTypeMissing() {
186     $migration = $this->prophesize(MigrationInterface::class)->reveal();
187     $configuration = [];
188     $plugin_definition = [
189       'entity_type' => '',
190     ];
191     $this->setExpectedException(InvalidPluginDefinitionException::class, 'Missing required "entity_type" definition.');
192     ContentEntity::create($this->container, $configuration, 'content_entity', $plugin_definition, $migration);
193   }
194
195   /**
196    * Tests the constructor for non content entity.
197    */
198   public function testConstructorNonContentEntity() {
199     $migration = $this->prophesize(MigrationInterface::class)->reveal();
200     $configuration = [];
201     $plugin_definition = [
202       'entity_type' => 'node_type',
203     ];
204     $this->setExpectedException(InvalidPluginDefinitionException::class, 'The entity type (node_type) is not supported. The "content_entity" source plugin only supports content entities.');
205     ContentEntity::create($this->container, $configuration, 'content_entity:node_type', $plugin_definition, $migration);
206   }
207
208   /**
209    * Tests the constructor for not bundleable entity.
210    */
211   public function testConstructorNotBundable() {
212     $migration = $this->prophesize(MigrationInterface::class)->reveal();
213     $configuration = [
214       'bundle' => 'foo',
215     ];
216     $plugin_definition = [
217       'entity_type' => 'user',
218     ];
219     $this->setExpectedException(\InvalidArgumentException::class, 'A bundle was provided but the entity type (user) is not bundleable');
220     ContentEntity::create($this->container, $configuration, 'content_entity:user', $plugin_definition, $migration);
221   }
222
223   /**
224    * Tests the constructor for invalid entity bundle.
225    */
226   public function testConstructorInvalidBundle() {
227     $migration = $this->prophesize(MigrationInterface::class)->reveal();
228     $configuration = [
229       'bundle' => 'foo',
230     ];
231     $plugin_definition = [
232       'entity_type' => 'node',
233     ];
234     $this->setExpectedException(\InvalidArgumentException::class, 'The provided bundle (foo) is not valid for the (node) entity type.');
235     ContentEntity::create($this->container, $configuration, 'content_entity:node', $plugin_definition, $migration);
236   }
237
238   /**
239    * Tests user source plugin.
240    */
241   public function testUserSource() {
242     $configuration = [
243       'include_translations' => FALSE,
244     ];
245     $migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:user'));
246     $user_source = $this->sourcePluginManager->createInstance('content_entity:user', $configuration, $migration);
247     $this->assertSame('users', $user_source->__toString());
248     $this->assertEquals(1, $user_source->count());
249     $ids = $user_source->getIds();
250     $this->assertArrayHasKey('langcode', $ids);
251     $this->assertArrayHasKey('uid', $ids);
252     $fields = $user_source->fields();
253     $this->assertArrayHasKey('name', $fields);
254     $this->assertArrayHasKey('pass', $fields);
255     $this->assertArrayHasKey('mail', $fields);
256     $this->assertArrayHasKey('uid', $fields);
257     $this->assertArrayHasKey('roles', $fields);
258     $user_source->rewind();
259     $values = $user_source->current()->getSource();
260     $this->assertEquals('example@example.com', $values['mail'][0]['value']);
261     $this->assertEquals('user123', $values['name'][0]['value']);
262     $this->assertEquals(1, $values['uid']);
263     $this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
264   }
265
266   /**
267    * Tests file source plugin.
268    */
269   public function testFileSource() {
270     $file = File::create([
271       'filename' => 'foo.txt',
272       'uid' => $this->user->id(),
273       'uri' => 'public://foo.txt',
274     ]);
275     $file->save();
276
277     $configuration = [
278       'include_translations' => FALSE,
279     ];
280     $migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:file'));
281     $file_source = $this->sourcePluginManager->createInstance('content_entity:file', $configuration, $migration);
282     $this->assertSame('files', $file_source->__toString());
283     $this->assertEquals(1, $file_source->count());
284     $ids = $file_source->getIds();
285     $this->assertArrayHasKey('fid', $ids);
286     $fields = $file_source->fields();
287     $this->assertArrayHasKey('fid', $fields);
288     $this->assertArrayHasKey('filemime', $fields);
289     $this->assertArrayHasKey('filename', $fields);
290     $this->assertArrayHasKey('uid', $fields);
291     $this->assertArrayHasKey('uri', $fields);
292     $file_source->rewind();
293     $values = $file_source->current()->getSource();
294     $this->assertEquals('text/plain', $values['filemime'][0]['value']);
295     $this->assertEquals('public://foo.txt', $values['uri'][0]['value']);
296     $this->assertEquals('foo.txt', $values['filename'][0]['value']);
297     $this->assertEquals(1, $values['fid']);
298   }
299
300   /**
301    * Tests node source plugin.
302    */
303   public function testNodeSource() {
304     $migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:node'));
305     $node_source = $this->sourcePluginManager->createInstance('content_entity:node', ['bundle' => $this->bundle], $migration);
306     $this->assertSame('content items', $node_source->__toString());
307     $ids = $node_source->getIds();
308     $this->assertArrayHasKey('langcode', $ids);
309     $this->assertArrayHasKey('nid', $ids);
310     $fields = $node_source->fields();
311     $this->assertArrayHasKey('nid', $fields);
312     $this->assertArrayHasKey('vid', $fields);
313     $this->assertArrayHasKey('title', $fields);
314     $this->assertArrayHasKey('uid', $fields);
315     $this->assertArrayHasKey('sticky', $fields);
316     $node_source->rewind();
317     $values = $node_source->current()->getSource();
318     $this->assertEquals($this->bundle, $values['type'][0]['target_id']);
319     $this->assertEquals(1, $values['nid']);
320     $this->assertEquals('en', $values['langcode']);
321     $this->assertEquals(1, $values['status'][0]['value']);
322     $this->assertEquals('Apples', $values['title'][0]['value']);
323     $this->assertEquals(1, $values['default_langcode'][0]['value']);
324     $this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
325     $node_source->next();
326     $values = $node_source->current()->getSource();
327     $this->assertEquals($this->bundle, $values['type'][0]['target_id']);
328     $this->assertEquals(1, $values['nid']);
329     $this->assertEquals('fr', $values['langcode']);
330     $this->assertEquals(1, $values['status'][0]['value']);
331     $this->assertEquals('Pommes', $values['title'][0]['value']);
332     $this->assertEquals(0, $values['default_langcode'][0]['value']);
333     $this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
334   }
335
336   /**
337    * Tests media source plugin.
338    */
339   public function testMediaSource() {
340     $values = [
341       'id' => 'image',
342       'label' => 'Image',
343       'source' => 'test',
344       'new_revision' => FALSE,
345     ];
346     $media_type = $this->createMediaType('test', $values);
347     $media = Media::create([
348       'name' => 'Foo media',
349       'uid' => $this->user->id(),
350       'bundle' => $media_type->id(),
351     ]);
352     $media->save();
353
354     $configuration = [
355       'include_translations' => FALSE,
356       'bundle' => 'image',
357     ];
358     $migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:media'));
359     $media_source = $this->sourcePluginManager->createInstance('content_entity:media', $configuration, $migration);
360     $this->assertSame('media items', $media_source->__toString());
361     $this->assertEquals(1, $media_source->count());
362     $ids = $media_source->getIds();
363     $this->assertArrayHasKey('langcode', $ids);
364     $this->assertArrayHasKey('mid', $ids);
365     $fields = $media_source->fields();
366     $this->assertArrayHasKey('bundle', $fields);
367     $this->assertArrayHasKey('mid', $fields);
368     $this->assertArrayHasKey('name', $fields);
369     $this->assertArrayHasKey('status', $fields);
370     $media_source->rewind();
371     $values = $media_source->current()->getSource();
372     $this->assertEquals(1, $values['mid']);
373     $this->assertEquals('Foo media', $values['name'][0]['value']);
374     $this->assertNull($values['thumbnail'][0]['title']);
375     $this->assertEquals(1, $values['uid'][0]['target_id']);
376     $this->assertEquals('image', $values['bundle'][0]['target_id']);
377   }
378
379   /**
380    * Tests term source plugin.
381    */
382   public function testTermSource() {
383     $term2 = Term::create([
384       'vid' => $this->vocabulary,
385       'name' => 'Granny Smith',
386       'uid' => $this->user->id(),
387       'parent' => 1,
388     ]);
389     $term2->save();
390
391     $configuration = [
392       'include_translations' => FALSE,
393       'bundle' => $this->vocabulary,
394     ];
395     $migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:taxonomy_term'));
396     $term_source = $this->sourcePluginManager->createInstance('content_entity:taxonomy_term', $configuration, $migration);
397     $this->assertSame('taxonomy terms', $term_source->__toString());
398     $this->assertEquals(2, $term_source->count());
399     $ids = $term_source->getIds();
400     $this->assertArrayHasKey('langcode', $ids);
401     $this->assertArrayHasKey('tid', $ids);
402     $fields = $term_source->fields();
403     $this->assertArrayHasKey('vid', $fields);
404     $this->assertArrayHasKey('tid', $fields);
405     $this->assertArrayHasKey('name', $fields);
406     $term_source->rewind();
407     $values = $term_source->current()->getSource();
408     $this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']);
409     $this->assertEquals(1, $values['tid']);
410     // @TODO: Add test coverage for parent in
411     // https://www.drupal.org/project/drupal/issues/2940198
412     $this->assertEquals('Apples', $values['name'][0]['value']);
413     $term_source->next();
414     $values = $term_source->current()->getSource();
415     $this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']);
416     $this->assertEquals(2, $values['tid']);
417     // @TODO: Add test coverage for parent in
418     // https://www.drupal.org/project/drupal/issues/2940198
419     $this->assertEquals('Granny Smith', $values['name'][0]['value']);
420   }
421
422   /**
423    * Get a migration definition.
424    *
425    * @param string $plugin_id
426    *   The plugin id.
427    *
428    * @return array
429    *   The definition.
430    */
431   protected function migrationDefinition($plugin_id) {
432     return [
433       'source' => [
434         'plugin' => $plugin_id,
435       ],
436       'process' => [],
437       'destination' => [
438         'plugin' => 'null',
439       ],
440     ];
441   }
442
443 }