From cb451afa0293ef1838dc4c2c9bde1dcaaf8452e7 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Fri, 12 Jun 2015 00:24:48 +0100 Subject: [PATCH] Issue #2107249 by Jelle_S, tstoeckler, amateescu, Xano, jibran, yched: Don't assume that content entities have numeric IDs in EntityReferenceItem --- .../Field/FieldType/EntityReferenceItem.php | 14 ++-- .../EntityReferenceItemTest.php | 28 ++++++++ .../tests/src/Unit/EntityViewsDataTest.php | 72 ++++++++++++++----- 3 files changed, 92 insertions(+), 22 deletions(-) diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php index 47874bece5f8..fa0b4a04e0c9 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -72,9 +72,15 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel $settings = $field_definition->getSettings(); $target_type_info = \Drupal::entityManager()->getDefinition($settings['target_type']); + $target_id_data_type = 'string'; if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) { - // @todo: Lookup the entity type's ID data type and use it here. - // https://www.drupal.org/node/2107249 + $id_definition = \Drupal::entityManager()->getBaseFieldDefinitions($settings['target_type'])[$target_type_info->getKey('id')]; + if ($id_definition->getType() === 'integer') { + $target_id_data_type = 'integer'; + } + } + + if ($target_id_data_type === 'integer') { $target_id_definition = DataDefinition::create('integer') ->setLabel(t('@label ID', array($target_type_info->getLabel()))) ->setSetting('unsigned', TRUE); @@ -119,8 +125,8 @@ public static function mainPropertyName() { public static function schema(FieldStorageDefinitionInterface $field_definition) { $target_type = $field_definition->getSetting('target_type'); $target_type_info = \Drupal::entityManager()->getDefinition($target_type); - - if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) { + $properties = static::propertyDefinitions($field_definition)['target_id']; + if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface') && $properties->getDataType() === 'integer') { $columns = array( 'target_id' => array( 'description' => 'The ID of the target entity.', diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php index e75f33aaaf9e..4601c343f17e 100644 --- a/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php @@ -12,6 +12,8 @@ use Drupal\Core\Field\FieldItemInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\entity_reference\Tests\EntityReferenceTestTrait; +use Drupal\entity_test\Entity\EntityTest; +use Drupal\entity_test\Entity\EntityTestStringId; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Tests\FieldUnitTestBase; @@ -49,12 +51,20 @@ class EntityReferenceItemTest extends FieldUnitTestBase { */ protected $term; + /** + * The test entity with a string ID. + * + * @var \Drupal\entity_test\Entity\EntityTestStringId + */ + protected $entityStringId; + /** * Sets up the test. */ protected function setUp() { parent::setUp(); + $this->installEntitySchema('entity_test_string_id'); $this->installEntitySchema('taxonomy_term'); $this->vocabulary = entity_create('taxonomy_vocabulary', array( @@ -71,8 +81,14 @@ protected function setUp() { )); $this->term->save(); + $this->entityStringId = EntityTestStringId::create([ + 'id' => $this->randomMachineName(), + ]); + $this->entityStringId->save(); + // Use the util to create an instance. $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_taxonomy_term', 'Test content entity reference', 'taxonomy_term'); + $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_entity_test_string_id', 'Test content entity reference with string ID', 'entity_test_string_id'); $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_taxonomy_vocabulary', 'Test config entity reference', 'taxonomy_vocabulary'); } @@ -152,6 +168,18 @@ public function testContentEntityReferenceItem() { $this->entityValidateAndSave($entity); } + /** + * Tests referencing content entities with string IDs. + */ + public function testContentEntityReferenceItemWithStringId() { + $entity = EntityTest::create(); + $entity->field_test_entity_test_string_id->target_id = $this->entityStringId->id(); + $entity->save(); + $storage = \Drupal::entityManager()->getStorage('entity_test'); + $storage->resetCache(); + $this->assertEqual($this->entityStringId->id(), $storage->load($entity->id())->field_test_entity_test_string_id->target_id); + } + /** * Tests the entity reference field type for referencing config entities. */ diff --git a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php index fb347941070a..3dedb8252a59 100644 --- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php +++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php @@ -83,6 +83,12 @@ protected function setUp() { ->getMock(); $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); + $typed_data_manager = $this->getMockBuilder('Drupal\Core\TypedData\TypedDataManager') + ->disableOriginalConstructor() + ->getMock(); + $typed_data_manager->expects($this->any()) + ->method('createDataDefinition') + ->willReturn($this->getMock('Drupal\Core\TypedData\DataDefinitionInterface')); $this->baseEntityType = new TestEntityType([ 'base_table' => 'entity_test', 'id' => 'entity_test', @@ -110,6 +116,7 @@ protected function setUp() { $container = new ContainerBuilder(); $container->set('plugin.manager.field.field_type', $field_type_manager); $container->set('entity.manager', $this->entityManager); + $container->set('typed_data_manager', $typed_data_manager); \Drupal::setContainer($container); } @@ -360,6 +367,9 @@ protected function setupFieldStorageDefinition() { ->method('getSetting') ->with('target_type') ->willReturn('user'); + $user_id_field_storage_definition->expects($this->any()) + ->method('getSettings') + ->willReturn(['target_type' => 'user']); $user_id_field_storage_definition->expects($this->any()) ->method('getSchema') ->willReturn(EntityReferenceItem::schema($user_id_field_storage_definition)); @@ -389,12 +399,19 @@ protected function setupFieldStorageDefinition() { */ public function testBaseTableFields() { $base_field_definitions = $this->setupBaseFields(EntityTest::baseFieldDefinitions($this->baseEntityType)); - - $this->entityManager->expects($this->once()) + $user_base_field_definitions = [ + 'uid' => BaseFieldDefinition::create('integer') + ->setLabel(t('ID')) + ->setDescription(t('The ID of the user entity.')) + ->setReadOnly(TRUE) + ->setSetting('unsigned', TRUE) + ]; + $this->entityManager->expects($this->any()) ->method('getBaseFieldDefinitions') - ->with('entity_test') - ->willReturn($base_field_definitions); - + ->will($this->returnValueMap([ + ['user', $user_base_field_definitions], + ['entity_test', $base_field_definitions], + ])); // Setup the table mapping. $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface'); $table_mapping->expects($this->any()) @@ -471,19 +488,21 @@ public function testDataTableFields() { ->setSettings(array('target_type' => 'entity_test_bundle')) ->setTranslatable(TRUE); $base_field_definitions = $this->setupBaseFields($base_field_definitions); + $user_base_field_definitions = [ + 'uid' => BaseFieldDefinition::create('integer') + ->setLabel(t('ID')) + ->setDescription(t('The ID of the user entity.')) + ->setReadOnly(TRUE) + ->setSetting('unsigned', TRUE) + ]; $entity_test_type = new ConfigEntityType(['id' => 'entity_test_bundle']); - $user_entity_type = static::userEntityInfo(); - $this->entityManager->expects($this->any()) - ->method('getDefinition') - ->willReturnMap([ - ['entity_test_bundle', TRUE, $entity_test_type], - ['user', TRUE, $user_entity_type], - ]); - $this->entityManager->expects($this->once()) + $this->entityManager->expects($this->any()) ->method('getBaseFieldDefinitions') - ->with('entity_test_mul') - ->willReturn($base_field_definitions); + ->will($this->returnValueMap([ + ['user', $user_base_field_definitions], + ['entity_test_mul', $base_field_definitions], + ])); $this->viewsData->setEntityType($entity_type); @@ -517,6 +536,14 @@ public function testDataTableFields() { $this->setupFieldStorageDefinition(); + $user_entity_type = static::userEntityInfo(); + $this->entityManager->expects($this->any()) + ->method('getDefinition') + ->will($this->returnValueMap([ + ['user', TRUE, $user_entity_type], + ['entity_test_bundle', TRUE, $entity_test_type], + ])); + $data = $this->viewsData->getViewsData(); // Check the base fields. @@ -575,10 +602,19 @@ public function testRevisionTableFields() { ->set('revision_data_table', 'entity_test_mulrev_property_revision') ->set('id', 'entity_test_mulrev'); $base_field_definitions = $this->setupBaseFields(EntityTestMulRev::baseFieldDefinitions($this->baseEntityType)); - $this->entityManager->expects($this->once()) + $user_base_field_definitions = [ + 'uid' => BaseFieldDefinition::create('integer') + ->setLabel(t('ID')) + ->setDescription(t('The ID of the user entity.')) + ->setReadOnly(TRUE) + ->setSetting('unsigned', TRUE) + ]; + $this->entityManager->expects($this->any()) ->method('getBaseFieldDefinitions') - ->with('entity_test_mulrev') - ->willReturn($base_field_definitions); + ->will($this->returnValueMap([ + ['user', $user_base_field_definitions], + ['entity_test_mulrev', $base_field_definitions], + ])); $this->viewsData->setEntityType($entity_type); -- GitLab