diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index 846e89a578234bb0634dad199ee03a76c4ef1274..29156095927e0e46c045dfe07c348f8672bb0fe4 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -312,7 +312,9 @@ public function isDefaultRevision($new_value = NULL) { if (isset($new_value)) { $this->isDefaultRevision = (bool) $new_value; } - return $return; + // New entities should always ensure at least one default revision exists, + // creating an entity without a default revision is an invalid state. + return $this->isNew() || $return; } /** diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDuplicateTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDuplicateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e2c1af472f5ba7e53d9643dd62ab8ef02ec2230d --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDuplicateTest.php @@ -0,0 +1,55 @@ +installEntitySchema('entity_test_rev'); + $this->entityTestRevStorage = $this->container->get('entity_type.manager')->getStorage('entity_test_rev'); + } + + /** + * Test duplicating a non-default revision. + */ + public function testDuplicateNonDefaultRevision() { + $entity = EntityTestRev::create([ + 'name' => 'First Revision', + ]); + $entity->save(); + $first_revision_id = $entity->getRevisionId(); + + $entity->setNewRevision(TRUE); + $entity->name = 'Second Revision'; + $entity->save(); + + $duplicate_first_revision = $this->entityTestRevStorage->loadRevision($first_revision_id)->createDuplicate(); + $this->assertTrue($duplicate_first_revision->isDefaultRevision(), 'Duplicating a non-default revision creates a default revision.'); + $this->assertEquals($duplicate_first_revision->label(), 'First Revision'); + $duplicate_first_revision->save(); + + $duplicate_first_revision->name = 'Updated name'; + $duplicate_first_revision->save(); + + $this->entityTestRevStorage->resetCache(); + $duplicate_first_revision = EntityTestRev::load($duplicate_first_revision->id()); + $this->assertEquals('Updated name', $duplicate_first_revision->label()); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php index 38fc3cc5c0c963e137cb281cbae18d80cfe15a02..e8134ef900f294ffa495db11616281812cf71497 100644 --- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php @@ -182,8 +182,8 @@ protected function setUp() { ->method('getFieldDefinitions') ->with($this->entityTypeId, $this->bundle) ->will($this->returnValue($this->fieldDefinitions)); - $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\ContentEntityBase', array($values, $this->entityTypeId, $this->bundle)); + $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\ContentEntityBase', array($values, $this->entityTypeId, $this->bundle), '', TRUE, TRUE, TRUE, ['isNew']); $values['defaultLangcode'] = array(LanguageInterface::LANGCODE_DEFAULT => LanguageInterface::LANGCODE_NOT_SPECIFIED); $this->entityUnd = $this->getMockForAbstractClass('\Drupal\Core\Entity\ContentEntityBase', array($values, $this->entityTypeId, $this->bundle)); } @@ -262,6 +262,12 @@ public function testIsDefaultRevision() { $this->assertTrue($this->entity->isDefaultRevision(FALSE)); // The last call changed the return value for this call. $this->assertFalse($this->entity->isDefaultRevision()); + // The revision for a new entity should always be the default revision. + $this->entity->expects($this->any()) + ->method('isNew') + ->will($this->returnValue(TRUE)); + $this->entity->isDefaultRevision(FALSE); + $this->assertTrue($this->entity->isDefaultRevision()); } /**