diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index a284a87..303d42a 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -610,4 +610,19 @@ public function getAllBundleInfo() { return $this->bundleInfo; } + /** + * Builds a list of entity type labels suitable for a Form API options list. + * + * @return array + * An array of entity type labels, keyed by entity type name. + */ + public function getEntityTypeLabels() { + $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/field/field_type/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Plugin/field/field_type/EntityReferenceItem.php index 5e37050..db2f465 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/field/field_type/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/field/field_type/EntityReferenceItem.php @@ -10,7 +10,6 @@ use Drupal\Core\TypedData\Annotation\DataType; use Drupal\Core\Annotation\Translation; use Drupal\Core\Entity\Field\FieldItemBase; -use Drupal\Core\TypedData\TypedDataInterface; /** * Defines the 'entity_reference' entity field type. @@ -44,19 +43,32 @@ class EntityReferenceItem extends FieldItemBase { * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). */ public function getPropertyDefinitions() { + $target_type = $this->definition['settings']['target_type']; + // Definitions vary by entity type and bundle, so key them accordingly. - $key = $this->definition['settings']['target_type'] . ':'; + $key = $target_type . ':'; $key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : ''; 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', - 'label' => t('Entity ID'), - 'constraints' => array( - 'Range' => array('min' => 0), - ), - ); + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + if (is_subclass_of($target_type_info['class'], '\Drupal\Core\Entity\ContentEntityInterface')) { + static::$propertyDefinitions[$key]['target_id'] = array( + // @todo: Lookup the entity type's ID data type and use it here. + // https://drupal.org/node/2107249 + 'type' => 'integer', + 'label' => t('Entity ID'), + 'constraints' => array( + 'Range' => array('min' => 0), + ), + ); + } + else { + static::$propertyDefinitions[$key]['target_id'] = array( + 'type' => 'string', + 'label' => t('Entity ID'), + ); + } + static::$propertyDefinitions[$key]['entity'] = array( 'type' => 'entity_reference', 'constraints' => array( diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php index 3ce6be2..3aebba8 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php @@ -7,9 +7,9 @@ namespace Drupal\entity_reference; +use Drupal\field\FieldInterface; use Drupal\field\Plugin\Type\FieldType\ConfigEntityReferenceItemBase; use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemInterface; -use Drupal\field\FieldInterface; /** * Alternative plugin implementation of the 'entity_reference' field type. @@ -26,8 +26,11 @@ class ConfigurableEntityReferenceItem extends ConfigEntityReferenceItemBase impl * {@inheritdoc} */ public static function schema(FieldInterface $field) { - $schema = array( - 'columns' => array( + $target_type = $field->getFieldSetting('target_type'); + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + + if (is_subclass_of($target_type_info['class'], '\Drupal\Core\Entity\ContentEntityInterface')) { + $columns = array( 'target_id' => array( 'description' => 'The ID of the target entity.', 'type' => 'int', @@ -40,24 +43,25 @@ public static function schema(FieldInterface $field) { 'unsigned' => TRUE, 'not null' => FALSE, ), - ), + ); + } + else { + $columns = array( + 'target_id' => array( + 'description' => 'The ID of the target entity.', + 'type' => 'varchar', + 'length' => '255', + ), + ); + } + + $schema = array( + 'columns' => $columns, 'indexes' => array( 'target_id' => array('target_id'), ), ); - // Create a foreign key to the target entity type base type. - $entity_manager = \Drupal::service('entity.manager'); - $target_type = $field->getFieldSetting('target_type'); - if (is_subclass_of($entity_manager->getControllerClass($target_type, 'storage'), 'Drupal\Core\Entity\FieldableDatabaseStorageController')) { - $entity_info = $entity_manager->getDefinition($target_type); - $base_table = $entity_info['base_table']; - $schema['foreign keys'][$base_table] = array( - 'table' => $base_table, - 'columns' => array('target_id' => $entity_info['entity_keys']['id']), - ); - } - return $schema; } @@ -78,21 +82,10 @@ public function preSave() { * {@inheritdoc} */ public function settingsForm(array $form, array &$form_state, $has_data) { - // Select the target entity type. - $entity_type_options = array(); - foreach (\Drupal::entityManager()->getDefinitions() 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']; - } - } - $element['target_type'] = array( '#type' => 'select', '#title' => t('Type of item to reference'), - '#options' => $entity_type_options, + '#options' => \Drupal::entityManager()->getEntityTypeLabels(), '#default_value' => $this->getFieldSetting('target_type'), '#required' => TRUE, '#disabled' => $has_data, diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php index d9419ce..34ae667 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php @@ -102,50 +102,54 @@ public static function settingsForm(FieldDefinitionInterface $field_definition) ); } - // @todo Use Entity::getPropertyDefinitions() when all entity types are - // converted to the new Field API. - $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_info['base_table'])); - foreach (field_info_instances($target_type) as $bundle_instances) { - foreach ($bundle_instances as $instance_name => $instance) { - foreach ($instance->getField()->getColumns() as $column_name => $column_info) { - $fields[$instance_name . '.' . $column_name] = t('@label (@column)', array('@label' => $instance->getFieldLabel(), '@column' => $column_name)); + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + if (is_subclass_of($target_type_info['class'], '\Drupal\Core\Entity\ContentEntityInterface')) { + // @todo Use Entity::getPropertyDefinitions() when all entity types are + // converted to the new Field API. + $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_info['base_table'])); + foreach (field_info_instances($target_type) as $bundle_instances) { + foreach ($bundle_instances as $instance_name => $instance) { + foreach ($instance->getField()->getColumns() as $column_name => $column_info) { + $fields[$instance_name . '.' . $column_name] = t('@label (@column)', array('@label' => $instance->getFieldLabel(), '@column' => $column_name)); + } + } } - } - - $form['sort']['field'] = array( - '#type' => 'select', - '#title' => t('Sort by'), - '#options' => array( - '_none' => t('- None -'), - ) + $fields, - '#ajax' => TRUE, - '#limit_validation_errors' => array(), - '#default_value' => $selection_handler_settings['sort']['field'], - ); - $form['sort']['settings'] = array( - '#type' => 'container', - '#attributes' => array('class' => array('entity_reference-settings')), - '#process' => array('_entity_reference_form_process_merge_parent'), - ); - - if ($selection_handler_settings['sort']['field'] != '_none') { - // Merge-in default values. - $selection_handler_settings['sort'] += array( - 'direction' => 'ASC', - ); - - $form['sort']['settings']['direction'] = array( + $form['sort']['field'] = array( '#type' => 'select', - '#title' => t('Sort direction'), - '#required' => TRUE, + '#title' => t('Sort by'), '#options' => array( - 'ASC' => t('Ascending'), - 'DESC' => t('Descending'), - ), - '#default_value' => $selection_handler_settings['sort']['direction'], + '_none' => t('- None -'), + ) + $fields, + '#ajax' => TRUE, + '#limit_validation_errors' => array(), + '#default_value' => $selection_handler_settings['sort']['field'], + ); + + $form['sort']['settings'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('entity_reference-settings')), + '#process' => array('_entity_reference_form_process_merge_parent'), ); + + if ($selection_handler_settings['sort']['field'] != '_none') { + // Merge-in default values. + $selection_handler_settings['sort'] += array( + 'direction' => 'ASC', + ); + + $form['sort']['settings']['direction'] = array( + '#type' => 'select', + '#title' => t('Sort direction'), + '#required' => TRUE, + '#options' => array( + 'ASC' => t('Ascending'), + 'DESC' => t('Descending'), + ), + '#default_value' => $selection_handler_settings['sort']['direction'], + ); + } } return $form; diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php index 55063cc..b45b9b8 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php @@ -61,10 +61,15 @@ public function elementValidate($element, &$form_state, $form) { $value = ''; if (!empty($element['#value'])) { // Take "label (entity id)', match the id from parenthesis. - if (preg_match("/.+\((\d+)\)/", $element['#value'], $matches)) { + // @todo: Lookup the entity type's ID data type and use it here. + // https://drupal.org/node/2107249 + if ($this->isContentReferenced() && preg_match("/.+\((\d+)\)/", $element['#value'], $matches)) { $value = $matches[1]; } - else { + elseif (preg_match("/.+\(([\w.]+)\)/", $element['#value'], $matches)) { + $value = $matches[1]; + } + if (!$value) { // Try to get a match from the input string when the user didn't use the // autocomplete but filled in a value manually. $handler = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($this->fieldDefinition); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php index 0428cc4..6e55f2b 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php @@ -193,4 +193,15 @@ protected function getSelectionHandlerSetting($setting_name) { return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL; } + /** + * Checks whether a content entity is referenced. + * + * @return bool + */ + protected function isContentReferenced() { + $target_type = $this->getFieldSetting('target_type'); + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + return is_subclass_of($target_type_info['class'], '\Drupal\Core\Entity\ContentEntityInterface'); + } + } 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 7914840..4c7327d 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 @@ -15,7 +15,7 @@ class EntityReferenceAdminTest extends WebTestBase { public static function getInfo() { return array( - 'name' => 'Entity Reference UI', + 'name' => 'Entity Reference admin UI', 'description' => 'Tests for the administrative UI.', 'group' => 'Entity Reference', ); @@ -75,6 +75,11 @@ public function testFieldAdminHandler() { // Node should be selected by default. $this->assertFieldByName('field[settings][target_type]', 'node'); + // Check that all entity types can be referenced. + foreach (\Drupal::entityManager()->getDefinitions() as $entity_type => $entity_info) { + $this->assertFieldByXPath("//select[@name='field[settings][target_type]']/option[@value='" . $entity_type . "']"); + } + // Second step: 'Instance settings' form. $this->drupalPostForm(NULL, array(), t('Save field settings')); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php new file mode 100644 index 0000000..2d17a78 --- /dev/null +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php @@ -0,0 +1,95 @@ + 'Entity reference components (widgets, formatters, etc.)', + 'description' => 'Tests for various Entity reference components.', + 'group' => 'Entity Reference', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + // Create a test user. + $web_user = $this->drupalCreateUser(array('administer entity_test content')); + $this->drupalLogin($web_user); + } + + /** + * Tests the autocomplete widget when targeting a config entity type. + */ + public function testConfigAutocompleteWidget() { + // Create an Entity reference field targeting a config entity type. + entity_reference_create_instance($this->entityType, $this->bundle, $this->fieldName, 'Field test', 'config_test'); + + // Add the field to the default form mode. + entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName)->save(); + + // Create a test config entity. + $config_entity_id = $this->randomName(); + $config_entity_label = $this->randomString(); + $config_entity = entity_create('config_test', array('id' => $config_entity_id, 'label' => $config_entity_label)); + $config_entity->save(); + + $entity_name = $this->randomName(); + $edit = array( + 'name' => $entity_name, + 'user_id' => mt_rand(0, 128), + $this->fieldName . '[0][target_id]' => $config_entity_label . ' (' . $config_entity_id . ')', + ); + $this->drupalPostForm($this->entityType . '/add', $edit, t('Save')); + $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name))); + + $this->assertTrue($entity, format_string('%entity_type: Entity found in the database.', array('%entity_type' => $this->entityType))); + $this->assertEqual($entity->{$this->fieldName}->target_id, $config_entity_id); + $this->assertEqual($entity->{$this->fieldName}->entity->id(), $config_entity_id); + $this->assertEqual($entity->{$this->fieldName}->entity->label(), $config_entity_label); + } + +} 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 69257b0..3960948 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 @@ -7,7 +7,6 @@ namespace Drupal\entity_reference\Tests; -use Drupal\Core\Entity\FieldableDatabaseStorageController; use Drupal\Core\Entity\Field\FieldItemListInterface; use Drupal\Core\Entity\Field\FieldItemInterface; use Drupal\Core\Language\Language; @@ -25,6 +24,20 @@ class EntityReferenceItemTest extends FieldUnitTestBase { */ public static $modules = array('entity_reference', 'taxonomy', 'options'); + /** + * The taxonomy vocabulary to test with. + * + * @var \Drupal\taxonomy\VocabularyInterface + */ + protected $vocabulary; + + /** + * The taxonomy term to test with. + * + * @var \Drupal\taxonomy\TermInterface + */ + protected $term; + public static function getInfo() { return array( 'name' => 'Entity Reference field item', @@ -42,48 +55,49 @@ 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 content entity reference', 'taxonomy_term'); + entity_reference_create_instance('entity_test', 'entity_test', 'field_test_taxonomy_vocabulary', 'Test config entity reference', 'taxonomy_vocabulary'); } /** - * Tests using entity fields of the entity reference field type. + * Tests the entity reference field type for referencing content entities. */ - public function testEntityReferenceItem() { + public function testContentEntityReferenceItem() { $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->field_test_taxonomy_term->target_id = $tid; $entity->name->value = $this->randomName(); $entity->save(); $entity = entity_load('entity_test', $entity->id()); - $this->assertTrue($entity->field_test_taxonomy instanceof FieldItemListInterface, '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()); + $this->assertTrue($entity->field_test_taxonomy_term instanceof FieldItemListInterface, 'Field implements interface.'); + $this->assertTrue($entity->field_test_taxonomy_term[0] instanceof FieldItemInterface, 'Field item implements interface.'); + $this->assertEqual($entity->field_test_taxonomy_term->target_id, $tid); + $this->assertEqual($entity->field_test_taxonomy_term->entity->name->value, $this->term->name->value); + $this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $tid); + $this->assertEqual($entity->field_test_taxonomy_term->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(); + $entity->field_test_taxonomy_term->entity->name = $new_name; + $entity->field_test_taxonomy_term->entity->save(); // Verify it is the correct name. $term = entity_load('taxonomy_term', $tid); $this->assertEqual($term->name->value, $new_name); @@ -96,9 +110,9 @@ public function testEntityReferenceItem() { )); $term2->save(); - $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); + $entity->field_test_taxonomy_term->target_id = $term2->id(); + $this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $term2->id()); + $this->assertEqual($entity->field_test_taxonomy_term->entity->name->value, $term2->name->value); // Delete terms so we have nothing to reference and try again $term->delete(); @@ -108,30 +122,50 @@ public function testEntityReferenceItem() { } /** - * Tests foreign key support. + * Tests the entity reference field type for referencing config entities. */ - public function testEntityReferenceFieldSchema() { - $field = field_info_field('entity_test', 'field_test_taxonomy'); - $foreign_key_column_name = 'target_id'; - - // Grab the SQL schema and verify that the 'foreign keys' are present. - $schemas = FieldableDatabaseStorageController::_fieldSqlSchema($field); - $schema = $schemas[FieldableDatabaseStorageController::_fieldTableName($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 = FieldableDatabaseStorageController::_fieldColumnName($field, $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('entity_test', $field_name); - - $schemas = FieldableDatabaseStorageController::_fieldSqlSchema($field); - $schema = $schemas[FieldableDatabaseStorageController::_fieldTableName($field)]; - $this->assertFalse(isset($schema['foreign keys']), 'There is no foreign key in the schema.'); + public function testConfigEntityReferenceItem() { + $referenced_entity_id = $this->vocabulary->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_vocabulary->target_id = $referenced_entity_id; + $entity->name->value = $this->randomName(); + $entity->save(); + + $entity = entity_load('entity_test', $entity->id()); + $this->assertTrue($entity->field_test_taxonomy_vocabulary instanceof FieldItemListInterface, 'Field implements interface.'); + $this->assertTrue($entity->field_test_taxonomy_vocabulary[0] instanceof FieldItemInterface, 'Field item implements interface.'); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->target_id, $referenced_entity_id); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->entity->name, $this->vocabulary->name); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->entity->id(), $referenced_entity_id); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->entity->uuid(), $this->vocabulary->uuid()); + + // Change the name of the term via the reference. + $new_name = $this->randomName(); + $entity->field_test_taxonomy_vocabulary->entity->name = $new_name; + $entity->field_test_taxonomy_vocabulary->entity->save(); + // Verify it is the correct name. + $term = entity_load('taxonomy_vocabulary', $referenced_entity_id); + $this->assertEqual($term->name, $new_name); + + // Make sure the computed term reflects updates to the term id. + $vocabulary2 = entity_create('taxonomy_vocabulary', array( + 'name' => $this->randomName(), + 'vid' => drupal_strtolower($this->randomName()), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + )); + $vocabulary2->save(); + + $entity->field_test_taxonomy_vocabulary->target_id = $vocabulary2->id(); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->entity->id(), $vocabulary2->id()); + $this->assertEqual($entity->field_test_taxonomy_vocabulary->entity->name, $vocabulary2->name); + + // Delete terms so we have nothing to reference and try again + $this->vocabulary->delete(); + $vocabulary2->delete(); + $entity = entity_create('entity_test', array('name' => $this->randomName())); + $entity->save(); } + } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php index 18cb2e0..b0e436f 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php @@ -8,9 +8,9 @@ namespace Drupal\field\Plugin\Type\FieldType; use Drupal\Core\Entity\Plugin\field\field_type\EntityReferenceItem; -use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemInterface; -use Drupal\field\FieldInterface; use Drupal\field\FieldInstanceInterface; +use Drupal\field\FieldInterface; +use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemInterface; /** * A common base class for configurable entity reference fields. @@ -36,22 +36,29 @@ class ConfigEntityReferenceItemBase extends EntityReferenceItem implements Confi * {@inheritdoc} */ public function getPropertyDefinitions() { + $target_type = $this->definition['settings']['target_type']; + // Definitions vary by entity type and bundle, so key them accordingly. - $key = $this->definition['settings']['target_type'] . ':'; + $key = $target_type . ':'; $key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : ''; if (!isset(static::$propertyDefinitions[$key])) { // Call the parent to define the target_id and entity properties. parent::getPropertyDefinitions(); - static::$propertyDefinitions[$key]['revision_id'] = array( - // @todo: Lookup the entity type's ID data type and use it here. - 'type' => 'integer', - 'label' => t('Revision ID'), - 'constraints' => array( - 'Range' => array('min' => 0), - ), - ); + // Only add the revision ID property if the target entity type supports + // revisions. + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + if (!empty($target_type_info['entity_keys']['revision']) && !empty($target_type_info['revision_table'])) { + static::$propertyDefinitions[$key]['revision_id'] = array( + 'type' => 'integer', + 'label' => t('Revision ID'), + 'constraints' => array( + 'Range' => array('min' => 0), + ), + ); + } + static::$propertyDefinitions[$key]['label'] = array( 'type' => 'string', 'label' => t('Label (auto-create)'), @@ -87,8 +94,8 @@ public static function schema(FieldInterface $field) { */ public function isEmpty() { // Avoid loading the entity by first checking the 'target_id'. - $target_id = $this->get('target_id')->getValue(); - if (!empty($target_id) && is_numeric($target_id)) { + $target_id = $this->target_id; + if (!empty($target_id)) { return FALSE; } // Allow auto-create entities. diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php index e90a4a3..8258a40 100644 --- a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php @@ -28,7 +28,7 @@ class TypedDataTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('system', 'entity', 'field', 'file'); + public static $modules = array('system', 'entity', 'field', 'file', 'user'); public static function getInfo() { return array( diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php index 1ef1d3b..72c0fe9 100644 --- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php @@ -26,7 +26,7 @@ class TextPlainUnitTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('entity', 'field', 'text', 'entity_test', 'system', 'filter'); + public static $modules = array('entity', 'field', 'text', 'entity_test', 'system', 'filter', 'user'); /** * Contains rendered content. diff --git a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php index 7c09bbf..280000c 100644 --- a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php @@ -24,7 +24,7 @@ class QueryGroupByTest extends ViewUnitTestBase { * * @var array */ - public static $modules = array('entity_test', 'system', 'field'); + public static $modules = array('entity_test', 'system', 'field', 'user'); /** * The storage controller for the test entity type.