function ContentEntityCacheTest::testCacheInvalidationOnSave

Tests that the correct caches are invalidated when an entity is saved.

File

core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCacheTest.php, line 300

Class

ContentEntityCacheTest
Tests the entity static cache when used by content entities.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testCacheInvalidationOnSave() : void {
  /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
  $entity_type_manager = $this->container
    ->get('entity_type.manager');
  /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
  $storage = $entity_type_manager->getStorage($this->revEntityTypeId);
  // Create an entity and load it by id and revision to ensure that the
  // caches are set.
  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
  $entity = $storage->create();
  $entity->save();
  $first_revision_id = $entity->getRevisionId();
  $storage->loadRevision($first_revision_id);
  $loaded_entity = $storage->load($entity->id());
  $persistent_cache = \Drupal::cache('entity');
  $memory_cache = \Drupal::service('entity.memory_cache');
  $assert_cache_exists = function ($cid) use ($persistent_cache, $memory_cache) {
    $this->assertNotFalse($persistent_cache->get($cid));
    $this->assertNotFalse($memory_cache->get($cid));
  };
  $assert_cache_not_exists = function ($cid) use ($persistent_cache, $memory_cache) {
    $this->assertFalse($persistent_cache->get($cid));
    $this->assertFalse($memory_cache->get($cid));
  };
  $first_revision_cache_id = "values:{$entity->getEntityTypeId()}:revision:" . $first_revision_id;
  $assert_cache_exists($first_revision_cache_id);
  $cache_id = "values:{$entity->getEntityTypeId()}:" . $entity->id();
  $assert_cache_exists($cache_id);
  // Create and load a second entity.
  $other_entity = $storage->create();
  $other_entity->save();
  $storage->loadRevision($other_entity->getRevisionId());
  $other_entity = $storage->load($other_entity->id());
  // Save as a new default revision. Currently, all saves always invalidate
  // all caches for this entity, this may be improved in the future.
  $loaded_entity->setNewRevision();
  $loaded_entity->save();
  $assert_cache_not_exists($first_revision_cache_id);
  $assert_cache_not_exists($cache_id);
  $second_revision_id = $loaded_entity->getRevisionId();
  // Populate the revision cache.
  $storage->loadMultipleRevisions([
    $first_revision_id,
    $second_revision_id,
  ]);
  $second_revision_cache_id = "values:{$entity->getEntityTypeId()}:revision:" . $second_revision_id;
  $assert_cache_exists($first_revision_cache_id);
  $assert_cache_exists($second_revision_cache_id);
  // Save as a new non-default revision. This does not need
  // to invalidate the previous revisions. Entity caches are currently
  // always invalidated, this could be further optimized.
  $loaded_entity = $storage->load($entity->id());
  $this->assertEquals($second_revision_id, $loaded_entity->getRevisionId());
  $loaded_entity->setNewRevision();
  $loaded_entity->isDefaultRevision(FALSE);
  $loaded_entity->save();
  $assert_cache_not_exists($first_revision_cache_id);
  $assert_cache_not_exists($second_revision_cache_id);
  $assert_cache_not_exists($cache_id);
  $this->assertNotEquals($second_revision_id, $loaded_entity->getRevisionId());
  // Update that non-default revision, ensure it remains the non-default
  // revision and that the revision cache has been invalidated for this
  // revision but not the first two revisions.
  $loaded_revision = $storage->loadRevision($loaded_entity->getRevisionId());
  $this->assertFalse($loaded_revision->isDefaultRevision());
  $loaded_revision->isDefaultRevision(FALSE);
  $loaded_revision->save();
  $assert_cache_not_exists($first_revision_cache_id);
  $assert_cache_not_exists($second_revision_cache_id);
  $revision_cache_id = "values:{$entity->getEntityTypeId()}:revision:" . $loaded_revision->getRevisionId();
  $assert_cache_not_exists($revision_cache_id);
  $assert_cache_not_exists($cache_id);
  $loaded_revision = $storage->loadRevision($loaded_revision->getRevisionId());
  $this->assertFalse($loaded_revision->isDefaultRevision());
  // Update that non-default revision to be the new default revision,
  // without saving it as a new revision. This has invalidated all revisions
  // as an optimization.
  $loaded_revision = $storage->loadRevision($loaded_revision->getRevisionId());
  $this->assertFalse($loaded_revision->isDefaultRevision());
  $loaded_entity->isDefaultRevision(TRUE);
  $loaded_entity->save();
  $assert_cache_not_exists($first_revision_cache_id);
  $assert_cache_not_exists($second_revision_cache_id);
  $revision_cache_id = "values:{$entity->getEntityTypeId()}:revision:" . $loaded_revision->getRevisionId();
  $assert_cache_not_exists($revision_cache_id);
  $assert_cache_not_exists($cache_id);
  $loaded_revision = $storage->loadRevision($loaded_revision->getRevisionId());
  $this->assertTrue($loaded_revision->isDefaultRevision());
  // The other entity is still cached.
  $other_revision_cache_id = "values:{$entity->getEntityTypeId()}:revision:" . $other_entity->getRevisionId();
  $assert_cache_exists($other_revision_cache_id);
  $other_cache_id = "values:{$entity->getEntityTypeId()}:" . $other_entity->id();
  $assert_cache_exists($other_cache_id);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.