core/lib/Drupal/Core/Entity/Entity.php | 13 +++++ core/lib/Drupal/Core/Entity/EntityViewBuilder.php | 6 +-- .../Config/Entity/ConfigEntityBaseUnitTest.php | 31 ------------ .../Drupal/Tests/Core/Entity/EntityUnitTest.php | 50 +++++++++++++++++--- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index b3b3546..64704ef 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Entity; +use Drupal\Core\Cache\Cache; use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\Language\Language; use Drupal\Core\Session\AccountInterface; @@ -368,8 +369,15 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { $this->onSaveOrDelete(); if ($update) { + // An existing entity was updated, invalidate its own cache tag. + Cache::invalidateTags(array($this->entityTypeId => array($this->id()))); $this->onUpdateBundleEntity(); } + else { + // A new entity was created, invalidate its listing cache tag. (So the new + // entity appears in listings.) + Cache::invalidateTags(array($this->entityTypeId . 's' => TRUE)); + } } /** @@ -398,6 +406,11 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont foreach ($entities as $entity) { $entity->onSaveOrDelete(); } + + // An entity was deleted, invalidate its own cache tag. + $ids = array_keys($entities); + $entity_type_id = $entities[$ids[0]]->getEntityTypeId(); + Cache::invalidateTags(array($entity_type_id => $ids)); } /** diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php index 7cbadb2..26efb47 100644 --- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php @@ -270,14 +270,12 @@ public function resetCache(array $entities = NULL) { if (isset($entities)) { $tags = array(); foreach ($entities as $entity) { - $id = $entity->id(); - $tags[$this->entityTypeId][$id] = $id; $tags[$this->entityTypeId . '_view_' . $entity->bundle()] = TRUE; } - Cache::deleteTags($tags); + Cache::invalidateTags($tags); } else { - Cache::deleteTags(array($this->entityTypeId . '_view' => TRUE)); + Cache::invalidateTags(array($this->entityTypeId . '_view' => TRUE)); } } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index 1e503d1..b2b2a36 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -255,35 +255,4 @@ public function testGetExportProperties() { } } - /** - * @covers ::postSave - */ - public function testPostSave() { - $this->cacheBackend->expects($this->at(0)) - ->method('invalidateTags') - ->with(array($this->entityTypeId . 's' => TRUE)); - $this->cacheBackend->expects($this->at(1)) - ->method('invalidateTags') - ->with(array($this->entityTypeId => array($this->entityId))); - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - - // A creation should trigger the invalidation of the "listing" cache tag. - $this->entity->postSave($storage, FALSE); - // An update should trigger the invalidation of the "own" cache tag. - $this->entity->postSave($storage, TRUE); - } - - /** - * @covers ::postDelete - */ - public function testPostDelete() { - $this->cacheBackend->expects($this->once()) - ->method('invalidateTags') - ->with(array($this->entityTypeId => array($this->entityId))); - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - - $entities = array($this->entityId => $this->entity); - \Drupal\Core\Config\Entity\ConfigEntityBase::postDelete($storage, $entities); - } - } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php index a467a90..2afc1f0 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php @@ -25,6 +25,13 @@ class EntityUnitTest extends UnitTestCase { protected $entity; /** + * The ID of the the entity under test. + * + * @var string + */ + protected $entityId; + + /** * The entity info used for testing.. * * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject @@ -60,6 +67,13 @@ class EntityUnitTest extends UnitTestCase { protected $uuid; /** + * The mocked cache backend. + * + * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheBackend; + + /** * {@inheritdoc} */ public static function getInfo() { @@ -74,7 +88,7 @@ public static function getInfo() { * {@inheritdoc} */ public function setUp() { - $values = array(); + $this->entityId = $this->randomName(); $this->entityTypeId = $this->randomName(); $this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); @@ -87,11 +101,18 @@ public function setUp() { $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); + $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); + $container = new ContainerBuilder(); $container->set('entity.manager', $this->entityManager); $container->set('uuid', $this->uuid); + $container->set('cache.test', $this->cacheBackend); + $container->setParameter('cache_bins', array('cache.test' => 'test')); \Drupal::setContainer($container); + $values = array( + 'id' => $this->entityId, + ); $this->entity = $this->getMockBuilder('\Drupal\Core\Entity\Entity') ->setConstructorArgs(array($values, $this->entityTypeId)) ->setMethods(array('languageLoad')) @@ -105,8 +126,7 @@ public function setUp() { * @covers ::id */ public function testId() { - // @todo How to test this? - $this->assertNull($this->entity->id()); + $this->assertSame($this->entityId, $this->entity->id()); } /** @@ -264,9 +284,20 @@ public function testPreSave() { * @covers ::postSave */ public function testPostSave() { + $this->cacheBackend->expects($this->at(0)) + ->method('invalidateTags') + ->with(array($this->entityTypeId . 's' => TRUE)); + $this->cacheBackend->expects($this->at(1)) + ->method('invalidateTags') + ->with(array($this->entityTypeId => array($this->entityId))); + // This method is internal, so check for errors on calling it only. $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $this->entity->postSave($storage); + + // A creation should trigger the invalidation of the "listing" cache tag. + $this->entity->postSave($storage, FALSE); + // An update should trigger the invalidation of the "own" cache tag. + $this->entity->postSave($storage, TRUE); } /** @@ -301,16 +332,23 @@ public function testPreDelete() { * @covers ::postDelete */ public function testPostDelete() { + $this->cacheBackend->expects($this->once()) + ->method('invalidateTags') + ->with(array($this->entityTypeId => array($this->entityId))); $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $values = array( + 'id' => $this->entityId, + ); $entity = $this->getMockBuilder('\Drupal\Core\Entity\Entity') + ->setConstructorArgs(array($values, $this->entityTypeId)) ->setMethods(array('onSaveOrDelete')) - ->disableOriginalConstructor() ->getMock(); $entity->expects($this->once()) ->method('onSaveOrDelete'); - $this->entity->postDelete($storage, array($entity)); + $entities = array($this->entityId => $entity); + $this->entity->postDelete($storage, $entities); } /**