diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 3effe8b3c2..12b9324402 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -331,6 +331,20 @@ public function isDefaultRevision($new_value = NULL) {
return $this->isNew() || $return;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function wasDefaultRevision() {
+ if (!$this->getEntityType()->isRevisionable()) {
+ throw new \LogicException("Entity type {$this->getEntityTypeId()} does not support revisions.");
+ }
+ $value = $this->get('default_revision')->value;
+ if (isset($value)) {
+ return (bool) $value;
+ }
+ throw new \LogicException("Missing data for the \"default_revision\" field on the entity {$this->getEntityTypeId()}:{$this->id()}.");
+ }
+
/**
* {@inheritdoc}
*/
@@ -1269,23 +1283,33 @@ protected function getEntityKey($key) {
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = [];
+
if ($entity_type->hasKey('id')) {
$fields[$entity_type->getKey('id')] = BaseFieldDefinition::create('integer')
->setLabel(new TranslatableMarkup('ID'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
}
+
if ($entity_type->hasKey('uuid')) {
$fields[$entity_type->getKey('uuid')] = BaseFieldDefinition::create('uuid')
->setLabel(new TranslatableMarkup('UUID'))
->setReadOnly(TRUE);
}
- if ($entity_type->hasKey('revision')) {
+
+ if ($entity_type->isRevisionable()) {
$fields[$entity_type->getKey('revision')] = BaseFieldDefinition::create('integer')
->setLabel(new TranslatableMarkup('Revision ID'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
+
+ $fields['default_revision'] = BaseFieldDefinition::create('boolean')
+ ->setLabel(new TranslatableMarkup('Default revision'))
+ ->setDescription(new TranslatableMarkup('A flag indicating whether this was a default revision when it was saved.'))
+ ->setTranslatable(FALSE)
+ ->setRevisionable(TRUE);
}
+
if ($entity_type->hasKey('langcode')) {
$fields[$entity_type->getKey('langcode')] = BaseFieldDefinition::create('language')
->setLabel(new TranslatableMarkup('Language'))
@@ -1303,6 +1327,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields[$entity_type->getKey('langcode')]->setTranslatable(TRUE);
}
}
+
if ($entity_type->hasKey('bundle')) {
if ($bundle_entity_type_id = $entity_type->getBundleEntityType()) {
$fields[$entity_type->getKey('bundle')] = BaseFieldDefinition::create('entity_reference')
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
index 3053d23694..e85a299312 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
@@ -106,4 +106,16 @@ public function getLoadedRevisionId();
*/
public function updateLoadedRevisionId();
+ /**
+ * Checks whether the entity object was a default revision when it was saved.
+ *
+ * @return bool
+ * TRUE if the entity object was a revision, FALSE otherwise.
+ *
+ * @throws \LogicException
+ * If the entity type is not revisionable or the default revision data is
+ * missing.
+ */
+ public function wasDefaultRevision();
+
}
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index a3bb20508f..8803d36802 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -334,6 +334,9 @@ protected function doSave($id, EntityInterface $entity) {
}
$this->populateAffectedRevisionTranslations($entity);
+ if ($this->entityType->isRevisionable()) {
+ $entity->set('default_revision', $entity->isDefaultRevision());
+ }
$this->doSaveFieldItems($entity);
return $return;
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
index 60712eeb21..3b15161380 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
@@ -293,6 +293,10 @@ protected function copyData(array &$sandbox) {
// returned was always TRUE.
$entity->set($revision_translation_affected_key, TRUE);
+ // We cannot know what type the revision was so we assume the core
+ // default behavior of always creating a default revision.
+ $entity->set('default_revision', TRUE);
+
// Treat the entity as new in order to make the storage do an INSERT
// rather than an UPDATE.
$entity->enforceIsNew(TRUE);
@@ -380,6 +384,20 @@ protected function updateFieldStorageDefinitionsToRevisionable(ContentEntityType
}
$updated_storage_definitions[$entity_type->getKey('revision')] = $revision_field;
+ // Add the default revision flag.
+ $field_name = 'default_revision';
+ $default_revision_field = BaseFieldDefinition::create('boolean')
+ ->setName($field_name)
+ ->setLabel(new TranslatableMarkup('Default revision'))
+ ->setDescription(new TranslatableMarkup('A flag indicating whether this was a default revision when it was saved.'))
+ ->setTranslatable(FALSE)
+ ->setRevisionable(TRUE);
+
+ if ($update_cached_definitions) {
+ $this->entityDefinitionUpdateManager->installFieldStorageDefinition($default_revision_field->getName(), $entity_type->id(), $entity_type->getProvider(), $default_revision_field);
+ }
+ $updated_storage_definitions[$default_revision_field->getName()] = $default_revision_field;
+
// Add the 'revision_translation_affected' field if needed.
if ($entity_type->isTranslatable()) {
$revision_translation_affected_field = BaseFieldDefinition::create('boolean')
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentResourceTestBase.php
index 5d7329feb9..c652a2c4be 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentResourceTestBase.php
@@ -121,6 +121,11 @@ protected function getExpectedNormalizedEntity() {
'value' => TRUE,
],
],
+ 'default_revision' => [
+ [
+ 'value' => TRUE,
+ ],
+ ],
'default_langcode' => [
[
'value' => TRUE,
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Media/MediaResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Media/MediaResourceTestBase.php
index 1875d004a4..b84c96632e 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Media/MediaResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Media/MediaResourceTestBase.php
@@ -212,6 +212,11 @@ protected function getExpectedNormalizedEntity() {
'value' => TRUE,
],
],
+ 'default_revision' => [
+ [
+ 'value' => TRUE,
+ ],
+ ],
];
}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
index 492ff642e4..fa972eaa6a 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
@@ -152,6 +152,11 @@ protected function getExpectedNormalizedEntity() {
'value' => TRUE,
],
],
+ 'default_revision' => [
+ [
+ 'value' => TRUE,
+ ],
+ ],
'default_langcode' => [
[
'value' => TRUE,
diff --git a/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php b/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
index 5b71b93b7a..88039ba799 100644
--- a/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
+++ b/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
@@ -129,6 +129,9 @@ public function testNormalize() {
'revision_translation_affected' => [
['value' => TRUE],
],
+ 'default_revision' => [
+ ['value' => TRUE],
+ ],
'non_rev_field' => [],
'field_test_text' => [
[
@@ -201,6 +204,7 @@ public function testSerialize() {
'revision_id' => '' . $this->entity->getRevisionId() . '',
'default_langcode' => '1',
'revision_translation_affected' => '1',
+ 'default_revision' => '1',
'non_rev_field' => '',
'field_test_text' => '' . $this->values['field_test_text']['value'] . '' . $this->values['field_test_text']['format'] . '',
];
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index ef6f124f51..38c63517f7 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2056,3 +2056,39 @@ function system_update_8403() {
}
}
}
+
+/**
+ * Add the 'revision_type' field to all entity types.
+ */
+function system_update_8501() {
+ /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
+ $field_manager = \Drupal::service('entity_field.manager');
+ $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+
+ // Get a list of entity types to process.
+ /** @var \Drupal\Core\Entity\ContentEntityTypeInterface[] $definitions */
+ $definitions = array_filter(\Drupal::entityTypeManager()->getDefinitions(), function (EntityTypeInterface $entity_type) use ($field_manager, $definition_update_manager) {
+ $entity_type_id = $entity_type->id();
+ if ($entity_type = $definition_update_manager->getEntityType($entity_type_id)) {
+ $field_name = 'default_revision';
+ return $entity_type->isRevisionable()
+ && isset($field_manager->getFieldStorageDefinitions($entity_type_id)[$field_name])
+ && !$definition_update_manager->getFieldStorageDefinition($field_name, $entity_type_id);
+ }
+ return FALSE;
+ });
+
+ $storage_definition = BaseFieldDefinition::create('boolean')
+ ->setLabel(t('Default revision'))
+ ->setDescription(t('A flag indicating whether this was a default revision when it was saved.'))
+ ->setTranslatable(FALSE)
+ ->setRevisionable(TRUE)
+ ->setInitialValue(TRUE);
+
+ // Install the 'default_revision' field.
+ foreach ($definitions as $entity_type_id => $entity_type) {
+ $field_name = 'default_revision';
+ $definition_update_manager
+ ->installFieldStorageDefinition($field_name, $entity_type_id, $entity_type_id, $storage_definition);
+ }
+}
diff --git a/core/modules/system/tests/modules/entity_test_update/src/Entity/EntityTestUpdate.php b/core/modules/system/tests/modules/entity_test_update/src/Entity/EntityTestUpdate.php
index 286e8e62bd..175bc7ad80 100644
--- a/core/modules/system/tests/modules/entity_test_update/src/Entity/EntityTestUpdate.php
+++ b/core/modules/system/tests/modules/entity_test_update/src/Entity/EntityTestUpdate.php
@@ -69,11 +69,17 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDescription(new TranslatableMarkup('The bundle of the test entity.'))
->setRequired(TRUE);
- if ($entity_type->hasKey('revision')) {
+ if ($entity_type->isRevisionable()) {
$fields[$entity_type->getKey('revision')] = BaseFieldDefinition::create('integer')
->setLabel(new TranslatableMarkup('Revision ID'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
+
+ $fields['default_revision'] = BaseFieldDefinition::create('boolean')
+ ->setLabel(new TranslatableMarkup('Default revision'))
+ ->setDescription(new TranslatableMarkup('A flag indicating whether this was a default revision when it was saved.'))
+ ->setTranslatable(FALSE)
+ ->setRevisionable(TRUE);
}
$fields[$entity_type->getKey('langcode')] = BaseFieldDefinition::create('language')