summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGábor Hojtsy2018-07-16 08:20:58 (GMT)
committerGábor Hojtsy2018-07-16 08:22:07 (GMT)
commit687a1913e84b7ee8ffbf2d00a468b8f352dacc5d (patch)
tree2af8a60ea826f8d3f26c62bd794b4510257d8df3
parentd1b82959addc4488c950285a32817ba1b476fdb9 (diff)
Issue #2975754 by Berdir, plach, alexpott, hchonov, mkalkbrenner, tstoeckler, webchick: Add hooks to act on a new revision being created
(cherry picked from commit 1e8a4de636a8e2c287995c868c2b7b2d6e59ec2c)
-rw-r--r--core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php7
-rw-r--r--core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php4
-rw-r--r--core/lib/Drupal/Core/Entity/entity.api.php48
-rw-r--r--core/modules/system/tests/modules/entity_test/entity_test.module17
-rw-r--r--core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php54
5 files changed, 129 insertions, 1 deletions
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index bc56c42..2eb7c2f 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -241,6 +241,8 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$new_revision = clone $entity;
+ $original_keep_untranslatable_fields = $keep_untranslatable_fields;
+
// For translatable entities, create a merged revision of the active
// translation and the other translations in the default revision. This
// permits the creation of pending revisions that can always be saved as the
@@ -311,6 +313,11 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con
// to the correct translation.
$new_revision->setRevisionTranslationAffected(TRUE);
+ // Notify modules about the new revision.
+ $arguments = [$new_revision, $entity, $original_keep_untranslatable_fields];
+ $this->moduleHandler()->invokeAll($this->entityTypeId . '_revision_create', $arguments);
+ $this->moduleHandler()->invokeAll('entity_revision_create', $arguments);
+
return $new_revision;
}
diff --git a/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php b/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
index b86317f..b8a5565 100644
--- a/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
+++ b/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
@@ -20,7 +20,9 @@ interface TranslatableRevisionableStorageInterface extends TranslatableStorageIn
* to TRUE.
* @param bool|null $keep_untranslatable_fields
* (optional) Whether untranslatable field values should be kept or copied
- * from the default revision when generating a merged revision.
+ * from the default revision when generating a merged revision. Defaults to
+ * TRUE if the provided entity is the default translation and untranslatable
+ * fields should only affect the default translation, FALSE otherwise.
*
* @return \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface
* A new translatable entity revision object.
diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php
index b4eda00..ac13733 100644
--- a/core/lib/Drupal/Core/Entity/entity.api.php
+++ b/core/lib/Drupal/Core/Entity/entity.api.php
@@ -910,6 +910,54 @@ function hook_ENTITY_TYPE_create(\Drupal\Core\Entity\EntityInterface $entity) {
}
/**
+ * Respond to entity revision creation.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $new_revision
+ * The new revision that was created.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The original entity that was used to create the revision from.
+ * @param bool|null $keep_untranslatable_fields
+ * Whether untranslatable field values were kept (TRUE) or copied from the
+ * default revision (FALSE) when generating a merged revision. If no value was
+ * explicitly specified (NULL), a default value of TRUE should be assumed if
+ * the provided entity is the default translation and untranslatable fields
+ * should only affect the default translation, FALSE otherwise.
+ *
+ * @ingroup entity_crud
+ * @see \Drupal\Core\Entity\RevisionableStorageInterface::createRevision()
+ * @see \Drupal\Core\Entity\TranslatableRevisionableStorageInterface::createRevision()
+ */
+function hook_entity_revision_create(Drupal\Core\Entity\EntityInterface $new_revision, Drupal\Core\Entity\EntityInterface $entity, $keep_untranslatable_fields) {
+ // Retain the value from an untranslatable field, which are by default
+ // synchronized from the default revision.
+ $new_revision->set('untranslatable_field', $entity->get('untranslatable_field'));
+}
+
+/**
+ * Respond to entity revision creation.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $new_revision
+ * The new revision that was created.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The original entity that was used to create the revision from.
+ * @param bool|null $keep_untranslatable_fields
+ * Whether untranslatable field values were kept (TRUE) or copied from the
+ * default revision (FALSE) when generating a merged revision. If no value was
+ * explicitly specified (NULL), a default value of TRUE should be assumed if
+ * the provided entity is the default translation and untranslatable fields
+ * should only affect the default translation, FALSE otherwise.
+ *
+ * @ingroup entity_crud
+ * @see \Drupal\Core\Entity\RevisionableStorageInterface::createRevision()
+ * @see \Drupal\Core\Entity\TranslatableRevisionableStorageInterface::createRevision()
+ */
+function hook_ENTITY_TYPE_revision_create(Drupal\Core\Entity\EntityInterface $new_revision, Drupal\Core\Entity\EntityInterface $entity, $keep_untranslatable_fields) {
+ // Retain the value from an untranslatable field, which are by default
+ // synchronized from the default revision.
+ $new_revision->set('untranslatable_field', $entity->get('untranslatable_field'));
+}
+
+/**
* Act on entities when loaded.
*
* This is a generic load hook called for all entity types loaded via the
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index f98ae10..66a42e2 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -681,6 +681,23 @@ function entity_test_entity_test_mul_langcode_key_translation_delete(EntityInter
}
/**
+ * Implements hook_entity_revision_create().
+ */
+function entity_test_entity_revision_create(EntityInterface $new_revision, EntityInterface $entity, $keep_untranslatable_fields) {
+ _entity_test_record_hooks('entity_revision_create', ['new_revision' => $new_revision, 'entity' => $entity, 'keep_untranslatable_fields' => $keep_untranslatable_fields]);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_revision_create() for 'entity_test_mulrev'.
+ */
+function entity_test_entity_test_mulrev_revision_create(EntityInterface $new_revision, EntityInterface $entity, $keep_untranslatable_fields) {
+ if ($new_revision->get('name')->value == 'revision_create_test_it') {
+ $new_revision->set('name', 'revision_create_test_it_altered');
+ }
+ _entity_test_record_hooks('entity_test_mulrev_revision_create', ['new_revision' => $new_revision, 'entity' => $entity, 'keep_untranslatable_fields' => $keep_untranslatable_fields]);
+}
+
+/**
* Field default value callback.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
index 616ee16..d4fbcfc 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
@@ -588,4 +588,58 @@ class EntityDecoupledTranslationRevisionsTest extends EntityKernelTestBase {
$this->assertFalse($en_revision->hasTranslation('it'));
}
+ /**
+ * Checks that the revision create hook works as expected.
+ *
+ * @covers ::createRevision
+ */
+ public function testCreateRevisionHook() {
+ $entity = EntityTestMulRev::create();
+ $entity->get('name')->value = 'revision_create_test_en';
+ $this->storage->save($entity);
+
+ /** @var \Drupal\Core\Entity\ContentEntityInterface $translation */
+ $translation = $entity->addTranslation('it');
+ $translation->set('name', 'revision_create_test_it');
+ /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
+ $revision = $this->storage->createRevision($translation, FALSE, TRUE);
+
+ // Assert that the alter hook can alter the new revision.
+ $this->assertEquals('revision_create_test_it_altered', $revision->get('name')->value);
+
+ // Assert the data passed to the hook.
+ $data = $this->state->get('entity_test.hooks');
+ $this->assertEquals('revision_create_test_it', $data['entity_test_mulrev_revision_create']['entity']->get('name')->value);
+ $this->assertEquals('revision_create_test_it_altered', $data['entity_test_mulrev_revision_create']['new_revision']->get('name')->value);
+ $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
+ $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
+ $this->assertTrue($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
+ $this->assertFalse($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
+ $this->assertTrue($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
+
+ $this->assertEquals('revision_create_test_it', $data['entity_revision_create']['entity']->get('name')->value);
+ $this->assertEquals('revision_create_test_it_altered', $data['entity_revision_create']['new_revision']->get('name')->value);
+ $this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
+ $this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
+ $this->assertTrue($data['entity_revision_create']['entity']->isDefaultRevision());
+ $this->assertFalse($data['entity_revision_create']['new_revision']->isDefaultRevision());
+ $this->assertTrue($data['entity_revision_create']['keep_untranslatable_fields']);
+
+ // Test again with different arguments.
+ $translation->isDefaultRevision(FALSE);
+ $this->storage->createRevision($translation);
+ $data = $this->state->get('entity_test.hooks');
+ $this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
+ $this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
+ $this->assertFalse($data['entity_revision_create']['entity']->isDefaultRevision());
+ $this->assertTrue($data['entity_revision_create']['new_revision']->isDefaultRevision());
+ $this->assertNull($data['entity_revision_create']['keep_untranslatable_fields']);
+
+ $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
+ $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
+ $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
+ $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
+ $this->assertNull($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
+ }
+
}