diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 4766a91..e9a3783 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -454,4 +454,19 @@ public function clearCachedFieldDefinitions() { $this->cache->deleteTags(array('entity_field_info' => TRUE)); } + /** + * Build a list of entity type options. + * + * @return array + * Keys are plugin IDs and values are plugin labels. + */ + function options() { + $options = array(); + foreach ($this->getDefinitions() as $entity_type => $definition) { + $options[$entity_type] = $definition['label']; + } + + return $options; + } + } diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php index 3e67f7e..bf529a0 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php @@ -49,11 +49,12 @@ public function getPropertyDefinitions() { if (!isset(static::$propertyDefinitions[$key])) { static::$propertyDefinitions[$key]['target_id'] = array( - // @todo: Lookup the entity type's ID data type and use it here. - 'type' => 'integer', + 'type' => 'string', 'label' => t('Entity ID'), 'constraints' => array( - 'Range' => array('min' => 0), + 'Length' => array( + 'min' => 0, + ), ), ); static::$propertyDefinitions[$key]['entity'] = array( diff --git a/core/modules/entity_reference/entity_reference.install b/core/modules/entity_reference/entity_reference.install index c40d3ea..536d5e7 100644 --- a/core/modules/entity_reference/entity_reference.install +++ b/core/modules/entity_reference/entity_reference.install @@ -14,9 +14,8 @@ function entity_reference_field_schema($field) { 'columns' => array( 'target_id' => array( 'description' => 'The ID of the target entity.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, + 'type' => 'varchar', + 'length' => 255, ), 'revision_id' => array( 'description' => 'The revision ID of the target entity.', @@ -30,19 +29,5 @@ function entity_reference_field_schema($field) { ), ); - // Create a foreign key to the target entity type base type. - $entity_manager = Drupal::service('plugin.manager.entity'); - if (is_subclass_of($entity_manager->getControllerClass($field['settings']['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) { - $entity_info = $entity_manager->getDefinition($field['settings']['target_type']); - - $base_table = $entity_info['base_table']; - $id_column = $entity_info['entity_keys']['id']; - - $schema['foreign keys'][$base_table] = array( - 'table' => $base_table, - 'columns' => array('target_id' => $id_column), - ); - } - return $schema; } diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module index 54a7bac..c2800e6 100644 --- a/core/modules/entity_reference/entity_reference.module +++ b/core/modules/entity_reference/entity_reference.module @@ -133,21 +133,10 @@ function entity_reference_field_validate(EntityInterface $entity = NULL, $field, * Implements hook_field_settings_form(). */ function entity_reference_field_settings_form($field, $instance) { - // Select the target entity type. - $entity_type_options = array(); - foreach (entity_get_info() as $entity_type => $entity_info) { - // @todo As the database schema can currently only store numeric IDs of - // referenced entities and configuration entities have string IDs, prevent - // configuration entities from being referenced. - if (!is_subclass_of($entity_info['class'], '\Drupal\Core\Config\Entity\ConfigEntityInterface')) { - $entity_type_options[$entity_type] = $entity_info['label']; - } - } - $form['target_type'] = array( '#type' => 'select', '#title' => t('Type of item to reference'), - '#options' => $entity_type_options, + '#options' => Drupal::entityManager()->options(), '#default_value' => $field['settings']['target_type'], '#required' => TRUE, '#disabled' => $field->hasData(), diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php index 932f55f..0ccffc6 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php @@ -74,6 +74,10 @@ public function testFieldAdminHandler() { // Node should be selected by default. $this->assertFieldByName('field[settings][target_type]', 'node'); + $entity_manager = $this->container->get('plugin.manager.entity'); + foreach ($entity_manager->getDefinitions() as $plugin_id => $definition) { + $this->assertFieldByXPath("//select[@name='field[settings][target_type]']/option[@value='" . $plugin_id . "']"); + } // Second step: 'Instance settings' form. $this->drupalPost(NULL, array(), t('Save field settings')); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php index 8c17fd6..34b58b9 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php @@ -41,96 +41,81 @@ public function setUp() { $this->installSchema('taxonomy', 'taxonomy_term_data'); $this->installSchema('taxonomy', 'taxonomy_term_hierarchy'); - $vocabulary = entity_create('taxonomy_vocabulary', array( + $this->vocabulary = entity_create('taxonomy_vocabulary', array( 'name' => $this->randomName(), 'vid' => drupal_strtolower($this->randomName()), 'langcode' => Language::LANGCODE_NOT_SPECIFIED, )); - $vocabulary->save(); + $this->vocabulary->save(); $this->term = entity_create('taxonomy_term', array( 'name' => $this->randomName(), - 'vid' => $vocabulary->id(), + 'vid' => $this->vocabulary->id(), 'langcode' => Language::LANGCODE_NOT_SPECIFIED, )); $this->term->save(); // Use the util to create an instance. - entity_reference_create_instance('entity_test', 'entity_test', 'field_test_taxonomy', 'Test entity reference', 'taxonomy_term'); + entity_reference_create_instance('entity_test', 'entity_test', 'field_test_taxonomy_term', 'Test entity term reference', 'taxonomy_term'); + entity_reference_create_instance('entity_test', 'entity_test', 'field_test_taxonomy_vocabulary', 'Test entity vocabulary reference', 'taxonomy_vocabulary'); } /** * Tests using entity fields of the entity reference field type. */ public function testEntityReferenceItem() { - $tid = $this->term->id(); - - // Just being able to create the entity like this verifies a lot of code. - $entity = entity_create('entity_test', array()); - $entity->field_test_taxonomy->target_id = $tid; - $entity->name->value = $this->randomName(); - $entity->save(); - - $entity = entity_load('entity_test', $entity->id()); - $this->assertTrue($entity->field_test_taxonomy instanceof FieldInterface, 'Field implements interface.'); - $this->assertTrue($entity->field_test_taxonomy[0] instanceof FieldItemInterface, 'Field item implements interface.'); - $this->assertEqual($entity->field_test_taxonomy->target_id, $tid); - $this->assertEqual($entity->field_test_taxonomy->entity->name->value, $this->term->name->value); - $this->assertEqual($entity->field_test_taxonomy->entity->id(), $tid); - $this->assertEqual($entity->field_test_taxonomy->entity->uuid(), $this->term->uuid()); - - // Change the name of the term via the reference. - $new_name = $this->randomName(); - $entity->field_test_taxonomy->entity->name = $new_name; - $entity->field_test_taxonomy->entity->save(); - // Verify it is the correct name. - $term = entity_load('taxonomy_term', $tid); - $this->assertEqual($term->name->value, $new_name); - - // Make sure the computed term reflects updates to the term id. - $term2 = entity_create('taxonomy_term', array( - 'name' => $this->randomName(), - 'vid' => $this->term->bundle(), - 'langcode' => Language::LANGCODE_NOT_SPECIFIED, - )); - $term2->save(); + $entity_manager = $this->container->get('plugin.manager.entity'); - $entity->field_test_taxonomy->target_id = $term2->id(); - $this->assertEqual($entity->field_test_taxonomy->entity->id(), $term2->id()); - $this->assertEqual($entity->field_test_taxonomy->entity->name->value, $term2->name->value); - - // Delete terms so we have nothing to reference and try again - $term->delete(); - $term2->delete(); - $entity = entity_create('entity_test', array('name' => $this->randomName())); - $entity->save(); - } - - /** - * Tests foreign key support. - */ - public function testEntityReferenceFieldSchema() { - $field = field_info_field('field_test_taxonomy'); - $foreign_key_column_name = 'target_id'; - - // Grab the SQL schema and verify that the 'foreign keys' are present. - $schemas = _field_sql_storage_schema($field); - $schema = $schemas[_field_sql_storage_tablename($field)]; - $this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema.'); - - $foreign_key = reset($schema['foreign keys']); - $foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_column_name); - $this->assertEqual($foreign_key['table'], 'taxonomy_term_data', 'Foreign key table name preserved in the schema.'); - $this->assertEqual($foreign_key['columns'][$foreign_key_column], 'tid', 'Foreign key column name preserved in the schema.'); - - // Create a field that references a config entity type and check that no - // foreign key is present. - $field_name = 'field_test_vocabulary'; - entity_reference_create_instance('entity_test', 'entity_test', $field_name, 'Test vocabulary reference', 'taxonomy_vocabulary'); - $field = field_info_field($field_name); - - $schemas = _field_sql_storage_schema($field); - $schema = $schemas[_field_sql_storage_tablename($field)]; - $this->assertFalse(isset($schema['foreign keys']), 'There is no foreign key in the schema.'); + // Test a content and a configuration entity. + $fields = array( + 'field_test_taxonomy_term' => $this->term, + 'field_test_taxonomy_vocabulary' => $this->vocabulary, + ); + foreach ($fields as $field_name => $referenced_entity) { + $referenced_entity_definition = $entity_manager->getDefinition($referenced_entity->entityType()); + + // Just being able to create the entity like this verifies a lot of code. + $entity = entity_create('entity_test', array()); + $entity->get($field_name)->target_id = $referenced_entity->id(); + $entity->name->value = $this->randomName(); + $entity->save(); + + $entity = entity_load('entity_test', $entity->id()); + $this->assertTrue($entity->get($field_name) instanceof FieldInterface, 'Field implements interface.'); + $this->assertTrue($entity->get($field_name)[0] instanceof FieldItemInterface, 'Field item implements interface.'); + $this->assertEqual($entity->get($field_name)->target_id, $referenced_entity->id()); + $this->assertEqual($entity->get($field_name)->entity->label(), $referenced_entity->label()); + $this->assertEqual($entity->get($field_name)->entity->id(), $referenced_entity->id()); + $this->assertEqual($entity->get($field_name)->entity->uuid(), $referenced_entity->uuid()); + + // Change the label of the referenced entity via the reference. + $new_name = $this->randomName(); + $label_property = $referenced_entity_definition['entity_keys']['label']; + $entity->get($field_name)->entity->$label_property = $new_name; + $entity->get($field_name)->entity->save(); + // Verify it is the correct label. + $referenced_entity = entity_load($referenced_entity->entityType(), $referenced_entity->id()); + $this->assertEqual($referenced_entity->name->value, $new_name); + + // Make sure the computed referenced entity reflects updates to the + // reference ID. + $referenced_entity2 = entity_create($referenced_entity->entityType(), array( + 'name' => $this->randomName(), + $referenced_entity_definition['entity_keys']['bundle'] => $referenced_entity->bundle(), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + )); + $referenced_entity2->save(); + + $entity->get($field_name)->target_id = $referenced_entity2->id(); + $this->assertEqual($entity->get($field_name)->entity->id(), $referenced_entity2->id()); + $this->assertEqual($entity->get($field_name)->entity->label(), $referenced_entity2->label()); + + // Delete the referenced entities so we have nothing to reference and try + // again + $referenced_entity->delete(); + $referenced_entity2->delete(); + $entity = entity_create('entity_test', array('name' => $this->randomName())); + $entity->save(); + } } }