3 namespace Drupal\Tests\Core\Entity\Sql;
5 use Drupal\Core\Entity\Sql\DefaultTableMapping;
6 use Drupal\Core\Entity\Sql\SqlContentEntityStorageException;
7 use Drupal\Tests\UnitTestCase;
10 * @coversDefaultClass \Drupal\Core\Entity\Sql\DefaultTableMapping
13 class DefaultTableMappingTest extends UnitTestCase {
16 * The entity type definition.
18 * @var \Drupal\Core\Entity\ContentEntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
20 protected $entityType;
25 protected function setUp() {
28 $this->entityType = $this->getMock('\Drupal\Core\Entity\ContentEntityTypeInterface');
30 ->expects($this->any())
32 ->willReturn('entity_test');
36 * Tests DefaultTableMapping::getTableNames().
38 * @covers ::getTableNames
40 public function testGetTableNames() {
41 // The storage definitions are only used in getColumnNames() so we do not
42 // need to provide any here.
43 $table_mapping = new DefaultTableMapping($this->entityType, []);
44 $this->assertSame([], $table_mapping->getTableNames());
46 $table_mapping->setFieldNames('foo', []);
47 $this->assertSame(['foo'], $table_mapping->getTableNames());
49 $table_mapping->setFieldNames('bar', []);
50 $this->assertSame(['foo', 'bar'], $table_mapping->getTableNames());
52 $table_mapping->setExtraColumns('baz', []);
53 $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
55 // Test that table names are not duplicated.
56 $table_mapping->setExtraColumns('foo', []);
57 $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
61 * Tests DefaultTableMapping::getAllColumns().
63 * @covers ::__construct
64 * @covers ::getAllColumns
65 * @covers ::getFieldNames
66 * @covers ::getColumnNames
67 * @covers ::setFieldNames
68 * @covers ::getExtraColumns
69 * @covers ::setExtraColumns
71 public function testGetAllColumns() {
72 // Set up single-column and multi-column definitions.
73 $definitions['id'] = $this->setUpDefinition('id', ['value']);
74 $definitions['name'] = $this->setUpDefinition('name', ['value']);
75 $definitions['type'] = $this->setUpDefinition('type', ['value']);
76 $definitions['description'] = $this->setUpDefinition('description', ['value', 'format']);
77 $definitions['owner'] = $this->setUpDefinition('owner', [
82 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
84 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
86 // Test adding field columns.
87 $table_mapping->setFieldNames('test', ['id']);
89 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
91 $table_mapping->setFieldNames('test', ['id', 'name']);
92 $expected = ['id', 'name'];
93 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
95 $table_mapping->setFieldNames('test', ['id', 'name', 'type']);
96 $expected = ['id', 'name', 'type'];
97 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
99 $table_mapping->setFieldNames('test', [
109 'description__value',
110 'description__format',
112 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
114 $table_mapping->setFieldNames('test', [
125 'description__value',
126 'description__format',
128 'owner__target_revision_id',
130 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
132 // Test adding extra columns.
133 $table_mapping->setFieldNames('test', []);
134 $table_mapping->setExtraColumns('test', ['default_langcode']);
135 $expected = ['default_langcode'];
136 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
138 $table_mapping->setExtraColumns('test', [
142 $expected = ['default_langcode', 'default_revision'];
143 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
145 // Test adding both field and extra columns.
146 $table_mapping->setFieldNames('test', [
153 $table_mapping->setExtraColumns('test', [
161 'description__value',
162 'description__format',
164 'owner__target_revision_id',
168 $this->assertSame($expected, $table_mapping->getAllColumns('test'));
172 * Tests DefaultTableMapping::getFieldNames().
174 * @covers ::getFieldNames
175 * @covers ::setFieldNames
177 public function testGetFieldNames() {
178 // The storage definitions are only used in getColumnNames() so we do not
179 // need to provide any here.
180 $table_mapping = new DefaultTableMapping($this->entityType, []);
182 // Test that requesting the list of field names for a table for which no
183 // fields have been added does not fail.
184 $this->assertSame([], $table_mapping->getFieldNames('foo'));
186 $return = $table_mapping->setFieldNames('foo', ['id', 'name', 'type']);
187 $this->assertSame($table_mapping, $return);
188 $expected = ['id', 'name', 'type'];
189 $this->assertSame($expected, $table_mapping->getFieldNames('foo'));
190 $this->assertSame([], $table_mapping->getFieldNames('bar'));
192 $return = $table_mapping->setFieldNames('bar', ['description', 'owner']);
193 $this->assertSame($table_mapping, $return);
194 $expected = ['description', 'owner'];
195 $this->assertSame($expected, $table_mapping->getFieldNames('bar'));
196 // Test that the previously added field names are unaffected.
197 $expected = ['id', 'name', 'type'];
198 $this->assertSame($expected, $table_mapping->getFieldNames('foo'));
202 * Tests DefaultTableMapping::getColumnNames().
204 * @covers ::__construct
205 * @covers ::getColumnNames
207 public function testGetColumnNames() {
208 $definitions['test'] = $this->setUpDefinition('test', []);
209 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
211 $this->assertSame($expected, $table_mapping->getColumnNames('test'));
213 $definitions['test'] = $this->setUpDefinition('test', ['value']);
214 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
215 $expected = ['value' => 'test'];
216 $this->assertSame($expected, $table_mapping->getColumnNames('test'));
218 $definitions['test'] = $this->setUpDefinition('test', ['value', 'format']);
219 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
220 $expected = ['value' => 'test__value', 'format' => 'test__format'];
221 $this->assertSame($expected, $table_mapping->getColumnNames('test'));
223 $definitions['test'] = $this->setUpDefinition('test', ['value']);
224 // Set custom storage.
225 $definitions['test']->expects($this->any())
226 ->method('hasCustomStorage')
228 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
229 // Should return empty for column names.
230 $this->assertSame([], $table_mapping->getColumnNames('test'));
234 * Tests DefaultTableMapping::getExtraColumns().
236 * @covers ::getExtraColumns
237 * @covers ::setExtraColumns
239 public function testGetExtraColumns() {
240 // The storage definitions are only used in getColumnNames() so we do not
241 // need to provide any here.
242 $table_mapping = new DefaultTableMapping($this->entityType, []);
244 // Test that requesting the list of field names for a table for which no
245 // fields have been added does not fail.
246 $this->assertSame([], $table_mapping->getExtraColumns('foo'));
248 $return = $table_mapping->setExtraColumns('foo', ['id', 'name', 'type']);
249 $this->assertSame($table_mapping, $return);
250 $expected = ['id', 'name', 'type'];
251 $this->assertSame($expected, $table_mapping->getExtraColumns('foo'));
252 $this->assertSame([], $table_mapping->getExtraColumns('bar'));
254 $return = $table_mapping->setExtraColumns('bar', ['description', 'owner']);
255 $this->assertSame($table_mapping, $return);
256 $expected = ['description', 'owner'];
257 $this->assertSame($expected, $table_mapping->getExtraColumns('bar'));
258 // Test that the previously added field names are unaffected.
259 $expected = ['id', 'name', 'type'];
260 $this->assertSame($expected, $table_mapping->getExtraColumns('foo'));
264 * Tests DefaultTableMapping::getFieldColumnName() with valid parameters.
266 * @param bool $base_field
267 * Flag indicating whether the field should be treated as a base or bundle
269 * @param string[] $columns
270 * An array of available field column names.
271 * @param string $column
272 * The name of the column to be processed.
273 * @param string $expected
274 * The expected result.
276 * @covers ::getFieldColumnName
278 * @dataProvider providerTestGetFieldColumnName
280 public function testGetFieldColumnName($base_field, $columns, $column, $expected) {
281 $definitions['test'] = $this->setUpDefinition('test', $columns, $base_field);
282 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
283 $result = $table_mapping->getFieldColumnName($definitions['test'], $column);
284 $this->assertEquals($expected, $result);
288 * Tests DefaultTableMapping::getFieldColumnName() with invalid parameters.
290 * @param bool $base_field
291 * Flag indicating whether the field should be treated as a base or bundle
293 * @param string[] $columns
294 * An array of available field column names.
295 * @param string $column
296 * The name of the column to be processed.
298 * @covers ::getFieldColumnName
300 * @dataProvider providerTestGetFieldColumnName
302 public function testGetFieldColumnNameInvalid($base_field, $columns, $column) {
303 $definitions['test'] = $this->setUpDefinition('test', $columns, $base_field);
305 // Mark field storage definition as custom storage.
306 $definitions['test']->expects($this->any())
307 ->method('hasCustomStorage')
310 $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
311 $this->setExpectedException(SqlContentEntityStorageException::class, "Column information not available for the 'test' field.");
312 $table_mapping->getFieldColumnName($definitions['test'], $column);
316 * Provides test data for testGetFieldColumnName().
319 * An nested array where each inner array has the following values: test
320 * field name, base field status, list of field columns, name of the column
321 * to be retrieved, expected result, whether an exception is expected.
323 public function providerTestGetFieldColumnName() {
325 // Base field with single column.
326 $data[] = [TRUE, ['foo'], 'foo', 'test'];
328 // Base field with multiple columns.
329 $data[] = [TRUE, ['foo', 'bar'], 'foo', 'test__foo'];
330 $data[] = [TRUE, ['foo', 'bar'], 'bar', 'test__bar'];
331 // Bundle field with single column.
332 $data[] = [FALSE, ['foo'], 'foo', 'test_foo'];
333 // Bundle field with multiple columns.
334 $data[] = [FALSE, ['foo', 'bar'], 'foo', 'test_foo'];
335 $data[] = [FALSE, ['foo', 'bar'], 'bar', 'test_bar'];
336 // Bundle field with reserved column.
337 $data[] = [FALSE, ['foo', 'bar'], 'deleted', 'deleted'];
343 * Tests DefaultTableMapping::getFieldTableName().
345 * @param string[] $table_names
346 * An associative array of table names that should hold the field columns,
347 * where keys can be 'base', 'data' and 'revision'.
348 * @param string $expected
349 * The expected table name.
351 * @covers ::getFieldTableName
353 * @dataProvider providerTestGetFieldTableName
355 public function testGetFieldTableName($table_names, $expected) {
356 $field_name = 'test';
359 $definition = $this->setUpDefinition($field_name, $columns);
361 ->expects($this->any())
362 ->method('getColumns')
363 ->willReturn($columns);
365 $storage = $this->getMockBuilder('\Drupal\Core\Entity\Sql\SqlContentEntityStorage')
366 ->disableOriginalConstructor()
370 ->expects($this->any())
371 ->method('getBaseTable')
372 ->willReturn(isset($table_names['base']) ? $table_names['base'] : 'base_table');
375 ->expects($this->any())
376 ->method('getDataTable')
377 ->willReturn(isset($table_names['data']) ? $table_names['data'] : NULL);
380 ->expects($this->any())
381 ->method('getRevisionTable')
382 ->willReturn(isset($table_names['revision']) ? $table_names['revision'] : NULL);
384 $entity_manager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
386 ->expects($this->any())
387 ->method('getStorage')
388 ->willReturn($storage);
390 $container = $this->getMock('\Symfony\Component\DependencyInjection\ContainerInterface');
392 ->expects($this->any())
394 ->willReturn($entity_manager);
396 \Drupal::setContainer($container);
398 $table_mapping = new DefaultTableMapping($this->entityType, [$field_name => $definition]);
400 // Add the field to all the defined tables to ensure the correct one is
402 foreach ($table_names as $table_name) {
403 $table_mapping->setFieldNames($table_name, [$field_name]);
406 $this->assertEquals($expected, $table_mapping->getFieldTableName('test'));
410 * Provides test data for testGetFieldColumnName().
413 * A nested array where each inner array has the following values: a list of
414 * table names and the expected table name.
416 public function providerTestGetFieldTableName() {
419 $data[] = [['data' => 'data_table', 'base' => 'base_table', 'revision' => 'revision_table'], 'data_table'];
420 $data[] = [['data' => 'data_table', 'revision' => 'revision_table', 'base' => 'base_table'], 'data_table'];
421 $data[] = [['base' => 'base_table', 'data' => 'data_table', 'revision' => 'revision_table'], 'data_table'];
422 $data[] = [['base' => 'base_table', 'revision' => 'revision_table', 'data' => 'data_table'], 'data_table'];
423 $data[] = [['revision' => 'revision_table', 'data' => 'data_table', 'base' => 'base_table'], 'data_table'];
424 $data[] = [['revision' => 'revision_table', 'base' => 'base_table', 'data' => 'data_table'], 'data_table'];
426 $data[] = [['data' => 'data_table', 'revision' => 'revision_table'], 'data_table'];
427 $data[] = [['revision' => 'revision_table', 'data' => 'data_table'], 'data_table'];
429 $data[] = [['base' => 'base_table', 'revision' => 'revision_table'], 'base_table'];
430 $data[] = [['revision' => 'revision_table', 'base' => 'base_table'], 'base_table'];
432 $data[] = [['data' => 'data_table'], 'data_table'];
433 $data[] = [['base' => 'base_table'], 'base_table'];
434 $data[] = [['revision' => 'revision_table'], 'revision_table'];
440 * Tests DefaultTableMapping::getFieldTableName() with an invalid parameter.
442 * @covers ::getFieldTableName
444 public function testGetFieldTableNameInvalid() {
445 $table_mapping = new DefaultTableMapping($this->entityType, []);
446 $this->setExpectedException(SqlContentEntityStorageException::class, "Table information not available for the 'invalid_field_name' field.");
447 $table_mapping->getFieldTableName('invalid_field_name');
451 * Sets up a field storage definition for the test.
453 * @param string $name
455 * @param array $column_names
456 * An array of column names for the storage definition.
458 * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
460 protected function setUpDefinition($name, array $column_names, $base_field = TRUE) {
461 $definition = $this->getMock('Drupal\Tests\Core\Field\TestBaseFieldDefinitionInterface');
462 $definition->expects($this->any())
463 ->method('isBaseField')
464 ->willReturn($base_field);
465 $definition->expects($this->any())
467 ->will($this->returnValue($name));
468 $definition->expects($this->any())
469 ->method('getColumns')
470 ->will($this->returnValue(array_fill_keys($column_names, [])));