e9a306dd4cdc639a869f7e9ccd257409296b2453
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Entity / Sql / DefaultTableMappingTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Entity\Sql;
4
5 use Drupal\Core\Entity\Sql\DefaultTableMapping;
6 use Drupal\Core\Entity\Sql\SqlContentEntityStorageException;
7 use Drupal\Tests\UnitTestCase;
8
9 /**
10  * @coversDefaultClass \Drupal\Core\Entity\Sql\DefaultTableMapping
11  * @group Entity
12  */
13 class DefaultTableMappingTest extends UnitTestCase {
14
15   /**
16    * The entity type definition.
17    *
18    * @var \Drupal\Core\Entity\ContentEntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
19    */
20   protected $entityType;
21
22   /**
23    * {@inheritdoc}
24    */
25   protected function setUp() {
26     parent::setUp();
27
28     $this->entityType = $this->getMock('\Drupal\Core\Entity\ContentEntityTypeInterface');
29     $this->entityType
30       ->expects($this->any())
31       ->method('id')
32       ->willReturn('entity_test');
33   }
34
35   /**
36    * Tests DefaultTableMapping::getTableNames().
37    *
38    * @covers ::getTableNames
39    */
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());
45
46     $table_mapping->setFieldNames('foo', []);
47     $this->assertSame(['foo'], $table_mapping->getTableNames());
48
49     $table_mapping->setFieldNames('bar', []);
50     $this->assertSame(['foo', 'bar'], $table_mapping->getTableNames());
51
52     $table_mapping->setExtraColumns('baz', []);
53     $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
54
55     // Test that table names are not duplicated.
56     $table_mapping->setExtraColumns('foo', []);
57     $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
58   }
59
60   /**
61    * Tests DefaultTableMapping::getAllColumns().
62    *
63    * @covers ::__construct
64    * @covers ::getAllColumns
65    * @covers ::getFieldNames
66    * @covers ::getColumnNames
67    * @covers ::setFieldNames
68    * @covers ::getExtraColumns
69    * @covers ::setExtraColumns
70    */
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', [
78       'target_id',
79       'target_revision_id',
80     ]);
81
82     $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
83     $expected = [];
84     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
85
86     // Test adding field columns.
87     $table_mapping->setFieldNames('test', ['id']);
88     $expected = ['id'];
89     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
90
91     $table_mapping->setFieldNames('test', ['id', 'name']);
92     $expected = ['id', 'name'];
93     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
94
95     $table_mapping->setFieldNames('test', ['id', 'name', 'type']);
96     $expected = ['id', 'name', 'type'];
97     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
98
99     $table_mapping->setFieldNames('test', [
100       'id',
101       'name',
102       'type',
103       'description',
104     ]);
105     $expected = [
106       'id',
107       'name',
108       'type',
109       'description__value',
110       'description__format',
111     ];
112     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
113
114     $table_mapping->setFieldNames('test', [
115       'id',
116       'name',
117       'type',
118       'description',
119       'owner',
120     ]);
121     $expected = [
122       'id',
123       'name',
124       'type',
125       'description__value',
126       'description__format',
127       'owner__target_id',
128       'owner__target_revision_id',
129     ];
130     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
131
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'));
137
138     $table_mapping->setExtraColumns('test', [
139       'default_langcode',
140       'default_revision',
141     ]);
142     $expected = ['default_langcode', 'default_revision'];
143     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
144
145     // Test adding both field and extra columns.
146     $table_mapping->setFieldNames('test', [
147       'id',
148       'name',
149       'type',
150       'description',
151       'owner',
152     ]);
153     $table_mapping->setExtraColumns('test', [
154       'default_langcode',
155       'default_revision',
156     ]);
157     $expected = [
158       'id',
159       'name',
160       'type',
161       'description__value',
162       'description__format',
163       'owner__target_id',
164       'owner__target_revision_id',
165       'default_langcode',
166       'default_revision',
167     ];
168     $this->assertSame($expected, $table_mapping->getAllColumns('test'));
169   }
170
171   /**
172    * Tests DefaultTableMapping::getFieldNames().
173    *
174    * @covers ::getFieldNames
175    * @covers ::setFieldNames
176    */
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, []);
181
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'));
185
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'));
191
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'));
199   }
200
201   /**
202    * Tests DefaultTableMapping::getColumnNames().
203    *
204    * @covers ::__construct
205    * @covers ::getColumnNames
206    */
207   public function testGetColumnNames() {
208     $definitions['test'] = $this->setUpDefinition('test', []);
209     $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
210     $expected = [];
211     $this->assertSame($expected, $table_mapping->getColumnNames('test'));
212
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'));
217
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'));
222
223     $definitions['test'] = $this->setUpDefinition('test', ['value']);
224     // Set custom storage.
225     $definitions['test']->expects($this->any())
226       ->method('hasCustomStorage')
227       ->wilLReturn(TRUE);
228     $table_mapping = new DefaultTableMapping($this->entityType, $definitions);
229     // Should return empty for column names.
230     $this->assertSame([], $table_mapping->getColumnNames('test'));
231   }
232
233   /**
234    * Tests DefaultTableMapping::getExtraColumns().
235    *
236    * @covers ::getExtraColumns
237    * @covers ::setExtraColumns
238    */
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, []);
243
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'));
247
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'));
253
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'));
261   }
262
263   /**
264    * Tests DefaultTableMapping::getFieldColumnName() with valid parameters.
265    *
266    * @param bool $base_field
267    *   Flag indicating whether the field should be treated as a base or bundle
268    *   field.
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.
275    *
276    * @covers ::getFieldColumnName
277    *
278    * @dataProvider providerTestGetFieldColumnName
279    */
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);
285   }
286
287   /**
288    * Tests DefaultTableMapping::getFieldColumnName() with invalid parameters.
289    *
290    * @param bool $base_field
291    *   Flag indicating whether the field should be treated as a base or bundle
292    *   field.
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.
297    *
298    * @covers ::getFieldColumnName
299    *
300    * @dataProvider providerTestGetFieldColumnName
301    */
302   public function testGetFieldColumnNameInvalid($base_field, $columns, $column) {
303     $definitions['test'] = $this->setUpDefinition('test', $columns, $base_field);
304
305     // Mark field storage definition as custom storage.
306     $definitions['test']->expects($this->any())
307       ->method('hasCustomStorage')
308       ->willReturn(TRUE);
309
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);
313   }
314
315   /**
316    * Provides test data for testGetFieldColumnName().
317    *
318    * @return array[]
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.
322    */
323   public function providerTestGetFieldColumnName() {
324     $data = [];
325     // Base field with single column.
326     $data[] = [TRUE, ['foo'], 'foo', 'test'];
327
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'];
338
339     return $data;
340   }
341
342   /**
343    * Tests DefaultTableMapping::getFieldTableName().
344    *
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.
350    *
351    * @covers ::getFieldTableName
352    *
353    * @dataProvider providerTestGetFieldTableName
354    */
355   public function testGetFieldTableName($table_names, $expected) {
356     $field_name = 'test';
357     $columns = ['test'];
358
359     $definition = $this->setUpDefinition($field_name, $columns);
360     $definition
361       ->expects($this->any())
362       ->method('getColumns')
363       ->willReturn($columns);
364
365     $this->entityType
366       ->expects($this->any())
367       ->method('getBaseTable')
368       ->willReturn(isset($table_names['base']) ? $table_names['base'] : 'entity_test');
369
370     $this->entityType
371       ->expects($this->any())
372       ->method('getDataTable')
373       ->willReturn(isset($table_names['data']) ? $table_names['data'] : FALSE);
374
375     $this->entityType
376       ->expects($this->any())
377       ->method('getRevisionTable')
378       ->willReturn(isset($table_names['revision']) ? $table_names['revision'] : FALSE);
379
380     $this->entityType
381       ->expects($this->any())
382       ->method('isTranslatable')
383       ->willReturn(isset($table_names['data']));
384
385     $this->entityType
386       ->expects($this->any())
387       ->method('isRevisionable')
388       ->willReturn(isset($table_names['revision']));
389
390     $this->entityType
391       ->expects($this->any())
392       ->method('getRevisionMetadataKeys')
393       ->willReturn([]);
394
395     $table_mapping = new DefaultTableMapping($this->entityType, [$field_name => $definition]);
396
397     // Add the field to all the defined tables to ensure the correct one is
398     // picked.
399     foreach ($table_names as $table_name) {
400       $table_mapping->setFieldNames($table_name, [$field_name]);
401     }
402
403     $this->assertEquals($expected, $table_mapping->getFieldTableName('test'));
404   }
405
406   /**
407    * Provides test data for testGetFieldColumnName().
408    *
409    * @return array[]
410    *   A nested array where each inner array has the following values: a list of
411    *   table names and the expected table name.
412    */
413   public function providerTestGetFieldTableName() {
414     $data = [];
415
416     $data[] = [['data' => 'data_table', 'base' => 'base_table', 'revision' => 'revision_table'], 'data_table'];
417     $data[] = [['data' => 'data_table', 'revision' => 'revision_table', 'base' => 'base_table'], 'data_table'];
418     $data[] = [['base' => 'base_table', 'data' => 'data_table', 'revision' => 'revision_table'], 'data_table'];
419     $data[] = [['base' => 'base_table', 'revision' => 'revision_table', 'data' => 'data_table'], 'data_table'];
420     $data[] = [['revision' => 'revision_table', 'data' => 'data_table', 'base' => 'base_table'], 'data_table'];
421     $data[] = [['revision' => 'revision_table', 'base' => 'base_table', 'data' => 'data_table'], 'data_table'];
422
423     $data[] = [['data' => 'data_table', 'revision' => 'revision_table'], 'data_table'];
424     $data[] = [['revision' => 'revision_table', 'data' => 'data_table'], 'data_table'];
425
426     $data[] = [['base' => 'base_table', 'revision' => 'revision_table'], 'base_table'];
427     $data[] = [['revision' => 'revision_table', 'base' => 'base_table'], 'base_table'];
428
429     $data[] = [['data' => 'data_table'], 'data_table'];
430     $data[] = [['base' => 'base_table'], 'base_table'];
431     $data[] = [['revision' => 'revision_table'], 'revision_table'];
432
433     return $data;
434   }
435
436   /**
437    * Tests DefaultTableMapping::getFieldTableName() with an invalid parameter.
438    *
439    * @covers ::getFieldTableName
440    */
441   public function testGetFieldTableNameInvalid() {
442     $table_mapping = new DefaultTableMapping($this->entityType, []);
443     $this->setExpectedException(SqlContentEntityStorageException::class, "Table information not available for the 'invalid_field_name' field.");
444     $table_mapping->getFieldTableName('invalid_field_name');
445   }
446
447   /**
448    * Sets up a field storage definition for the test.
449    *
450    * @param string $name
451    *   The field name.
452    * @param array $column_names
453    *   An array of column names for the storage definition.
454    *
455    * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
456    */
457   protected function setUpDefinition($name, array $column_names, $base_field = TRUE) {
458     $definition = $this->getMock('Drupal\Tests\Core\Field\TestBaseFieldDefinitionInterface');
459     $definition->expects($this->any())
460       ->method('isBaseField')
461       ->willReturn($base_field);
462     $definition->expects($this->any())
463       ->method('getName')
464       ->will($this->returnValue($name));
465     $definition->expects($this->any())
466       ->method('getColumns')
467       ->will($this->returnValue(array_fill_keys($column_names, [])));
468     return $definition;
469   }
470
471 }