Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / migrate / tests / src / Unit / process / DedupeEntityTest.php
1 <?php
2
3 namespace Drupal\Tests\migrate\Unit\process;
4
5 use Drupal\Core\Entity\EntityStorageInterface;
6 use Drupal\Core\Entity\EntityTypeManagerInterface;
7 use Drupal\Core\Entity\Query\QueryInterface;
8 use Drupal\migrate\Plugin\migrate\process\DedupeEntity;
9 use Drupal\Component\Utility\Unicode;
10
11 /**
12  * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\DedupeEntity
13  * @group migrate
14  * @group legacy
15  */
16 class DedupeEntityTest extends MigrateProcessTestCase {
17
18   /**
19    * The mock entity query.
20    *
21    * @var \Drupal\Core\Entity\Query\QueryInterface|\Drupal\Core\Entity\Query\QueryFactory
22    */
23   protected $entityQuery;
24
25   /**
26    * The mocked entity type manager.
27    *
28    * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $entityTypeManager;
31
32   /**
33    * The migration configuration, initialized to set the ID to test.
34    *
35    * @var array
36    */
37   protected $migrationConfiguration = [
38     'id' => 'test',
39   ];
40
41   /**
42    * {@inheritdoc}
43    */
44   protected function setUp() {
45     $this->entityQuery = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryInterface')
46       ->disableOriginalConstructor()
47       ->getMock();
48     $this->entityTypeManager = $this->getMock(EntityTypeManagerInterface::class);
49
50     $storage = $this->getMock(EntityStorageInterface::class);
51     $storage->expects($this->any())
52       ->method('getQuery')
53       ->willReturn($this->entityQuery);
54     $this->entityTypeManager->expects($this->any())
55       ->method('getStorage')
56       ->with('test_entity_type')
57       ->willReturn($storage);
58     parent::setUp();
59   }
60
61   /**
62    * Tests entity based deduplication based on providerTestDedupe() values.
63    *
64    * @dataProvider providerTestDedupe
65    */
66   public function testDedupe($count, $postfix = '', $start = NULL, $length = NULL) {
67     $configuration = [
68       'entity_type' => 'test_entity_type',
69       'field' => 'test_field',
70     ];
71     if ($postfix) {
72       $configuration['postfix'] = $postfix;
73     }
74     $configuration['start'] = isset($start) ? $start : NULL;
75     $configuration['length'] = isset($length) ? $length : NULL;
76     $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
77     $this->entityQueryExpects($count);
78     $value = $this->randomMachineName(32);
79     $actual = $plugin->transform($value, $this->migrateExecutable, $this->row, 'testproperty');
80     $expected = Unicode::substr($value, $start, $length);
81     $expected .= $count ? $postfix . $count : '';
82     $this->assertSame($expected, $actual);
83   }
84
85   /**
86    * Tests that invalid start position throws an exception.
87    */
88   public function testDedupeEntityInvalidStart() {
89     $configuration = [
90       'entity_type' => 'test_entity_type',
91       'field' => 'test_field',
92       'start' => 'foobar',
93     ];
94     $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
95     $this->setExpectedException('Drupal\migrate\MigrateException', 'The start position configuration key should be an integer. Omit this key to capture from the beginning of the string.');
96     $plugin->transform('test_start', $this->migrateExecutable, $this->row, 'testproperty');
97   }
98
99   /**
100    * Tests that invalid length option throws an exception.
101    */
102   public function testDedupeEntityInvalidLength() {
103     $configuration = [
104       'entity_type' => 'test_entity_type',
105       'field' => 'test_field',
106       'length' => 'foobar',
107     ];
108     $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
109     $this->setExpectedException('Drupal\migrate\MigrateException', 'The character length configuration key should be an integer. Omit this key to capture the entire string.');
110     $plugin->transform('test_length', $this->migrateExecutable, $this->row, 'testproperty');
111   }
112
113   /**
114    * Data provider for testDedupe().
115    */
116   public function providerTestDedupe() {
117     return [
118       // Tests no duplication.
119       [0],
120       // Tests no duplication and start position.
121       [0, NULL, 10],
122       // Tests no duplication, start position, and length.
123       [0, NULL, 5, 10],
124       // Tests no duplication and length.
125       [0, NULL, NULL, 10],
126       // Tests duplication.
127       [3],
128       // Tests duplication and start position.
129       [3, NULL, 10],
130       // Tests duplication, start position, and length.
131       [3, NULL, 5, 10],
132       // Tests duplication and length.
133       [3, NULL, NULL, 10],
134       // Tests no duplication and postfix.
135       [0, '_'],
136       // Tests no duplication, postfix, and start position.
137       [0, '_', 5],
138       // Tests no duplication, postfix, start position, and length.
139       [0, '_', 5, 10],
140       // Tests no duplication, postfix, and length.
141       [0, '_', NULL, 10],
142       // Tests duplication and postfix.
143       [2, '_'],
144       // Tests duplication, postfix, and start position.
145       [2, '_', 5],
146       // Tests duplication, postfix, start position, and length.
147       [2, '_', 5, 10],
148       // Tests duplication, postfix, and length.
149       [2, '_', NULL, 10],
150     ];
151   }
152
153   /**
154    * Helper function to add expectations to the mock entity query object.
155    *
156    * @param int $count
157    *   The number of deduplications to be set up.
158    */
159   protected function entityQueryExpects($count) {
160     $this->entityQuery->expects($this->exactly($count + 1))
161       ->method('condition')
162       ->will($this->returnValue($this->entityQuery));
163     $this->entityQuery->expects($this->exactly($count + 1))
164       ->method('count')
165       ->will($this->returnValue($this->entityQuery));
166     $this->entityQuery->expects($this->exactly($count + 1))
167       ->method('execute')
168       ->will($this->returnCallback(function () use (&$count) {
169         return $count--;
170       }));
171   }
172
173   /**
174    * Test deduplicating only migrated entities.
175    */
176   public function testDedupeMigrated() {
177     $configuration = [
178       'entity_type' => 'test_entity_type',
179       'field' => 'test_field',
180       'migrated' => TRUE,
181     ];
182     $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
183
184     // Setup the entityQuery used in DedupeEntity::exists. The map, $map, is
185     // an array consisting of the four input parameters to the query condition
186     // method and then the query to return. Both 'forum' and
187     // 'test_vocab' are existing entities. There is no 'test_vocab1'.
188     $map = [];
189     foreach (['forums', 'test_vocab', 'test_vocab1'] as $id) {
190       $query = $this->prophesize(QueryInterface::class);
191       $query->willBeConstructedWith([]);
192       $query->execute()->willReturn($id === 'test_vocab1' ? [] : [$id]);
193       $map[] = ['test_field', $id, NULL, NULL, $query->reveal()];
194     }
195     $this->entityQuery
196       ->method('condition')
197       ->will($this->returnValueMap($map));
198
199     // Entity 'forums' is pre-existing, entity 'test_vocab' was migrated.
200     $this->idMap
201       ->method('lookupSourceID')
202       ->will($this->returnValueMap([
203         [['test_field' => 'forums'], FALSE],
204         [['test_field' => 'test_vocab'], ['source_id' => 42]],
205       ]));
206
207     // Existing entity 'forums' was not migrated, it should not be deduplicated.
208     $actual = $plugin->transform('forums', $this->migrateExecutable, $this->row, 'testproperty');
209     $this->assertEquals('forums', $actual, 'Pre-existing name is re-used');
210
211     // Entity 'test_vocab' was migrated, should be deduplicated.
212     $actual = $plugin->transform('test_vocab', $this->migrateExecutable, $this->row, 'testproperty');
213     $this->assertEquals('test_vocab1', $actual, 'Migrated name is deduplicated');
214   }
215
216 }