diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 3fdf81b7488f2d9a0e2e6fee32cf413968cb680b..48545d22ded94b4a7f6b651200196095f18458a5 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -821,10 +821,13 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names if ($update) { $default_revision = $entity->isDefaultRevision(); if ($default_revision) { + // Remove the ID from the record to enable updates on SQL variants + // that prevent updating serial columns, for example, mssql. + unset($record->{$this->idKey}); $this->database ->update($this->baseTable) ->fields((array) $record) - ->condition($this->idKey, $record->{$this->idKey}) + ->condition($this->idKey, $entity->get($this->idKey)->value) ->execute(); } if ($this->revisionTable) { @@ -833,11 +836,15 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names } else { $record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable); + // Remove the revision ID from the record to enable updates on SQL + // variants that prevent updating serial columns, for example, + // mssql. + unset($record->{$this->revisionKey}); $entity->preSaveRevision($this, $record); $this->database ->update($this->revisionTable) ->fields((array) $record) - ->condition($this->revisionKey, $record->{$this->revisionKey}) + ->condition($this->revisionKey, $entity->getRevisionId()) ->execute(); } } @@ -1064,19 +1071,21 @@ protected function saveRevision(ContentEntityInterface $entity) { ->condition($this->idKey, $record->{$this->idKey}) ->execute(); } + // Make sure to update the new revision key for the entity. + $entity->{$this->revisionKey}->value = $record->{$this->revisionKey}; } else { + // Remove the revision ID from the record to enable updates on SQL + // variants that prevent updating serial columns, for example, + // mssql. + unset($record->{$this->revisionKey}); $this->database ->update($this->revisionTable) ->fields((array) $record) - ->condition($this->revisionKey, $record->{$this->revisionKey}) + ->condition($this->revisionKey, $entity->getRevisionId()) ->execute(); } - - // Make sure to update the new revision key for the entity. - $entity->{$this->revisionKey}->value = $record->{$this->revisionKey}; - - return $record->{$this->revisionKey}; + return $entity->getRevisionId(); } /** diff --git a/core/lib/Drupal/Core/Path/AliasStorage.php b/core/lib/Drupal/Core/Path/AliasStorage.php index a02bc3534d0157ba61813f0dad1a9b8e567acdf5..b6898487197d0b2d9b67644918613fcedc9abb96 100644 --- a/core/lib/Drupal/Core/Path/AliasStorage.php +++ b/core/lib/Drupal/Core/Path/AliasStorage.php @@ -106,11 +106,11 @@ public function save($source, $alias, $langcode = LanguageInterface::LANGCODE_NO $this->catchException($e); $original = FALSE; } - $fields['pid'] = $pid; $query = $this->connection->update(static::TABLE) ->fields($fields) ->condition('pid', $pid); $pid = $query->execute(); + $fields['pid'] = $pid; $fields['original'] = $original; $operation = 'update'; } diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php index 3fd17d86b47798da09b4aa795e4a3663c7b66b10..1695d9378c9f0da75a96bae97e24383210c0114f 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php @@ -3,6 +3,7 @@ namespace Drupal\KernelTests\Core\Entity; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\RevisionLogInterface; use Drupal\Core\Entity\TypedData\EntityDataDefinition; use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface; @@ -919,4 +920,33 @@ protected function doTestComputedProperties($entity_type) { $this->assertEqual($entity->field_test_text->processed, $target, format_string('%entity_type: Text is processed with the default filter.', ['%entity_type' => $entity_type])); } + /** + * Tests explicit entity ID assignment. + */ + public function testEntityIdAssignment() { + $entity_type = 'entity_test'; + /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ + $storage = $this->container->get('entity_type.manager')->getStorage($entity_type); + + // Check that an ID can be explicitly assigned on creation. + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + $entity = $this->createTestEntity($entity_type); + $entity_id = 3; + $entity->set('id', $entity_id); + $this->assertSame($entity_id, $entity->id()); + $storage->save($entity); + $entity = $storage->loadUnchanged($entity->id()); + $this->assertTrue($entity); + + // Check that an explicitly-assigned ID is preserved on update. + $storage->save($entity); + $entity = $storage->loadUnchanged($entity->id()); + $this->assertTrue($entity); + + // Check that an ID cannot be explicitly assigned on update. + $this->setExpectedException(EntityStorageException::class); + $entity->set('id', $entity_id + 1); + $storage->save($entity); + } + }