diff --git a/core/includes/cache.inc b/core/includes/cache.inc index 06b0ab1..9dba4c8 100644 --- a/core/includes/cache.inc +++ b/core/includes/cache.inc @@ -40,6 +40,25 @@ function cache($bin = 'cache') { } /** + * Deletes the items associated with given list of tags. + * + * Many sites have more than one active cache backend, and each backend my 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 array $tags + * The list of tags to invalidate cache items for. + */ +function cache_delete_tags(array $tags) { + foreach (CacheFactory::getBackends() as $bin => $class) { + cache($bin)->invalidateTags($tags); + } +} + +/** * Invalidates the items associated with given list of tags. * * Many sites have more than one active cache backend, and each backend my use @@ -47,12 +66,12 @@ function cache($bin = 'cache') { * cache items associated with a given tag. * * When invalidating a given list of tags, we iterate over each cache backend, - * and call invalidate on each. + * and call invalidateTags() on each. * * @param array $tags * The list of tags to invalidate cache items for. */ -function cache_invalidate(array $tags) { +function cache_invalidate_tags(array $tags) { foreach (CacheFactory::getBackends() as $bin => $class) { cache($bin)->invalidateTags($tags); } diff --git a/core/includes/common.inc b/core/includes/common.inc index c47494e..16895ac 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -6791,7 +6791,7 @@ function drupal_flush_all_caches() { // This is executed based on old/previously known information, which is // sufficient, since new extensions cannot have any primed caches yet. foreach (module_invoke_all('cache_flush') as $bin) { - cache($bin)->flush(); + cache($bin)->deleteAll(); } // Flush asset file caches. diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 639e1cf..a0acfd5 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2620,7 +2620,7 @@ function menu_cache_clear($menu_name = 'navigation') { * might have been made to the router items or menu links. */ function menu_cache_clear_all() { - cache('menu')->flush(); + cache('menu')->deleteAll(); menu_reset_static_cache(); } @@ -3249,13 +3249,13 @@ function _menu_clear_page_cache() { // Clear the page and block caches, but at most twice, including at // the end of the page load when there are multiple links saved or deleted. if ($cache_cleared == 0) { - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); // Keep track of which menus have expanded items. _menu_set_expanded_menus(); $cache_cleared = 1; } elseif ($cache_cleared == 1) { - drupal_register_shutdown_function('cache_invalidate', array('content', TRUE)); + drupal_register_shutdown_function('cache_invalidate_tags', array('content', TRUE)); // Keep track of which menus have expanded items. drupal_register_shutdown_function('_menu_set_expanded_menus'); $cache_cleared = 2; diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 2140960..ea023d8 100644 --- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -38,8 +38,8 @@ namespace Drupal\Core\Cache; * To access your custom cache bin, specify the name of the bin when storing * or retrieving cached data: * @code - * cache_set($cid, $data, 'custom_bin', $expire); - * cache_get($cid, 'custom_bin'); + * cache('custom_bin')->set($cid, $data, $expire); + * cache('custom_bin')->get($cid); * @endcode * * @see cache() @@ -48,9 +48,7 @@ namespace Drupal\Core\Cache; interface CacheBackendInterface { /** - * Indicates that the item should never be removed unless explicitly selected. - * - * The item may be removed using cache()->delete() with a cache ID. + * Indicates that the item should never be removed unless explicitly deleted. */ const CACHE_PERMANENT = 0; @@ -65,45 +63,48 @@ interface CacheBackendInterface { /** * Returns data from the persistent cache. * - * Data may be stored as either plain text or as serialized data. cache_get() - * will automatically return unserialized objects and arrays. - * - * @param $cid + * @param string $cid * The cache ID of the data to retrieve. + * @param boolean $allowInvalid + * (optional) If TRUE, a cache item may be returned even if it is expired or + * has been invalidated. The "valid" property of the returned object + * indicates whether the item is valid or not. Defaults to FALSE. * - * @return - * The cache or FALSE on failure. + * @return object|false + * The cache item or FALSE on failure. */ - function get($cid); + function get($cid, $allowInvalid = FALSE); /** * Returns data from the persistent cache when given an array of cache IDs. * - * @param $cids + * @param array $cids * An array of cache IDs for the data to retrieve. This is passed by * reference, and will have the IDs successfully returned from cache * removed. + * @param bool $allowInvalid + * (optional) If TRUE, cache items may be returned even if they have expired + * or been invalidated. The "valid" property of the returned objects + * indicates whether each item is valid or not. Defaults to FALSE. * - * @return - * An array of the items successfully returned from cache indexed by cid. + * @return array + * An array of cache item objects indexed by cache ID. */ - function getMultiple(&$cids); + function getMultiple(&$cids, $allowInvalid = FALSE); /** * Stores data in the persistent cache. * - * @param $cid + * @param string $cid * The cache ID of the data to store. - * @param $data - * The data to store in the cache. Complex data types will be automatically - * serialized before insertion. - * Strings will be stored as plain text and not serialized. - * @param $expire + * @param mixed $data + * The data to store in the cache. + * @param int $expire * One of the following values: - * - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item - * should never be removed unless cache->delete($cid) is used explicitly. - * - A Unix timestamp: Indicates that the item should be kept at least until - * the given time. + * - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item should + * not be removed unless unless it is deleted explicitly. + * - A Unix timestamp: Indicates that the item will be considered invalid + * after this time. * @param array $tags * An array of tags to be stored with the cache item. These should normally * identify objects used to build the cache item, which should trigger @@ -116,39 +117,72 @@ interface CacheBackendInterface { /** * Deletes an item from the cache. * - * @param $cid - * The cache ID to delete. + * @param string $cid + * The cache ID to delete. */ function delete($cid); /** * Deletes multiple items from the cache. * - * @param $cids - * An array of $cids to delete. + * @param array $cids + * An array of cache IDs to delete. */ - function deleteMultiple(Array $cids); + function deleteMultiple(array $cids); /** - * Deletes items from the cache using a wildcard prefix. + * Deletes items from the cache with this specified cache ID prefix. * - * @param $prefix - * A wildcard prefix. + * @param string $prefix + * A cache ID prefix. */ function deletePrefix($prefix); /** - * Flushes all cache items in a bin. + * Deletes items with any of the specified tags. + * + * @param array $tags + * Associative array of tags, in the same format that is passed to + * CacheBackendInterface::set(). + * + * @see CacheBackendInterface::set() + */ + function deleteTags(array $tags); + + /** + * Delete all cache items in a bin. + */ + function deleteAll(); + + /** + * Delete expired items from the cache. + */ + function deleteExpired(); + + /** + * Marks items as invalid. + * + * Invalid items may be returned in later calls to get(), if the $allowInvalid + * argument is TRUE. + * + * @param string $cid + * The cache ID to invalidate. */ - function flush(); + function invalidate($cid); /** - * Expires temporary items from the cache. + * Marks items as invalid. + * + * Invalid items may be returned in later calls to get(), if the $allowInvalid + * argument is TRUE. + * + * @param string $cids + * An array of cache IDs to invalidate. */ - function expire(); + function invalidateMultiple(array $cids); /** - * Invalidates each tag in the $tags array. + * Invalidates items with any of the specified tags. * * @param array $tags * Associative array of tags, in the same format that is passed to @@ -160,6 +194,8 @@ interface CacheBackendInterface { /** * Performs garbage collection on a cache bin. + * + * The backend may choose to delete expired or invalidated items. */ function garbageCollection(); diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index d4de8bf..4437abe 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -9,6 +9,7 @@ namespace Drupal\Core\Cache; use Drupal\Core\Database\Database; use Exception; +use PDO; /** * Defines a default cache implementation. @@ -24,11 +25,6 @@ class DatabaseBackend implements CacheBackendInterface { protected $bin; /** - * A static cache of all tags checked during the request. - */ - protected static $tagCache = array(); - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). */ function __construct($bin) { @@ -43,16 +39,16 @@ class DatabaseBackend implements CacheBackendInterface { /** * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ - function get($cid) { + function get($cid, $allowInvalid = FALSE) { $cids = array($cid); - $cache = $this->getMultiple($cids); + $cache = $this->getMultiple($cids, $allowInvalid); return reset($cache); } /** * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ - function getMultiple(&$cids) { + function getMultiple(&$cids, $allowInvalid = FALSE) { try { // When serving cached pages, the overhead of using ::select() was found // to add around 30% overhead to the request. Since $this->bin is a @@ -61,10 +57,10 @@ class DatabaseBackend implements CacheBackendInterface { // is used here only due to the performance overhead we would incur // otherwise. When serving an uncached page, the overhead of using // ::select() is a much smaller proportion of the request. - $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); + $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); $cache = array(); foreach ($result as $item) { - $item = $this->prepareItem($item); + $item = $this->prepareItem($item, $allowInvalid); if ($item) { $cache[$item->cid] = $item; } @@ -87,24 +83,39 @@ class DatabaseBackend implements CacheBackendInterface { * * @param stdClass $cache * An item loaded from cache_get() or cache_get_multiple(). + * @param bool $allowInvalid + * If FALSE, the method returns FALSE if the cache item is not valid. * * @return mixed - * The item with data unserialized as appropriate or FALSE if there is no - * valid item to load. + * The item with data unserialized as appropriate and a property indicating + * whether the item is valid, or FALSE if there is no valid item to load. */ - protected function prepareItem($cache) { + protected function prepareItem($cache, $allowInvalid) { global $user; if (!isset($cache->data)) { return FALSE; } - // The cache data is invalid if any of its tags have been cleared since. - if ($cache->tags) { - $cache->tags = explode(' ', $cache->tags); - if (!$this->validTags($cache->checksum, $cache->tags)) { - return FALSE; - } + $flat_tags = $cache->tags ? explode(' ', $cache->tags) : array(); + + $checksum = $this->checksumTags($flat_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 == CacheBackendInterface::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']) { + $cache->valid = FALSE; + } + + if (!$allowInvalid && !$cache->valid) { + return FALSE; } // Unserialize and return the cached data. @@ -119,12 +130,15 @@ class DatabaseBackend implements CacheBackendInterface { * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) { + $flat_tags = $this->flattenTags($tags); + $checksum = $this->checksumTags($flat_tags); $fields = array( 'serialized' => 0, 'created' => REQUEST_TIME, 'expire' => $expire, - 'tags' => implode(' ', $this->flattenTags($tags)), - 'checksum' => $this->checksumTags($tags), + 'tags' => implode(' ', $flat_tags), + 'checksum_invalidations' => $checksum['invalidations'], + 'checksum_deletions' => $checksum['deletions'], ); if (!is_string($data)) { $fields['data'] = serialize($data); @@ -169,6 +183,21 @@ class DatabaseBackend implements CacheBackendInterface { } /** + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). + */ + public function deleteTags(array $tags) { + $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache'); + foreach ($this->flattenTags($tags) as $tag) { + unset($tag_cache[$tag]); + Database::getConnection()->merge('cache_tags') + ->insertFields(array('deletions' => 1)) + ->expression('deletions', 'deletions + 1') + ->key(array('tag' => $tag)) + ->execute(); + } + } + + /** * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix(). */ function deletePrefix($prefix) { @@ -180,14 +209,14 @@ class DatabaseBackend implements CacheBackendInterface { /** * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ - function flush() { + function deleteAll() { Database::getConnection()->truncate($this->bin)->execute(); } /** * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ - function expire() { + function deleteExpired() { Database::getConnection()->delete($this->bin) ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>') ->condition('expire', REQUEST_TIME, '<') @@ -195,26 +224,46 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate(). */ - function garbageCollection() { - $this->expire(); + function invalidate($cid) { + $this->invalidateMultiple(array($cid)); } /** - * Compares two checksums of tags. Used to determine whether to serve a cached - * item or treat it as invalidated. - * - * @param integer @checksum - * The initial checksum to compare against. - * @param array @tags - * An array of tags to calculate a checksum for. - * - * @return boolean - * TRUE if the checksums match, FALSE otherwise. + * Implements Drupal\Core\Cache\CacheBackendInterface::invalideMultiple(). */ - protected function validTags($checksum, array $tags) { - return $checksum == $this->checksumTags($tags); + function invalidateMultiple(array $cids) { + // Update in chunks when a large array is passed. + do { + Database::getConnection()->update($this->bin) + ->fields(array('expire' => REQUEST_TIME - 1)) + ->condition('cid', array_splice($cids, 0, 1000), 'IN') + ->execute(); + } + while (count($cids)); + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + */ + public function invalidateTags(array $tags) { + $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache'); + foreach ($this->flattenTags($tags) as $tag) { + unset($tag_cache[$tag]); + Database::getConnection()->merge('cache_tags') + ->insertFields(array('invalidations' => 1)) + ->expression('invalidations', 'invalidations + 1') + ->key(array('tag' => $tag)) + ->execute(); + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). + */ + function garbageCollection() { + $this->deleteExpired(); } /** @@ -224,7 +273,7 @@ class DatabaseBackend implements CacheBackendInterface { * Associative array of tags to flatten. * * @return - * Numeric array of flattened tag identifiers. + * Numeric array of flat tag identifiers. */ protected function flattenTags(array $tags) { if (isset($tags[0])) { @@ -246,51 +295,40 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). - */ - public function invalidateTags(array $tags) { - foreach ($this->flattenTags($tags) as $tag) { - unset(self::$tagCache[$tag]); - Database::getConnection()->merge('cache_tags') - ->key(array('tag' => $tag)) - ->fields(array('invalidations' => 1)) - ->expression('invalidations', 'invalidations + 1') - ->execute(); - } - } - - /** * Returns the sum total of validations for a given set of tags. * * @param array $tags - * Associative array of tags. + * Array of flat tags. * * @return integer * Sum of all invalidations. */ - protected function checksumTags($tags) { - $checksum = 0; - $query_tags = array(); + protected function checksumTags($flat_tags) { + $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array()); - foreach ($this->flattenTags($tags) as $tag) { - if (isset(self::$tagCache[$tag])) { - $checksum += self::$tagCache[$tag]; - } - else { - $query_tags[] = $tag; - } - } + $checksum = array( + 'invalidations' => 0, + 'deletions' => 0, + ); + + $query_tags = array_diff($flat_tags, array_keys($tag_cache)); if ($query_tags) { try { - if ($db_tags = Database::getConnection()->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) { - self::$tagCache = array_merge(self::$tagCache, $db_tags); - $checksum += array_sum($db_tags); - } + $db_tags = Database::getConnection()->query('SELECT tag, invalidations, deletions FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', PDO::FETCH_ASSOC); + $tag_cache += $db_tags; } catch (Exception $e) { // The database may not be available, so we'll ignore cache_set requests. } + // 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 ($flat_tags as $tag) { + $checksum['invalidations'] += $tag_cache[$tag]['invalidations']; + $checksum['deletions'] += $tag_cache[$tag]['deletions']; } + return $checksum; } diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php index b507684..3c7a6bb 100644 --- a/core/lib/Drupal/Core/Cache/InstallBackend.php +++ b/core/lib/Drupal/Core/Cache/InstallBackend.php @@ -36,14 +36,14 @@ class InstallBackend extends DatabaseBackend { /** * Overrides Drupal\Core\Cache\DatabaseBackend::get(). */ - function get($cid) { + function get($cid, $allowInvalid = FALSE) { return FALSE; } /** * Overrides Drupal\Core\Cache\DatabaseBackend::getMultiple(). */ - function getMultiple(&$cids) { + function getMultiple(&$cids, $allowInvalid = FALSE) { return array(); } @@ -89,36 +89,72 @@ class InstallBackend extends DatabaseBackend { } /** - * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags(). + * Overrides Drupal\Core\Cache\DatabaseBackend::deleteAll(). */ - function invalidateTags(array $tags) { + function deleteAll() { try { if (class_exists('Drupal\Core\Database\Database')) { - parent::invalidateTags($tags); + parent::deleteAll(); } } catch (Exception $e) {} } /** - * Overrides Drupal\Core\Cache\DatabaseBackend::flush(). + * Overrides Drupal\Core\Cache\DatabaseBackend::deleteExpired(). */ - function flush() { + function deleteExpired() { try { if (class_exists('Drupal\Core\Database\Database')) { - parent::flush(); + parent::deleteExpired(); } } catch (Exception $e) {} } /** - * Overrides Drupal\Core\Cache\DatabaseBackend::expire(). + * Overrides Drupal\Core\Cache\DatabaseBackend::deleteTags(). */ - function expire() { + function deleteTags(array $tags) { try { if (class_exists('Drupal\Core\Database\Database')) { - parent::expire(); + parent::deleteTags($tags); + } + } + catch (Exception $e) {} + } + + /** + * Overrides Drupal\Core\Cache\DatabaseBackend::invalidate(). + */ + function invalidate($cid) { + try { + if (class_exists('Drupal\Core\Database\Database')) { + parent::invalidate($cid); + } + } + catch (Exception $e) {} + } + + /** + * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateMultiple(). + */ + function invalidateMultiple(array $cids) { + try { + if (class_exists('Drupal\Core\Database\Database')) { + parent::invalidateMultiple($cids); + } + } + catch (Exception $e) {} + } + + /** + * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags(). + */ + function invalidateTags(array $tags) { + try { + if (class_exists('Drupal\Core\Database\Database')) { + parent::invalidateTags($tags); } } catch (Exception $e) {} diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php index 021b818..32ec501 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackend.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php @@ -24,11 +24,6 @@ class MemoryBackend implements CacheBackendInterface { protected $cache = array(); /** - * All tags invalidated during the request. - */ - protected $invalidatedTags = array(); - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). */ public function __construct($bin) { @@ -37,9 +32,9 @@ class MemoryBackend implements CacheBackendInterface { /** * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ - public function get($cid) { + public function get($cid, $allowInvalid = FALSE) { if (isset($this->cache[$cid])) { - return $this->prepareItem($this->cache[$cid]); + return $this->prepareItem($this->cache[$cid], $allowInvalid); } else { return FALSE; @@ -49,13 +44,13 @@ class MemoryBackend implements CacheBackendInterface { /** * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ - public function getMultiple(&$cids) { + public function getMultiple(&$cids, $allowInvalid = FALSE) { $ret = array(); $items = array_intersect_key($this->cache, array_flip($cids)); foreach ($items as $item) { - $item = $this->prepareItem($item); + $item = $this->prepareItem($item, $allowInvalid); if ($item) { $ret[$item->cid] = $item; } @@ -79,13 +74,15 @@ class MemoryBackend implements CacheBackendInterface { * The item with data as appropriate or FALSE if there is no * valid item to load. */ - protected function prepareItem($cache) { + protected function prepareItem($cache, $allowInvalid) { if (!isset($cache->data)) { return FALSE; } - // The cache data is invalid if any of its tags have been cleared since. - if (count($cache->tags) && $this->hasInvalidatedTags($cache)) { + // Check expire time. + $cache->valid = $cache->expire == CacheBackendInterface::CACHE_PERMANENT || $cache->expire >= REQUEST_TIME; + + if (!$allowInvalid && !$cache->valid) { return FALSE; } @@ -99,28 +96,12 @@ class MemoryBackend implements CacheBackendInterface { $this->cache[$cid] = (object) array( 'cid' => $cid, 'data' => $data, + 'created' => REQUEST_TIME, 'expire' => $expire, - 'tags' => $tags, - 'checksum' => $this->checksum($this->flattenTags($tags)), + 'flat_tags' => $this->flattenTags($tags), ); } - /* - * Calculates a checksum so data can be invalidated using tags. - */ - function checksum($tags) { - $checksum = ""; - - foreach($tags as $tag) { - // Has the tag already been invalidated. - if (isset($this->invalidatedTags[$tag])) { - $checksum = $checksum . $tag . ':' . $this->invalidatedTags[$tag]; - } - } - - return $checksum; - } - /** * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ @@ -147,37 +128,60 @@ class MemoryBackend implements CacheBackendInterface { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). + */ + public function deleteTags(array $tags) { + $flat_tags = $this->flattenTags($tags); + foreach ($this->cache as $cid => $item) { + if (array_intersect($flat_tags, $item->flat_tags)) { + unset($this->cache[$cid]); + } + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). */ - public function flush() { + public function deleteAll() { $this->cache = array(); } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteExpired(). * - * Cache expiration is not implemented for PHP ArrayBackend as this backend - * only persists during a single request and expiration are done using + * Cache expiration is not implemented for MemoryBackend as this backend only + * persists during a single request and expiration are done using * REQUEST_TIME. */ - public function expire() { + public function deleteExpired() { } /** - * Checks to see if any of the tags associated with a cache object have been - * invalidated. - * - * @param object @cache - * An cache object to calculate and compare it's original checksum for. - * - * @return boolean - * TRUE if the a tag has been invalidated, FALSE otherwise. + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate(). */ - protected function hasInvalidatedTags($cache) { - if ($cache->checksum != $this->checksum($this->flattenTags($cache->tags))) { - return TRUE; + public function invalidate($cid) { + $this->cache[$cid]->expire = REQUEST_TIME - 1; + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple(). + */ + public function invalidateMultiple(array $cids) { + foreach ($cids as $cid) { + $this->cache[$cid]->expire = REQUEST_TIME - 1; + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + */ + public function invalidateTags(array $tags) { + $flat_tags = $this->flattenTags($tags); + foreach ($this->cache as $cid => $item) { + if (array_intersect($flat_tags, $item->flat_tags)) { + $this->cache[$cid]->expire = REQUEST_TIME - 1; + } } - return FALSE; } /** @@ -187,7 +191,7 @@ class MemoryBackend implements CacheBackendInterface { * Associative array of tags to flatten. * * @return - * An array of flattened tag identifiers. + * An array of flat tag identifiers. */ protected function flattenTags(array $tags) { if (isset($tags[0])) { @@ -209,21 +213,6 @@ class MemoryBackend implements CacheBackendInterface { } /** - * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). - */ - public function invalidateTags(array $tags) { - $flat_tags = $this->flattenTags($tags); - foreach($flat_tags as $tag) { - if (isset($this->invalidatedTags[$tag])) { - $this->invalidatedTags[$tag] = $this->invalidatedTags[$tag] + 1; - } - else { - $this->invalidatedTags[$tag] = 1; - } - } - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty(). */ public function isEmpty() { diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php index dedd033..cae3321 100644 --- a/core/lib/Drupal/Core/Cache/NullBackend.php +++ b/core/lib/Drupal/Core/Cache/NullBackend.php @@ -28,14 +28,14 @@ class NullBackend implements CacheBackendInterface { /** * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ - function get($cid) { + function get($cid, $allowInvalid = FALSE) { return FALSE; } /** * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ - function getMultiple(&$cids) { + function getMultiple(&$cids, $allowInvalid = FALSE) { return array(); } @@ -60,19 +60,29 @@ class NullBackend implements CacheBackendInterface { function deletePrefix($prefix) {} /** - * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). */ - function flush() {} + function deleteAll() {} /** - * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteExpired(). */ - function expire() {} + function deleteExpired() {} /** - * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll(). */ - function garbageCollection() {} + function deleteTags(array $tags) {} + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate(). + */ + public function invalidate($cid) {} + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple(). + */ + public function invalidateMultiple(array $cids) {} /** * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). @@ -80,6 +90,11 @@ class NullBackend implements CacheBackendInterface { public function invalidateTags(array $tags) {} /** + * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). + */ + function garbageCollection() {} + + /** * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty(). */ function isEmpty() { diff --git a/core/lib/Drupal/Core/Database/Query/Merge.php b/core/lib/Drupal/Core/Database/Query/Merge.php index 547a223..13637a5 100644 --- a/core/lib/Drupal/Core/Database/Query/Merge.php +++ b/core/lib/Drupal/Core/Database/Query/Merge.php @@ -421,6 +421,7 @@ class Merge extends Query implements ConditionInterface { $insert->useDefaults($this->defaultFields); } $insert->execute(); + #mail('chsc@chsc.dk', __METHOD__, ''.$insert.print_r(debug_backtrace(),1));exit; return self::STATUS_INSERT; } catch (Exception $e) { @@ -442,6 +443,7 @@ class Merge extends Query implements ConditionInterface { $update->expression($field, $data['expression'], $data['arguments']); } } + #mail('chsc@chsc.dk', __METHOD__, ''.$update); $update->execute(); return self::STATUS_UPDATE; } diff --git a/core/modules/aggregator/aggregator.parser.inc b/core/modules/aggregator/aggregator.parser.inc index bacaa84..ff2e522 100644 --- a/core/modules/aggregator/aggregator.parser.inc +++ b/core/modules/aggregator/aggregator.parser.inc @@ -45,7 +45,7 @@ function aggregator_aggregator_parse($feed) { $feed->modified = $modified; // Clear the page and block caches. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); return TRUE; } diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc index 848298f..a5668c8 100644 --- a/core/modules/block/block.admin.inc +++ b/core/modules/block/block.admin.inc @@ -205,7 +205,7 @@ function block_admin_display_form_submit($form, &$form_state) { throw $e; } drupal_set_message(t('The block settings have been updated.')); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** @@ -603,7 +603,7 @@ function block_admin_configure_submit($form, &$form_state) { throw $e; } drupal_set_message(t('The block configuration has been saved.')); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $form_state['redirect'] = 'admin/structure/block'; } } @@ -712,7 +712,7 @@ function block_add_block_form_submit($form, &$form_state) { } drupal_set_message(t('The block has been created.')); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $form_state['redirect'] = 'admin/structure/block'; } @@ -760,7 +760,7 @@ function block_custom_block_delete_submit($form, &$form_state) { ->execute(); drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['info']))); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $form_state['redirect'] = 'admin/structure/block'; return; } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php index 90327f9..f3520d7 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php @@ -74,7 +74,7 @@ class BlockCacheTest extends WebTestBase { $this->assertText($old_content, t('Block is served from the cache.')); // Clear the cache and verify that the stale data is no longer there. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $this->drupalGet(''); $this->assertNoText($old_content, t('Block cache clear removes stale cache data.')); $this->assertText($current_content, t('Fresh block content is displayed after clearing the cache.')); diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc index 6210cc5..54cc238 100644 --- a/core/modules/comment/comment.admin.inc +++ b/core/modules/comment/comment.admin.inc @@ -194,7 +194,7 @@ function comment_admin_overview_submit($form, &$form_state) { } drupal_set_message(t('The update has been performed.')); $form_state['redirect'] = 'admin/content/comment'; - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** @@ -242,7 +242,7 @@ function comment_multiple_delete_confirm($form, &$form_state) { function comment_multiple_delete_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { comment_delete_multiple(array_keys($form_state['values']['comments'])); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $count = count($form_state['values']['comments']); watchdog('content', 'Deleted @count comments.', array('@count' => $count)); drupal_set_message(format_plural($count, 'Deleted 1 comment.', 'Deleted @count comments.')); @@ -301,7 +301,7 @@ function comment_confirm_delete_submit($form, &$form_state) { drupal_set_message(t('The comment and all its replies have been deleted.')); watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->cid)); // Clear the cache so an anonymous user sees that his comment was deleted. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $form_state['redirect'] = "node/$comment->nid"; } diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index bd9c107..be2649c 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -2064,7 +2064,7 @@ function comment_unpublish_by_keyword_action_submit($form, $form_state) { */ function comment_save_action(Comment $comment) { comment_save($comment); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); watchdog('action', 'Saved comment %title', array('%title' => $comment->subject)); } diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index 7dae92d..91a62f9 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -373,6 +373,6 @@ class CommentFormController extends EntityFormController { $form_state['redirect'] = $redirect; // Clear the block and page caches so that anonymous users see the comment // they have posted. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php index b43029f..66385f3 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php @@ -51,7 +51,7 @@ class CommentBlockTest extends CommentTestBase { user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access comments')); // drupalCreateNode() does not automatically flush content caches unlike // posting a node from a node form. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); $this->drupalGet(''); $this->assertNoText($block['title'], t('Block was not found.')); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access comments')); diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 72b6d91..9e438b0 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -763,7 +763,7 @@ function _field_extra_fields_pre_render($elements) { * Clear the field info and field data caches. */ function field_cache_clear() { - cache('field')->flush(); + cache('field')->deleteAll(); field_info_cache_clear(); } diff --git a/core/modules/forum/forum.admin.inc b/core/modules/forum/forum.admin.inc index e3c564a..e128aa4 100644 --- a/core/modules/forum/forum.admin.inc +++ b/core/modules/forum/forum.admin.inc @@ -115,7 +115,7 @@ function forum_form_submit($form, &$form_state) { case SAVED_UPDATED: drupal_set_message(t('The @type %term has been updated.', array('%term' => $form_state['values']['name'], '@type' => $type))); // Clear the page and block caches to avoid stale data. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); break; } $form_state['redirect'] = 'admin/structure/forum'; diff --git a/core/modules/image/image.api.php b/core/modules/image/image.api.php index 758d38b..12be933 100644 --- a/core/modules/image/image.api.php +++ b/core/modules/image/image.api.php @@ -116,7 +116,7 @@ function hook_image_style_delete($style) { */ function hook_image_style_flush($style) { // Empty cached data that contains information about the style. - cache('mymodule')->flush(); + cache('mymodule')->deleteAll(); } /** diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 4fd2be8..c6c178e 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -909,9 +909,9 @@ function image_style_flush($style) { // Clear page caches when flushing. if (module_exists('block')) { - cache('block')->flush(); + cache('block')->deleteAll(); } - cache('page')->flush(); + cache('page')->deleteAll(); } /** diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php index 1c7265c..292a49a 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php @@ -249,7 +249,7 @@ class LocaleTranslationTest extends WebTestBase { // Test JavaScript translation rebuilding. file_unmanaged_delete($js_file); $this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found')))); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); _locale_rebuild_js($langcode); $this->assertTrue($result = file_exists($js_file), t('JavaScript file rebuilt: %file', array('%file' => $result ? $js_file : t('not found')))); } diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 86689ac..d688d03 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -192,7 +192,7 @@ function locale_stream_wrappers() { function locale_language_insert($language) { // @todo move these two cache clears out. See http://drupal.org/node/1293252 // Changing the language settings impacts the interface. - cache('page')->flush(); + cache('page')->deleteAll(); // Force JavaScript translation file re-creation for the new language. _locale_invalidate_js($language->langcode); } @@ -203,7 +203,7 @@ function locale_language_insert($language) { function locale_language_update($language) { // @todo move these two cache clears out. See http://drupal.org/node/1293252 // Changing the language settings impacts the interface. - cache('page')->flush(); + cache('page')->deleteAll(); // Force JavaScript translation file re-creation for the modified language. _locale_invalidate_js($language->langcode); } @@ -224,7 +224,7 @@ function locale_language_delete($language) { _locale_invalidate_js($language->langcode); // Changing the language settings impacts the interface: - cache('page')->flush(); + cache('page')->deleteAll(); // Clearing all locale cache from database cache()->delete('locale:' . $language->langcode); diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 7924acc..5178376 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -408,7 +408,7 @@ class NodeFormController extends EntityFormController { } // Clear the page and block caches. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php index 0c86de2..666039d 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php @@ -113,7 +113,7 @@ class NodeBlockFunctionalTest extends NodeTestBase { $node4 = $this->drupalCreateNode($default_settings); // drupalCreateNode() does not automatically flush content caches unlike // posting a node from a node form. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); // Test that all four nodes are shown. $this->drupalGet(''); diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc index 5cbe4ef..0a1fc24 100644 --- a/core/modules/node/node.admin.inc +++ b/core/modules/node/node.admin.inc @@ -612,7 +612,7 @@ function node_admin_nodes_submit($form, &$form_state) { } call_user_func_array($function, $args); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } else { // We need to rebuild the form to go to a second step. For example, to diff --git a/core/modules/node/node.module b/core/modules/node/node.module index bfba2fd..2fa9532 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -3555,7 +3555,7 @@ function node_access_rebuild($batch_mode = FALSE) { if (!isset($batch)) { drupal_set_message(t('Content permissions have been rebuilt.')); node_access_needs_rebuild(FALSE); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } } @@ -3605,7 +3605,7 @@ function _node_access_rebuild_batch_finished($success, $results, $operations) { else { drupal_set_message(t('The content access permissions have not been properly rebuilt.'), 'error'); } - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** diff --git a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php index dcaf945..835a981 100644 --- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php +++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php @@ -50,12 +50,12 @@ class PathAliasTest extends PathTestBase { // Visit the system path for the node and confirm a cache entry is // created. - cache('path')->flush(); + cache('path')->deleteAll(); $this->drupalGet($edit['source']); $this->assertTrue(cache('path')->get($edit['source']), t('Cache entry was created.')); // Visit the alias for the node and confirm a cache entry is created. - cache('path')->flush(); + cache('path')->deleteAll(); $this->drupalGet($edit['alias']); // @todo The alias should actually have been cached with the system path as // the key, see the todo in drupal_cache_system_paths() in path.inc. diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module index dc4722e..1bd4b22 100644 --- a/core/modules/poll/poll.module +++ b/core/modules/poll/poll.module @@ -759,7 +759,7 @@ function poll_vote($form, &$form_state) { ->condition('chid', $choice) ->execute(); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); if (!$user->uid) { // The vote is recorded so the user gets the result view instead of the diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php index e4b275e..49a3d21 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php @@ -98,6 +98,6 @@ abstract class CacheTestBase extends WebTestBase { $bin = $this->default_bin; } - cache($bin)->expire(); + cache($bin)->deleteExpired(); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php index 5cc023b..5ca1dfa 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php @@ -99,7 +99,7 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { if (!isset($this->cachebackends[$bin])) { $this->cachebackends[$bin] = $this->createCacheBackend($bin); // Ensure the backend is empty. - $this->cachebackends[$bin]->flush(); + $this->cachebackends[$bin]->deleteAll(); } return $this->cachebackends[$bin]; } @@ -115,10 +115,10 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { public function tearDown() { // Destruct the registered backend, each test will get a fresh instance, - // properly flushing it here ensure that on persistant data backends they + // properly emptying it here ensure that on persistant data backends they // will come up empty the next test. foreach ($this->cachebackends as $bin => $cachebackend) { - $this->cachebackends[$bin]->flush(); + $this->cachebackends[$bin]->deleteAll(); } unset($this->cachebackends); @@ -134,19 +134,31 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { public function testSetGet() { $backend = $this->getCacheBackend(); - $data = 7; $this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1."); - $backend->set('test1', $data); + $backend->set('test1', 7); $cached = $backend->get('test1'); $this->assert(is_object($cached), "Backend returned an object for cache id test1."); - $this->assertIdentical($data, $cached->data); + $this->assertIdentical(7, $cached->data); + $this->assertTrue($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.'); - $data = array('value' => 3); $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); - $backend->set('test2', $data); + $backend->set('test2', array('value' => 3), REQUEST_TIME + 3); $cached = $backend->get('test2'); $this->assert(is_object($cached), "Backend returned an object for cache id test2."); - $this->assertIdentical($data, $cached->data); + $this->assertIdentical(array('value' => 3), $cached->data); + $this->assertTrue($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, REQUEST_TIME + 3, 'Expire time is correct.'); + + $backend->set('test3', 'foobar', REQUEST_TIME - 3); + $this->assertFalse($backend->get('test3'), 'Invalid item not returned.'); + $cached = $backend->get('test3', TRUE); + $this->assert(is_object($cached), 'Backend returned an object for cache id test3.'); + $this->assertFalse($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, REQUEST_TIME - 3, 'Expire time is correct.'); } /** @@ -184,7 +196,7 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { 'test2' => '0', 'test3' => '', 'test4' => 12.64, - 'test5' => false, + 'test5' => FALSE, 'test6' => array(1,2,3), ); @@ -222,7 +234,7 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { 'test7', 'test21', // Cid does not exist. 'test6', - 'test19', // Cid does not exist until added before second getMulitple(). + 'test19', // Cid does not exist until added before second getMultiple(). 'test2', ); @@ -233,6 +245,10 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { $this->assert(isset($ret['test3']), "Existing cache id test3 is set."); $this->assert(isset($ret['test6']), "Existing cache id test6 is set."); $this->assert(isset($ret['test7']), "Existing cache id test7 is set."); + // Test return - ensure that objects has expected properties. + $this->assertTrue($ret['test2']->valid, 'Item is marked as valid.'); + $this->assertEqual($ret['test2']->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($ret['test2']->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.'); // Test return - ensure it does not contain nonexistent cache ids. $this->assertFalse(isset($ret['test19']), "Nonexistent cache id test19 is not set."); $this->assertFalse(isset($ret['test21']), "Nonexistent cache id test21 is not set."); @@ -296,7 +312,8 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { } /** - * Test Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). + * Test Drupal\Core\Cache\CacheBackendInterface::delete() and + * Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). */ public function testDeleteMultiple() { $backend = $this->getCacheBackend(); @@ -310,8 +327,9 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { $backend->set('test6', 13); $backend->set('test7', 17); + $backend->delete('test1'); + $backend->delete('test23'); // Nonexistent key should not cause an error. $backend->deleteMultiple(array( - 'test1', 'test3', 'test5', 'test7', @@ -371,92 +389,155 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { } /** - * Test Drupal\Core\Cache\CacheBackendInterface::flush(). + * Test Drupal\Core\Cache\CacheBackendInterface::deleteTags(). */ - public function testFlush() { + function testDeleteTags() { + $backend = $this->getCacheBackend(); + + // Create two cache entries with the same tag and tag value. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::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, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(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' => array(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, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); + $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(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' => array(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' => array(1, 2, 3)); + $bins = array('path', 'bootstrap', 'page'); + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::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' => array(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() { $backend = $this->getCacheBackend(); // Set both expiring and permanent keys. $backend->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT); $backend->set('test2', 3, time() + 1000); - $backend->flush(); + $backend->deleteAll(); - $this->assertTrue($backend->isEmpty(), "Backend is empty after flush."); + $this->assertTrue($backend->isEmpty(), "Backend is empty after deleteAll()."); - $this->assertIdentical(FALSE, $backend->get('test1'), "First key has been flushed."); - $this->assertIdentical(FALSE, $backend->get('test2'), "Second key has been flushed."); + $this->assertIdentical(FALSE, $backend->get('test1'), "First key has been deleted."); + $this->assertIdentical(FALSE, $backend->get('test2'), "Second key has been deleted."); } /** - * Check whether or not a cache entry exists. - * - * @param $cid - * The cache id. - * @param $bin - * The cache bin to use. If not provided the default test bin wil be used. - * - * @return - * TRUE on pass, FALSE on fail. + * Test Drupal\Core\Cache\CacheBackendInterface::invalidate() and + * Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple(). */ - protected function checkCacheExists($cid, $bin = null) { - $cached = $this->getCacheBackend($bin)->get($cid); - return isset($cached->data); + function testInvalidate() { + $backend = $this->getCacheBackend(); + $backend->set('test1', 1); + $backend->set('test2', 2); + $backend->set('test3', 2); + $backend->set('test4', 2); + + $reference = array('test1', 'test2', 'test3', 'test4'); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + $this->assertEqual(count($ret), 4, 'Four items returned.'); + + $backend->invalidate('test1'); + $backend->invalidateMultiple(array('test2', 'test3')); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + $this->assertEqual(count($ret), 1, 'Only one item element returned.'); + + $cids = $reference; + $ret = $backend->getMultiple($cids, TRUE); + $this->assertEqual(count($ret), 4, 'Four items returned.'); } /** * Test Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). */ - function testClearTags() { + function testInvalidateTags() { $backend = $this->getCacheBackend(); // Create two cache entries with the same tag and tag value. - $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); - $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); - $this->assertTrue($this->checkCacheExists('test_cid_clear1') - && $this->checkCacheExists('test_cid_clear2'), - 'Two cache items were created.'); + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $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)); - $this->assertFalse($this->checkCacheExists('test_cid_clear1') - || $this->checkCacheExists('test_cid_clear2'), - 'Two caches removed after clearing a cache tag.'); + $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.'); // Create two cache entries with the same tag and an array tag value. - $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); - $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1') - && $this->checkCacheExists('test_cid_clear2'), - 'Two cache items were created.'); + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $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' => array(1))); - $this->assertFalse($this->checkCacheExists('test_cid_clear1') - || $this->checkCacheExists('test_cid_clear2'), - 'Two caches removed after clearing a cache tag.'); + $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.'); // Create three cache entries with a mix of tags and tag values. - $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); - $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); - $backend->set('test_cid_clear3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(3))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1') - && $this->checkCacheExists('test_cid_clear2') - && $this->checkCacheExists('test_cid_clear3'), - 'Two cached items were created.'); + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); + $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(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' => array(3))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1') - && $this->checkCacheExists('test_cid_clear2'), - 'Cached items not matching the tag were not cleared.'); - - $this->assertFalse($this->checkCacheExists('test_cid_clear3'), - 'Cached item matching the tag was removed.'); + $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.'); - // Create cache entry in multiple bins. Two cache entries (test_cid_clear1 - // and test_cid_clear2) still exist from previous tests. + // 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' => array(1, 2, 3)); $bins = array('path', 'bootstrap', 'page'); foreach ($bins as $bin) { $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, $tags); - $this->assertTrue($this->checkCacheExists('test', $bin), 'Cache item was set in bin.'); + $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.'); } // Invalidate tag in mulitple bins. @@ -466,11 +547,11 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase { // Test that cache entry has been invalidated in multple bins. foreach ($bins as $bin) { - $this->assertFalse($this->checkCacheExists('test', $bin), 'Tag expire affected item in bin.'); + $this->assertFalse($this->getCacheBackend($bin)->get('test'), 'Tag invalidation affected item in bin.'); } // Test that the cache entry with a matching tag has been invalidated. - $this->assertFalse($this->checkCacheExists('test_cid_clear2', $bin), 'Cached items matching tag were cleared.'); + $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2'), 'Cache items matching tag were invalidated.'); // Test that the cache entry with without a matching tag still exists. - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $bin), 'Cached items not matching tag were not cleared.'); + $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php index a2199c2..84313b9 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php @@ -96,7 +96,7 @@ class InstallTest extends CacheTestBase { $database_cache->set('cache_two', 'Two'); $this->assertEqual($database_cache->get('cache_one')->data, 'One'); $this->assertEqual($database_cache->get('cache_two')->data, 'Two'); - $install_cache->flush(); + $install_cache->deleteAll(); $this->assertFalse($database_cache->get('cache_one')); $this->assertFalse($database_cache->get('cache_two')); @@ -118,8 +118,8 @@ class InstallTest extends CacheTestBase { $install_cache->delete('cache_one'); $install_cache->deleteMultiple(array('cache_one', 'cache_two')); $install_cache->deletePrefix('cache_'); - $install_cache->flush(); - $install_cache->expire(); + $install_cache->deleteAll(); + $install_cache->deleteExpired(); $install_cache->garbageCollection(); $install_cache->invalidateTags(array('tag')); $this->pass("The installer's cache backend can be used even when the cache database tables are unavailable."); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 2bf4343..a500334 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -735,7 +735,7 @@ function system_theme_settings_submit($form, &$form_state) { variable_set($key, $values); drupal_set_message(t('The configuration options have been saved.')); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** @@ -1812,7 +1812,7 @@ function system_clear_cache_submit($form, &$form_state) { * @ingroup forms */ function system_clear_page_cache_submit($form, &$form_state) { - cache('page')->flush(); + cache('page')->deleteAll(); } /** diff --git a/core/modules/system/system.install b/core/modules/system/system.install index a6856ec..7db5efc 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -667,6 +667,12 @@ function system_schema() { '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'), ); @@ -712,12 +718,18 @@ function system_schema() { 'size' => 'big', 'not null' => FALSE, ), - 'checksum' => array( + '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', + 'not null' => TRUE, + 'default' => 0, + ), ), 'indexes' => array( 'expire' => array('expire'), @@ -1522,12 +1534,18 @@ function system_schema_cache_8007() { 'size' => 'big', 'not null' => FALSE, ), - 'checksum' => array( + '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', + 'not null' => TRUE, + 'default' => 0, + ), ), 'indexes' => array( 'expire' => array('expire'), @@ -1648,12 +1666,18 @@ function system_update_8003() { 'size' => 'big', 'not null' => FALSE, ), - 'checksum' => array( + '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', + 'not null' => TRUE, + 'default' => 0, + ), ), 'indexes' => array( 'expire' => array('expire'), @@ -1724,6 +1748,12 @@ function system_update_8006() { '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'), ); @@ -1747,12 +1777,18 @@ function system_update_8007() { 'size' => 'big', 'not null' => FALSE, )); - db_add_field($table, 'checksum', array( + db_add_field($table, 'checksum_invalidations', array( 'description' => 'The tag invalidation sum when this entry was saved.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, )); + db_add_field($table, 'checksum_deletions', array( + 'description' => 'The tag deletion sum when this entry was saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + )); } } } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index e5dc768..0078cde 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -3482,7 +3482,7 @@ function system_cron() { $cache_bins = array_merge(module_invoke_all('cache_flush'), array('form', 'menu')); foreach ($cache_bins as $bin) { - cache($bin)->expire(); + cache($bin)->deleteExpired(); } // Cleanup the batch table and the queue for failed batches. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index c7ee415..4fd859e 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -167,7 +167,7 @@ class TermFormController extends EntityFormController { drupal_set_message(t('Updated term %term.', array('%term' => $term->label()))); watchdog('taxonomy', 'Updated term %term.', array('%term' => $term->label()), WATCHDOG_NOTICE, l(t('edit'), 'taxonomy/term/' . $term->tid . '/edit')); // Clear the page and block caches to avoid stale data. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); break; } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php index dd5b478..9f246e8 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php @@ -84,6 +84,6 @@ class VocabularyStorageController extends DatabaseStorageController { public function resetCache(array $ids = NULL) { drupal_static_reset('taxonomy_vocabulary_get_names'); parent::resetCache($ids); - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } } diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc index ecef0b5..5e1b133 100644 --- a/core/modules/taxonomy/taxonomy.admin.inc +++ b/core/modules/taxonomy/taxonomy.admin.inc @@ -562,7 +562,7 @@ function taxonomy_term_confirm_delete_submit($form, &$form_state) { if (!isset($_GET['destination'])) { $form_state['redirect'] = 'admin/structure/taxonomy'; } - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); return; } @@ -602,7 +602,7 @@ function taxonomy_vocabulary_confirm_delete_submit($form, &$form_state) { drupal_set_message(t('Deleted vocabulary %name.', array('%name' => $form_state['values']['name']))); watchdog('taxonomy', 'Deleted vocabulary %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE); $form_state['redirect'] = 'admin/structure/taxonomy'; - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); return; } diff --git a/core/modules/user/lib/Drupal/user/ProfileFormController.php b/core/modules/user/lib/Drupal/user/ProfileFormController.php index d2a7e81..c80be72 100644 --- a/core/modules/user/lib/Drupal/user/ProfileFormController.php +++ b/core/modules/user/lib/Drupal/user/ProfileFormController.php @@ -55,7 +55,7 @@ class ProfileFormController extends AccountFormController { // Clear the page cache because pages can contain usernames and/or profile // information: - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); drupal_set_message(t('The changes have been saved.')); } diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc index f9b1c23..1feffd4 100644 --- a/core/modules/user/user.admin.inc +++ b/core/modules/user/user.admin.inc @@ -776,7 +776,7 @@ function user_admin_permissions_submit($form, &$form_state) { drupal_set_message(t('The changes have been saved.')); // Clear the cached pages and blocks. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 3b69966..cfcecf2 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1969,7 +1969,7 @@ function _user_cancel($edit, $account, $method) { } // Clear the cache for anonymous users. - cache_invalidate(array('content' => TRUE)); + cache_invalidate_tags(array('content' => TRUE)); } /** diff --git a/core/update.php b/core/update.php index 52cf3d0..941f2ec 100644 --- a/core/update.php +++ b/core/update.php @@ -267,7 +267,7 @@ function update_info_page() { _drupal_flush_css_js(); // Flush the cache of all data for the update status module. if (db_table_exists('cache_update')) { - cache('update')->flush(); + cache('update')->deleteAll(); } update_task_list('info');