Chris@0: container->get('router.builder')->rebuild(); Chris@0: $this->installEntitySchema('entity_test_rev'); Chris@0: $this->createFieldWithStorage(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Test rendering fields with EntityDisplay build(). Chris@0: */ Chris@0: public function testEntityDisplayBuild() { Chris@0: $this->createFieldWithStorage('_2'); Chris@0: Chris@0: $entity_type = 'entity_test'; Chris@0: $entity_init = $this->container->get('entity_type.manager') Chris@0: ->getStorage($entity_type) Chris@0: ->create(); Chris@0: Chris@0: // Populate values to be displayed. Chris@0: $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality()); Chris@0: $entity_init->{$this->fieldTestData->field_name}->setValue($values); Chris@0: $values_2 = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality()); Chris@0: $entity_init->{$this->fieldTestData->field_name_2}->setValue($values_2); Chris@0: Chris@0: // Simple formatter, label displayed. Chris@0: $entity = clone($entity_init); Chris@0: $display = entity_get_display($entity_type, $entity->bundle(), 'full'); Chris@0: Chris@0: $formatter_setting = $this->randomMachineName(); Chris@0: $display_options = [ Chris@0: 'label' => 'above', Chris@0: 'type' => 'field_test_default', Chris@0: 'settings' => [ Chris@0: 'test_formatter_setting' => $formatter_setting, Chris@0: ], Chris@0: ]; Chris@0: $display->setComponent($this->fieldTestData->field_name, $display_options); Chris@0: Chris@0: $formatter_setting_2 = $this->randomMachineName(); Chris@0: $display_options_2 = [ Chris@0: 'label' => 'above', Chris@0: 'type' => 'field_test_default', Chris@0: 'settings' => [ Chris@0: 'test_formatter_setting' => $formatter_setting_2, Chris@0: ], Chris@0: ]; Chris@0: $display->setComponent($this->fieldTestData->field_name_2, $display_options_2); Chris@0: Chris@0: // View all fields. Chris@0: $content = $display->build($entity); Chris@0: $this->render($content); Chris@0: $this->assertRaw($this->fieldTestData->field->getLabel(), "First field's label is displayed."); Chris@0: foreach ($values as $delta => $value) { Chris@0: $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); Chris@0: } Chris@0: $this->assertRaw($this->fieldTestData->field_2->getLabel(), "Second field's label is displayed."); Chris@0: foreach ($values_2 as $delta => $value) { Chris@0: $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); Chris@0: } Chris@0: Chris@0: // Label hidden. Chris@0: $entity = clone($entity_init); Chris@0: $display_options['label'] = 'hidden'; Chris@0: $display->setComponent($this->fieldTestData->field_name, $display_options); Chris@0: $content = $display->build($entity); Chris@0: $this->render($content); Chris@0: $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden label: label is not displayed."); Chris@0: Chris@0: // Field hidden. Chris@0: $entity = clone($entity_init); Chris@0: $display->removeComponent($this->fieldTestData->field_name); Chris@0: $content = $display->build($entity); Chris@0: $this->render($content); Chris@0: $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden field: label is not displayed."); Chris@0: foreach ($values as $delta => $value) { Chris@0: $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed."); Chris@0: } Chris@0: Chris@0: // Multiple formatter. Chris@0: $entity = clone($entity_init); Chris@0: $formatter_setting = $this->randomMachineName(); Chris@0: $display->setComponent($this->fieldTestData->field_name, [ Chris@0: 'label' => 'above', Chris@0: 'type' => 'field_test_multiple', Chris@0: 'settings' => [ Chris@0: 'test_formatter_setting_multiple' => $formatter_setting, Chris@0: ], Chris@0: ]); Chris@0: $content = $display->build($entity); Chris@0: $this->render($content); Chris@0: $expected_output = $formatter_setting; Chris@0: foreach ($values as $delta => $value) { Chris@0: $expected_output .= "|$delta:{$value['value']}"; Chris@0: } Chris@0: $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied."); Chris@0: Chris@0: // Test a formatter that uses hook_field_formatter_prepare_view(). Chris@0: $entity = clone($entity_init); Chris@0: $formatter_setting = $this->randomMachineName(); Chris@0: $display->setComponent($this->fieldTestData->field_name, [ Chris@0: 'label' => 'above', Chris@0: 'type' => 'field_test_with_prepare_view', Chris@0: 'settings' => [ Chris@0: 'test_formatter_setting_additional' => $formatter_setting, Chris@0: ], Chris@0: ]); Chris@0: $content = $display->build($entity); Chris@0: $this->render($content); Chris@0: foreach ($values as $delta => $value) { Chris@0: $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1); Chris@0: $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied."); Chris@0: } Chris@0: Chris@0: // TODO: Chris@0: // - check display order with several fields Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests rendering fields with EntityDisplay::buildMultiple(). Chris@0: */ Chris@0: public function testEntityDisplayViewMultiple() { Chris@0: // Use a formatter that has a prepareView() step. Chris@0: $display = entity_get_display('entity_test', 'entity_test', 'full') Chris@0: ->setComponent($this->fieldTestData->field_name, [ Chris@0: 'type' => 'field_test_with_prepare_view', Chris@0: ]); Chris@0: Chris@0: // Create two entities. Chris@0: $entity1 = EntityTest::create(['id' => 1, 'type' => 'entity_test']); Chris@0: $entity1->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1)); Chris@0: $entity2 = EntityTest::create(['id' => 2, 'type' => 'entity_test']); Chris@0: $entity2->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1)); Chris@0: Chris@0: // Run buildMultiple(), and check that the entities come out as expected. Chris@0: $display->buildMultiple([$entity1, $entity2]); Chris@0: $item1 = $entity1->{$this->fieldTestData->field_name}[0]; Chris@0: $this->assertEqual($item1->additional_formatter_value, $item1->value + 1, 'Entity 1 ran through the prepareView() formatter method.'); Chris@0: $item2 = $entity2->{$this->fieldTestData->field_name}[0]; Chris@0: $this->assertEqual($item2->additional_formatter_value, $item2->value + 1, 'Entity 2 ran through the prepareView() formatter method.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Test entity cache. Chris@0: * Chris@0: * Complements unit test coverage in Chris@0: * \Drupal\Tests\Core\Entity\Sql\SqlContentEntityStorageTest. Chris@0: */ Chris@0: public function testEntityCache() { Chris@0: // Initialize random values and a test entity. Chris@0: $entity_init = EntityTest::create(['type' => $this->fieldTestData->field->getTargetBundle()]); Chris@0: $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality()); Chris@0: Chris@0: // Non-cacheable entity type. Chris@0: $entity_type = 'entity_test'; Chris@0: $cid = "values:$entity_type:" . $entity_init->id(); Chris@0: Chris@0: // Check that no initial cache entry is present. Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no initial cache entry'); Chris@0: Chris@0: // Save, and check that no cache entry is present. Chris@0: $entity = clone($entity_init); Chris@0: $entity->{$this->fieldTestData->field_name}->setValue($values); Chris@0: $entity = $this->entitySaveReload($entity); Chris@0: $cid = "values:$entity_type:" . $entity->id(); Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no cache entry on insert and load'); Chris@0: Chris@0: // Cacheable entity type. Chris@0: $entity_type = 'entity_test_rev'; Chris@0: $this->createFieldWithStorage('_2', $entity_type); Chris@0: Chris@0: $entity_init = $this->container->get('entity_type.manager') Chris@0: ->getStorage($entity_type) Chris@0: ->create([ Chris@0: 'type' => $entity_type, Chris@0: ]); Chris@0: Chris@0: // Check that no initial cache entry is present. Chris@0: $cid = "values:$entity_type:" . $entity->id(); Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no initial cache entry'); Chris@0: Chris@0: // Save, and check that no cache entry is present. Chris@0: $entity = clone($entity_init); Chris@0: $entity->{$this->fieldTestData->field_name_2} = $values; Chris@0: $entity->save(); Chris@0: $cid = "values:$entity_type:" . $entity->id(); Chris@0: Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on insert'); Chris@0: // Load, and check that a cache entry is present with the expected values. Chris@0: $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId()); Chris@0: $controller->resetCache(); Chris@0: $cached_entity = $controller->load($entity->id()); Chris@0: $cache = \Drupal::cache('entity')->get($cid); Chris@0: $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load'); Chris@0: Chris@0: // Update with different values, and check that the cache entry is wiped. Chris@0: $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality()); Chris@0: $entity->{$this->fieldTestData->field_name_2} = $values; Chris@0: $entity->save(); Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on update'); Chris@0: Chris@0: // Load, and check that a cache entry is present with the expected values. Chris@0: $controller->resetCache(); Chris@0: $cached_entity = $controller->load($entity->id()); Chris@0: $cache = \Drupal::cache('entity')->get($cid); Chris@0: $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load'); Chris@0: Chris@0: // Create a new revision, and check that the cache entry is wiped. Chris@0: $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality()); Chris@0: $entity->{$this->fieldTestData->field_name_2} = $values; Chris@0: $entity->setNewRevision(); Chris@0: $entity->save(); Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on new revision creation'); Chris@0: Chris@0: // Load, and check that a cache entry is present with the expected values. Chris@0: $controller->resetCache(); Chris@0: $cached_entity = $controller->load($entity->id()); Chris@0: $cache = \Drupal::cache('entity')->get($cid); Chris@0: $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load'); Chris@0: Chris@0: // Delete, and check that the cache entry is wiped. Chris@0: $entity->delete(); Chris@0: $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry after delete'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::buildForm(). Chris@0: * Chris@0: * This could be much more thorough, but it does verify that the correct Chris@0: * widgets show up. Chris@0: */ Chris@0: public function testEntityFormDisplayBuildForm() { Chris@0: $this->createFieldWithStorage('_2'); Chris@0: Chris@0: $entity_type = 'entity_test'; Chris@0: $entity = entity_create($entity_type, ['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]); Chris@0: Chris@0: // Test generating widgets for all fields. Chris@0: $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default'); Chris@0: $form = []; Chris@0: $form_state = new FormState(); Chris@0: $display->buildForm($entity, $form, $form_state); Chris@0: Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name]['widget']['#title'], $this->fieldTestData->field->getLabel(), "First field's form title is {$this->fieldTestData->field->getLabel()}"); Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}"); Chris@0: for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) { Chris@0: // field_test_widget uses 'textfield' Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name]['widget'][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield"); Chris@0: } Chris@0: for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) { Chris@0: // field_test_widget uses 'textfield' Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield"); Chris@0: } Chris@0: Chris@0: // Test generating widgets for all fields. Chris@0: $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default'); Chris@0: foreach ($display->getComponents() as $name => $options) { Chris@0: if ($name != $this->fieldTestData->field_name_2) { Chris@0: $display->removeComponent($name); Chris@0: } Chris@0: } Chris@0: $form = []; Chris@0: $form_state = new FormState(); Chris@0: $display->buildForm($entity, $form, $form_state); Chris@0: Chris@0: $this->assertFalse(isset($form[$this->fieldTestData->field_name]), 'The first field does not exist in the form'); Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}"); Chris@0: for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) { Chris@0: // field_test_widget uses 'textfield' Chris@0: $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield"); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::extractFormValues(). Chris@0: */ Chris@0: public function testEntityFormDisplayExtractFormValues() { Chris@0: $this->createFieldWithStorage('_2'); Chris@0: Chris@0: $entity_type = 'entity_test'; Chris@0: $entity_init = $this->container->get('entity_type.manager') Chris@0: ->getStorage($entity_type) Chris@0: ->create(['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]); Chris@0: Chris@0: // Build the form for all fields. Chris@0: $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default'); Chris@0: $form = []; Chris@0: $form_state = new FormState(); Chris@0: $display->buildForm($entity_init, $form, $form_state); Chris@0: Chris@0: // Simulate incoming values. Chris@0: // First field. Chris@0: $values = []; Chris@0: $weights = []; Chris@0: for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) { Chris@0: $values[$delta]['value'] = mt_rand(1, 127); Chris@0: // Assign random weight. Chris@0: do { Chris@0: $weight = mt_rand(0, $this->fieldTestData->field_storage->getCardinality()); Chris@0: } while (in_array($weight, $weights)); Chris@0: $weights[$delta] = $weight; Chris@0: $values[$delta]['_weight'] = $weight; Chris@0: } Chris@0: // Leave an empty value. 'field_test' fields are empty if empty(). Chris@0: $values[1]['value'] = 0; Chris@0: // Second field. Chris@0: $values_2 = []; Chris@0: $weights_2 = []; Chris@0: for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) { Chris@0: $values_2[$delta]['value'] = mt_rand(1, 127); Chris@0: // Assign random weight. Chris@0: do { Chris@0: $weight = mt_rand(0, $this->fieldTestData->field_storage_2->getCardinality()); Chris@0: } while (in_array($weight, $weights_2)); Chris@0: $weights_2[$delta] = $weight; Chris@0: $values_2[$delta]['_weight'] = $weight; Chris@0: } Chris@0: // Leave an empty value. 'field_test' fields are empty if empty(). Chris@0: $values_2[1]['value'] = 0; Chris@0: Chris@0: // Pretend the form has been built. Chris@0: $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type, 'default')); Chris@0: \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state); Chris@0: \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state); Chris@0: $form_state->setValue($this->fieldTestData->field_name, $values); Chris@0: $form_state->setValue($this->fieldTestData->field_name_2, $values_2); Chris@0: Chris@0: // Extract values for all fields. Chris@0: $entity = clone($entity_init); Chris@0: $display->extractFormValues($entity, $form, $form_state); Chris@0: Chris@0: asort($weights); Chris@0: asort($weights_2); Chris@0: $expected_values = []; Chris@0: $expected_values_2 = []; Chris@0: foreach ($weights as $key => $value) { Chris@0: if ($key != 1) { Chris@0: $expected_values[] = ['value' => $values[$key]['value']]; Chris@0: } Chris@0: } Chris@0: $this->assertIdentical($entity->{$this->fieldTestData->field_name}->getValue(), $expected_values, 'Submit filters empty values'); Chris@0: foreach ($weights_2 as $key => $value) { Chris@0: if ($key != 1) { Chris@0: $expected_values_2[] = ['value' => $values_2[$key]['value']]; Chris@0: } Chris@0: } Chris@0: $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values'); Chris@0: Chris@0: // Call EntityFormDisplayInterface::extractFormValues() for a single field (the second field). Chris@0: foreach ($display->getComponents() as $name => $options) { Chris@0: if ($name != $this->fieldTestData->field_name_2) { Chris@0: $display->removeComponent($name); Chris@0: } Chris@0: } Chris@0: $entity = clone($entity_init); Chris@0: $display->extractFormValues($entity, $form, $form_state); Chris@0: $expected_values_2 = []; Chris@0: foreach ($weights_2 as $key => $value) { Chris@0: if ($key != 1) { Chris@0: $expected_values_2[] = ['value' => $values_2[$key]['value']]; Chris@0: } Chris@0: } Chris@0: $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'The first field is empty in the entity object'); Chris@0: $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values'); Chris@0: } Chris@0: Chris@0: }