5 * Contains \Drupal\Tests\views\Unit\Plugin\field\FieldTest.
8 namespace Drupal\Tests\views\Unit\Plugin\field;
10 use Drupal\Core\Field\FieldStorageDefinitionInterface;
11 use Drupal\Tests\UnitTestCase;
12 use Drupal\Tests\views\Unit\Plugin\HandlerTestTrait;
13 use Drupal\views\Plugin\views\field\EntityField;
14 use Drupal\views\ResultRow;
15 use Symfony\Component\DependencyInjection\ContainerBuilder;
18 * @coversDefaultClass \Drupal\views\Plugin\views\field\EntityField
21 class FieldTest extends UnitTestCase {
28 * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
30 protected $entityManager;
33 * The mocked formatter plugin manager.
35 * @var \Drupal\Core\Field\FormatterPluginManager|\PHPUnit_Framework_MockObject_MockObject
37 protected $formatterPluginManager;
40 * The mocked language manager.
42 * @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
44 protected $languageManager;
47 * The mocked field type plugin manager.
49 * @var \Drupal\Core\Field\FieldTypePluginManagerInterface|\PHPUnit_Framework_MockObject_MockObject
51 protected $fieldTypePluginManager;
56 * @var \Drupal\Core\Render\RendererInterface|\PHPUnit_Framework_MockObject_MockObject
63 * @var \Drupal\Core\DependencyInjection\Container
70 protected function setUp() {
73 $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
74 $this->formatterPluginManager = $this->getMockBuilder('Drupal\Core\Field\FormatterPluginManager')
75 ->disableOriginalConstructor()
78 $this->fieldTypePluginManager = $this->getMock('Drupal\Core\Field\FieldTypePluginManagerInterface');
79 $this->fieldTypePluginManager->expects($this->any())
80 ->method('getDefaultStorageSettings')
82 $this->fieldTypePluginManager->expects($this->any())
83 ->method('getDefaultFieldSettings')
86 $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
87 $this->renderer = $this->getMock('Drupal\Core\Render\RendererInterface');
89 $this->setupExecutableAndView();
90 $this->setupViewsData();
91 $this->display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
92 ->disableOriginalConstructor()
95 $this->container = new ContainerBuilder();
96 $this->container->set('plugin.manager.field.field_type', $this->fieldTypePluginManager);
97 \Drupal::setContainer($this->container);
101 * @covers ::__construct
103 public function testConstruct() {
105 'entity_type' => 'test_entity',
106 // Just provide 'entity field' as definition. This is how EntityViewsData
108 'entity field' => 'title',
110 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
112 $this->assertEquals('title', $handler->definition['field_name']);
116 * @covers ::defineOptions
118 public function testDefineOptionsWithNoOptions() {
120 'entity_type' => 'test_entity',
121 'field_name' => 'title',
123 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
125 // Setup the entity manager to allow fetching the storage definitions.
126 $title_storage = $this->getBaseFieldStorage();
128 $this->entityManager->expects($this->atLeastOnce())
129 ->method('getFieldStorageDefinitions')
130 ->with('test_entity')
132 'title' => $title_storage,
136 $handler->init($this->executable, $this->display, $options);
138 $this->assertEquals('value', $handler->options['group_column']);
139 $this->assertEquals(0, $handler->options['delta_limit']);
143 * @covers ::defineOptions
145 public function testDefineOptionsWithDefaultFormatterOnFieldDefinition() {
147 'entity_type' => 'test_entity',
148 'field_name' => 'title',
149 'default_formatter' => 'test_example',
150 'default_formatter_settings' => ['link_to_entity' => TRUE],
152 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
154 // Setup the entity manager to allow fetching the storage definitions.
155 $title_storage = $this->getBaseFieldStorage();
157 $this->entityManager->expects($this->atLeastOnce())
158 ->method('getFieldStorageDefinitions')
159 ->with('test_entity')
161 'title' => $title_storage,
165 $handler->init($this->executable, $this->display, $options);
167 $this->assertEquals('test_example', $handler->options['type']);
171 * @covers ::defineOptions
173 public function testDefineOptionsWithDefaultFormatterOnFieldType() {
175 'entity_type' => 'test_entity',
176 'field_name' => 'title',
177 'default_formatter_settings' => ['link_to_entity' => TRUE],
179 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
181 // Setup the entity manager to allow fetching the storage definitions.
182 $title_storage = $this->getBaseFieldStorage();
184 $this->entityManager->expects($this->atLeastOnce())
185 ->method('getFieldStorageDefinitions')
186 ->with('test_entity')
188 'title' => $title_storage,
192 $handler->init($this->executable, $this->display, $options);
194 $this->assertEquals(['link_to_entity' => TRUE], $handler->options['settings']);
198 * @covers ::calculateDependencies
200 public function testCalculateDependenciesWithBaseField() {
202 'entity_type' => 'test_entity',
203 'field_name' => 'title',
205 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
207 $title_storage = $this->getBaseFieldStorage();
208 $this->entityManager->expects($this->atLeastOnce())
209 ->method('getFieldStorageDefinitions')
210 ->with('test_entity')
212 'title' => $title_storage,
215 $dependencies = $handler->calculateDependencies();
216 $this->assertEmpty($dependencies);
220 * @covers ::calculateDependencies
222 public function testCalculateDependenciesWithConfiguredField() {
224 'entity_type' => 'test_entity',
225 'field_name' => 'body',
227 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
229 $body_storage = $this->getConfigFieldStorage();
230 $this->entityManager->expects($this->atLeastOnce())
231 ->method('getFieldStorageDefinitions')
232 ->with('test_entity')
234 'body' => $body_storage,
237 $body_storage->expects($this->atLeastOnce())
238 ->method('getConfigDependencyName')
239 ->willReturn('field.field_storage_config.body');
241 $dependencies = $handler->calculateDependencies();
242 $this->assertEquals(['config' => ['field.field_storage_config.body']], $dependencies);
248 public function testAccess() {
250 'entity_type' => 'test_entity',
251 'field_name' => 'title',
253 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
254 $handler->view = $this->executable;
255 $handler->setViewsData($this->viewsData);
257 $this->view->expects($this->atLeastOnce())
260 ->willReturn('test_entity_table');
262 $this->viewsData->expects($this->atLeastOnce())
264 ->with('test_entity_table')
266 'table' => ['entity type' => 'test_entity'],
269 $access_control_handler = $this->getMock('Drupal\Core\Entity\EntityAccessControlHandlerInterface');
270 $this->entityManager->expects($this->atLeastOnce())
271 ->method('getAccessControlHandler')
272 ->with('test_entity')
273 ->willReturn($access_control_handler);
275 $title_storage = $this->getBaseFieldStorage();
276 $this->entityManager->expects($this->atLeastOnce())
277 ->method('getFieldStorageDefinitions')
278 ->with('test_entity')
280 'title' => $title_storage,
283 $account = $this->getMock('Drupal\Core\Session\AccountInterface');
285 $access_control_handler->expects($this->atLeastOnce())
286 ->method('fieldAccess')
287 ->with('view', $this->anything(), $account, NULL, $this->anything())
290 $this->assertTrue($handler->access($account));
294 * @dataProvider providerSortOrders
296 * @param string $order
299 public function testClickSortWithOutConfiguredColumn($order) {
301 'entity_type' => 'test_entity',
302 'field_name' => 'title',
304 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
305 $handler->view = $this->executable;
307 $this->entityManager->expects($this->never())
308 ->method('getFieldStorageDefinitions');
310 $handler->clickSort($order);
314 * @dataProvider providerSortOrders
316 * @param string $order
319 * @covers ::clickSort
321 public function testClickSortWithBaseField($order) {
323 'entity_type' => 'test_entity',
324 'field_name' => 'title',
326 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
327 $handler->view = $this->executable;
329 $field_storage = $this->getBaseFieldStorage();
330 $this->entityManager->expects($this->atLeastOnce())
331 ->method('getFieldStorageDefinitions')
332 ->with('test_entity')
334 'title' => $field_storage,
337 $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
339 ->expects($this->atLeastOnce())
340 ->method('getFieldColumnName')
341 ->with($field_storage, 'value')
342 ->willReturn('title');
343 $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
344 $entity_storage->expects($this->atLeastOnce())
345 ->method('getTableMapping')
346 ->willReturn($table_mapping);
347 $this->entityManager->expects($this->atLeastOnce())
348 ->method('getStorage')
349 ->with('test_entity')
350 ->willReturn($entity_storage);
352 // Setup a click sort configuration.
354 'click_sort_column' => 'value',
355 'table' => 'test_entity',
357 $handler->init($this->executable, $this->display, $options);
359 $handler->query = $this->getMockBuilder('Drupal\views\Plugin\views\query\Sql')
360 ->disableOriginalConstructor()
362 $handler->query->expects($this->atLeastOnce())
363 ->method('ensureTable')
364 ->with('test_entity', NULL)
365 ->willReturn('test_entity');
367 $handler->query->expects($this->atLeastOnce())
368 ->method('addOrderBy')
369 ->with(NULL, NULL, $order, 'test_entity.title', []);
370 $handler->clickSort($order);
374 * @dataProvider providerSortOrders
376 * @param string $order
379 * @covers ::clickSort
381 public function testClickSortWithConfiguredField($order) {
383 'entity_type' => 'test_entity',
384 'field_name' => 'body',
386 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
387 $handler->view = $this->executable;
389 $field_storage = $this->getConfigFieldStorage();
390 $this->entityManager->expects($this->atLeastOnce())
391 ->method('getFieldStorageDefinitions')
392 ->with('test_entity')
394 'body' => $field_storage,
397 $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
399 ->expects($this->atLeastOnce())
400 ->method('getFieldColumnName')
401 ->with($field_storage, 'value')
402 ->willReturn('body_value');
403 $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
404 $entity_storage->expects($this->atLeastOnce())
405 ->method('getTableMapping')
406 ->willReturn($table_mapping);
407 $this->entityManager->expects($this->atLeastOnce())
408 ->method('getStorage')
409 ->with('test_entity')
410 ->willReturn($entity_storage);
412 // Setup a click sort configuration.
414 'click_sort_column' => 'value',
415 'table' => 'test_entity__body',
417 $handler->init($this->executable, $this->display, $options);
419 $handler->query = $this->getMockBuilder('Drupal\views\Plugin\views\query\Sql')
420 ->disableOriginalConstructor()
422 $handler->query->expects($this->atLeastOnce())
423 ->method('ensureTable')
424 ->with('test_entity__body', NULL)
425 ->willReturn('test_entity__body_alias');
427 $handler->query->expects($this->atLeastOnce())
428 ->method('addOrderBy')
429 ->with(NULL, NULL, $order, 'test_entity__body_alias.body_value', []);
430 $handler->clickSort($order);
436 public function testQueryWithGroupByForBaseField() {
438 'entity_type' => 'test_entity',
439 'field_name' => 'title',
441 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
442 $handler->view = $this->executable;
443 $handler->view->field = [$handler];
445 $this->setupLanguageRenderer($handler, $definition);
447 $field_storage = $this->getBaseFieldStorage();
448 $this->entityManager->expects($this->any())
449 ->method('getFieldStorageDefinitions')
450 ->with('test_entity')
452 'title' => $field_storage,
455 $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
457 ->expects($this->any())
458 ->method('getFieldColumnName')
459 ->with($field_storage, 'value')
460 ->willReturn('title');
461 $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
462 $entity_storage->expects($this->any())
463 ->method('getTableMapping')
464 ->willReturn($table_mapping);
465 $this->entityManager->expects($this->any())
466 ->method('getStorage')
467 ->with('test_entity')
468 ->willReturn($entity_storage);
471 'group_column' => 'value',
472 'group_columns' => [],
473 'table' => 'test_entity_table',
475 $handler->init($this->executable, $this->display, $options);
477 $query = $this->getMockBuilder('Drupal\views\Plugin\views\query\Sql')
478 ->disableOriginalConstructor()
480 $query->expects($this->once())
481 ->method('ensureTable')
482 ->with('test_entity_table', NULL)
483 ->willReturn('test_entity_table');
484 // Ensure that we add the title field to the query, if we group by some
485 // other field in the view.
486 $query->expects($this->once())
488 ->with('test_entity_table', 'title');
490 $this->executable->query = $query;
492 $handler->query(TRUE);
498 public function testQueryWithGroupByForConfigField() {
500 'entity_type' => 'test_entity',
501 'field_name' => 'body',
503 $handler = new EntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
504 $handler->view = $this->executable;
505 $handler->view->field = [$handler];
507 $this->setupLanguageRenderer($handler, $definition);
509 $field_storage = $this->getConfigFieldStorage();
510 $this->entityManager->expects($this->any())
511 ->method('getFieldStorageDefinitions')
512 ->with('test_entity')
514 'body' => $field_storage,
517 $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
519 ->expects($this->any())
520 ->method('getFieldColumnName')
521 ->with($field_storage, 'value')
522 ->willReturn('body_value');
523 $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
524 $entity_storage->expects($this->any())
525 ->method('getTableMapping')
526 ->willReturn($table_mapping);
527 $this->entityManager->expects($this->any())
528 ->method('getStorage')
529 ->with('test_entity')
530 ->willReturn($entity_storage);
533 'group_column' => 'value',
534 'group_columns' => [],
535 'table' => 'test_entity__body',
537 $handler->init($this->executable, $this->display, $options);
539 $query = $this->getMockBuilder('Drupal\views\Plugin\views\query\Sql')
540 ->disableOriginalConstructor()
542 $query->expects($this->once())
543 ->method('ensureTable')
544 ->with('test_entity__body', NULL)
545 ->willReturn('test_entity__body');
546 // Ensure that we add the title field to the query, if we group by some
547 // other field in the view.
548 $query->expects($this->once())
550 ->with('test_entity__body', 'body_value');
552 $this->executable->query = $query;
554 $handler->query(TRUE);
558 * @covers ::prepareItemsByDelta
560 * @dataProvider providerTestPrepareItemsByDelta
562 public function testPrepareItemsByDelta(array $options, array $expected_values) {
564 'entity_type' => 'test_entity',
565 'field_name' => 'integer',
567 $handler = new FieldTestEntityField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
568 $handler->view = $this->executable;
569 $handler->view->field = [$handler];
571 $this->setupLanguageRenderer($handler, $definition);
573 $field_storage = $this->getConfigFieldStorage();
574 $field_storage->expects($this->any())
575 ->method('getCardinality')
576 ->willReturn(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
578 $this->entityManager->expects($this->any())
579 ->method('getFieldStorageDefinitions')
580 ->with('test_entity')
582 'integer' => $field_storage,
585 $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
587 ->expects($this->any())
588 ->method('getFieldColumnName')
589 ->with($field_storage, 'value')
590 ->willReturn('integer_value');
591 $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
592 $entity_storage->expects($this->any())
593 ->method('getTableMapping')
594 ->willReturn($table_mapping);
595 $this->entityManager->expects($this->any())
596 ->method('getStorage')
597 ->with('test_entity')
598 ->willReturn($entity_storage);
601 'group_column' => 'value',
602 'group_columns' => [],
603 'table' => 'test_entity__integer',
605 $handler->init($this->executable, $this->display, $options);
607 $this->executable->row_index = 0;
608 $this->executable->result = [0 => new ResultRow([])];
610 $items = [3, 1, 4, 1, 5, 9];
611 $this->assertEquals($expected_values, $handler->executePrepareItemsByDelta($items));
615 * Provides test data for testPrepareItemsByDelta().
617 public function providerTestPrepareItemsByDelta() {
620 // Let's display all values.
621 $data[] = [[], [3, 1, 4, 1, 5, 9]];
622 // Test just reversed deltas.
623 $data[] = [['delta_reversed' => TRUE], [9, 5, 1, 4, 1, 3]];
625 // Test combinations of delta limit, offset and first_last.
626 $data[] = [['group_rows' => TRUE, 'delta_limit' => 3], [3, 1, 4]];
627 $data[] = [['group_rows' => TRUE, 'delta_limit' => 3, 'delta_offset' => 2], [4, 1, 5]];
628 $data[] = [['group_rows' => TRUE, 'delta_reversed' => TRUE, 'delta_limit' => 3, 'delta_offset' => 2], [1, 4, 1]];
629 $data[] = [['group_rows' => TRUE, 'delta_first_last' => TRUE], [3, 9]];
630 $data[] = [['group_rows' => TRUE, 'delta_limit' => 1, 'delta_first_last' => TRUE], [3]];
631 $data[] = [['group_rows' => TRUE, 'delta_offset' => 1, 'delta_first_last' => TRUE], [1, 9]];
637 * Returns a mocked base field storage object.
639 * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
641 protected function getBaseFieldStorage() {
642 $title_storage = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
643 $title_storage->expects($this->any())
644 ->method('getColumns')
645 ->willReturn(['value' => ['type' => 'varchar']]);
646 $title_storage->expects($this->any())
647 ->method('getSettings')
649 $title_storage->expects($this->any())
650 ->method('getConstraints')
652 return $title_storage;
656 * Returns a mocked configurable field storage object.
658 * @return \Drupal\field\FieldStorageConfigInterface|\PHPUnit_Framework_MockObject_MockObject
660 protected function getConfigFieldStorage() {
661 $title_storage = $this->getMock('Drupal\field\FieldStorageConfigInterface');
662 $title_storage->expects($this->any())
663 ->method('getColumns')
664 ->willReturn(['value' => ['type' => 'varchar']]);
665 $title_storage->expects($this->any())
666 ->method('getSettings')
668 $title_storage->expects($this->any())
669 ->method('getConstraints')
671 return $title_storage;
675 * Provides sort orders for clickSort() test methods.
679 public function providerSortOrders() {
689 * Setup the mock data needed to make language renderers work.
691 * @param \Drupal\views\Plugin\views\field\EntityField $handler
694 * An array with entity type definition data.
696 protected function setupLanguageRenderer(EntityField $handler, $definition) {
697 $display_handler = $this->getMockBuilder('\Drupal\views\Plugin\views\display\DisplayPluginBase')
698 ->disableOriginalConstructor()
700 $display_handler->expects($this->any())
701 ->method('getOption')
702 ->with($this->equalTo('rendering_language'))
704 $handler->view->display_handler = $display_handler;
706 $data['table']['entity type'] = $definition['entity_type'];
707 $views_data = $this->getMockBuilder('\Drupal\views\ViewsData')
708 ->disableOriginalConstructor()
710 $views_data->expects($this->any())
713 $this->container->set('views.views_data', $views_data);
715 $entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
716 $entity_type->expects($this->any())
718 ->willReturn($definition['entity_type']);
720 $this->entityManager->expects($this->any())
721 ->method('getDefinition')
722 ->willReturn($entity_type);
727 class FieldTestEntityField extends EntityField {
729 public function executePrepareItemsByDelta(array $all_values) {
730 return $this->prepareItemsByDelta($all_values);