diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index afddb22..c5421ed 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -322,7 +322,7 @@ public function isDefaultRevision($new_value = NULL) {
* {@inheritdoc}
*/
public function isRevisionTranslationAffected() {
- $field_name = 'revision_translation_affected';
+ $field_name = $this->getEntityType()->getKey('revision_translation_affected');
return $this->hasField($field_name) ? $this->get($field_name)->value : TRUE;
}
@@ -330,7 +330,7 @@ public function isRevisionTranslationAffected() {
* {@inheritdoc}
*/
public function setRevisionTranslationAffected($affected) {
- $field_name = 'revision_translation_affected';
+ $field_name = $this->getEntityType()->getKey('revision_translation_affected');
if ($this->hasField($field_name)) {
$this->set($field_name, $affected);
}
diff --git a/core/lib/Drupal/Core/Entity/EntityFieldManager.php b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
index 378a95c..a0fff7e 100644
--- a/core/lib/Drupal/Core/Entity/EntityFieldManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
@@ -220,6 +220,20 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
}
}
+ // Make sure that revisionable entity types are correctly defined.
+ if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
+ // The 'revision_translation_affected' field should always be defined.
+ // This field has been added unconditionally in Drupal 8.4.0 and it is
+ // overriding any pre-existing definition on purpose so that any
+ // differences are immediately available in the status report.
+ $base_field_definitions[$keys['revision_translation_affected']] = BaseFieldDefinition::create('boolean')
+ ->setLabel($this->t('Revision translation affected'))
+ ->setDescription($this->t('Indicates if the last edit of a translation belongs to current revision.'))
+ ->setReadOnly(TRUE)
+ ->setRevisionable(TRUE)
+ ->setTranslatable(TRUE);
+ }
+
// Assign base field definitions the entity type provider.
$provider = $entity_type->getProvider();
foreach ($base_field_definitions as $definition) {
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index b39fb3f..5f6589a 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -302,6 +302,7 @@ public function __construct($definition) {
'bundle' => '',
'langcode' => '',
'default_langcode' => 'default_langcode',
+ 'revision_translation_affected' => 'revision_translation_affected',
];
$this->handlers += [
'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index ad28f76..915af91 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -1689,8 +1689,9 @@ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $st
// few "entity keys", in order to keep their indexes optimized.
// @todo Fix this in https://www.drupal.org/node/2841291.
$not_null_keys = $this->entityType->getKeys();
- // Label fields are not necessarily required.
- unset($not_null_keys['label']);
+ // Label and the 'revision_translation_affected' fields are not necessarily
+ // required.
+ unset($not_null_keys['label'], $not_null_keys['revision_translation_affected']);
// Because entity ID and revision ID are both serial fields in the base and
// revision table respectively, the revision ID is not known yet, when
// inserting data into the base table. Instead the revision ID in the base
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
index 30befd2..a589f56 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php
@@ -245,6 +245,7 @@ protected function copyData(array &$sandbox) {
$original_base_table = $original_entity_type->getBaseTable();
$revision_id_key = $temporary_entity_type->getKey('revision');
+ $revision_translation_affected_key = $temporary_entity_type->getKey('revision_translation_affected');
// If 'progress' is not set, then this will be the first run of the batch.
if (!isset($sandbox['progress'])) {
@@ -287,6 +288,11 @@ protected function copyData(array &$sandbox) {
// Set the revision ID to be same as the entity ID.
$entity->set($revision_id_key, $entity_id);
+ // Set the 'revision_translation_affected' flag to TRUE to match the
+ // previous API return value: if the field was not defined the value
+ // returned was always TRUE.
+ $entity->set($revision_translation_affected_key, TRUE);
+
// Treat the entity as new in order to make the storage do an INSERT
// rather than an UPDATE.
$entity->enforceIsNew(TRUE);
@@ -370,9 +376,26 @@ protected function updateFieldStorageDefinitionsToRevisionable(ContentEntityType
if ($update_cached_definitions) {
$this->entityDefinitionUpdateManager->installFieldStorageDefinition($revision_field->getName(), $entity_type->id(), $entity_type->getProvider(), $revision_field);
}
-
$updated_storage_definitions[$entity_type->getKey('revision')] = $revision_field;
+ // Add the 'revision_translation_affected' field if needed.
+ if ($entity_type->isTranslatable()) {
+ $revision_translation_affected_field = BaseFieldDefinition::create('boolean')
+ ->setName($entity_type->getKey('revision_translation_affected'))
+ ->setTargetEntityTypeId($entity_type->id())
+ ->setTargetBundle(NULL)
+ ->setLabel(new TranslatableMarkup('Revision translation affected'))
+ ->setDescription(new TranslatableMarkup('Indicates if the last edit of a translation belongs to current revision.'))
+ ->setReadOnly(TRUE)
+ ->setRevisionable(TRUE)
+ ->setTranslatable(TRUE);
+
+ if ($update_cached_definitions) {
+ $this->entityDefinitionUpdateManager->installFieldStorageDefinition($revision_translation_affected_field->getName(), $entity_type->id(), $entity_type->getProvider(), $revision_translation_affected_field);
+ }
+ $updated_storage_definitions[$entity_type->getKey('revision_translation_affected')] = $revision_translation_affected_field;
+ }
+
return $updated_storage_definitions;
}
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 76071df..66a7a8f 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -216,13 +216,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setSetting('target_type', 'user')
->setRevisionable(TRUE);
- $fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
- ->setLabel(t('Revision translation affected'))
- ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
- ->setReadOnly(TRUE)
- ->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
-
return $fields;
}
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index e5544a2..368ce1b 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -400,13 +400,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
])
->setDisplayConfigurable('form', TRUE);
- $fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
- ->setLabel(t('Revision translation affected'))
- ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
- ->setReadOnly(TRUE)
- ->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
-
return $fields;
}
diff --git a/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php b/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
index ebd4e03..5b71b93 100644
--- a/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
+++ b/core/modules/serialization/tests/src/Kernel/EntitySerializationTest.php
@@ -126,6 +126,9 @@ public function testNormalize() {
'default_langcode' => [
['value' => TRUE],
],
+ 'revision_translation_affected' => [
+ ['value' => TRUE],
+ ],
'non_rev_field' => [],
'field_test_text' => [
[
@@ -197,6 +200,7 @@ public function testSerialize() {
'user_id' => '' . $this->user->id() . '' . $this->user->getEntityTypeId() . '' . $this->user->uuid() . '' . $this->user->url() . '',
'revision_id' => '' . $this->entity->getRevisionId() . '',
'default_langcode' => '1',
+ 'revision_translation_affected' => '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/src/Tests/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php b/core/modules/system/src/Tests/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php
index 3a0aca2..b6a8695 100644
--- a/core/modules/system/src/Tests/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php
+++ b/core/modules/system/src/Tests/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php
@@ -92,6 +92,9 @@ public function testMakeRevisionable() {
$entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update');
$this->assertTrue($entity_test_update->isRevisionable());
+ $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+ $this->assertTrue(isset($field_storage_definitions['revision_translation_affected']));
+
/** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_update');
$this->assertEqual(count($storage->loadMultiple()), 102, 'All test entities were found.');
@@ -104,6 +107,10 @@ public function testMakeRevisionable() {
$this->assertEqual($i, $revision->id());
$this->assertEqual($i, $revision->getRevisionId());
+ // Check that the correct initial value was provided for the
+ // 'revision_translation_affected' field.
+ $this->assertTrue($revision->revision_translation_affected->value);
+
$this->assertEqual($i . ' - test single property', $revision->test_single_property->value);
$this->assertEqual($i . ' - test multiple properties - value1', $revision->test_multiple_properties->value1);
diff --git a/core/modules/system/src/Tests/Update/EntityUpdateAddRevisionTranslationAffectedTest.php b/core/modules/system/src/Tests/Update/EntityUpdateAddRevisionTranslationAffectedTest.php
new file mode 100644
index 0000000..190e175
--- /dev/null
+++ b/core/modules/system/src/Tests/Update/EntityUpdateAddRevisionTranslationAffectedTest.php
@@ -0,0 +1,88 @@
+entityManager = \Drupal::entityManager();
+ $this->lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository');
+ $this->state = \Drupal::state();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setDatabaseDumpFiles() {
+ $this->databaseDumpFiles = [
+ __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul_rev.php.gz',
+ ];
+ }
+
+ /**
+ * Tests the addition of the 'revision_translation_affected' base field.
+ *
+ * @covers system_update_8402
+ */
+ public function testAddingTheRevisionTranslationAffectedField() {
+ // Make the entity type revisionable and translatable prior to running the
+ // updates.
+ $this->updateEntityTypeToRevisionableAndTranslatable();
+
+ // Check that the test entity type does not have the
+ // 'revision_translation_affected' field before running the updates.
+ $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+ $this->assertFalse(isset($field_storage_definitions['revision_translation_affected']));
+
+ $this->runUpdates();
+
+ // Check that the 'revision_translation_affected' field has been added by
+ // system_update_8402().
+ $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+ $this->assertTrue(isset($field_storage_definitions['revision_translation_affected']));
+
+ // Check that the correct initial value was set when the field was
+ // installed.
+ $entity = $this->entityManager->getStorage('entity_test_update')->load(1);
+ $this->assertTrue($entity->revision_translation_affected->value);
+ }
+
+}
diff --git a/core/modules/system/src/Tests/Update/EntityUpdateToRevisionableAndPublishableTest.php b/core/modules/system/src/Tests/Update/EntityUpdateToRevisionableAndPublishableTest.php
index 167bf12..3edf6f7 100644
--- a/core/modules/system/src/Tests/Update/EntityUpdateToRevisionableAndPublishableTest.php
+++ b/core/modules/system/src/Tests/Update/EntityUpdateToRevisionableAndPublishableTest.php
@@ -77,6 +77,8 @@ protected function setDatabaseDumpFiles() {
/**
* Tests the conversion of an entity type to revisionable and publishable.
+ *
+ * @covers entity_test_update_update_8400
*/
public function testConvertToRevisionableAndPublishable() {
// Check that entity type is not revisionable nor publishable prior to
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index a4ffffa..3c8332e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -17,6 +17,7 @@
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\DrupalKernel;
+use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\PrivateStream;
use Drupal\Core\StreamWrapper\PublicStream;
@@ -1984,3 +1985,43 @@ function system_update_8401() {
->clear('response')
->save();
}
+
+/**
+ * Add the 'revision_translation_affected' field to all entity types.
+ */
+function system_update_8402() {
+ $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+
+ // Clear the cached entity type definitions so we get the new
+ // 'revision_translation_affected' entity key.
+ \Drupal::entityTypeManager()->clearCachedDefinitions();
+
+ // Get a list of revisionable and translatable entity types.
+ /** @var \Drupal\Core\Entity\ContentEntityTypeInterface[] $definitions */
+ $definitions = array_filter(\Drupal::entityTypeManager()->getDefinitions(), function (EntityTypeInterface $entity_type) use ($definition_update_manager) {
+ if ($entity_type = $definition_update_manager->getEntityType($entity_type->id())) {
+ return $entity_type->isRevisionable() && $entity_type->isTranslatable();
+ }
+ return FALSE;
+ });
+
+ foreach ($definitions as $entity_type_id => $entity_type) {
+ $field_name = $entity_type->getKey('revision_translation_affected');
+ // Install the 'revision_translation_affected' field if needed.
+ if (!$definition_update_manager->getFieldStorageDefinition($field_name, $entity_type_id)) {
+ $storage_definition = BaseFieldDefinition::create('boolean')
+ ->setLabel(t('Revision translation affected'))
+ ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
+ ->setReadOnly(TRUE)
+ ->setRevisionable(TRUE)
+ ->setTranslatable(TRUE)
+ // Mark all pre-existing revisions as affected in order to be consistent
+ // with the previous API return value: if the field was not defined the
+ // value returned was always TRUE.
+ ->setInitialValue(TRUE);
+
+ $definition_update_manager
+ ->installFieldStorageDefinition($field_name, $entity_type_id, $entity_type_id, $storage_definition);
+ }
+ }
+}
diff --git a/core/modules/system/tests/fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul_rev.php.gz b/core/modules/system/tests/fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul_rev.php.gz
new file mode 100644
index 0000000..d7a8ba1
--- /dev/null
+++ b/core/modules/system/tests/fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul_rev.php.gz
@@ -0,0 +1,624 @@
+ԍY drupal-8.0.0-rc1-filled.standard.entity_test_update_mul_rev.php i㸙jf0Ud:A&tږ%$wO%ᄂ.%[r3z]6!!?kݿ7QQz>|0`c *+n) geaGCFbE|Ʊ3(ɖ+F@~(VbyD&7oq0wy1?y4N/+E3O~(C$.[_}
Ͽz 8ۇoE7zg_ǚ߉o=O~ LiЇ2$GhcC{g8_g=$G,'-687,>my;x"NCd+'=WIyGG/G'_xvHoe{7]0MxyZz0~H?nă ~3<@m?yisqkޱݧjޣ
3_RF~>if4zS3ukMJf#oCIi6$4wЖQ}rſ8 o'
ˠ0V`c]|sMǸ>*\a#Qk^rBRNS\$UBv^:#ῌ,G7);f6*rsee$Ws=jC1n8Ć4Ԉh:@.{ƎZ
pSr:7[;vҞCϋPL|>oD8},1`t0jkȫzu*FSAl${;qrhnp
mђgZ(
UJxQUvlD9БŁ#;J
$/>x IdҶzKBb|/a{ɌœYoDxOP>^esVoMcBvy-YDH1VЋ#YG~M,3*tL=g
+ib.`2x3lVU>
+?yG˞g/MD5
+6i>Y҆
RiyO{(yRVZHZ|cz˧,RxFpYv>Fi%!狁D>I1'#b8eQ!.6lplj5J`*>lP(FQIYqFZVS1kl
+{ W]̥<|aX U`TbYЭ mCÎt]S,;* Cds5
l{خp\=BwE{#^³VHhN5x!ѷaBm2A t c pb
+^<>+u\8##p1\c/\o?"TJw G8 5T`Ȱuhezv;
+?sGHgztVr'=)NCuFxr?f:4LW(\;TMH~uB?uD%YH''J