installEntitySchema('entity_test_rev'); } /** * Check field values insert, update and load. * * Works independently of the underlying field storage backend. Inserts or * updates random field data and then loads and verifies the data. */ public function testFieldAttachSaveLoad() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); $cardinality = $this->fieldTestData->field_storage->getCardinality(); // TODO : test empty values filtering and "compression" (store consecutive deltas). // Preparation: create three revisions and store them in $revision array. $values = []; $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(); for ($revision_id = 0; $revision_id < 3; $revision_id++) { // Note: we try to insert one extra value. $current_values = $this->_generateTestFieldValues($cardinality + 1); $entity->{$this->fieldTestData->field_name}->setValue($current_values); $entity->setNewRevision(); $entity->save(); $entity_id = $entity->id(); $current_revision = $entity->getRevisionId(); $values[$current_revision] = $current_values; } $storage = $this->container->get('entity.manager')->getStorage($entity_type); $storage->resetCache(); $entity = $storage->load($entity_id); // Confirm current revision loads the correct data. // Number of values per field loaded equals the field cardinality. $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), $cardinality, 'Current revision: expected number of values'); for ($delta = 0; $delta < $cardinality; $delta++) { // The field value loaded matches the one inserted or updated. $this->assertEqual($entity->{$this->fieldTestData->field_name}[$delta]->value, $values[$current_revision][$delta]['value'], format_string('Current revision: expected value %delta was found.', ['%delta' => $delta])); } // Confirm each revision loads the correct data. foreach (array_keys($values) as $revision_id) { $entity = $storage->loadRevision($revision_id); // Number of values per field loaded equals the field cardinality. $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), $cardinality, format_string('Revision %revision_id: expected number of values.', ['%revision_id' => $revision_id])); for ($delta = 0; $delta < $cardinality; $delta++) { // The field value loaded matches the one inserted or updated. $this->assertEqual($entity->{$this->fieldTestData->field_name}[$delta]->value, $values[$revision_id][$delta]['value'], format_string('Revision %revision_id: expected value %delta was found.', ['%revision_id' => $revision_id, '%delta' => $delta])); } } } /** * Test the 'multiple' load feature. */ public function testFieldAttachLoadMultiple() { $entity_type = 'entity_test_rev'; // Define 2 bundles. $bundles = [ 1 => 'test_bundle_1', 2 => 'test_bundle_2', ]; entity_test_create_bundle($bundles[1]); entity_test_create_bundle($bundles[2]); // Define 3 fields: // - field_1 is in bundle_1 and bundle_2, // - field_2 is in bundle_1, // - field_3 is in bundle_2. $field_bundles_map = [ 1 => [1, 2], 2 => [1], 3 => [2], ]; for ($i = 1; $i <= 3; $i++) { $field_names[$i] = 'field_' . $i; $field_storage = FieldStorageConfig::create([ 'field_name' => $field_names[$i], 'entity_type' => $entity_type, 'type' => 'test_field', ]); $field_storage->save(); $field_ids[$i] = $field_storage->uuid(); foreach ($field_bundles_map[$i] as $bundle) { FieldConfig::create([ 'field_name' => $field_names[$i], 'entity_type' => $entity_type, 'bundle' => $bundles[$bundle], ])->save(); } } // Create one test entity per bundle, with random values. foreach ($bundles as $index => $bundle) { $entities[$index] = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['id' => $index, 'revision_id' => $index, 'type' => $bundle]); $entity = clone($entities[$index]); foreach ($field_names as $field_name) { if (!$entity->hasField($field_name)) { continue; } $values[$index][$field_name] = mt_rand(1, 127); $entity->$field_name->setValue(['value' => $values[$index][$field_name]]); } $entity->enforceIsnew(); $entity->save(); } // Check that a single load correctly loads field values for both entities. $controller = \Drupal::entityManager()->getStorage($entity->getEntityTypeId()); $controller->resetCache(); $entities = $controller->loadMultiple(); foreach ($entities as $index => $entity) { foreach ($field_names as $field_name) { if (!$entity->hasField($field_name)) { continue; } // The field value loaded matches the one inserted. $this->assertEqual($entity->{$field_name}->value, $values[$index][$field_name], format_string('Entity %index: expected value was found.', ['%index' => $index])); } } } /** * Tests insert and update with empty or NULL fields. */ public function testFieldAttachSaveEmptyData() { $entity_type = 'entity_test'; $this->createFieldWithStorage('', $entity_type); $entity_init = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['id' => 1]); // Insert: Field is NULL. $entity = clone $entity_init; $entity->{$this->fieldTestData->field_name} = NULL; $entity->enforceIsNew(); $entity = $this->entitySaveReload($entity); $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'Insert: NULL field results in no value saved'); // All saves after this point should be updates, not inserts. $entity_init->enforceIsNew(FALSE); // Add some real data. $entity = clone($entity_init); $values = $this->_generateTestFieldValues(1); $entity->{$this->fieldTestData->field_name} = $values; $entity = $this->entitySaveReload($entity); $this->assertEqual($entity->{$this->fieldTestData->field_name}->getValue(), $values, 'Field data saved'); // Update: Field is NULL. Data should be wiped. $entity = clone($entity_init); $entity->{$this->fieldTestData->field_name} = NULL; $entity = $this->entitySaveReload($entity); $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'Update: NULL field removes existing values'); // Re-add some data. $entity = clone($entity_init); $values = $this->_generateTestFieldValues(1); $entity->{$this->fieldTestData->field_name} = $values; $entity = $this->entitySaveReload($entity); $this->assertEqual($entity->{$this->fieldTestData->field_name}->getValue(), $values, 'Field data saved'); // Update: Field is empty array. Data should be wiped. $entity = clone($entity_init); $entity->{$this->fieldTestData->field_name} = []; $entity = $this->entitySaveReload($entity); $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'Update: empty array removes existing values'); } /** * Test insert with empty or NULL fields, with default value. */ public function testFieldAttachSaveEmptyDataDefaultValue() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); // Add a default value function. $this->fieldTestData->field->set('default_value_callback', 'field_test_default_value'); $this->fieldTestData->field->save(); // Verify that fields are populated with default values. $entity_init = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['id' => 1, 'revision_id' => 1]); $default = field_test_default_value($entity_init, $this->fieldTestData->field); $this->assertEqual($entity_init->{$this->fieldTestData->field_name}->getValue(), $default, 'Default field value correctly populated.'); // Insert: Field is NULL. $entity = clone($entity_init); $entity->{$this->fieldTestData->field_name} = NULL; $entity->enforceIsNew(); $entity = $this->entitySaveReload($entity); $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'Insert: NULL field results in no value saved'); // Verify that prepopulated field values are not overwritten by defaults. $value = [['value' => $default[0]['value'] - mt_rand(1, 127)]]; $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['type' => $entity_init->bundle(), $this->fieldTestData->field_name => $value]); $this->assertEqual($entity->{$this->fieldTestData->field_name}->getValue(), $value, 'Prepopulated field value correctly maintained.'); } /** * Test entity deletion. */ public function testFieldAttachDelete() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); $cardinality = $this->fieldTestData->field_storage->getCardinality(); $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['type' => $this->fieldTestData->field->getTargetBundle()]); $vids = []; // Create revision 0 $values = $this->_generateTestFieldValues($cardinality); $entity->{$this->fieldTestData->field_name} = $values; $entity->save(); $vids[] = $entity->getRevisionId(); // Create revision 1 $entity->setNewRevision(); $entity->save(); $vids[] = $entity->getRevisionId(); // Create revision 2 $entity->setNewRevision(); $entity->save(); $vids[] = $entity->getRevisionId(); $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId()); $controller->resetCache(); // Confirm each revision loads foreach ($vids as $vid) { $revision = $controller->loadRevision($vid); $this->assertEqual(count($revision->{$this->fieldTestData->field_name}), $cardinality, "The test entity revision $vid has $cardinality values."); } // Delete revision 1, confirm the other two still load. $controller->deleteRevision($vids[1]); $controller->resetCache(); foreach ([0, 2] as $key) { $vid = $vids[$key]; $revision = $controller->loadRevision($vid); $this->assertEqual(count($revision->{$this->fieldTestData->field_name}), $cardinality, "The test entity revision $vid has $cardinality values."); } // Confirm the current revision still loads $controller->resetCache(); $current = $controller->load($entity->id()); $this->assertEqual(count($current->{$this->fieldTestData->field_name}), $cardinality, "The test entity current revision has $cardinality values."); // Delete all field data, confirm nothing loads $entity->delete(); $controller->resetCache(); foreach ([0, 1, 2] as $vid) { $revision = $controller->loadRevision($vid); $this->assertFalse($revision); } $this->assertFalse($controller->load($entity->id())); } /** * Test entity_bundle_create(). */ public function testEntityCreateBundle() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); $cardinality = $this->fieldTestData->field_storage->getCardinality(); // Create a new bundle. $new_bundle = 'test_bundle_' . Unicode::strtolower($this->randomMachineName()); entity_test_create_bundle($new_bundle, NULL, $entity_type); // Add a field to that bundle. $this->fieldTestData->field_definition['bundle'] = $new_bundle; FieldConfig::create($this->fieldTestData->field_definition)->save(); // Save an entity with data in the field. $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['type' => $this->fieldTestData->field->getTargetBundle()]); $values = $this->_generateTestFieldValues($cardinality); $entity->{$this->fieldTestData->field_name} = $values; // Verify the field data is present on load. $entity = $this->entitySaveReload($entity); $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), $cardinality, "Data is retrieved for the new bundle"); } /** * Test entity_bundle_delete(). */ public function testEntityDeleteBundle() { $entity_type = 'entity_test_rev'; $this->createFieldWithStorage('', $entity_type); // Create a new bundle. $new_bundle = 'test_bundle_' . Unicode::strtolower($this->randomMachineName()); entity_test_create_bundle($new_bundle, NULL, $entity_type); // Add a field to that bundle. $this->fieldTestData->field_definition['bundle'] = $new_bundle; FieldConfig::create($this->fieldTestData->field_definition)->save(); // Create a second field for the test bundle $field_name = Unicode::strtolower($this->randomMachineName() . '_field_name'); $field_storage = [ 'field_name' => $field_name, 'entity_type' => $entity_type, 'type' => 'test_field', 'cardinality' => 1, ]; FieldStorageConfig::create($field_storage)->save(); $field = [ 'field_name' => $field_name, 'entity_type' => $entity_type, 'bundle' => $this->fieldTestData->field->getTargetBundle(), 'label' => $this->randomMachineName() . '_label', 'description' => $this->randomMachineName() . '_description', 'weight' => mt_rand(0, 127), ]; FieldConfig::create($field)->save(); // Save an entity with data for both fields $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['type' => $this->fieldTestData->field->getTargetBundle()]); $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality()); $entity->{$this->fieldTestData->field_name} = $values; $entity->{$field_name} = $this->_generateTestFieldValues(1); $entity = $this->entitySaveReload($entity); // Verify the fields are present on load $this->assertEqual(count($entity->{$this->fieldTestData->field_name}), 4, 'First field got loaded'); $this->assertEqual(count($entity->{$field_name}), 1, 'Second field got loaded'); // Delete the bundle. entity_test_delete_bundle($this->fieldTestData->field->getTargetBundle(), $entity_type); // Verify no data gets loaded $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId()); $controller->resetCache(); $entity = $controller->load($entity->id()); $this->assertTrue(empty($entity->{$this->fieldTestData->field_name}), 'No data for first field'); $this->assertTrue(empty($entity->{$field_name}), 'No data for second field'); // Verify that the fields are gone. $this->assertFalse(FieldConfig::load('entity_test.' . $this->fieldTestData->field->getTargetBundle() . '.' . $this->fieldTestData->field_name), "First field is deleted"); $this->assertFalse(FieldConfig::load('entity_test.' . $field['bundle'] . '.' . $field_name), "Second field is deleted"); } }