MakeUniqueEntityFieldTest.php 7.68 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

namespace Drupal\Tests\migrate\Unit\process;

use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\migrate\Plugin\migrate\process\MakeUniqueEntityField;

/**
 * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\MakeUniqueEntityField
 * @group migrate
 */
class MakeUniqueEntityFieldTest extends MigrateProcessTestCase {

  /**
   * The mock entity query.
   *
19
   * @var \Drupal\Core\Entity\Query\QueryInterface
20
21
22
23
24
25
   */
  protected $entityQuery;

  /**
   * The mocked entity type manager.
   *
26
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
   */
  protected $entityTypeManager;

  /**
   * The migration configuration, initialized to set the ID to test.
   *
   * @var array
   */
  protected $migrationConfiguration = [
    'id' => 'test',
  ];

  /**
   * {@inheritdoc}
   */
42
  protected function setUp(): void {
43
44
45
    $this->entityQuery = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryInterface')
      ->disableOriginalConstructor()
      ->getMock();
46
47
48
    $this->entityQuery->expects($this->any())
      ->method('accessCheck')
      ->will($this->returnSelf());
49
    $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
50

51
    $storage = $this->createMock(EntityStorageInterface::class);
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    $storage->expects($this->any())
      ->method('getQuery')
      ->willReturn($this->entityQuery);
    $this->entityTypeManager->expects($this->any())
      ->method('getStorage')
      ->with('test_entity_type')
      ->willReturn($storage);
    parent::setUp();
  }

  /**
   * Tests making an entity field value unique.
   *
   * @dataProvider providerTestMakeUniqueEntityField
   */
  public function testMakeUniqueEntityField($count, $postfix = '', $start = NULL, $length = NULL) {
    $configuration = [
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
    ];
    if ($postfix) {
      $configuration['postfix'] = $postfix;
    }
75
76
    $configuration['start'] = $start;
    $configuration['length'] = $length;
77
78
79
80
    $plugin = new MakeUniqueEntityField($configuration, 'make_unique', [], $this->getMigration(), $this->entityTypeManager);
    $this->entityQueryExpects($count);
    $value = $this->randomMachineName(32);
    $actual = $plugin->transform($value, $this->migrateExecutable, $this->row, 'testproperty');
81
    $expected = mb_substr($value, $start ?? 0, $length);
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    $expected .= $count ? $postfix . $count : '';
    $this->assertSame($expected, $actual);
  }

  /**
   * Tests that invalid start position throws an exception.
   */
  public function testMakeUniqueEntityFieldEntityInvalidStart() {
    $configuration = [
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'start' => 'foobar',
    ];
    $plugin = new MakeUniqueEntityField($configuration, 'make_unique', [], $this->getMigration(), $this->entityTypeManager);
96
97
    $this->expectException('Drupal\migrate\MigrateException');
    $this->expectExceptionMessage('The start position configuration key should be an integer. Omit this key to capture from the beginning of the string.');
98
99
100
101
102
103
104
105
106
107
108
109
110
    $plugin->transform('test_start', $this->migrateExecutable, $this->row, 'testproperty');
  }

  /**
   * Tests that invalid length option throws an exception.
   */
  public function testMakeUniqueEntityFieldEntityInvalidLength() {
    $configuration = [
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'length' => 'foobar',
    ];
    $plugin = new MakeUniqueEntityField($configuration, 'make_unique', [], $this->getMigration(), $this->entityTypeManager);
111
112
    $this->expectException('Drupal\migrate\MigrateException');
    $this->expectExceptionMessage('The character length configuration key should be an integer. Omit this key to capture the entire string.');
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    $plugin->transform('test_length', $this->migrateExecutable, $this->row, 'testproperty');
  }

  /**
   * Data provider for testMakeUniqueEntityField().
   */
  public function providerTestMakeUniqueEntityField() {
    return [
      // Tests no duplication.
      [0],
      // Tests no duplication and start position.
      [0, NULL, 10],
      // Tests no duplication, start position, and length.
      [0, NULL, 5, 10],
      // Tests no duplication and length.
      [0, NULL, NULL, 10],
      // Tests duplication.
      [3],
      // Tests duplication and start position.
      [3, NULL, 10],
      // Tests duplication, start position, and length.
      [3, NULL, 5, 10],
      // Tests duplication and length.
      [3, NULL, NULL, 10],
      // Tests no duplication and postfix.
      [0, '_'],
      // Tests no duplication, postfix, and start position.
      [0, '_', 5],
      // Tests no duplication, postfix, start position, and length.
      [0, '_', 5, 10],
      // Tests no duplication, postfix, and length.
      [0, '_', NULL, 10],
      // Tests duplication and postfix.
      [2, '_'],
      // Tests duplication, postfix, and start position.
      [2, '_', 5],
      // Tests duplication, postfix, start position, and length.
      [2, '_', 5, 10],
      // Tests duplication, postfix, and length.
      [2, '_', NULL, 10],
    ];
  }

  /**
   * Helper function to add expectations to the mock entity query object.
   *
   * @param int $count
   *   The number of unique values to be set up.
   */
  protected function entityQueryExpects($count) {
    $this->entityQuery->expects($this->exactly($count + 1))
      ->method('condition')
      ->will($this->returnValue($this->entityQuery));
    $this->entityQuery->expects($this->exactly($count + 1))
      ->method('count')
      ->will($this->returnValue($this->entityQuery));
    $this->entityQuery->expects($this->exactly($count + 1))
      ->method('execute')
171
      ->willReturnCallback(function () use (&$count) {
172
        return $count--;
173
      });
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  }

  /**
   * Tests making an entity field value unique only for migrated entities.
   */
  public function testMakeUniqueEntityFieldMigrated() {
    $configuration = [
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'migrated' => TRUE,
    ];
    $plugin = new MakeUniqueEntityField($configuration, 'make_unique', [], $this->getMigration(), $this->entityTypeManager);

    // Setup the entityQuery used in MakeUniqueEntityFieldEntity::exists. The
    // map, $map, is an array consisting of the four input parameters to the
    // query condition method and then the query to return. Both 'forum' and
    // 'test_vocab' are existing entities. There is no 'test_vocab1'.
    $map = [];
    foreach (['forums', 'test_vocab', 'test_vocab1'] as $id) {
      $query = $this->prophesize(QueryInterface::class);
      $query->willBeConstructedWith([]);
195
      $query->accessCheck()->willReturn($query);
196
197
198
199
200
      $query->execute()->willReturn($id === 'test_vocab1' ? [] : [$id]);
      $map[] = ['test_field', $id, NULL, NULL, $query->reveal()];
    }
    $this->entityQuery
      ->method('condition')
201
      ->willReturnMap($map);
202
203
204

    // Entity 'forums' is pre-existing, entity 'test_vocab' was migrated.
    $this->idMap
205
      ->method('lookupSourceId')
206
      ->willReturnMap([
207
208
        [['test_field' => 'forums'], FALSE],
        [['test_field' => 'test_vocab'], ['source_id' => 42]],
209
      ]);
210
211
212
213
214
215
216
217
218
219
220

    // Existing entity 'forums' was not migrated, value should not be unique.
    $actual = $plugin->transform('forums', $this->migrateExecutable, $this->row, 'testproperty');
    $this->assertEquals('forums', $actual, 'Pre-existing name is re-used');

    // Entity 'test_vocab' was migrated, value should be unique.
    $actual = $plugin->transform('test_vocab', $this->migrateExecutable, $this->row, 'testproperty');
    $this->assertEquals('test_vocab1', $actual, 'Migrated name is deduplicated');
  }

}