diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 064a780..a68ea0d 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -444,8 +444,12 @@ protected function loadMultipleRevisions(array $revision_ids) { $revisions = $this->doLoadMutlipleRevisions($revision_ids); if ($revisions) { - $this->invokeStorageLoadHook($revisions); - $this->postLoad($revisions); + // The hooks are invoked keyed by entity ID so we have to do one by one. + foreach ($revisions as &$revision) { + $data = [$revision->id() => $revision]; + $this->invokeStorageLoadHook($data); + $this->postLoad($data); + } } return $revisions; diff --git a/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module b/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module index 0325dbd..6341ea4 100644 --- a/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module +++ b/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module @@ -6,6 +6,7 @@ */ use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\RevisionableInterface; /** * Implements hook_entity_create(). @@ -344,6 +345,25 @@ function entity_crud_hook_test_user_predelete() { } /** + * Implements hook_entity_revision_delete(). + */ +function entity_crud_hook_test_entity_revision_delete(EntityInterface $entity) { + if ($entity instanceof RevisionableInterface) { + $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId() . ' for revision ID ' . $entity->getRevisionId()); + } + else { + $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId()); + } +} + +/** + * Implements hook_ENTITY_TYPE_revision_delete() for node entities. + */ +function entity_crud_hook_test_node_revision_delete(EntityInterface $entity) { + $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called on revision ID ' . $entity->getRevisionId()); +} + +/** * Implements hook_entity_delete(). */ function entity_crud_hook_test_entity_delete(EntityInterface $entity) { diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php index 935fd7a..6857285 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php @@ -345,6 +345,49 @@ public function testNodeHooks() { 'entity_crud_hook_test_node_delete called', 'entity_crud_hook_test_entity_delete called for type node', )); + + $node = Node::create([ + 'uid' => $account->id(), + 'type' => 'article', + 'title' => 'Test node', + 'status' => 0, + 'promote' => 0, + 'sticky' => 0, + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + 'created' => REQUEST_TIME, + 'changed' => REQUEST_TIME, + ]); + $node->save(); + $first_revision_id = $node->getRevisionId(); + // Create a new revision. + $node->setNewRevision(TRUE); + $node->setPublished(TRUE); + $node->save(); + $second_revision_id = $node->getRevisionId(); + // Create a forward revision. + $node->setNewRevision(TRUE); + $node->setPublished(FALSE); + $node->isDefaultRevision(FALSE); + $node->save(); + $third_revision_id = $node->getRevisionId(); + + $GLOBALS['entity_crud_hook_test'] = array(); + $node->delete(); + + $this->assertHookMessageOrder(array( + 'entity_crud_hook_test_node_revision_delete called on revision ID ' . $first_revision_id, + 'entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $first_revision_id, + 'entity_crud_hook_test_node_revision_delete called on revision ID ' . $third_revision_id, + 'entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $third_revision_id, + 'entity_crud_hook_test_node_predelete called', + 'entity_crud_hook_test_entity_predelete called for type node', + 'entity_crud_hook_test_node_delete called', + 'entity_crud_hook_test_entity_delete called for type node', + )); + + // Ensure default revision is deleted normally. + $this->assertFalse(in_array('entity_crud_hook_test_node_revision_delete called on revision ID ' . $second_revision_id, $GLOBALS['entity_crud_hook_test'], TRUE), 'As the second revision is the default revision if won\'t have the revision delete hooks fired.'); + $this->assertFalse(in_array('entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $second_revision_id, $GLOBALS['entity_crud_hook_test'], TRUE), 'As the second revision is the default revision if won\'t have the revision delete hooks fired.'); } /**