diff --git a/core/core.services.yml b/core/core.services.yml index 3e2feb6..a666703 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -32,6 +32,15 @@ services: class: Drupal\Core\Cache\TimeZoneCacheContext tags: - { name: cache.context} + cache_tags: + class: Drupal\Core\Cache\CacheTagHandler + tags: + - { name: service_collector } + cache_tag_storage: + class: Drupal\Core\Cache\DatabaseCacheTagStorage + arguments: ['@database'] + tags: + - { name: cache_tags } cache.backend.chainedfast: class: Drupal\Core\Cache\ChainedFastBackendFactory arguments: ['@settings'] @@ -39,12 +48,16 @@ services: - [setContainer, ['@service_container']] cache.backend.database: class: Drupal\Core\Cache\DatabaseBackendFactory - arguments: ['@database'] + arguments: ['@database', '@cache_tag_storage'] cache.backend.apcu: class: Drupal\Core\Cache\ApcuBackendFactory arguments: ['@app.root'] + tags: + - { name: cache_tags } cache.backend.php: class: Drupal\Core\Cache\PhpBackendFactory + tags: + - { name: cache_tags } cache.bootstrap: class: Drupal\Core\Cache\CacheBackendInterface tags: @@ -98,6 +111,7 @@ services: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin, default_backend: cache.backend.chainedfast } + - { name: cache_tags } factory_method: get factory_service: cache_factory arguments: [discovery] diff --git a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php index ffe5993..dd77ed1 100644 --- a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php @@ -9,7 +9,7 @@ use \Drupal\Component\Utility\Crypt; -class ApcuBackendFactory implements CacheFactoryInterface { +class ApcuBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface { /** * The site prefix string. @@ -41,4 +41,43 @@ public function get($bin) { return new ApcuBackend($bin, $this->sitePrefix); } + /** + * 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\CacheTagInvalidationInterface::invalidateTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::delete() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll() + */ + public function deleteTags(array $tags) { + // TODO: Implement deleteTags() method. + } + + /** + * 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\CacheTagInvalidationInterface::deleteTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll() + */ + public function invalidateTags(array $tags) { + // TODO: Implement invalidateTags() method. + } } diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php index ddf444e..b8e6cdc 100644 --- a/core/lib/Drupal/Core/Cache/Cache.php +++ b/core/lib/Drupal/Core/Cache/Cache.php @@ -96,41 +96,25 @@ public static function buildTags($prefix, array $suffixes) { /** * 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) { + // @todo Move to service. static::validateTags($tags); - foreach (static::getBins() as $cache_backend) { - $cache_backend->deleteTags($tags); - } + \Drupal::service('cache_tags')->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) { + // @todo Move to service. static::validateTags($tags); - foreach (static::getBins() as $cache_backend) { - $cache_backend->invalidateTags($tags); - } + \Drupal::service('cache_tags')->invalidateTags($tags); } /** diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 39c8c26..fd1ae87 100644 --- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -18,7 +18,7 @@ * * @ingroup cache */ -interface CacheBackendInterface { +interface CacheBackendInterface extends CacheTagInvalidationInterface { /** * Indicates that the item should never be removed unless explicitly deleted. @@ -161,27 +161,6 @@ public function delete($cid); 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() @@ -224,21 +203,6 @@ public function invalidate($cid); 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 diff --git a/core/lib/Drupal/Core/Cache/CacheTagHandler.php b/core/lib/Drupal/Core/Cache/CacheTagHandler.php new file mode 100644 index 0000000..d439954 --- /dev/null +++ b/core/lib/Drupal/Core/Cache/CacheTagHandler.php @@ -0,0 +1,38 @@ +invalidators as $invalidator) { + $invalidator->invalidateTags($tags); + } + } + + public function deleteTags(array $tags) { + foreach ($this->invalidators as $invalidator) { + $invalidator->deleteTags($tags); + } + } + + public function addHandler(CacheTagInvalidationInterface $service) { + $this->invalidators[] = $service; + } + +} diff --git a/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php b/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php new file mode 100644 index 0000000..288e04b --- /dev/null +++ b/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php @@ -0,0 +1,31 @@ +bin = $bin; $this->connection = $connection; + $this->cacheTagStorage = $cacheTagStorage; } /** @@ -116,7 +126,7 @@ protected function prepareItem($cache, $allow_invalid) { $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array(); - $checksum = $this->checksumTags($cache->tags); + $checksum = $this->cacheTagStorage->checksumTags($cache->tags); // Check if deleteTags() has been called with any of the entry's tags. if ($cache->checksum_deletions != $checksum['deletions']) { @@ -147,10 +157,13 @@ protected function prepareItem($cache, $allow_invalid) { * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) { - Cache::validateTags($tags); - $tags = array_unique($tags); - // Sort the cache tags so that they are stored consistently in the database. - sort($tags); + if ($tags) { + Cache::validateTags($tags); + $tags = array_unique($tags); + // Sort the cache tags so that they are stored consistently in the database. + sort($tags); + $this->cacheTagStorage->onCacheTagsWrite($tags); + } $try_again = FALSE; try { // The bin might not yet exist. @@ -174,20 +187,7 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array * 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); + $checksum = $this->cacheTagStorage->checksumTags($tags); $fields = array( 'serialized' => 0, 'created' => round(microtime(TRUE), 3), @@ -215,9 +215,6 @@ protected function doSet($cid, $data, $expire, $tags) { * {@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(); @@ -237,24 +234,14 @@ public function setMultiple(array $items) { 'tags' => array(), ); - Cache::validateTags($item['tags']); - $item['tags'] = array_unique($item['tags']); - // 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]); - } + if ($item['tags']) { + Cache::validateTags($item['tags']); + $item['tags'] = array_unique($item['tags']); + // Sort the cache tags so that they are stored consistently in the DB. + sort($item['tags']); + $this->cacheTagStorage->onCacheTagsWrite($item['tags']); } - - $checksum = $this->checksumTags($item['tags']); + $checksum = $this->cacheTagStorage->checksumTags($item['tags']); $fields = array( 'cid' => $cid, @@ -319,28 +306,7 @@ public function deleteMultiple(array $cids) { /** * 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'); - } - } - } + public function deleteTags(array $tags) {} /** * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). @@ -386,30 +352,9 @@ public function invalidateMultiple(array $cids) { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + * Implements Drupal\Core\Cache\CacheTagHandlerInterface::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'); - } - } + public function invalidateTags(array $tags) {} /** * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll(). @@ -443,40 +388,6 @@ public function garbageCollection() { } /** - * 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 +407,7 @@ protected function ensureBinExists() { $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 +423,16 @@ protected function ensureBinExists() { /** * Act on an exception when cache might be stale. * - * If the {cachetags} table does not yet exist, that's fine but if the table + * 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 +461,10 @@ protected function normalizeCid($cid) { } /** - * Defines the schema for the {cache_*} bin and {cachetags} tables. + * Defines the schema for the {cache_*} bin table. */ public function schemaDefinition() { - $schema['bin'] = array( + $schema = array( 'description' => 'Storage for the cache API.', 'fields' => array( 'cid' => array( @@ -617,31 +526,6 @@ public function schemaDefinition() { ), '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..2772bab 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php @@ -23,8 +23,9 @@ class DatabaseBackendFactory implements CacheFactoryInterface { * * @param \Drupal\Core\Database\Connection $connection */ - function __construct(Connection $connection) { + function __construct(Connection $connection, CacheTagInvalidationStorageInterface $cacheTagStorage) { $this->connection = $connection; + $this->cacheTagStorage = $cacheTagStorage; } /** @@ -37,7 +38,7 @@ function __construct(Connection $connection) { * The cache backend object for the specified cache bin. */ function get($bin) { - return new DatabaseBackend($this->connection, $bin); + return new DatabaseBackend($this->connection, $this->cacheTagStorage, $bin); } } diff --git a/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php b/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php new file mode 100644 index 0000000..150d073 --- /dev/null +++ b/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php @@ -0,0 +1,247 @@ +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 a cache table is cleared before it is set + // with {cache_render} and {cache_data}. + if (!$this->ensureTableExists()) { + $this->catchException($e); + } + } + } + + /** + * {@inheritdoc} + */ + public function deleteTags(array $tags) { + foreach ($tags as $tag) { + // Only delete tags once per request unless they are written again. + if (isset($this->deletedTags[$tag])) { + continue; + } + $this->deletedTags[$tag] = TRUE; + unset($this->tagCache[$tag]); + try { + $this->connection->merge('cachetags') + ->insertFields(array('deletions' => 1)) + ->expression('deletions', 'deletions + 1') + ->key('tag', $tag) + ->execute(); + } + catch (\Exception $e) { + // Create the cache table, which will be empty. This fixes cases during + // core install where a cache table is cleared before it is set + // with {cache_render} and {cache_data}. + if (!$this->ensureTableExists()) { + $this->catchException($e); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function checksumTags(array $tags) { + $checksum = array( + 'invalidations' => 0, + 'deletions' => 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, deletions FROM {cachetags} WHERE tag IN (:tags)', array(':tags' => $query_tags)) + ->fetchAllAssoc('tag', \PDO::FETCH_ASSOC); + $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)), $checksum); + } + + foreach ($tags as $tag) { + $checksum['invalidations'] += $this->tagCache[$tag]['invalidations']; + $checksum['deletions'] += $this->tagCache[$tag]['deletions']; + } + + return $checksum; + } + + /** + * {@inheritdoc} + */ + public function onCacheTagsWrite(array $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 ($tags as $tag) { + unset($this->deletedTags[$tag]); + unset($this->invalidatedTags[$tag]); + } + } + + /** + * {@inheritdoc} + */ + public function reset() { + $this->tagCache = array(); + $this->deletedTags = 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 cache tags 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 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; + } + + /** + * 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/MemoryBackendFactory.php b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php index c9e288d..6783720 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php @@ -7,13 +7,40 @@ namespace Drupal\Core\Cache; -class MemoryBackendFactory implements CacheFactoryInterface { +class MemoryBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface { + + /** + * 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]; } + /** + * {@inheritdoc} + */ + public function deleteTags(array $tags) { + foreach ($this->bins as $bin) { + $bin->deleteTags($tags); + } + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) { + foreach ($this->bins as $bin) { + $bin->deleteTags($tags); + } + } } diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php index d27bc13..fb898de 100644 --- a/core/lib/Drupal/Core/Cache/NullBackend.php +++ b/core/lib/Drupal/Core/Cache/NullBackend.php @@ -70,7 +70,7 @@ public function deleteMultiple(array $cids) {} public function deleteAll() {} /** - * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). + * Implements Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags(). */ public function deleteTags(array $tags) {} @@ -85,7 +85,7 @@ public function invalidate($cid) {} public function invalidateMultiple(array $cids) {} /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + * Implements Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags(). */ public function invalidateTags(array $tags) {} diff --git a/core/lib/Drupal/Core/Cache/NullBackendFactory.php b/core/lib/Drupal/Core/Cache/NullBackendFactory.php index 0101a8e..b1d9365 100644 --- a/core/lib/Drupal/Core/Cache/NullBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/NullBackendFactory.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Cache; -class NullBackendFactory implements CacheFactoryInterface { +class NullBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface { /** * {@inheritdoc} @@ -16,4 +16,43 @@ function get($bin) { return new NullBackend($bin); } + /** + * 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\CacheTagInvalidationInterface::invalidateTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::delete() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll() + */ + public function deleteTags(array $tags) { + // TODO: Implement deleteTags() method. + } + + /** + * 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\CacheTagInvalidationInterface::deleteTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll() + */ + public function invalidateTags(array $tags) { + // TODO: Implement invalidateTags() method. + } } diff --git a/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php b/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php new file mode 100644 index 0000000..76b4c41 --- /dev/null +++ b/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php @@ -0,0 +1,30 @@ +invalidators[] = $service; + } + +} diff --git a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php index 0801b72..872bf16 100644 --- a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Cache; -class PhpBackendFactory implements CacheFactoryInterface { +class PhpBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface { /** * Gets PhpBackend for the specified cache bin. @@ -22,4 +22,43 @@ function get($bin) { return new PhpBackend($bin); } + /** + * 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\CacheTagInvalidationInterface::invalidateTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::delete() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll() + */ + public function deleteTags(array $tags) { + // TODO: Implement deleteTags() method. + } + + /** + * 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\CacheTagInvalidationInterface::deleteTags() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple() + * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll() + */ + public function invalidateTags(array $tags) { + // TODO: Implement invalidateTags() method. + } } diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php index 6e93561..af823f7 100644 --- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php +++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php @@ -48,6 +48,8 @@ public function register(ContainerBuilder $container) { ->addArgument(new Reference('request_stack')); $container ->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper'); + $container + ->register('cache_tags', 'Drupal\Core\Cache\NullCacheTagHandler'); // Replace the route builder with an empty implementation. // @todo Convert installer steps into routes; add an installer.routing.yml. diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php index 3f5cfdc..e1f4282 100644 --- a/core/modules/book/src/BookManager.php +++ b/core/modules/book/src/BookManager.php @@ -433,7 +433,7 @@ public function deleteFromBook($nid) { } $this->updateOriginalParent($original); $this->books = NULL; - \Drupal::cache('data')->deleteTags(array('bid:' . $original['bid'])); + Cache::deleteTags(array('bid:' . $original['bid'])); } /** @@ -763,7 +763,7 @@ public function saveBookLink(array $link, $new) { foreach ($affected_bids as $bid) { $cache_tags[] = 'bid:' . $bid; } - \Drupal::cache('data')->deleteTags($cache_tags); + Cache::deleteTags($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..2d4e464 100644 --- a/core/modules/config/src/Tests/Storage/CachedStorageTest.php +++ b/core/modules/config/src/Tests/Storage/CachedStorageTest.php @@ -90,7 +90,8 @@ public function containerBuild(ContainerBuilder $container) { 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_tag_storage')); } } diff --git a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php index e9919cd..740bb0d 100644 --- a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php +++ b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php @@ -137,7 +137,7 @@ public function testStringTranslation() { // 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'); + \Drupal::service('cache_tag_storage')->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/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index f26c5d4..7abd200 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -256,7 +256,8 @@ public function containerBuild(ContainerBuilder $container) { $this->container->setParameter('language.default_values', Language::$defaultValues); $container->register('lock', 'Drupal\Core\Lock\NullLockBackend'); - $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory'); + $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory') + ->addTag('cache_tags'); $container ->register('config.storage', 'Drupal\Core\Config\DatabaseStorage') diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index d2b31ae..deda382 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -1148,12 +1148,7 @@ protected function resetAll() { */ 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_tag_storage')->reset(); foreach (Cache::getBins() as $backend) { if (is_callable(array($backend, 'reset'))) { $backend->reset(); diff --git a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php index da8f565..c10f25a 100644 --- a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php +++ b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php @@ -34,7 +34,9 @@ protected function checkRequirements() { } protected function createCacheBackend($bin) { - return new ApcuBackend($bin, $this->databasePrefix); + $backend = new ApcuBackend($bin, $this->databasePrefix); + \Drupal::service('cache_tags')->addHandler($backend); + return $backend; } protected function tearDown() { diff --git a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php index cbfaf16..cc5760b 100644 --- a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php +++ b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php @@ -26,6 +26,8 @@ protected function createCacheBackend($bin) { ->prependBackend(new MemoryBackend('bar')) ->appendBackend(new MemoryBackend('baz')); + \Drupal::service('cache_tags')->addHandler($chain); + return $chain; } } diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php index bd2952e..518383b 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_tag_storage'), $bin); } } diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php index 97d7ccd..5ce1ab5 100644 --- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php +++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php @@ -485,7 +485,7 @@ function testDeleteTags() { $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')); + Cache::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.'); @@ -495,7 +495,7 @@ function testDeleteTags() { $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')); + Cache::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.'); @@ -504,7 +504,7 @@ function testDeleteTags() { $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')); + Cache::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.'); @@ -518,10 +518,7 @@ function testDeleteTags() { $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')); - } + Cache::deleteTags(array('test_tag:2')); // Test that cache entry has been deleted in multple bins. foreach ($bins as $bin) { @@ -597,7 +594,7 @@ function testInvalidateTags() { $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.'); @@ -607,7 +604,7 @@ function testInvalidateTags() { $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.'); @@ -616,7 +613,7 @@ function testInvalidateTags() { $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.'); @@ -630,10 +627,7 @@ function testInvalidateTags() { $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..3a99482 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')->addHandler($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..01b58ca 100644 --- a/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php +++ b/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php @@ -23,7 +23,9 @@ class PhpBackendUnitTest extends GenericCacheBackendUnitTestBase { * A new MemoryBackend object. */ protected function createCacheBackend($bin) { - return new PhpBackend($bin); + $backend = new PhpBackend($bin); + \Drupal::service('cache_tags')->addHandler($backend); + return $backend; } } diff --git a/core/modules/views/tests/src/Unit/ViewsDataTest.php b/core/modules/views/tests/src/Unit/ViewsDataTest.php index 0476ffd..4bd856d 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 tag handler. + * + * @var \Drupal\Core\Cache\CacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheTagHandler; + + /** * 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->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); - $this->getContainerWithCacheBins($this->cacheBackend); + $this->getContainerWithCacheBins($this->cacheTagHandler); $configs = array(); $configs['views.settings']['skip_cache'] = FALSE; @@ -250,20 +258,21 @@ public function testFullAndTableGetCache() { $this->cacheBackend->expects($this->at(3)) ->method('set') ->with("views_data:$random_table_name:en", array()); + $this->cacheTagHandler->expects($this->once()) + ->method('deleteTags') + ->with(['views_data']); $this->cacheBackend->expects($this->at(4)) - ->method('deleteAll'); + ->method('get') + ->with("views_data:en") + ->will($this->returnValue(FALSE)); $this->cacheBackend->expects($this->at(5)) - ->method('get') - ->with("views_data:en") - ->will($this->returnValue(FALSE)); + ->method('set') + ->with("views_data:en", $expected_views_data); $this->cacheBackend->expects($this->at(6)) - ->method('set') - ->with("views_data:en", $expected_views_data); + ->method('get') + ->with("views_data:$random_table_name:en") + ->will($this->returnValue(FALSE)); $this->cacheBackend->expects($this->at(7)) - ->method('get') - ->with("views_data:$random_table_name:en") - ->will($this->returnValue(FALSE)); - $this->cacheBackend->expects($this->at(8)) ->method('set') ->with("views_data:$random_table_name:en", array()); diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php index cf5b3f1..2b53e0a 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php @@ -21,7 +21,14 @@ class CacheCollectorTest extends UnitTestCase { * * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + protected $cacheBackend; + + /** + * The cache tag handler. + * + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheTagHandler; /** * 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->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $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->getContainerWithCacheBins($this->cacheTagHandler); } @@ -90,7 +98,7 @@ public function testSetAndGetNull() { $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 @@ public function testGetFromCache() { '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 @@ public function testDelete() { $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 @@ public function testDelete() { 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 @@ public function testUpdateCache() { ->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 @@ public function testUpdateCacheLockFail() { ->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 @@ public function testUpdateCacheInvalidatedConflict() { '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 @@ public function testUpdateCacheInvalidatedConflict() { '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 @@ public function testUpdateCacheMerge() { '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 @@ public function testUpdateCacheDelete() { '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 @@ public function testUpdateCacheDelete() { ->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,10 +381,10 @@ public function testUpdateCacheClear() { $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()) + $this->cacheTagHandler->expects($this->never()) ->method('deleteTags'); $this->collector->clear(); $this->assertEquals($value, $this->collector->get($key)); @@ -390,7 +398,7 @@ public function testUpdateCacheClearTags() { $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,9 +409,9 @@ public function testUpdateCacheClearTags() { $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()) + $this->cacheTagHandler->expects($this->once()) ->method('deleteTags') ->with($tags); $this->collector->clear(); diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index 2da84fe..02ce8b5 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\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheBackend; + protected $cacheTagHandler; /** * The mocked typed config manager. @@ -121,7 +121,7 @@ protected function setUp() { ->with('en') ->will($this->returnValue(new Language(array('id' => 'en')))); - $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); + $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface'); @@ -129,9 +129,8 @@ protected function setUp() { $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', $this->cacheTagHandler); $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 @@ public function testEnable() { * @depends testSetStatus */ public function testDisable() { - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->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 ddfbd81..bf7ca84 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\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheBackend; + protected $cacheTagHandler; /** * The mocked typed config manager. @@ -153,7 +153,7 @@ protected function setUp() { ->with('test_entity_type') ->will($this->returnValue($this->entityType)); - $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); + $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface'); $this->typedConfigManager->expects($this->any()) @@ -162,8 +162,7 @@ protected function setUp() { $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', $this->cacheTagHandler); \Drupal::setContainer($container); } @@ -173,7 +172,7 @@ protected function setUp() { * @covers ::doCreate */ public function testCreateWithPredefinedUuid() { - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->moduleHandler->expects($this->at(0)) @@ -198,7 +197,7 @@ public function testCreateWithPredefinedUuid() { * @return \Drupal\Core\Entity\EntityInterface */ public function testCreate() { - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->moduleHandler->expects($this->at(0)) @@ -240,7 +239,7 @@ public function testSaveInsert(EntityInterface $entity) { $config_object->expects($this->once()) ->method('save'); - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('invalidateTags') ->with(array( $this->entityTypeId . '_list', // List cache tag. @@ -299,7 +298,7 @@ public function testSaveUpdate(EntityInterface $entity) { $config_object->expects($this->once()) ->method('save'); - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('invalidateTags') ->with(array( $this->entityTypeId . ':foo', // Own cache tag. @@ -359,7 +358,7 @@ public function testSaveRename(ConfigEntityInterface $entity) { $config_object->expects($this->once()) ->method('save'); - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('invalidateTags') ->with(array( $this->entityTypeId .':bar', // Own cache tag. @@ -403,7 +402,7 @@ public function testSaveRename(ConfigEntityInterface $entity) { * @expectedExceptionMessage The entity does not have an ID. */ public function testSaveInvalid() { - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $entity = $this->getMockEntity(); @@ -428,7 +427,7 @@ public function testSaveDuplicate() { $config_object->expects($this->never()) ->method('save'); - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->configFactory->expects($this->once()) @@ -459,7 +458,7 @@ public function testSaveMismatch() { $config_object->expects($this->never()) ->method('save'); - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->configFactory->expects($this->once()) @@ -492,7 +491,7 @@ public function testSaveNoMismatch() { $config_object->expects($this->once()) ->method('save'); - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('invalidateTags') ->with(array( $this->entityTypeId . '_list', // List cache tag. @@ -542,7 +541,7 @@ public function testSaveChangedUuid() { array('id', 'foo'), ))); - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->configFactory->expects($this->at(1)) @@ -699,7 +698,7 @@ public function testLoadRevision() { * @covers ::deleteRevision */ public function testDeleteRevision() { - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->expects($this->never()) ->method('invalidateTags'); $this->assertSame(NULL, $this->entityStorage->deleteRevision(1)); @@ -725,7 +724,7 @@ public function testDelete() { $config_map[] = array("the_config_prefix.$id", $config_object); } - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('invalidateTags') ->with(array( $this->entityTypeId . ':bar', // Own cache tag. @@ -775,7 +774,7 @@ public function testDeleteNothing() { $this->configFactory->expects($this->never()) ->method('get'); - $this->cacheBackend->expects($this->never()) + $this->cacheTagHandler->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 933b7ed..cf7a2f4 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php @@ -63,7 +63,14 @@ class EntityManagerTest extends UnitTestCase { * * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + protected $cacheBackend; + + /** + * The cache tag handler. + * + * @var \Drupal\Core\Cache\CacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheTagHandler; /** * The language manager. @@ -119,7 +126,8 @@ protected function setUp() { ->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->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $language = $this->getMock('Drupal\Core\Language\LanguageInterface'); $language->expects($this->any()) @@ -139,7 +147,7 @@ protected function setUp() { $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface'); $this->controllerResolver = $this->getClassResolverStub(); - $this->container = $this->getContainerWithCacheBins($this->cache); + $this->container = $this->getContainerWithCacheBins($this->cacheTagHandler); $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface'); @@ -180,7 +188,7 @@ protected function setUpEntityManager($definitions = array()) { ->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); } @@ -193,13 +201,13 @@ protected function setUpEntityManager($definitions = array()) { */ public function testClearCachedDefinitions() { $this->setUpEntityManager(); - $this->cache->expects($this->at(0)) + $this->cacheTagHandler->expects($this->at(0)) ->method('deleteTags') ->with(array('entity_types')); - $this->cache->expects($this->at(1)) + $this->cacheTagHandler->expects($this->at(1)) ->method('deleteTags') ->with(array('entity_bundles')); - $this->cache->expects($this->at(2)) + $this->cacheTagHandler->expects($this->at(2)) ->method('deleteTags') ->with(array('entity_field_info')); @@ -524,21 +532,21 @@ public function testGetBaseFieldDefinitionsWithCaching() { $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))); @@ -558,27 +566,27 @@ public function testGetFieldDefinitionsWithCaching() { $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))); @@ -617,29 +625,29 @@ public function testGetFieldStorageDefinitionsWithCaching() { '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))); @@ -771,7 +779,7 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f */ public function testClearCachedFieldDefinitions() { $this->setUpEntityManager(); - $this->cache->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('deleteTags') ->with(array('entity_field_info')); $this->typedDataManager->expects($this->once()) @@ -787,7 +795,7 @@ public function testClearCachedFieldDefinitions() { */ public function testClearCachedBundles() { $this->setUpEntityManager(); - $this->cache->expects($this->once()) + $this->cacheTagHandler->expects($this->once()) ->method('deleteTags') ->with(array('entity_bundles')); @@ -859,30 +867,30 @@ public function testGetAllBundleInfo() { '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)) + $this->cacheTagHandler->expects($this->at(0)) ->method('deleteTags') ->with(array('entity_types')); - $this->cache->expects($this->at(5)) + $this->cacheTagHandler->expects($this->at(1)) ->method('deleteTags') ->with(array('entity_bundles')); - $this->cache->expects($this->at(6)) + $this->cacheTagHandler->expects($this->at(2)) ->method('deleteTags') ->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'))); @@ -1015,7 +1023,7 @@ function testgetExtraFields() { ->method('getCurrentLanguage') ->will($this->returnValue($language)); - $this->cache->expects($this->once()) + $this->cacheBackend->expects($this->once()) ->method('get') ->with($cache_id); @@ -1027,7 +1035,7 @@ function testgetExtraFields() { ->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]); @@ -1167,7 +1175,7 @@ public function testGetFieldMapFromCache() { ) ); $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 6535732..c512fb1 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php @@ -75,9 +75,9 @@ class EntityUnitTest extends UnitTestCase { /** * The mocked cache backend. * - * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheBackend; + protected $cacheTagHandler; /** * The entity values. @@ -116,14 +116,13 @@ protected function setUp() { ->with('en') ->will($this->returnValue(new Language(array('id' => 'en')))); - $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); + $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandler'); $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', $this->cacheTagHandler); \Drupal::setContainer($container); $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\Entity', array($this->values, $this->entityTypeId)); @@ -393,12 +392,12 @@ public function testPreSave() { * @covers ::postSave */ public function testPostSave() { - $this->cacheBackend->expects($this->at(0)) + $this->cacheTagHandler->expects($this->at(0)) ->method('invalidateTags') ->with(array( $this->entityTypeId . '_list', // List cache tag. )); - $this->cacheBackend->expects($this->at(1)) + $this->cacheTagHandler->expects($this->at(1)) ->method('invalidateTags') ->with(array( $this->entityTypeId . ':' . $this->values['id'], // Own cache tag. @@ -450,7 +449,7 @@ public function testPreDelete() { * @covers ::postDelete */ public function testPostDelete() { - $this->cacheBackend->expects($this->once()) + $this->cacheTagHandler->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 ee10e54..a79b9c3 100644 --- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php @@ -70,9 +70,9 @@ class KeyValueEntityStorageTest extends UnitTestCase { /** * The mocked cache backend. * - * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheBackend; + protected $cacheTagHandler; /** * {@inheritdoc} @@ -110,7 +110,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') { ->with('test_entity_type') ->will($this->returnValue($this->entityType)); - $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); + $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $this->keyValueStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface'); $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); @@ -130,8 +130,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') { $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', $this->cacheTagHandler); \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..89ed10c 100644 --- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php +++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php @@ -121,7 +121,7 @@ protected function setUp() { $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'); + $cache_backend = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); $this->getContainerWithCacheBins($cache_backend); } diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php index c2ef841..db6bda3 100644 --- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php @@ -190,10 +190,9 @@ public function testDefaultPluginManagerWithFilledCache() { */ 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_tag_handler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface'); + $cache_tag_handler ->expects($this->once()) ->method('deleteTags') ->with(array('tag')); @@ -201,7 +200,7 @@ public function testCacheClearWithTags() { ->expects($this->never()) ->method('deleteMultiple'); - $this->getContainerWithCacheBins($cache_backend); + $this->getContainerWithCacheBins($cache_tag_handler); $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..268dadd 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\CacheTagHandlerInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; /** @@ -199,22 +198,18 @@ public function getStringTranslationStub() { /** * Sets up a container with cache bins. * - * @param \Drupal\Core\Cache\CacheBackendInterface $backend + * @param \Drupal\Core\Cache\CacheTagHandlerInterface $cache_tags_handler * The cache backend to set up. * * @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject * The container with the cache bins set up. */ - protected function getContainerWithCacheBins(CacheBackendInterface $backend) { + protected function getContainerWithCacheBins(CacheTagHandlerInterface $cache_tags_handler) { $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') + ->will($this->returnValue($cache_tags_handler)); \Drupal::setContainer($container); return $container; diff --git a/sites/development.services.yml b/sites/development.services.yml index cc21211..75c5f44 100644 --- a/sites/development.services.yml +++ b/sites/development.services.yml @@ -5,5 +5,9 @@ services: cache.backend.memory: class: Drupal\Core\Cache\MemoryBackendFactory + tags: + - { name: cache_tags } cache.backend.null: class: Drupal\Core\Cache\NullBackendFactory + tags: + - { name: cache_tags }