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 6ff9e10..0737733 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -165,16 +165,21 @@ public function setValue($values, $notify = TRUE) { if (isset($values['target_id']) && !isset($values['entity'])) { $this->onChange('target_id', FALSE); } - elseif (!isset($values['target_id']) && isset($values['entity'])) { + // NULL is a valid value, so we use array_key_exists(). + elseif (is_array($values) && !array_key_exists('target_id', $values) && isset($values['entity'])) { $this->onChange('entity', FALSE); } - elseif (isset($values['target_id']) && isset($values['entity'])) { + // NULL is a valid value, so we use array_key_exists(). + elseif (is_array($values) && array_key_exists('target_id', $values) && isset($values['entity'])) { // If both properties are passed, verify the passed values match. The // only exception we allow is when we have a new entity: in this case // its actual id and target_id will be different, due to the new entity // marker. $entity_id = $this->get('entity')->getTargetIdentifier(); - if ($entity_id != $values['target_id'] && (!$this->entity->isNew())) { + // If the entity has been saved and we're trying to set both the + // target_id and the entity values with a non-null target ID, then the + // value for target_id should match the ID of the entity value. + if (!$this->entity->isNew() && $values['target_id'] !== NULL && ($entity_id !== $values['target_id'])) { throw new \InvalidArgumentException('The target id and entity passed to the entity reference item do not match.'); } } @@ -210,7 +215,7 @@ public function onChange($property_name, $notify = TRUE) { $target_id = $property->isTargetNew() ? NULL : $property->getTargetIdentifier(); $this->writePropertyValue('target_id', $target_id); } - elseif ($property_name == 'target_id' && $this->target_id) { + elseif ($property_name == 'target_id' && $this->target_id !== NULL) { $this->writePropertyValue('entity', $this->target_id); } parent::onChange($property_name, $notify); @@ -236,11 +241,12 @@ public function preSave() { if ($this->entity->isNew()) { $this->entity->save(); } - } - if ($this->entity && ($id = $this->entity->id()) && $this->target_id !== $id) { // Make sure the parent knows we are updating this property so it can // react properly. - $this->target_id = $id; + $this->target_id = $this->entity->id(); + } + if (!$this->isEmpty() && $this->target_id === NULL) { + $this->target_id = $this->entity->id(); } } diff --git a/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php b/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php index 14a67ef..01dd0c1 100644 --- a/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php +++ b/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php @@ -238,16 +238,16 @@ function testAutocreateApi() { }); $this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) { $entity->user_id[0]->get('entity')->setValue($user); - $entity->user_id[0]->get('target_id')->setValue(-1); + $entity->user_id[0]->get('target_id')->setValue(NULL); }); $this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) { - $entity->user_id->setValue(array('entity' => $user, 'target_id' => -1)); + $entity->user_id->setValue(array('entity' => $user, 'target_id' => NULL)); }); try { $message = 'Setting both the entity and an invalid target_id property fails.'; $this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) { $user->save(); - $entity->user_id->setValue(array('entity' => $user, 'target_id' => -1)); + $entity->user_id->setValue(array('entity' => $user, 'target_id' => $this->generateRandomEntityId())); }); $this->fail($message); } @@ -273,16 +273,16 @@ function testAutocreateApi() { }); $this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) { $entity->user_role[0]->get('entity')->setValue($role); - $entity->user_role[0]->get('target_id')->setValue(-1); + $entity->user_role[0]->get('target_id')->setValue(NULL); }); $this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) { - $entity->user_role->setValue(array('entity' => $role, 'target_id' => -1)); + $entity->user_role->setValue(array('entity' => $role, 'target_id' => NULL)); }); try { $message = 'Setting both the entity and an invalid target_id property fails.'; $this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) { $role->save(); - $entity->user_role->setValue(array('entity' => $role, 'target_id' => -1)); + $entity->user_role->setValue(array('entity' => $role, 'target_id' => $this->generateRandomEntityId(TRUE))); }); $this->fail($message); }