DedupeEntityTest.php 7.46 KB
Newer Older
1 2
<?php

3
namespace Drupal\Tests\migrate\Unit\process;
4

5 6
use Drupal\Core\Entity\EntityStorageInterface;
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 17 18 19 20 21
 */
class DedupeEntityTest extends MigrateProcessTestCase {

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

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

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

42 43 44
  /**
   * {@inheritdoc}
   */
45
  protected function setUp() {
46 47 48
    $this->entityQuery = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryInterface')
      ->disableOriginalConstructor()
      ->getMock();
49 50 51 52 53 54 55 56 57 58
    $this->entityTypeManager = $this->getMock(EntityTypeManagerInterface::class);

    $storage = $this->getMock(EntityStorageInterface::class);
    $storage->expects($this->any())
      ->method('getQuery')
      ->willReturn($this->entityQuery);
    $this->entityTypeManager->expects($this->any())
      ->method('getStorage')
      ->with('test_entity_type')
      ->willReturn($storage);
59 60 61 62
    parent::setUp();
  }

  /**
63 64 65
   * Tests entity based deduplication based on providerTestDedupe() values.
   *
   * @dataProvider providerTestDedupe
66
   */
67
  public function testDedupe($count, $postfix = '', $start = NULL, $length = NULL) {
68
    $configuration = [
69 70
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
71
    ];
72 73 74
    if ($postfix) {
      $configuration['postfix'] = $postfix;
    }
75 76
    $configuration['start'] = isset($start) ? $start : NULL;
    $configuration['length'] = isset($length) ? $length : NULL;
77
    $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
78
    $this->entityQueryExpects($count);
79
    $value = $this->randomMachineName(32);
80 81 82 83 84 85 86 87 88 89
    $actual = $plugin->transform($value, $this->migrateExecutable, $this->row, 'testproperty');
    $expected = Unicode::substr($value, $start, $length);
    $expected .= $count ? $postfix . $count : '';
    $this->assertSame($expected, $actual);
  }

  /**
   * Tests that invalid start position throws an exception.
   */
  public function testDedupeEntityInvalidStart() {
90
    $configuration = [
91 92 93
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'start' => 'foobar',
94 95
    ];
    $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
96 97 98 99 100 101 102 103
    $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.');
    $plugin->transform('test_start', $this->migrateExecutable, $this->row, 'testproperty');
  }

  /**
   * Tests that invalid length option throws an exception.
   */
  public function testDedupeEntityInvalidLength() {
104
    $configuration = [
105 106 107
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'length' => 'foobar',
108 109
    ];
    $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
110 111
    $this->setExpectedException('Drupal\migrate\MigrateException', 'The character length configuration key should be an integer. Omit this key to capture the entire string.');
    $plugin->transform('test_length', $this->migrateExecutable, $this->row, 'testproperty');
112 113 114
  }

  /**
115
   * Data provider for testDedupe().
116
   */
117
  public function providerTestDedupe() {
118
    return [
119
      // Tests no duplication.
120
      [0],
121
      // Tests no duplication and start position.
122
      [0, NULL, 10],
123
      // Tests no duplication, start position, and length.
124
      [0, NULL, 5, 10],
125
      // Tests no duplication and length.
126
      [0, NULL, NULL, 10],
127
      // Tests duplication.
128
      [3],
129
      // Tests duplication and start position.
130
      [3, NULL, 10],
131
      // Tests duplication, start position, and length.
132
      [3, NULL, 5, 10],
133
      // Tests duplication and length.
134
      [3, NULL, NULL, 10],
135
      // Tests no duplication and postfix.
136
      [0, '_'],
137
      // Tests no duplication, postfix, and start position.
138
      [0, '_', 5],
139
      // Tests no duplication, postfix, start position, and length.
140
      [0, '_', 5, 10],
141
      // Tests no duplication, postfix, and length.
142
      [0, '_', NULL, 10],
143
      // Tests duplication and postfix.
144
      [2, '_'],
145
      // Tests duplication, postfix, and start position.
146
      [2, '_', 5],
147
      // Tests duplication, postfix, start position, and length.
148
      [2, '_', 5, 10],
149
      // Tests duplication, postfix, and length.
150 151
      [2, '_', NULL, 10],
    ];
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  }

  /**
   * Helper function to add expectations to the mock entity query object.
   *
   * @param int $count
   *   The number of deduplications 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')
      ->will($this->returnCallback(function () use (&$count) { return $count--;}));
  }
171

172 173 174 175
  /**
   * Test deduplicating only migrated entities.
   */
  public function testDedupeMigrated() {
176
    $configuration = [
177 178 179
      'entity_type' => 'test_entity_type',
      'field' => 'test_field',
      'migrated' => TRUE,
180 181
    ];
    $plugin = new DedupeEntity($configuration, 'dedupe_entity', [], $this->getMigration(), $this->entityTypeManager);
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

    // Setup the entityQuery used in DedupeEntity::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([]);
      $query->execute()->willReturn($id === 'test_vocab1' ? [] : [$id]);
      $map[] = ['test_field', $id, NULL, NULL, $query->reveal()];
    }
    $this->entityQuery
      ->method('condition')
      ->will($this->returnValueMap($map));

    // Entity 'forums' is pre-existing, entity 'test_vocab' was migrated.
    $this->idMap
      ->method('lookupSourceID')
      ->will($this->returnValueMap([
        [['test_field' => 'forums'], FALSE],
        [['test_field' => 'test_vocab'], ['source_id' => 42]],
      ]));

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

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

215
}