More updates to stop using dev or alpha or beta versions.
[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     $storage = $this->getMockBuilder('\Drupal\Core\Entity\Sql\SqlContentEntityStorage')
366       ->disableOriginalConstructor()
367       ->getMock();
368
369     $storage
370       ->expects($this->any())
371       ->method('getBaseTable')
372       ->willReturn(isset($table_names['base']) ? $table_names['base'] : 'base_table');
373
374     $storage
375       ->expects($this->any())
376       ->method('getDataTable')
377       ->willReturn(isset($table_names['data']) ? $table_names['data'] : NULL);
378
379     $storage
380       ->expects($this->any())
381       ->method('getRevisionTable')
382       ->willReturn(isset($table_names['revision']) ? $table_names['revision'] : NULL);
383
384     $entity_manager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
385     $entity_manager
386       ->expects($this->any())
387       ->method('getStorage')
388       ->willReturn($storage);
389
390     $container = $this->getMock('\Symfony\Component\DependencyInjection\ContainerInterface');
391     $container
392       ->expects($this->any())
393       ->method('get')
394       ->willReturn($entity_manager);
395
396     \Drupal::setContainer($container);
397
398     $table_mapping = new DefaultTableMapping($this->entityType, [$field_name => $definition]);
399
400     // Add the field to all the defined tables to ensure the correct one is
401     // picked.
402     foreach ($table_names as $table_name) {
403       $table_mapping->setFieldNames($table_name, [$field_name]);
404     }
405
406     $this->assertEquals($expected, $table_mapping->getFieldTableName('test'));
407   }
408
409   /**
410    * Provides test data for testGetFieldColumnName().
411    *
412    * @return array[]
413    *   A nested array where each inner array has the following values: a list of
414    *   table names and the expected table name.
415    */
416   public function providerTestGetFieldTableName() {
417     $data = [];
418
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'];
425
426     $data[] = [['data' => 'data_table', 'revision' => 'revision_table'], 'data_table'];
427     $data[] = [['revision' => 'revision_table', 'data' => 'data_table'], 'data_table'];
428
429     $data[] = [['base' => 'base_table', 'revision' => 'revision_table'], 'base_table'];
430     $data[] = [['revision' => 'revision_table', 'base' => 'base_table'], 'base_table'];
431
432     $data[] = [['data' => 'data_table'], 'data_table'];
433     $data[] = [['base' => 'base_table'], 'base_table'];
434     $data[] = [['revision' => 'revision_table'], 'revision_table'];
435
436     return $data;
437   }
438
439   /**
440    * Tests DefaultTableMapping::getFieldTableName() with an invalid parameter.
441    *
442    * @covers ::getFieldTableName
443    */
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');
448   }
449
450   /**
451    * Sets up a field storage definition for the test.
452    *
453    * @param string $name
454    *   The field name.
455    * @param array $column_names
456    *   An array of column names for the storage definition.
457    *
458    * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
459    */
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())
466       ->method('getName')
467       ->will($this->returnValue($name));
468     $definition->expects($this->any())
469       ->method('getColumns')
470       ->will($this->returnValue(array_fill_keys($column_names, [])));
471     return $definition;
472   }
473
474 }