summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2015-01-06 13:25:59 (GMT)
committerNathaniel Catchpole2015-01-06 13:25:59 (GMT)
commit503e46bb6b477a93a2b4186c658d323ffaa0b0d4 (patch)
tree9bf42318eb939846270921bcaacb37f6f5639151
parent370d6fdafe8a5f4bebc4f6fb05210ca495063cdc (diff)
Issue #918538 by Berdir, slashrsm, damiankloip, sun, tobiasb: Decouple cache tags from cache bins
-rw-r--r--core/core.services.yml17
-rw-r--r--core/lib/Drupal/Core/Cache/ApcuBackend.php104
-rw-r--r--core/lib/Drupal/Core/Cache/ApcuBackendFactory.php14
-rw-r--r--core/lib/Drupal/Core/Cache/BackendChain.php15
-rw-r--r--core/lib/Drupal/Core/Cache/Cache.php32
-rw-r--r--core/lib/Drupal/Core/Cache/CacheBackendInterface.php47
-rw-r--r--core/lib/Drupal/Core/Cache/CacheCollector.php2
-rw-r--r--core/lib/Drupal/Core/Cache/CacheTagsChecksumInterface.php62
-rw-r--r--core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php72
-rw-r--r--core/lib/Drupal/Core/Cache/CacheTagsInvalidatorInterface.php29
-rw-r--r--core/lib/Drupal/Core/Cache/ChainedFastBackend.php14
-rw-r--r--core/lib/Drupal/Core/Cache/DatabaseBackend.php210
-rw-r--r--core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php15
-rw-r--r--core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php207
-rw-r--r--core/lib/Drupal/Core/Cache/MemoryBackend.php15
-rw-r--r--core/lib/Drupal/Core/Cache/MemoryBackendFactory.php12
-rw-r--r--core/lib/Drupal/Core/Cache/NullBackend.php10
-rw-r--r--core/lib/Drupal/Core/Cache/PhpBackend.php42
-rw-r--r--core/lib/Drupal/Core/Cache/PhpBackendFactory.php19
-rw-r--r--core/lib/Drupal/Core/Config/CachedStorage.php6
-rw-r--r--core/lib/Drupal/Core/Entity/EntityManager.php4
-rw-r--r--core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php3
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/MenuRouterRebuildSubscriber.php2
-rw-r--r--core/lib/Drupal/Core/Extension/ThemeHandler.php2
-rw-r--r--core/lib/Drupal/Core/Installer/InstallerServiceProvider.php6
-rw-r--r--core/lib/Drupal/Core/Plugin/DefaultPluginManager.php2
-rw-r--r--core/lib/Drupal/Core/Utility/Token.php3
-rw-r--r--core/modules/book/src/BookManager.php4
-rw-r--r--core/modules/config/src/Tests/Storage/CachedStorageTest.php3
-rw-r--r--core/modules/locale/locale.module2
-rw-r--r--core/modules/locale/src/Tests/LocaleTranslationUiTest.php4
-rw-r--r--core/modules/simpletest/src/WebTestBase.php7
-rw-r--r--core/modules/system/core.api.php9
-rw-r--r--core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php2
-rw-r--r--core/modules/system/src/Tests/Cache/BackendChainUnitTest.php2
-rw-r--r--core/modules/system/src/Tests/Cache/ChainedFastBackendUnitTest.php10
-rw-r--r--core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php24
-rw-r--r--core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php2
-rw-r--r--core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php71
-rw-r--r--core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php4
-rw-r--r--core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php3
-rw-r--r--core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php4
-rw-r--r--core/modules/views/src/ViewsData.php2
-rw-r--r--core/modules/views/tests/src/Unit/ViewsDataTest.php21
-rw-r--r--core/modules/views/views.module6
-rw-r--r--core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php6
-rw-r--r--core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php64
-rw-r--r--core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php68
-rw-r--r--core/tests/Drupal/Tests/Core/Cache/CacheTest.php20
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php11
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php35
-rw-r--r--core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php102
-rw-r--r--core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php17
-rw-r--r--core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php11
-rw-r--r--core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php4
-rw-r--r--core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php11
-rw-r--r--core/tests/Drupal/Tests/UnitTestCase.php21
57 files changed, 790 insertions, 726 deletions
diff --git a/core/core.services.yml b/core/core.services.yml
index fca6395..9ab7af7 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -32,6 +32,18 @@ services:
class: Drupal\Core\Cache\TimeZoneCacheContext
tags:
- { name: cache.context}
+ cache_tags.invalidator:
+ parent: container.trait
+ class: Drupal\Core\Cache\CacheTagsInvalidator
+ calls:
+ - [setContainer, ['@service_container']]
+ tags:
+ - { name: service_collector, call: addInvalidator, tag: cache_tags_invalidator }
+ cache_tags.invalidator.checksum:
+ class: Drupal\Core\Cache\DatabaseCacheTagsChecksum
+ arguments: ['@database']
+ tags:
+ - { name: cache_tags_invalidator}
cache.backend.chainedfast:
class: Drupal\Core\Cache\ChainedFastBackendFactory
arguments: ['@settings']
@@ -39,12 +51,13 @@ services:
- [setContainer, ['@service_container']]
cache.backend.database:
class: Drupal\Core\Cache\DatabaseBackendFactory
- arguments: ['@database']
+ arguments: ['@database', '@cache_tags.invalidator.checksum']
cache.backend.apcu:
class: Drupal\Core\Cache\ApcuBackendFactory
- arguments: ['@app.root']
+ arguments: ['@app.root', '@cache_tags.invalidator.checksum']
cache.backend.php:
class: Drupal\Core\Cache\PhpBackendFactory
+ arguments: ['@cache_tags.invalidator.checksum']
cache.bootstrap:
class: Drupal\Core\Cache\CacheBackendInterface
tags:
diff --git a/core/lib/Drupal/Core/Cache/ApcuBackend.php b/core/lib/Drupal/Core/Cache/ApcuBackend.php
index 50fb0fd..9bac79e 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackend.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackend.php
@@ -36,29 +36,11 @@ class ApcuBackend implements CacheBackendInterface {
protected $binPrefix;
/**
- * Prefix for keys holding invalidation cache tags.
+ * The cache tags checksum provider.
*
- * Includes the site-specific prefix in $sitePrefix.
- *
- * @var string
- */
- protected $invalidationsTagsPrefix;
-
- /**
- * Prefix for keys holding invalidation cache tags.
- *
- * Includes the site-specific prefix in $sitePrefix.
- *
- * @var string
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
*/
- protected $deletionsTagsPrefix;
-
- /**
- * A static cache of all tags checked during the request.
- *
- * @var array
- */
- protected static $tagCache = array('deletions' => array(), 'invalidations' => array());
+ protected $checksumProvider;
/**
* Constructs a new ApcuBackend instance.
@@ -67,13 +49,14 @@ class ApcuBackend implements CacheBackendInterface {
* The name of the cache bin.
* @param string $site_prefix
* The prefix to use for all keys in the storage that belong to this site.
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
*/
- public function __construct($bin, $site_prefix) {
+ public function __construct($bin, $site_prefix, CacheTagsChecksumInterface $checksum_provider) {
$this->bin = $bin;
$this->sitePrefix = $site_prefix;
+ $this->checksumProvider = $checksum_provider;
$this->binPrefix = $this->sitePrefix . '::' . $this->bin . '::';
- $this->invalidationsTagsPrefix = $this->sitePrefix . '::itags::';
- $this->deletionsTagsPrefix = $this->sitePrefix . '::dtags::';
}
/**
@@ -163,18 +146,12 @@ class ApcuBackend implements CacheBackendInterface {
}
$cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
- $checksum = $this->checksumTags($cache->tags);
-
- // Check if deleteTags() has been called with any of the entry's tags.
- if ($cache->checksum_deletions != $checksum['deletions']) {
- return FALSE;
- }
// Check expire time.
$cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
// Check if invalidateTags() has been called with any of the entry's tags.
- if ($cache->checksum_invalidations != $checksum['invalidations']) {
+ if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
$cache->valid = FALSE;
}
@@ -196,9 +173,7 @@ class ApcuBackend implements CacheBackendInterface {
$cache->created = round(microtime(TRUE), 3);
$cache->expire = $expire;
$cache->tags = implode(' ', $tags);
- $checksum = $this->checksumTags($tags);
- $cache->checksum_invalidations = $checksum['invalidations'];
- $cache->checksum_deletions = $checksum['deletions'];
+ $cache->checksum = $this->checksumProvider->getCurrentChecksum($tags);
// APC serializes/unserializes any structure itself.
$cache->serialized = 0;
$cache->data = $data;
@@ -283,65 +258,4 @@ class ApcuBackend implements CacheBackendInterface {
}
}
- /**
- * {@inheritdoc}
- */
- public function deleteTags(array $tags) {
- foreach ($tags as $tag) {
- apc_inc($this->deletionsTagsPrefix . $tag, 1, $success);
- if (!$success) {
- apc_store($this->deletionsTagsPrefix . $tag, 1);
- }
- }
- }
-
- /**
- * {@inheritdoc}
- */
- public function invalidateTags(array $tags) {
- foreach ($tags as $tag) {
- apc_inc($this->invalidationsTagsPrefix . $tag, 1, $success);
- if (!$success) {
- apc_store($this->invalidationsTagsPrefix . $tag, 1);
- }
- }
- }
-
- /**
- * Returns the sum total of validations for a given set of tags.
- *
- * @param array $tags
- * Associative array of tags.
- *
- * @return int
- * Sum of all invalidations.
- */
- protected function checksumTags(array $tags) {
- $checksum = array('invalidations' => 0, 'deletions' => 0);
- $query_tags = array('invalidations' => array(), 'deletions' => array());
-
- foreach ($tags as $tag) {
- foreach (array('deletions', 'invalidations') as $type) {
- if (isset(static::$tagCache[$type][$tag])) {
- $checksum[$type] += static::$tagCache[$type][$tag];
- }
- else {
- $query_tags[$type][] = $this->{$type . 'TagsPrefix'} . $tag;
- }
- }
- }
-
- foreach (array('deletions', 'invalidations') as $type) {
- if ($query_tags[$type]) {
- $result = apc_fetch($query_tags[$type]);
- if ($result) {
- static::$tagCache[$type] = array_merge(static::$tagCache[$type], $result);
- $checksum[$type] += array_sum($result);
- }
- }
- }
-
- return $checksum;
- }
-
}
diff --git a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
index ffe5993..bbc4e3d 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
@@ -19,13 +19,23 @@ class ApcuBackendFactory implements CacheFactoryInterface {
protected $sitePrefix;
/**
+ * The cache tags checksum provider.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+ */
+ protected $checksumProvider;
+
+ /**
* Constructs an ApcuBackendFactory object.
*
* @param string $root
* The app root.
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
*/
- public function __construct($root) {
+ public function __construct($root, CacheTagsChecksumInterface $checksum_provider) {
$this->sitePrefix = Crypt::hashBase64($root . '/' . conf_path());
+ $this->checksumProvider = $checksum_provider;
}
/**
@@ -38,7 +48,7 @@ class ApcuBackendFactory implements CacheFactoryInterface {
* The cache backend object for the specified cache bin.
*/
public function get($bin) {
- return new ApcuBackend($bin, $this->sitePrefix);
+ return new ApcuBackend($bin, $this->sitePrefix, $this->checksumProvider);
}
}
diff --git a/core/lib/Drupal/Core/Cache/BackendChain.php b/core/lib/Drupal/Core/Cache/BackendChain.php
index 0cea142..f7681d9 100644
--- a/core/lib/Drupal/Core/Cache/BackendChain.php
+++ b/core/lib/Drupal/Core/Cache/BackendChain.php
@@ -23,7 +23,7 @@ namespace Drupal\Core\Cache;
* @ingroup cache
*/
-class BackendChain implements CacheBackendInterface {
+class BackendChain implements CacheBackendInterface, CacheTagsInvalidatorInterface {
/**
* Ordered list of CacheBackendInterface instances.
@@ -159,15 +159,6 @@ class BackendChain implements CacheBackendInterface {
}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
- */
- public function deleteTags(array $tags) {
- foreach ($this->backends as $backend) {
- $backend->deleteTags($tags);
- }
- }
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
*/
public function deleteAll() {
@@ -199,7 +190,9 @@ class BackendChain implements CacheBackendInterface {
*/
public function invalidateTags(array $tags) {
foreach ($this->backends as $backend) {
- $backend->invalidateTags($tags);
+ if ($backend instanceof CacheTagsInvalidatorInterface) {
+ $backend->invalidateTags($tags);
+ }
}
}
diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php
index ddf444e..4ce3610 100644
--- a/core/lib/Drupal/Core/Cache/Cache.php
+++ b/core/lib/Drupal/Core/Cache/Cache.php
@@ -94,43 +94,13 @@ class Cache {
}
/**
- * Deletes items from all bins with any of the specified tags.
- *
- * Many sites have more than one active cache backend, and each backend may
- * use a different strategy for storing tags against cache items, and
- * deleting cache items associated with a given tag.
- *
- * When deleting a given list of tags, we iterate over each cache backend, and
- * and call deleteTags() on each.
- *
- * @param string[] $tags
- * The list of tags to delete cache items for.
- */
- public static function deleteTags(array $tags) {
- static::validateTags($tags);
- foreach (static::getBins() as $cache_backend) {
- $cache_backend->deleteTags($tags);
- }
- }
-
- /**
* Marks cache items from all bins with any of the specified tags as invalid.
*
- * Many sites have more than one active cache backend, and each backend my use
- * a different strategy for storing tags against cache items, and invalidating
- * cache items associated with a given tag.
- *
- * When invalidating a given list of tags, we iterate over each cache backend,
- * and call invalidateTags() on each.
- *
* @param string[] $tags
* The list of tags to invalidate cache items for.
*/
public static function invalidateTags(array $tags) {
- static::validateTags($tags);
- foreach (static::getBins() as $cache_backend) {
- $cache_backend->invalidateTags($tags);
- }
+ \Drupal::service('cache_tags.invalidator')->invalidateTags($tags);
}
/**
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index 39c8c26..faf2459 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -136,7 +136,6 @@ interface CacheBackendInterface {
*
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
*/
public function delete($cid);
@@ -155,39 +154,16 @@ interface CacheBackendInterface {
*
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
* @see \Drupal\Core\Cache\CacheBackendInterface::delete()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
*/
public function deleteMultiple(array $cids);
/**
- * Deletes items with any of the specified tags.
- *
- * If the cache items are being deleted because they are no longer "fresh",
- * you may consider using invalidateTags() instead. This allows callers to
- * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
- * In some cases an invalid item may be acceptable rather than having to
- * rebuild the cache.
- *
- * @param array $tags
- * Associative array of tags, in the same format that is passed to
- * CacheBackendInterface::set().
- *
- * @see \Drupal\Core\Cache\CacheBackendInterface::set()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
- * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
- */
- public function deleteTags(array $tags);
-
- /**
* Deletes all cache items in a bin.
*
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
* @see \Drupal\Core\Cache\CacheBackendInterface::delete()
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
*/
public function deleteAll();
@@ -202,7 +178,6 @@ interface CacheBackendInterface {
*
* @see \Drupal\Core\Cache\CacheBackendInterface::delete()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
*/
public function invalidate($cid);
@@ -213,44 +188,24 @@ interface CacheBackendInterface {
* Invalid items may be returned in later calls to get(), if the $allow_invalid
* argument is TRUE.
*
- * @param string $cids
+ * @param string[] $cids
* An array of cache IDs to invalidate.
*
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
*/
public function invalidateMultiple(array $cids);
/**
- * Marks cache items with any of the specified tags as invalid.
- *
- * @param array $tags
- * Associative array of tags, in the same format that is passed to
- * CacheBackendInterface::set().
- *
- * @see \Drupal\Core\Cache\CacheBackendInterface::set()
- * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
- */
- public function invalidateTags(array $tags);
-
- /**
* Marks all cache items as invalid.
*
* Invalid items may be returned in later calls to get(), if the $allow_invalid
* argument is TRUE.
*
- * @param string $cids
- * An array of cache IDs to invalidate.
- *
* @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
* @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
- * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
*/
public function invalidateAll();
diff --git a/core/lib/Drupal/Core/Cache/CacheCollector.php b/core/lib/Drupal/Core/Cache/CacheCollector.php
index d80da7d..a6d8ab5 100644
--- a/core/lib/Drupal/Core/Cache/CacheCollector.php
+++ b/core/lib/Drupal/Core/Cache/CacheCollector.php
@@ -280,7 +280,7 @@ abstract class CacheCollector implements CacheCollectorInterface, DestructableIn
public function clear() {
$this->reset();
if ($this->tags) {
- Cache::deleteTags($this->tags);
+ Cache::invalidateTags($this->tags);
}
else {
$this->cache->delete($this->getCid());
diff --git a/core/lib/Drupal/Core/Cache/CacheTagsChecksumInterface.php b/core/lib/Drupal/Core/Cache/CacheTagsChecksumInterface.php
new file mode 100644
index 0000000..c9e3ff0
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagsChecksumInterface.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagsChecksumInterface.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Provides checksums for cache tag invalidations.
+ *
+ * Cache backends can use this to check if any cache tag invalidations happened
+ * for a stored cache item.
+ *
+ * To do so, they can inject the cache_tags.invalidator.checksum service, and
+ * when a cache item is written, store cache tags together with the current
+ * checksum, calculated by getCurrentChecksum(). When a cache item is fetched,
+ * the checksum can be validated with isValid(). The service will return FALSE
+ * if any of those cache tags were invalidated in the meantime.
+ *
+ * @ingroup cache
+ */
+interface CacheTagsChecksumInterface {
+
+ /**
+ * Returns the sum total of validations for a given set of tags.
+ *
+ * Called by a backend when storing a cache item.
+ *
+ * @param string[] $tags
+ * Array of cache tags.
+ *
+ * @return string
+ * Cache tag invalidations checksum.
+ */
+ public function getCurrentChecksum(array $tags);
+
+ /**
+ * Returns whether the checksum is valid for the given cache tags.
+ *
+ * Used when retrieving a cache item in a cache backend, to verify that no
+ * cache tag based invalidation happened.
+ *
+ * @param int $checksum
+ * The checksum that was stored together with the cache item.
+ * @param string[] $tags
+ * The cache tags that were stored together with the cache item.
+ *
+ * @return bool
+ * FALSE if cache tag invalidations happened for the passed in tags since
+ * the cache item was stored, TRUE otherwise.
+ */
+ public function isValid($checksum, array $tags);
+
+ /**
+ * Reset statically cached tags.
+ *
+ * This is only used by tests.
+ */
+ public function reset();
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php b/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php
new file mode 100644
index 0000000..636ce77
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagsInvalidator.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+
+/**
+ * Passes cache tag events to classes that wish to respond to them.
+ */
+class CacheTagsInvalidator implements CacheTagsInvalidatorInterface {
+
+ use ContainerAwareTrait;
+
+ /**
+ * Holds an array of cache tags invalidators.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface[]
+ */
+ protected $invalidators = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags) {
+ // Validate the tags.
+ Cache::validateTags($tags);
+
+ // Notify all added cache tags invalidators.
+ foreach ($this->invalidators as $invalidator) {
+ $invalidator->invalidateTags($tags);
+ }
+
+ // Additionally, notify each cache bin if it implements the service.
+ foreach ($this->getInvalidatorCacheBins() as $bin) {
+ $bin->invalidateTags($tags);
+ }
+ }
+
+ /**
+ * Adds a cache tags invalidator.
+ *
+ * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $invalidator
+ * A cache invalidator.
+ */
+ public function addInvalidator(CacheTagsInvalidatorInterface $invalidator) {
+ $this->invalidators[] = $invalidator;
+ }
+
+ /**
+ * Returns all cache bins that need to be notified about invalidations.
+ *
+ * @return \Drupal\Core\Cache\CacheTagsInvalidatorInterface[]
+ * An array of cache backend objects that implement the invalidator
+ * interface, keyed by their cache bin.
+ */
+ protected function getInvalidatorCacheBins() {
+ $bins = array();
+ foreach ($this->container->getParameter('cache_bins') as $service_id => $bin) {
+ $service = $this->container->get($service_id);
+ if ($service instanceof CacheTagsInvalidatorInterface) {
+ $bins[$bin] = $service;
+ }
+ }
+ return $bins;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagsInvalidatorInterface.php b/core/lib/Drupal/Core/Cache/CacheTagsInvalidatorInterface.php
new file mode 100644
index 0000000..bf63041
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagsInvalidatorInterface.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagsInvalidatorInterface
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Defines required methods for classes wanting to handle cache tag changes.
+ *
+ * Services that implement this interface must add the cache_tags_invalidator
+ * tag to be notified. Cache backends may implement this interface as well, they
+ * will be notified automatically.
+ *
+ * @ingroup cache
+ */
+interface CacheTagsInvalidatorInterface {
+
+ /**
+ * Marks cache items with any of the specified tags as invalid.
+ *
+ * @param string[] $tags
+ * The list of tags for which to invalidate cache items.
+ */
+ public function invalidateTags(array $tags);
+
+}
diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackend.php b/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
index 559cff7..ce5ddd2 100644
--- a/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
+++ b/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
@@ -41,7 +41,7 @@ namespace Drupal\Core\Cache;
*
* @ingroup cache
*/
-class ChainedFastBackend implements CacheBackendInterface {
+class ChainedFastBackend implements CacheBackendInterface, CacheTagsInvalidatorInterface {
/**
* Cache key prefix for the bin-specific entry to track the last write.
@@ -213,14 +213,6 @@ class ChainedFastBackend implements CacheBackendInterface {
/**
* {@inheritdoc}
*/
- public function deleteTags(array $tags) {
- $this->markAsOutdated();
- $this->consistentBackend->deleteTags($tags);
- }
-
- /**
- * {@inheritdoc}
- */
public function deleteAll() {
$this->consistentBackend->deleteAll();
$this->markAsOutdated();
@@ -245,7 +237,9 @@ class ChainedFastBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function invalidateTags(array $tags) {
- $this->consistentBackend->invalidateTags($tags);
+ if ($this->consistentBackend instanceof CacheTagsInvalidatorInterface) {
+ $this->consistentBackend->invalidateTags($tags);
+ }
$this->markAsOutdated();
}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 813c00a..cc08cc5 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -35,19 +35,29 @@ class DatabaseBackend implements CacheBackendInterface {
protected $connection;
/**
+ * The cache tags checksum provider.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+ */
+ protected $checksumProvider;
+
+ /**
* Constructs a DatabaseBackend object.
*
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
* @param string $bin
* The cache bin for which the object is created.
*/
- public function __construct(Connection $connection, $bin) {
+ public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin) {
// All cache tables should be prefixed with 'cache_'.
$bin = 'cache_' . $bin;
$this->bin = $bin;
$this->connection = $connection;
+ $this->checksumProvider = $checksum_provider;
}
/**
@@ -76,7 +86,7 @@ class DatabaseBackend implements CacheBackendInterface {
// ::select() is a much smaller proportion of the request.
$result = array();
try {
- $result = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => array_keys($cid_mapping)));
+ $result = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => array_keys($cid_mapping)));
}
catch (\Exception $e) {
// Nothing to do.
@@ -116,18 +126,11 @@ class DatabaseBackend implements CacheBackendInterface {
$cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
- $checksum = $this->checksumTags($cache->tags);
-
- // Check if deleteTags() has been called with any of the entry's tags.
- if ($cache->checksum_deletions != $checksum['deletions']) {
- return FALSE;
- }
-
// Check expire time.
$cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
- // Check if invalidateTags() has been called with any of the entry's tags.
- if ($cache->checksum_invalidations != $checksum['invalidations']) {
+ // Check if invalidateTags() has been called with any of the items's tags.
+ if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
$cache->valid = FALSE;
}
@@ -174,27 +177,11 @@ class DatabaseBackend implements CacheBackendInterface {
* Actually set the cache.
*/
protected function doSet($cid, $data, $expire, $tags) {
- $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
- $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
- // Remove tags that were already deleted or invalidated during this request
- // from the static caches so that another deletion or invalidation can
- // occur.
- foreach ($tags as $tag) {
- if (isset($deleted_tags[$tag])) {
- unset($deleted_tags[$tag]);
- }
- if (isset($invalidated_tags[$tag])) {
- unset($invalidated_tags[$tag]);
- }
- }
- $checksum = $this->checksumTags($tags);
$fields = array(
- 'serialized' => 0,
'created' => round(microtime(TRUE), 3),
'expire' => $expire,
'tags' => implode(' ', $tags),
- 'checksum_invalidations' => $checksum['invalidations'],
- 'checksum_deletions' => $checksum['deletions'],
+ 'checksum' => $this->checksumProvider->getCurrentChecksum($tags),
);
if (!is_string($data)) {
$fields['data'] = serialize($data);
@@ -215,9 +202,6 @@ class DatabaseBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function setMultiple(array $items) {
- $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
- $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
-
// Use a transaction so that the database can write the changes in a single
// commit.
$transaction = $this->connection->startTransaction();
@@ -229,7 +213,7 @@ class DatabaseBackend implements CacheBackendInterface {
$query = $this->connection
->insert($this->bin)
- ->fields(array('cid', 'data', 'expire', 'created', 'serialized', 'tags', 'checksum_invalidations', 'checksum_deletions'));
+ ->fields(array('cid', 'data', 'expire', 'created', 'serialized', 'tags', 'checksum'));
foreach ($items as $cid => $item) {
$item += array(
@@ -242,27 +226,12 @@ class DatabaseBackend implements CacheBackendInterface {
// Sort the cache tags so that they are stored consistently in the DB.
sort($item['tags']);
- // Remove tags that were already deleted or invalidated during this
- // request from the static caches so that another deletion or
- // invalidation can occur.
- foreach ($item['tags'] as $tag) {
- if (isset($deleted_tags[$tag])) {
- unset($deleted_tags[$tag]);
- }
- if (isset($invalidated_tags[$tag])) {
- unset($invalidated_tags[$tag]);
- }
- }
-
- $checksum = $this->checksumTags($item['tags']);
-
$fields = array(
'cid' => $cid,
'expire' => $item['expire'],
'created' => round(microtime(TRUE), 3),
'tags' => implode(' ', $item['tags']),
- 'checksum_invalidations' => $checksum['invalidations'],
- 'checksum_deletions' => $checksum['deletions'],
+ 'checksum' => $this->checksumProvider->getCurrentChecksum($item['tags']),
);
if (!is_string($item['data'])) {
@@ -317,32 +286,6 @@ class DatabaseBackend implements CacheBackendInterface {
}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
- */
- public function deleteTags(array $tags) {
- $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
- $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
- foreach ($tags as $tag) {
- // Only delete tags once per request unless they are written again.
- if (isset($deleted_tags[$tag])) {
- continue;
- }
- $deleted_tags[$tag] = TRUE;
- unset($tag_cache[$tag]);
- try {
- $this->connection->merge('cachetags')
- ->insertFields(array('deletions' => 1))
- ->expression('deletions', 'deletions + 1')
- ->key('tag', $tag)
- ->execute();
- }
- catch (\Exception $e) {
- $this->catchException($e, 'cachetags');
- }
- }
- }
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
*/
public function deleteAll() {
@@ -386,32 +329,6 @@ class DatabaseBackend implements CacheBackendInterface {
}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
- */
- public function invalidateTags(array $tags) {
- try {
- $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
- $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
- foreach ($tags as $tag) {
- // Only invalidate tags once per request unless they are written again.
- if (isset($invalidated_tags[$tag])) {
- continue;
- }
- $invalidated_tags[$tag] = TRUE;
- unset($tag_cache[$tag]);
- $this->connection->merge('cachetags')
- ->insertFields(array('invalidations' => 1))
- ->expression('invalidations', 'invalidations + 1')
- ->key('tag', $tag)
- ->execute();
- }
- }
- catch (\Exception $e) {
- $this->catchException($e, 'cachetags');
- }
- }
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
*/
public function invalidateAll() {
@@ -443,40 +360,6 @@ class DatabaseBackend implements CacheBackendInterface {
}
/**
- * Returns the sum total of validations for a given set of tags.
- *
- * @param array $tags
- * Array of cache tags.
- *
- * @return int
- * Sum of all invalidations.
- */
- protected function checksumTags(array $tags) {
- $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-
- $checksum = array(
- 'invalidations' => 0,
- 'deletions' => 0,
- );
-
- $query_tags = array_diff($tags, array_keys($tag_cache));
- if ($query_tags) {
- $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cachetags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
- $tag_cache += $db_tags;
-
- // Fill static cache with empty objects for tags not found in the database.
- $tag_cache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), $checksum);
- }
-
- foreach ($tags as $tag) {
- $checksum['invalidations'] += $tag_cache[$tag]['invalidations'];
- $checksum['deletions'] += $tag_cache[$tag]['deletions'];
- }
-
- return $checksum;
- }
-
- /**
* {@inheritdoc}
*/
public function removeBin() {
@@ -496,11 +379,7 @@ class DatabaseBackend implements CacheBackendInterface {
$database_schema = $this->connection->schema();
if (!$database_schema->tableExists($this->bin)) {
$schema_definition = $this->schemaDefinition();
- $database_schema->createTable($this->bin, $schema_definition['bin']);
- // If the bin doesn't exist, the cache tags table may also not exist.
- if (!$database_schema->tableExists('cachetags')) {
- $database_schema->createTable('cachetags', $schema_definition['cachetags']);
- }
+ $database_schema->createTable($this->bin, $schema_definition);
return TRUE;
}
}
@@ -516,14 +395,16 @@ class DatabaseBackend implements CacheBackendInterface {
/**
* Act on an exception when cache might be stale.
*
- * If the {cachetags} table does not yet exist, that's fine but if the table
- * exists and yet the query failed, then the cache is stale and the
- * exception needs to propagate.
+ * If the table does not yet exist, that's fine, but if the table exists and
+ * yet the query failed, then the cache is stale and the exception needs to
+ * propagate.
*
* @param $e
* The exception.
* @param string|null $table_name
- * The table name, defaults to $this->bin. Can be cachetags.
+ * The table name. Defaults to $this->bin.
+ *
+ * @throws \Exception
*/
protected function catchException(\Exception $e, $table_name = NULL) {
if ($this->connection->schema()->tableExists($table_name ?: $this->bin)) {
@@ -552,10 +433,10 @@ class DatabaseBackend implements CacheBackendInterface {
}
/**
- * Defines the schema for the {cache_*} bin and {cachetags} tables.
+ * Defines the schema for the {cache_*} bin tables.
*/
public function schemaDefinition() {
- $schema['bin'] = array(
+ $schema = array(
'description' => 'Storage for the cache API.',
'fields' => array(
'cid' => array(
@@ -599,17 +480,11 @@ class DatabaseBackend implements CacheBackendInterface {
'size' => 'big',
'not null' => FALSE,
),
- 'checksum_invalidations' => array(
- 'description' => 'The tag invalidation sum when this entry was saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'checksum_deletions' => array(
- 'description' => 'The tag deletion sum when this entry was saved.',
- 'type' => 'int',
+ 'checksum' => array(
+ 'description' => 'The tag invalidation checksum when this entry was saved.',
+ 'type' => 'varchar',
+ 'length' => 255,
'not null' => TRUE,
- 'default' => 0,
),
),
'indexes' => array(
@@ -617,31 +492,6 @@ class DatabaseBackend implements CacheBackendInterface {
),
'primary key' => array('cid'),
);
- $schema['cachetags'] = array(
- 'description' => 'Cache table for tracking cache tags related to the cache bin.',
- 'fields' => array(
- 'tag' => array(
- 'description' => 'Namespace-prefixed tag string.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'invalidations' => array(
- 'description' => 'Number incremented when the tag is invalidated.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'deletions' => array(
- 'description' => 'Number incremented when the tag is deleted.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'primary key' => array('tag'),
- );
return $schema;
}
}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
index 1d70164..59b0b22 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -19,12 +19,23 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
protected $connection;
/**
+ * The cache tags checksum provider.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+ */
+ protected $checksumProvider;
+
+ /**
* Constructs the DatabaseBackendFactory object.
*
* @param \Drupal\Core\Database\Connection $connection
+ * Database connection
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
*/
- function __construct(Connection $connection) {
+ function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider) {
$this->connection = $connection;
+ $this->checksumProvider = $checksum_provider;
}
/**
@@ -37,7 +48,7 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
* The cache backend object for the specified cache bin.
*/
function get($bin) {
- return new DatabaseBackend($this->connection, $bin);
+ return new DatabaseBackend($this->connection, $this->checksumProvider, $bin);
}
}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php b/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php
new file mode 100644
index 0000000..cbfab04
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\DatabaseCacheTagsChecksum.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\SchemaObjectExistsException;
+
+/**
+ * Cache tags invalidations checksum implementation that uses the database.
+ */
+class DatabaseCacheTagsChecksum implements CacheTagsChecksumInterface, CacheTagsInvalidatorInterface {
+
+ /**
+ * The database connection.
+ *
+ * @var \Drupal\Core\Database\Connection
+ */
+ protected $connection;
+
+ /**
+ * Contains already loaded cache invalidations from the database.
+ *
+ * @var array
+ */
+ protected $tagCache = array();
+
+ /**
+ * A list of tags that have already been invalidated in this request.
+ *
+ * Used to prevent the invalidation of the same cache tag multiple times.
+ *
+ * @var array
+ */
+ protected $invalidatedTags = array();
+
+ /**
+ * Constructs a DatabaseCacheTagsChecksum object.
+ *
+ * @param \Drupal\Core\Database\Connection $connection
+ * The database connection.
+ */
+ public function __construct(Connection $connection) {
+ $this->connection = $connection;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags) {
+ try {
+ foreach ($tags as $tag) {
+ // Only invalidate tags once per request unless they are written again.
+ if (isset($this->invalidatedTags[$tag])) {
+ continue;
+ }
+ $this->invalidatedTags[$tag] = TRUE;
+ unset($this->tagCache[$tag]);
+ $this->connection->merge('cachetags')
+ ->insertFields(array('invalidations' => 1))
+ ->expression('invalidations', 'invalidations + 1')
+ ->key('tag', $tag)
+ ->execute();
+ }
+ }
+ catch (\Exception $e) {
+ // Create the cache table, which will be empty. This fixes cases during
+ // core install where cache tags are invalidated before the table is
+ // created.
+ if (!$this->ensureTableExists()) {
+ $this->catchException($e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCurrentChecksum(array $tags) {
+ // Remove tags that were already invalidated during this request from the
+ // static caches so that another invalidation can occur later in the same
+ // request. Without that, written cache items would not be invalidated
+ // correctly.
+ foreach ($tags as $tag) {
+ unset($this->invalidatedTags[$tag]);
+ }
+ return $this->calculateChecksum($tags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isValid($checksum, array $tags) {
+ return $checksum == $this->calculateChecksum($tags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateChecksum(array $tags) {
+ $checksum = 0;
+
+ $query_tags = array_diff($tags, array_keys($this->tagCache));
+ if ($query_tags) {
+ $db_tags = array();
+ try {
+ $db_tags = $this->connection->query('SELECT tag, invalidations FROM {cachetags} WHERE tag IN (:tags)', array(':tags' => $query_tags))
+ ->fetchAllKeyed();
+ $this->tagCache += $db_tags;
+ }
+ catch (\Exception $e) {
+ // If the table does not exist yet, create.
+ if (!$this->ensureTableExists()) {
+ $this->catchException($e);
+ }
+ }
+ // Fill static cache with empty objects for tags not found in the database.
+ $this->tagCache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), 0);
+ }
+
+ foreach ($tags as $tag) {
+ $checksum += $this->tagCache[$tag];
+ }
+
+ return $checksum;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset() {
+ $this->tagCache = array();
+ $this->invalidatedTags = array();
+ }
+
+ /**
+ * Check if the cache tags table exists and create it if not.
+ */
+ protected function ensureTableExists() {
+ try {
+ $database_schema = $this->connection->schema();
+ // Create the cache tags table if it does not exist.
+ if (!$database_schema->tableExists('cachetags')) {
+ $schema_definition = $this->schemaDefinition();
+ $database_schema->createTable('cachetags', $schema_definition);
+
+ return TRUE;
+ }
+ }
+ // If another process has already created the cachetags table, attempting to
+ // recreate it will throw an exception. In this case just catch the
+ // exception and do nothing.
+ catch (SchemaObjectExistsException $e) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Defines the schema for the {cachetags} table.
+ */
+ public function schemaDefinition() {
+ $schema = array(
+ 'description' => 'Cache table for tracking cache tag invalidations.',
+ 'fields' => array(
+ 'tag' => array(
+ 'description' => 'Namespace-prefixed tag string.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'invalidations' => array(
+ 'description' => 'Number incremented when the tag is invalidated.',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ ),
+ 'primary key' => array('tag'),
+ );
+ return $schema;
+ }
+
+ /**
+ * Act on an exception when cache might be stale.
+ *
+ * If the {cachetags} table does not yet exist, that's fine but if the table
+ * exists and yet the query failed, then the cache is stale and the
+ * exception needs to propagate.
+ *
+ * @param \Exception $e
+ * The exception.
+ *
+ * @throws \Exception
+ */
+ protected function catchException(\Exception $e) {
+ if ($this->connection->schema()->tableExists('cachetags')) {
+ throw $e;
+ }
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index 23fddc5..5d7cfab 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -17,7 +17,7 @@ namespace Drupal\Core\Cache;
*
* @ingroup cache
*/
-class MemoryBackend implements CacheBackendInterface {
+class MemoryBackend implements CacheBackendInterface, CacheTagsInvalidatorInterface {
/**
* Array to store cache objects.
@@ -144,17 +144,6 @@ class MemoryBackend implements CacheBackendInterface {
}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
- */
- public function deleteTags(array $tags) {
- foreach ($this->cache as $cid => $item) {
- if (array_intersect($tags, $item->tags)) {
- unset($this->cache[$cid]);
- }
- }
- }
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
*/
public function deleteAll() {
@@ -180,7 +169,7 @@ class MemoryBackend implements CacheBackendInterface {
}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
+ * {@inheritdoc}
*/
public function invalidateTags(array $tags) {
foreach ($this->cache as $cid => $item) {
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
index c9e288d..53e5b07 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
@@ -10,10 +10,20 @@ namespace Drupal\Core\Cache;
class MemoryBackendFactory implements CacheFactoryInterface {
/**
+ * Instantiated memory cache bins.
+ *
+ * @var \Drupal\Core\Cache\MemoryBackend[]
+ */
+ protected $bins = array();
+
+ /**
* {@inheritdoc}
*/
function get($bin) {
- return new MemoryBackend($bin);
+ if (!isset($this->bins[$bin])) {
+ $this->bins[$bin] = new MemoryBackend($bin);
+ }
+ return $this->bins[$bin];
}
}
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index d27bc13..852da7b 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -70,11 +70,6 @@ class NullBackend implements CacheBackendInterface {
public function deleteAll() {}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
- */
- public function deleteTags(array $tags) {}
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
*/
public function invalidate($cid) {}
@@ -85,11 +80,6 @@ class NullBackend implements CacheBackendInterface {
public function invalidateMultiple(array $cids) {}
/**
- * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
- */
- public function invalidateTags(array $tags) {}
-
- /**
* Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
*/
public function invalidateAll() {}
diff --git a/core/lib/Drupal/Core/Cache/PhpBackend.php b/core/lib/Drupal/Core/Cache/PhpBackend.php
index e188ffb..b665e86 100644
--- a/core/lib/Drupal/Core/Cache/PhpBackend.php
+++ b/core/lib/Drupal/Core/Cache/PhpBackend.php
@@ -36,13 +36,23 @@ class PhpBackend implements CacheBackendInterface {
protected $cache = array();
/**
+ * The cache tags checksum provider.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+ */
+ protected $checksumProvider;
+
+ /**
* Constructs a PhpBackend object.
*
* @param string $bin
* The cache bin for which the object is created.
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
*/
- public function __construct($bin) {
+ public function __construct($bin, CacheTagsChecksumInterface $checksum_provider) {
$this->bin = 'cache_' . $bin;
+ $this->checksumProvider = $checksum_provider;
}
/**
@@ -122,6 +132,11 @@ class PhpBackend implements CacheBackendInterface {
// Check expire time.
$cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
+ // Check if invalidateTags() has been called with any of the item's tags.
+ if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
+ $cache->valid = FALSE;
+ }
+
if (!$allow_invalid && !$cache->valid) {
return FALSE;
}
@@ -140,6 +155,7 @@ class PhpBackend implements CacheBackendInterface {
'created' => round(microtime(TRUE), 3),
'expire' => $expire,
'tags' => array_unique($tags),
+ 'checksum' => $this->checksumProvider->getCurrentChecksum($tags),
);
$this->writeItem($this->normalizeCid($cid), $item);
}
@@ -163,18 +179,6 @@ class PhpBackend implements CacheBackendInterface {
/**
* {@inheritdoc}
*/
- public function deleteTags(array $tags) {
- foreach ($this->storage()->listAll() as $cidhash) {
- $item = $this->getByHash($cidhash);
- if (is_object($item) && array_intersect($tags, $item->tags)) {
- $this->delete($item->cid);
- }
- }
- }
-
- /**
- * {@inheritdoc}
- */
public function deleteAll() {
$this->storage()->deleteAll();
}
@@ -211,18 +215,6 @@ class PhpBackend implements CacheBackendInterface {
/**
* {@inheritdoc}
*/
- public function invalidateTags(array $tags) {
- foreach ($this->storage()->listAll() as $cidhash) {
- $item = $this->getByHash($cidhash);
- if ($item && array_intersect($tags, $item->tags)) {
- $this->invalidate($item->cid);
- }
- }
- }
-
- /**
- * {@inheritdoc}
- */
public function invalidateAll() {
foreach($this->storage()->listAll() as $cidhash) {
$this->invalidatebyHash($cidhash);
diff --git a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
index 0801b72..dde93d4 100644
--- a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
@@ -10,6 +10,23 @@ namespace Drupal\Core\Cache;
class PhpBackendFactory implements CacheFactoryInterface {
/**
+ * The cache tags checksum provider.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+ */
+ protected $checksumProvider;
+
+ /**
+ * Constructs a PhpBackendFactory object.
+ *
+ * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
+ * The cache tags checksum provider.
+ */
+ public function __construct(CacheTagsChecksumInterface $checksum_provider) {
+ $this->checksumProvider = $checksum_provider;
+ }
+
+ /**
* Gets PhpBackend for the specified cache bin.
*
* @param $bin
@@ -19,7 +36,7 @@ class PhpBackendFactory implements CacheFactoryInterface {
* The cache backend object for the specified cache bin.
*/
function get($bin) {
- return new PhpBackend($bin);
+ return new PhpBackend($bin, $this->checksumProvider);
}
}
diff --git a/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
index b657f66..5023c35 100644
--- a/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -131,7 +131,7 @@ class CachedStorage implements StorageInterface, StorageCacheInterface {
// While not all written data is read back, setting the cache instead of
// just deleting it avoids cache rebuild stampedes.
$this->cache->set($this->getCacheKey($name), $data);
- Cache::deleteTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
+ Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
$this->findByPrefixCache = array();
return TRUE;
}
@@ -146,7 +146,7 @@ class CachedStorage implements StorageInterface, StorageCacheInterface {
// rebuilding the cache before the storage is gone.
if ($this->storage->delete($name)) {
$this->cache->delete($this->getCacheKey($name));
- Cache::deleteTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
+ Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
$this->findByPrefixCache = array();
return TRUE;
}
@@ -162,7 +162,7 @@ class CachedStorage implements StorageInterface, StorageCacheInterface {
if ($this->storage->rename($name, $new_name)) {
$this->cache->delete($this->getCacheKey($name));
$this->cache->delete($this->getCacheKey($new_name));
- Cache::deleteTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
+ Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
$this->findByPrefixCache = array();
return TRUE;
}
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 58f75b7..96365cc 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -686,7 +686,7 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
$this->fieldMapByFieldType = array();
$this->displayModeInfo = array();
$this->extraFields = array();
- Cache::deleteTags(array('entity_field_info'));
+ Cache::invalidateTags(array('entity_field_info'));
// The typed data manager statically caches prototype objects with injected
// definitions, clear those as well.
$this->typedDataManager->clearCachedDefinitions();
@@ -697,7 +697,7 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
*/
public function clearCachedBundles() {
$this->bundleInfo = array();
- Cache::deleteTags(array('entity_bundles'));
+ Cache::invalidateTags(array('entity_bundles'));
// Entity bundles are exposed as data types, clear that cache too.
$this->typedDataManager->clearCachedDefinitions();
}
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index e531d09..af14f6e 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -8,6 +8,7 @@
namespace Drupal\Core\Entity\Sql;
use Drupal\Component\Utility\String;
+use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Database;
@@ -574,7 +575,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
else {
$this->entities = array();
if ($this->entityType->isPersistentlyCacheable()) {
- $this->cacheBackend->deleteTags(array($this->entityTypeId . '_values'));
+ Cache::invalidateTags(array($this->entityTypeId . '_values'));
}
}
}
diff --git a/core/lib/Drupal/Core/EventSubscriber/MenuRouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MenuRouterRebuildSubscriber.php
index 41b5a87..57cc618 100644
--- a/core/lib/Drupal/Core/EventSubscriber/MenuRouterRebuildSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/MenuRouterRebuildSubscriber.php
@@ -57,7 +57,7 @@ class MenuRouterRebuildSubscriber implements EventSubscriberInterface {
*/
public function onRouterRebuild(Event $event) {
$this->menuLinksRebuild();
- Cache::deleteTags(array('local_task'));
+ Cache::invalidateTags(array('local_task'));
}
/**
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 8beb184..89ad503 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -621,7 +621,7 @@ class ThemeHandler implements ThemeHandlerInterface {
// @todo It feels wrong to have the requirement to clear the local tasks
// cache here.
- Cache::deleteTags(array('local_task'));
+ Cache::invalidateTags(array('local_task'));
$this->themeRegistryRebuild();
}
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 6e93561..f9d86f0 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -49,6 +49,12 @@ class InstallerServiceProvider implements ServiceProviderInterface, ServiceModif
$container
->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper');
+ // Remove the cache tags invalidator tag from the cache tags storage, so
+ // that we don't call it when cache tags are invalidated very early in the
+ // installer.
+ $container->getDefinition('cache_tags.invalidator.checksum')
+ ->clearTag('cache_tags_invalidator');
+
// Replace the route builder with an empty implementation.
// @todo Convert installer steps into routes; add an installer.routing.yml.
$definition = $container->getDefinition('router.builder');
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index 5828d33..95928e4 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -161,7 +161,7 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
if ($this->cacheBackend) {
if ($this->cacheTags) {
// Use the cache tags to clear the cache.
- Cache::deleteTags($this->cacheTags);
+ Cache::invalidateTags($this->cacheTags);
}
else {
$this->cacheBackend->delete($this->cacheKey);
diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php
index 0f5d30e..0bf3367 100644
--- a/core/lib/Drupal/Core/Utility/Token.php
+++ b/core/lib/Drupal/Core/Utility/Token.php
@@ -7,6 +7,7 @@
namespace Drupal\Core\Utility;
+use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageInterface;
@@ -346,7 +347,7 @@ class Token {
*/
public function resetInfo() {
$this->tokenInfo = NULL;
- $this->cache->deleteTags(array(
+ Cache::invalidateTags(array(
static::TOKEN_INFO_CACHE_TAG => TRUE,
));
}
diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php
index 376cc69..cc6b8bb 100644
--- a/core/modules/book/src/BookManager.php
+++ b/core/modules/book/src/BookManager.php
@@ -433,7 +433,7 @@ class BookManager implements BookManagerInterface {
}
$this->updateOriginalParent($original);
$this->books = NULL;
- \Drupal::cache('data')->deleteTags(array('bid:' . $original['bid']));
+ Cache::invalidateTags(array('bid:' . $original['bid']));
}
/**
@@ -763,7 +763,7 @@ class BookManager implements BookManagerInterface {
foreach ($affected_bids as $bid) {
$cache_tags[] = 'bid:' . $bid;
}
- \Drupal::cache('data')->deleteTags($cache_tags);
+ Cache::invalidateTags($cache_tags);
return $link;
}
diff --git a/core/modules/config/src/Tests/Storage/CachedStorageTest.php b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
index 11c3599..66f6225 100644
--- a/core/modules/config/src/Tests/Storage/CachedStorageTest.php
+++ b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
@@ -90,7 +90,8 @@ class CachedStorageTest extends ConfigStorageTestBase {
parent::containerBuild($container);
// Use the regular database cache backend to aid testing.
$container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
- ->addArgument(new Reference('database'));
+ ->addArgument(new Reference('database'))
+ ->addArgument(new Reference('cache_tags.invalidator.checksum'));
}
}
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 82cff29..9e09a46 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -986,7 +986,7 @@ function _locale_refresh_translations($langcodes, $lids = array()) {
}
}
// Clear locale cache.
- Cache::deleteTags(array('locale'));
+ Cache::invalidateTags(array('locale'));
}
/**
diff --git a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
index 994eb38..83a967d 100644
--- a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
+++ b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
@@ -136,8 +136,8 @@ class LocaleTranslationUiTest extends WebTestBase {
$this->assertRaw($translation_to_en, 'English translation properly saved.');
// Reset the tag cache on the tester side in order to pick up the call to
- // Cache::deleteTags() on the tested side.
- drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+ // Cache::invalidateTags() on the tested side.
+ \Drupal::service('cache_tags.invalidator.checksum')->reset();
$this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, 't() works for non-English.');
// Refresh the locale() cache to get fresh data from t() below. We are in
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 2bd33fc..af19ada 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -1158,12 +1158,7 @@ abstract class WebTestBase extends TestBase {
*/
protected function refreshVariables() {
// Clear the tag cache.
- // @todo Replace drupal_static() usage within classes and provide a
- // proper interface for invoking reset() on a cache backend:
- // https://www.drupal.org/node/2311945.
- drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
- drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::deletedTags');
- drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::invalidatedTags');
+ \Drupal::service('cache_tags.invalidator.checksum')->reset();
foreach (Cache::getBins() as $backend) {
if (is_callable(array($backend, 'reset'))) {
$backend->reset();
diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php
index ad73fa0..78ffb9b 100644
--- a/core/modules/system/core.api.php
+++ b/core/modules/system/core.api.php
@@ -468,10 +468,10 @@
* - An array of values. For example, the "node" tag indicates that particular
* node's data is present in the cache item, so its value is an array of node
* IDs.
- * Data that has been tagged can be deleted or invalidated as a group: no matter
+ * Data that has been tagged can be invalidated as a group: no matter
* the Cache ID (cid) of the cache item, no matter in which cache bin a cache
* item lives; as long as it is tagged with a certain cache tag, it will be
- * deleted or invalidated.
+ * invalidated.
*
* Because of that, cache tags are a solution to the cache invalidation problem:
* - For caching to be effective, each cache item must only be invalidated when
@@ -495,8 +495,7 @@
* );
* \Drupal::cache()->set($cid, $data, CacheBackendInterface::CACHE_PERMANENT, $tags);
*
- * // Delete or invalidate all cache items with certain tags.
- * \Drupal\Core\Cache\Cache::deleteTags(array('node:1'));
+ * // Invalidate all cache items with certain tags.
* \Drupal\Core\Cache\Cache::invalidateTags(array('user:1'));
* @endcode
*
@@ -513,8 +512,6 @@
* \Drupal\Core\Entity\Entity::invalidateTagsOnSave() and
* \Drupal\Core\Entity\Entity::invalidateTagsOnDelete().
*
- * @todo Update cache tag deletion in https://drupal.org/node/918538
- *
* @section configuration Configuration
*
* By default cached data is stored in the database. This can be configured
diff --git a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
index da8f565..20fb3a4 100644
--- a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
@@ -34,7 +34,7 @@ class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
}
protected function createCacheBackend($bin) {
- return new ApcuBackend($bin, $this->databasePrefix);
+ return new ApcuBackend($bin, $this->databasePrefix, \Drupal::service('cache_tags.invalidator.checksum'));
}
protected function tearDown() {
diff --git a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
index c19a8ae..4c90701 100644
--- a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
@@ -26,6 +26,8 @@ class BackendChainUnitTest extends GenericCacheBackendUnitTestBase {
->prependBackend(new MemoryBackend('bar'))
->appendBackend(new MemoryBackend('baz'));
+ \Drupal::service('cache_tags.invalidator')->addInvalidator($chain);
+
return $chain;
}
diff --git a/core/modules/system/src/Tests/Cache/ChainedFastBackendUnitTest.php b/core/modules/system/src/Tests/Cache/ChainedFastBackendUnitTest.php
index 32488a6..c34563c 100644
--- a/core/modules/system/src/Tests/Cache/ChainedFastBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/ChainedFastBackendUnitTest.php
@@ -25,9 +25,13 @@ class ChainedFastBackendUnitTest extends GenericCacheBackendUnitTestBase {
* A new ChainedFastBackend object.
*/
protected function createCacheBackend($bin) {
- $consistent_backend = new DatabaseBackend($this->container->get('database'), $bin);
- $fast_backend = new PhpBackend($bin);
- return new ChainedFastBackend($consistent_backend, $fast_backend, $bin);
+ $consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);
+ $fast_backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'));
+ $backend = new ChainedFastBackend($consistent_backend, $fast_backend, $bin);
+ // Explicitly register the cache bin as it can not work through the
+ // cache bin list in the container.
+ \Drupal::service('cache_tags.invalidator')->addInvalidator($backend);
+ return $backend;
}
}
diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
index e2b9d37..24cef4d 100644
--- a/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
+++ b/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
@@ -62,28 +62,4 @@ class DatabaseBackendTagTest extends KernelTestBase {
$this->assertEqual($invalidations_after, $invalidations_before + 1, 'Only one addition cache tag invalidation has occurred after invalidating a tag used in multiple bins.');
}
- public function testTagDeletions() {
- // Create cache entry in multiple bins.
- $tags = array('test_tag:1', 'test_tag:2', 'test_tag:3');
- $bins = array('data', 'bootstrap', 'render');
- foreach ($bins as $bin) {
- $bin = \Drupal::cache($bin);
- $bin->set('test', 'value', Cache::PERMANENT, $tags);
- $this->assertTrue($bin->get('test'), 'Cache item was set in bin.');
- }
-
- $deletions_before = intval(db_select('cachetags')->fields('cachetags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField());
- Cache::deleteTags(array('test_tag:2'));
-
- // Test that cache entry has been deleted in multiple bins.
- foreach ($bins as $bin) {
- $bin = \Drupal::cache($bin);
- $this->assertFalse($bin->get('test'), 'Tag invalidation affected item in bin.');
- }
-
- // Test that only one tag deletion has occurred.
- $deletions_after = intval(db_select('cachetags')->fields('cachetags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField());
- $this->assertEqual($deletions_after, $deletions_before + 1, 'Only one addition cache tag deletion has occurred after deleting a tag used in multiple bins.');
- }
-
}
diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
index bd2952e..e54198b 100644
--- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
@@ -30,7 +30,7 @@ class DatabaseBackendUnitTest extends GenericCacheBackendUnitTestBase {
* A new DatabaseBackend object.
*/
protected function createCacheBackend($bin) {
- return new DatabaseBackend($this->container->get('database'), $bin);
+ return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin);
}
}
diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
index d6f31bf..463be08 100644
--- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -473,66 +473,6 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
}
/**
- * Tests Drupal\Core\Cache\CacheBackendInterface::deleteTags().
- */
- function testDeleteTags() {
- $backend = $this->getCacheBackend();
-
- // Create two cache entries with the same tag and tag value.
- $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
- $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
- $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
- // Delete test_tag of value 1. This should delete both entries.
- $backend->deleteTags(array('test_tag:2'));
- $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleting a cache tag.');
- $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
-
- // Create two cache entries with the same tag and an array tag value.
- $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag:1'));
- $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:1'));
- $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
- // Delete test_tag of value 1. This should delete both entries.
- $backend->deleteTags(array('test_tag:1'));
- $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleted a cache tag.');
- $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
-
- // Create three cache entries with a mix of tags and tag values.
- $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag:1'));
- $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
- $backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo:3'));
- $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
- $backend->deleteTags(array('test_tag_foo:3'));
- $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cached items not matching the tag were not deleted.');
- $this->assertFalse($backend->get('test_cid_invalidated3', TRUE), 'Cache item matching the tag was deleted.');
-
- // Create cache entry in multiple bins. Two cache entries
- // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous
- // tests.
- $tags = array('test_tag:1', 'test_tag:2', 'test_tag:3');
- $bins = array('path', 'bootstrap', 'page');
- foreach ($bins as $bin) {
- $this->getCacheBackend($bin)->set('test', $this->defaultValue, Cache::PERMANENT, $tags);
- $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
- }
-
- // Delete tag in mulitple bins.
- foreach ($bins as $bin) {
- $this->getCacheBackend($bin)->deleteTags(array('test_tag:2'));
- }
-
- // Test that cache entry has been deleted in multple bins.
- foreach ($bins as $bin) {
- $this->assertFalse($this->getCacheBackend($bin)->get('test', TRUE), 'Tag deletion affected item in bin.');
- }
- // Test that the cache entry with a matching tag has been invalidated.
- $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2', TRUE), 'Cache items matching tag were deleted.');
- // Test that the cache entry with without a matching tag still exists.
- $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.');
- }
-
- /**
* Test Drupal\Core\Cache\CacheBackendInterface::deleteAll().
*/
public function testDeleteAll() {
@@ -596,7 +536,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
// Invalidate test_tag of value 1. This should invalidate both entries.
- $backend->invalidateTags(array('test_tag:2'));
+ Cache::invalidateTags(array('test_tag:2'));
$this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after invalidating a cache tag.');
$this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
@@ -606,7 +546,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
// Invalidate test_tag of value 1. This should invalidate both entries.
- $backend->invalidateTags(array('test_tag:1'));
+ Cache::invalidateTags(array('test_tag:1'));
$this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two caches removed after invalidating a cache tag.');
$this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
@@ -615,7 +555,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
$backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo:3'));
$this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
- $backend->invalidateTags(array('test_tag_foo:3'));
+ Cache::invalidateTags(array('test_tag_foo:3'));
$this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cache items not matching the tag were not invalidated.');
$this->assertFalse($backend->get('test_cid_invalidated3'), 'Cached item matching the tag was removed.');
@@ -629,10 +569,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
}
- // Invalidate tag in mulitple bins.
- foreach ($bins as $bin) {
- $this->getCacheBackend($bin)->invalidateTags(array('test_tag:2'));
- }
+ Cache::invalidateTags(array('test_tag:2'));
// Test that cache entry has been invalidated in multple bins.
foreach ($bins as $bin) {
diff --git a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
index 85edfde..0dfeae7 100644
--- a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
@@ -23,6 +23,8 @@ class MemoryBackendUnitTest extends GenericCacheBackendUnitTestBase {
* A new MemoryBackend object.
*/
protected function createCacheBackend($bin) {
- return new MemoryBackend($bin);
+ $backend = new MemoryBackend($bin);
+ \Drupal::service('cache_tags.invalidator')->addInvalidator($backend);
+ return $backend;
}
}
diff --git a/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php b/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
index 57df19b..1751883 100644
--- a/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
@@ -23,7 +23,8 @@ class PhpBackendUnitTest extends GenericCacheBackendUnitTestBase {
* A new MemoryBackend object.
*/
protected function createCacheBackend($bin) {
- return new PhpBackend($bin);
+ $backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'));
+ return $backend;
}
}
diff --git a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
index e2adde7..c866e79 100644
--- a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
+++ b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
@@ -265,9 +265,9 @@ class ToolbarAdminMenuTest extends WebTestBase {
$cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'fr');
$this->assertEqual($cache->tags[2], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".');
- // Log in adminUser and clear the caches for this user using a tag.
+ // Log in the admin user and clear the caches for this user using a tag.
$this->drupalLogin($this->adminUser);
- Cache::deleteTags(array('user:' . $admin_user_id));
+ Cache::invalidateTags(array('user:' . $admin_user_id));
// Assert that no toolbar cache exists for adminUser against the
// language "en".
diff --git a/core/modules/views/src/ViewsData.php b/core/modules/views/src/ViewsData.php
index 796e94b..c90c69e 100644
--- a/core/modules/views/src/ViewsData.php
+++ b/core/modules/views/src/ViewsData.php
@@ -322,6 +322,6 @@ class ViewsData {
$this->storage = array();
$this->allStorage = array();
$this->fullyLoaded = FALSE;
- Cache::deleteTags(array('views_data'));
+ Cache::invalidateTags(array('views_data'));
}
}
diff --git a/core/modules/views/tests/src/Unit/ViewsDataTest.php b/core/modules/views/tests/src/Unit/ViewsDataTest.php
index 0476ffd..9002420 100644
--- a/core/modules/views/tests/src/Unit/ViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/ViewsDataTest.php
@@ -26,6 +26,13 @@ class ViewsDataTest extends UnitTestCase {
protected $cacheBackend;
/**
+ * The mocked cache tags invalidator.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $cacheTagsInvalidator;
+
+ /**
* The mocked module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -57,8 +64,9 @@ class ViewsDataTest extends UnitTestCase {
* {@inheritdoc}
*/
protected function setUp() {
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
- $this->getContainerWithCacheBins($this->cacheBackend);
+ $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
$configs = array();
$configs['views.settings']['skip_cache'] = FALSE;
@@ -250,20 +258,21 @@ class ViewsDataTest extends UnitTestCase {
$this->cacheBackend->expects($this->at(3))
->method('set')
->with("views_data:$random_table_name:en", array());
+ $this->cacheTagsInvalidator->expects($this->once())
+ ->method('invalidateTags')
+ ->with(['views_data']);
$this->cacheBackend->expects($this->at(4))
- ->method('deleteAll');
- $this->cacheBackend->expects($this->at(5))
->method('get')
->with("views_data:en")
->will($this->returnValue(FALSE));
- $this->cacheBackend->expects($this->at(6))
+ $this->cacheBackend->expects($this->at(5))
->method('set')
->with("views_data:en", $expected_views_data);
- $this->cacheBackend->expects($this->at(7))
+ $this->cacheBackend->expects($this->at(6))
->method('get')
->with("views_data:$random_table_name:en")
->will($this->returnValue(FALSE));
- $this->cacheBackend->expects($this->at(8))
+ $this->cacheBackend->expects($this->at(7))
->method('set')
->with("views_data:$random_table_name:en", array());
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index b84d983..d291717 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -470,7 +470,7 @@ function views_field_config_create(FieldConfigInterface $field) {
* Implements hook_ENTITY_TYPE_update() for 'field_config'.
*/
function views_field_config_update(FieldConfigInterface $field) {
- Cache::deleteTags(array('extension' => 'views'));
+ Cache::invalidateTags(array('extension' => 'views'));
\Drupal::cache('render')->deleteAll();
}
@@ -478,7 +478,7 @@ function views_field_config_update(FieldConfigInterface $field) {
* Implements hook_ENTITY_TYPE_delete() for 'field_config'.
*/
function views_field_config_delete(FieldConfigInterface $field) {
- Cache::deleteTags(array('extension' => 'views'));
+ Cache::invalidateTags(array('extension' => 'views'));
\Drupal::cache('render')->deleteAll();
}
@@ -487,7 +487,7 @@ function views_field_config_delete(FieldConfigInterface $field) {
*/
function views_invalidate_cache() {
// Clear Views' info cache entries.
- Cache::deleteTags(array('extension' => 'views'));
+ Cache::invalidateTags(array('extension' => 'views'));
// Set the menu as needed to be rebuilt.
\Drupal::service('router.builder_indicator')->setRebuildNeeded();
diff --git a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
index f977695..6ab09c4 100644
--- a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
@@ -229,7 +229,7 @@ class BackendChainImplementationUnitTest extends UnitTestCase {
'Two cache items were created in all backends.');
// Invalidate test_tag of value 1. This should invalidate both entries.
- $this->chain->deleteTags(array('test_tag:2'));
+ $this->chain->invalidateTags(array('test_tag:2'));
$this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
&& $this->firstBackend->get('test_cid_clear2')
&& $this->secondBackend->get('test_cid_clear1')
@@ -250,7 +250,7 @@ class BackendChainImplementationUnitTest extends UnitTestCase {
'Two cache items were created in all backends.');
// Invalidate test_tag of value 1. This should invalidate both entries.
- $this->chain->deleteTags(array('test_tag:1'));
+ $this->chain->invalidateTags(array('test_tag:1'));
$this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
&& $this->firstBackend->get('test_cid_clear2')
&& $this->secondBackend->get('test_cid_clear1')
@@ -274,7 +274,7 @@ class BackendChainImplementationUnitTest extends UnitTestCase {
&& $this->thirdBackend->get('test_cid_clear3'),
'Three cached items were created in all backends.');
- $this->chain->deleteTags(array('test_tag_foo:3'));
+ $this->chain->invalidateTags(array('test_tag_foo:3'));
$this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
&& $this->firstBackend->get('test_cid_clear2')
&& $this->secondBackend->get('test_cid_clear1')
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
index cf5b3f1..7e91fcb 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
@@ -19,9 +19,16 @@ class CacheCollectorTest extends UnitTestCase {
/**
* The cache backend that should be used.
*
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $cacheBackend;
+
+ /**
+ * The cache tags invalidator.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cache;
+ protected $cacheTagsInvalidator;
/**
* The lock backend that should be used.
@@ -48,12 +55,13 @@ class CacheCollectorTest extends UnitTestCase {
* {@inheritdoc}
*/
protected function setUp() {
- $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
$this->cid = $this->randomMachineName();
- $this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock);
+ $this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock);
- $this->getContainerWithCacheBins($this->cache);
+ $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
}
@@ -90,7 +98,7 @@ class CacheCollectorTest extends UnitTestCase {
$key = $this->randomMachineName();
$value = NULL;
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('invalidate')
->with($this->cid);
$this->collector->set($key, $value);
@@ -115,7 +123,7 @@ class CacheCollectorTest extends UnitTestCase {
'data' => array($key => $value),
'created' => REQUEST_TIME,
);
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('get')
->with($this->cid)
->will($this->returnValue($cache));
@@ -137,7 +145,7 @@ class CacheCollectorTest extends UnitTestCase {
$this->assertTrue($this->collector->has($key));
$this->assertEquals($value, $this->collector->get($key));
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('invalidate')
->with($this->cid);
$this->collector->delete($key);
@@ -151,7 +159,7 @@ class CacheCollectorTest extends UnitTestCase {
public function testUpdateCacheNoChanges() {
$this->lock->expects($this->never())
->method('acquire');
- $this->cache->expects($this->never())
+ $this->cacheBackend->expects($this->never())
->method('set');
// Destruct the object to trigger the update data process.
@@ -175,10 +183,10 @@ class CacheCollectorTest extends UnitTestCase {
->method('acquire')
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
->will($this->returnValue(TRUE));
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('get')
->with($this->cid, FALSE);
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('set')
->with($this->cid, array($key => $value), Cache::PERMANENT, array());
$this->lock->expects($this->once())
@@ -205,7 +213,7 @@ class CacheCollectorTest extends UnitTestCase {
->method('acquire')
->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
->will($this->returnValue(FALSE));
- $this->cache->expects($this->never())
+ $this->cacheBackend->expects($this->never())
->method('set');
// Destruct the object to trigger the update data process.
@@ -223,12 +231,12 @@ class CacheCollectorTest extends UnitTestCase {
'data' => array($key => $value),
'created' => REQUEST_TIME,
);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with($this->cid)
->will($this->returnValue($cache));
- $this->cache->expects($this->at(1))
+ $this->cacheBackend->expects($this->at(1))
->method('invalidate')
->with($this->cid);
$this->collector->set($key, 'new value');
@@ -244,11 +252,11 @@ class CacheCollectorTest extends UnitTestCase {
'data' => array($key => $value),
'created' => REQUEST_TIME + 1,
);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with($this->cid)
->will($this->returnValue($cache));
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('delete')
->with($this->cid);
$this->lock->expects($this->once())
@@ -280,11 +288,11 @@ class CacheCollectorTest extends UnitTestCase {
'data' => array('other key' => 'other value'),
'created' => REQUEST_TIME + 1,
);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with($this->cid)
->will($this->returnValue($cache));
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('set')
->with($this->cid, array('other key' => 'other value', $key => $value), Cache::PERMANENT, array());
$this->lock->expects($this->once())
@@ -306,7 +314,7 @@ class CacheCollectorTest extends UnitTestCase {
'data' => array($key => $value),
'created' => REQUEST_TIME,
);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with($this->cid)
->will($this->returnValue($cache));
@@ -322,10 +330,10 @@ class CacheCollectorTest extends UnitTestCase {
->will($this->returnValue(TRUE));
// The second argument is set to TRUE because we triggered a cache
// invalidation.
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with($this->cid, TRUE);
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('set')
->with($this->cid, array(), Cache::PERMANENT, array());
$this->lock->expects($this->once())
@@ -373,11 +381,11 @@ class CacheCollectorTest extends UnitTestCase {
$this->assertEquals(1, $this->collector->getCacheMisses());
// Clear the collected cache, should call it again.
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('delete')
->with($this->cid);
- $this->cache->expects($this->never())
- ->method('deleteTags');
+ $this->cacheTagsInvalidator->expects($this->never())
+ ->method('invalidateTags');
$this->collector->clear();
$this->assertEquals($value, $this->collector->get($key));
$this->assertEquals(2, $this->collector->getCacheMisses());
@@ -390,7 +398,7 @@ class CacheCollectorTest extends UnitTestCase {
$key = $this->randomMachineName();
$value = $this->randomMachineName();
$tags = array($this->randomMachineName());
- $this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock, $tags);
+ $this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock, $tags);
// Set the data and request it.
$this->collector->setCacheMissData($key, $value);
@@ -401,10 +409,10 @@ class CacheCollectorTest extends UnitTestCase {
$this->assertEquals(1, $this->collector->getCacheMisses());
// Clear the collected cache using the tags, should call it again.
- $this->cache->expects($this->never())
+ $this->cacheBackend->expects($this->never())
->method('delete');
- $this->cache->expects($this->once())
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->once())
+ ->method('invalidateTags')
->with($tags);
$this->collector->clear();
$this->assertEquals($value, $this->collector->get($key));
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php
new file mode 100644
index 0000000..1424b1e
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Cache\CacheTest.
+ */
+
+namespace Drupal\Tests\Core\Cache;
+
+use Drupal\Core\Cache\CacheTagsInvalidator;
+use Drupal\Core\DependencyInjection\Container;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Cache\CacheTagsInvalidator
+ * @group Cache
+ */
+class CacheTagsInvalidatorTest extends UnitTestCase {
+
+ /**
+ * @covers ::invalidateTags
+ *
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cache tags must be strings, array given.
+ */
+ public function testInvalidateTagsWithInvalidTags() {
+ $cache_tags_invalidator = new CacheTagsInvalidator();
+ $cache_tags_invalidator->invalidateTags(['node' => [2, 3, 5, 8, 13]]);
+ }
+
+ /**
+ * @covers ::invalidateTags
+ * @covers ::addInvalidator
+ * @covers ::getBins
+ */
+ public function testInvalidateTags() {
+ $cache_tags_invalidator = new CacheTagsInvalidator();
+
+ // This does not actually implement,
+ // \Drupal\Cache\Cache\CacheBackendInterface but we can not mock from two
+ // interfaces, we would need a test class for that.
+ $invalidator_cache_bin = $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidator');
+ $invalidator_cache_bin->expects($this->once())
+ ->method('invalidateTags')
+ ->with(array('node:1'));
+
+ // We do not have to define that invalidateTags() is never called as the
+ // interface does not define that method, trying to call it would result in
+ // a fatal error.
+ $non_invalidator_cache_bin = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
+
+ $container = new Container();
+ $container->set('cache.invalidator_cache_bin', $invalidator_cache_bin);
+ $container->set('cache.non_invalidator_cache_bin', $non_invalidator_cache_bin);
+ $container->setParameter('cache_bins', array('cache.invalidator_cache_bin' => 'invalidator_cache_bin', 'cache.non_invalidator_cache_bin' => 'non_invalidator_cache_bin'));
+ $cache_tags_invalidator->setContainer($container);
+
+ $invalidator = $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidator');
+ $invalidator->expects($this->once())
+ ->method('invalidateTags')
+ ->with(array('node:1'));
+
+ $cache_tags_invalidator->addInvalidator($invalidator);
+
+ $cache_tags_invalidator->invalidateTags(array('node:1'));
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
index a425572..ea30f1a 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
@@ -117,24 +117,4 @@ class CacheTest extends UnitTestCase {
$this->assertEquals($expected, Cache::buildTags($prefix, $suffixes));
}
- /**
- * @covers ::deleteTags
- *
- * @expectedException \LogicException
- * @expectedExceptionMessage Cache tags must be strings, array given.
- */
- public function testDeleteTags() {
- Cache::deleteTags(['node' => [2, 3, 5, 8, 13]]);
- }
-
- /**
- * @covers ::invalidateTags
- *
- * @expectedException \LogicException
- * @expectedExceptionMessage Cache tags must be strings, array given.
- */
- public function testInvalidateTags() {
- Cache::invalidateTags(['node' => [2, 3, 5, 8, 13]]);
- }
-
}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 2da84fe..0480f52 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -79,9 +79,9 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
/**
* The mocked cache backend.
*
- * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cacheBackend;
+ protected $cacheTagsInvalidator;
/**
* The mocked typed config manager.
@@ -121,7 +121,7 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
->with('en')
->will($this->returnValue(new Language(array('id' => 'en'))));
- $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
@@ -129,9 +129,8 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
$container->set('entity.manager', $this->entityManager);
$container->set('uuid', $this->uuid);
$container->set('language_manager', $this->languageManager);
- $container->set('cache.test', $this->cacheBackend);
+ $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
$container->set('config.typed', $this->typedConfigManager);
- $container->setParameter('cache_bins', array('cache.test' => 'test'));
\Drupal::setContainer($container);
$this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId));
@@ -361,7 +360,7 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
* @depends testSetStatus
*/
public function testDisable() {
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array($this->entityTypeId . ':' . $this->id));
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 3f95ed9..13438a8 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -85,9 +85,9 @@ class ConfigEntityStorageTest extends UnitTestCase {
/**
* The mocked cache backend.
*
- * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cacheBackend;
+ protected $cacheTagsInvalidator;
/**
* The mocked typed config manager.
@@ -154,7 +154,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
->with('test_entity_type')
->will($this->returnValue($this->entityType));
- $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
$this->typedConfigManager->expects($this->any())
@@ -163,8 +163,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('config.typed', $this->typedConfigManager);
- $container->set('cache.test', $this->cacheBackend);
- $container->setParameter('cache_bins', array('cache.test' => 'test'));
+ $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
\Drupal::setContainer($container);
}
@@ -174,7 +173,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
* @covers ::doCreate
*/
public function testCreateWithPredefinedUuid() {
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->moduleHandler->expects($this->at(0))
@@ -199,7 +198,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
* @return \Drupal\Core\Entity\EntityInterface
*/
public function testCreate() {
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->moduleHandler->expects($this->at(0))
@@ -241,7 +240,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->once())
->method('save');
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId . '_list', // List cache tag.
@@ -300,7 +299,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->once())
->method('save');
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId . ':foo', // Own cache tag.
@@ -360,7 +359,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->once())
->method('save');
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId .':bar', // Own cache tag.
@@ -404,7 +403,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
* @expectedExceptionMessage The entity does not have an ID.
*/
public function testSaveInvalid() {
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$entity = $this->getMockEntity();
@@ -429,7 +428,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->never())
->method('save');
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->configFactory->expects($this->once())
@@ -460,7 +459,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->never())
->method('save');
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->configFactory->expects($this->once())
@@ -493,7 +492,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_object->expects($this->once())
->method('save');
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId . '_list', // List cache tag.
@@ -543,7 +542,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
array('id', 'foo'),
)));
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->configFactory->expects($this->at(1))
@@ -700,7 +699,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
* @covers ::deleteRevision
*/
public function testDeleteRevision() {
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
@@ -726,7 +725,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$config_map[] = array("the_config_prefix.$id", $config_object);
}
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId . ':bar', // Own cache tag.
@@ -776,7 +775,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$this->configFactory->expects($this->never())
->method('get');
- $this->cacheBackend->expects($this->never())
+ $this->cacheTagsInvalidator->expects($this->never())
->method('invalidateTags');
$this->entityStorage->delete(array());
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index b7e73f9..8c159ec 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -62,7 +62,14 @@ class EntityManagerTest extends UnitTestCase {
*
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cache;
+ protected $cacheBackend;
+
+ /**
+ * The cache tags invalidator.
+ *
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $cacheTagsInvalidator;
/**
* The language manager.
@@ -118,7 +125,8 @@ class EntityManagerTest extends UnitTestCase {
->with('entity_type_build')
->will($this->returnValue(array()));
- $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$language = $this->getMock('Drupal\Core\Language\LanguageInterface');
$language->expects($this->any())
@@ -138,7 +146,7 @@ class EntityManagerTest extends UnitTestCase {
$this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
$this->controllerResolver = $this->getClassResolverStub();
- $this->container = $this->getContainerWithCacheBins($this->cache);
+ $this->container = $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
@@ -179,7 +187,7 @@ class EntityManagerTest extends UnitTestCase {
->method('getDefinitions')
->will($this->returnValue($definitions));
- $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->installedDefinitions, $this->eventDispatcher);
+ $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cacheBackend, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->installedDefinitions, $this->eventDispatcher);
$this->entityManager->setContainer($this->container);
$this->entityManager->setDiscovery($this->discovery);
}
@@ -192,14 +200,14 @@ class EntityManagerTest extends UnitTestCase {
*/
public function testClearCachedDefinitions() {
$this->setUpEntityManager();
- $this->cache->expects($this->at(0))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(0))
+ ->method('invalidateTags')
->with(array('entity_types'));
- $this->cache->expects($this->at(1))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(1))
+ ->method('invalidateTags')
->with(array('entity_bundles'));
- $this->cache->expects($this->at(2))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(2))
+ ->method('invalidateTags')
->with(array('entity_field_info'));
$this->entityManager->clearCachedDefinitions();
@@ -523,21 +531,21 @@ class EntityManagerTest extends UnitTestCase {
$expected = array('id' => $field_definition);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(1))
+ $this->cacheBackend->expects($this->at(1))
->method('get')
->with('entity_type', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(2))
+ $this->cacheBackend->expects($this->at(2))
->method('set')
->with('entity_type');
- $this->cache->expects($this->at(3))
+ $this->cacheBackend->expects($this->at(3))
->method('set')
->with('entity_base_field_definitions:test_entity_type:en');
- $this->cache->expects($this->at(4))
+ $this->cacheBackend->expects($this->at(4))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
@@ -557,27 +565,27 @@ class EntityManagerTest extends UnitTestCase {
$expected = array('id' => $field_definition);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
- $this->cache->expects($this->at(1))
+ $this->cacheBackend->expects($this->at(1))
->method('get')
->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(2))
+ $this->cacheBackend->expects($this->at(2))
->method('get')
->with('entity_type', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(3))
+ $this->cacheBackend->expects($this->at(3))
->method('set');
- $this->cache->expects($this->at(4))
+ $this->cacheBackend->expects($this->at(4))
->method('set');
- $this->cache->expects($this->at(5))
+ $this->cacheBackend->expects($this->at(5))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
- $this->cache->expects($this->at(6))
+ $this->cacheBackend->expects($this->at(6))
->method('get')
->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
@@ -616,29 +624,29 @@ class EntityManagerTest extends UnitTestCase {
'field_storage' => $field_storage_definition,
);
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
- $this->cache->expects($this->at(1))
+ $this->cacheBackend->expects($this->at(1))
->method('get')
->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(2))
+ $this->cacheBackend->expects($this->at(2))
->method('get')
->with('entity_type', FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(3))
+ $this->cacheBackend->expects($this->at(3))
->method('set')
->with('entity_type');
- $this->cache->expects($this->at(4))
+ $this->cacheBackend->expects($this->at(4))
->method('set')
->with('entity_field_storage_definitions:test_entity_type:en');
- $this->cache->expects($this->at(5))
+ $this->cacheBackend->expects($this->at(5))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
- $this->cache->expects($this->at(6))
+ $this->cacheBackend->expects($this->at(6))
->method('get')
->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
@@ -773,8 +781,8 @@ class EntityManagerTest extends UnitTestCase {
*/
public function testClearCachedFieldDefinitions() {
$this->setUpEntityManager();
- $this->cache->expects($this->once())
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->once())
+ ->method('invalidateTags')
->with(array('entity_field_info'));
$this->typedDataManager->expects($this->once())
->method('clearCachedDefinitions');
@@ -789,8 +797,8 @@ class EntityManagerTest extends UnitTestCase {
*/
public function testClearCachedBundles() {
$this->setUpEntityManager();
- $this->cache->expects($this->once())
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->once())
+ ->method('invalidateTags')
->with(array('entity_bundles'));
$this->entityManager->clearCachedBundles();
@@ -861,30 +869,30 @@ class EntityManagerTest extends UnitTestCase {
'apple' => $apple,
'banana' => $banana,
));
- $this->cache->expects($this->at(0))
+ $this->cacheBackend->expects($this->at(0))
->method('get')
->with("entity_bundle_info:en", FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(1))
+ $this->cacheBackend->expects($this->at(1))
->method('get')
->with("entity_type", FALSE)
->will($this->returnValue(FALSE));
- $this->cache->expects($this->at(2))
+ $this->cacheBackend->expects($this->at(2))
->method('set')
->with("entity_type");
- $this->cache->expects($this->at(3))
+ $this->cacheBackend->expects($this->at(3))
->method('set')
->with("entity_bundle_info:en");
- $this->cache->expects($this->at(4))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(0))
+ ->method('invalidateTags')
->with(array('entity_types'));
- $this->cache->expects($this->at(5))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(1))
+ ->method('invalidateTags')
->with(array('entity_bundles'));
- $this->cache->expects($this->at(6))
- ->method('deleteTags')
+ $this->cacheTagsInvalidator->expects($this->at(2))
+ ->method('invalidateTags')
->with(array('entity_field_info'));
- $this->cache->expects($this->at(7))
+ $this->cacheBackend->expects($this->at(4))
->method('get')
->with("entity_bundle_info:en", FALSE)
->will($this->returnValue((object) array('data' => 'cached data')));
@@ -1017,7 +1025,7 @@ class EntityManagerTest extends UnitTestCase {
->method('getCurrentLanguage')
->will($this->returnValue($language));
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('get')
->with($cache_id);
@@ -1029,7 +1037,7 @@ class EntityManagerTest extends UnitTestCase {
->method('alter')
->with('entity_extra_field_info', $hook_bundle_extra_fields);
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('set')
->with($cache_id, $processed_hook_bundle_extra_fields[$entity_type_id][$bundle]);
@@ -1169,7 +1177,7 @@ class EntityManagerTest extends UnitTestCase {
)
);
$this->setUpEntityManager();
- $this->cache->expects($this->once())
+ $this->cacheBackend->expects($this->once())
->method('get')
->with('entity_field_map')
->will($this->returnValue((object) array('data' => $expected)));
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index a531489..a9fe860 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -73,11 +73,11 @@ class EntityUnitTest extends UnitTestCase {
protected $languageManager;
/**
- * The mocked cache backend.
+ * The mocked cache tags invalidator.
*
- * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cacheBackend;
+ protected $cacheTagsInvalidator;
/**
* The entity values.
@@ -116,14 +116,13 @@ class EntityUnitTest extends UnitTestCase {
->with('en')
->will($this->returnValue(new Language(array('id' => 'en'))));
- $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidator');
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('uuid', $this->uuid);
$container->set('language_manager', $this->languageManager);
- $container->set('cache.test', $this->cacheBackend);
- $container->setParameter('cache_bins', array('cache.test' => 'test'));
+ $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
\Drupal::setContainer($container);
$this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\Entity', array($this->values, $this->entityTypeId));
@@ -398,12 +397,12 @@ class EntityUnitTest extends UnitTestCase {
* @covers ::postSave
*/
public function testPostSave() {
- $this->cacheBackend->expects($this->at(0))
+ $this->cacheTagsInvalidator->expects($this->at(0))
->method('invalidateTags')
->with(array(
$this->entityTypeId . '_list', // List cache tag.
));
- $this->cacheBackend->expects($this->at(1))
+ $this->cacheTagsInvalidator->expects($this->at(1))
->method('invalidateTags')
->with(array(
$this->entityTypeId . ':' . $this->values['id'], // Own cache tag.
@@ -455,7 +454,7 @@ class EntityUnitTest extends UnitTestCase {
* @covers ::postDelete
*/
public function testPostDelete() {
- $this->cacheBackend->expects($this->once())
+ $this->cacheTagsInvalidator->expects($this->once())
->method('invalidateTags')
->with(array(
$this->entityTypeId . ':' . $this->values['id'],
diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
index 300151a..0266229 100644
--- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
@@ -68,11 +68,11 @@ class KeyValueEntityStorageTest extends UnitTestCase {
protected $entityManager;
/**
- * The mocked cache backend.
+ * The mocked cache tags invalidator.
*
- * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $cacheBackend;
+ protected $cacheTagsInvalidator;
/**
* {@inheritdoc}
@@ -111,7 +111,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
->with('test_entity_type')
->will($this->returnValue($this->entityType));
- $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
$this->keyValueStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
@@ -131,8 +131,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('language_manager', $this->languageManager);
- $container->set('cache.test', $this->cacheBackend);
- $container->setParameter('cache_bins', array('cache.test' => 'test'));
+ $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
\Drupal::setContainer($container);
}
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 0a58e81..2c9a015 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -121,8 +121,8 @@ class ThemeHandlerTest extends UnitTestCase {
$logger = $this->getMock('Psr\Log\LoggerInterface');
$this->themeHandler = new TestThemeHandler($this->root, $this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $logger, $this->cssCollectionOptimizer, $this->configInstaller, $this->configManager, $this->routeBuilderIndicator, $this->extensionDiscovery);
- $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
- $this->getContainerWithCacheBins($cache_backend);
+ $cache_tags_invalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
+ $this->getContainerWithCacheTagsInvalidator($cache_tags_invalidator);
}
/**
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
index c2ef841..9cd9375 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
@@ -190,18 +190,17 @@ class DefaultPluginManagerTest extends UnitTestCase {
*/
public function testCacheClearWithTags() {
$cid = $this->randomMachineName();
- $cache_backend = $this->getMockBuilder('Drupal\Core\Cache\MemoryBackend')
- ->disableOriginalConstructor()
- ->getMock();
- $cache_backend
+ $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+ $cache_tags_invalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
+ $cache_tags_invalidator
->expects($this->once())
- ->method('deleteTags')
+ ->method('invalidateTags')
->with(array('tag'));
$cache_backend
->expects($this->never())
->method('deleteMultiple');
- $this->getContainerWithCacheBins($cache_backend);
+ $this->getContainerWithCacheTagsInvalidator($cache_tags_invalidator);
$plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
$plugin_manager->setCacheBackend($cache_backend, $cid, array('tag'));
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 43748e8..1a0ac77 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -8,8 +8,7 @@
namespace Drupal\Tests;
use Drupal\Component\Utility\Random;
-use Drupal\Component\Utility\String;
-use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
/**
@@ -197,24 +196,20 @@ abstract class UnitTestCase extends \PHPUnit_Framework_TestCase {
}
/**
- * Sets up a container with cache bins.
+ * Sets up a container with a cache tags invalidator.
*
- * @param \Drupal\Core\Cache\CacheBackendInterface $backend
- * The cache backend to set up.
+ * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_validator
+ * The cache tags invalidator.
*
* @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
- * The container with the cache bins set up.
+ * The container with the cache tags invalidator service.
*/
- protected function getContainerWithCacheBins(CacheBackendInterface $backend) {
+ protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container->expects($this->any())
- ->method('getParameter')
- ->with('cache_bins')
- ->will($this->returnValue(array('cache.test' => 'test')));
- $container->expects($this->any())
->method('get')
- ->with('cache.test')
- ->will($this->returnValue($backend));
+ ->with('cache_tags.invalidator')
+ ->will($this->returnValue($cache_tags_validator));
\Drupal::setContainer($container);
return $container;