Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 81 |
ApcuBackend | |
0.00% |
0 / 1 |
|
0.00% |
0 / 17 |
1056 | |
0.00% |
0 / 81 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
getApcuKey | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
get | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
getMultiple | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 18 |
|||
getAll | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
prepareItem | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 13 |
|||
set | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 12 |
|||
setMultiple | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 4 |
|||
delete | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
deleteMultiple | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
deleteAll | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
garbageCollection | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
removeBin | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
invalidate | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
invalidateMultiple | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
invalidateAll | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
getIterator | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Cache\ApcuBackend. | |
*/ | |
namespace Drupal\Core\Cache; | |
/** | |
* Stores cache items in the Alternative PHP Cache User Cache (APCu). | |
*/ | |
class ApcuBackend implements CacheBackendInterface { | |
/** | |
* The name of the cache bin to use. | |
* | |
* @var string | |
*/ | |
protected $bin; | |
/** | |
* Prefix for all keys in the storage that belong to this site. | |
* | |
* @var string | |
*/ | |
protected $sitePrefix; | |
/** | |
* Prefix for all keys in this cache bin. | |
* | |
* Includes the site-specific prefix in $sitePrefix. | |
* | |
* @var string | |
*/ | |
protected $binPrefix; | |
/** | |
* The cache tags checksum provider. | |
* | |
* @var \Drupal\Core\Cache\CacheTagsChecksumInterface | |
*/ | |
protected $checksumProvider; | |
/** | |
* Constructs a new ApcuBackend instance. | |
* | |
* @param string $bin | |
* The name of the cache bin. | |
* @param string $site_prefix | |
* The prefix to use for all keys in the storage that belong to this site. | |
* @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider | |
* The cache tags checksum provider. | |
*/ | |
public function __construct($bin, $site_prefix, CacheTagsChecksumInterface $checksum_provider) { | |
$this->bin = $bin; | |
$this->sitePrefix = $site_prefix; | |
$this->checksumProvider = $checksum_provider; | |
$this->binPrefix = $this->sitePrefix . '::' . $this->bin . '::'; | |
} | |
/** | |
* Prepends the APCu user variable prefix for this bin to a cache item ID. | |
* | |
* @param string $cid | |
* The cache item ID to prefix. | |
* | |
* @return string | |
* The APCu key for the cache item ID. | |
*/ | |
public function getApcuKey($cid) { | |
return $this->binPrefix . $cid; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function get($cid, $allow_invalid = FALSE) { | |
$cache = apcu_fetch($this->getApcuKey($cid)); | |
return $this->prepareItem($cache, $allow_invalid); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getMultiple(&$cids, $allow_invalid = FALSE) { | |
// Translate the requested cache item IDs to APCu keys. | |
$map = array(); | |
foreach ($cids as $cid) { | |
$map[$this->getApcuKey($cid)] = $cid; | |
} | |
$result = apcu_fetch(array_keys($map)); | |
$cache = array(); | |
if ($result) { | |
foreach ($result as $key => $item) { | |
$item = $this->prepareItem($item, $allow_invalid); | |
if ($item) { | |
$cache[$map[$key]] = $item; | |
} | |
} | |
} | |
unset($result); | |
$cids = array_diff($cids, array_keys($cache)); | |
return $cache; | |
} | |
/** | |
* Returns all cached items, optionally limited by a cache ID prefix. | |
* | |
* APCu is a memory cache, shared across all server processes. To prevent | |
* cache item clashes with other applications/installations, every cache item | |
* is prefixed with a unique string for this site. Therefore, functions like | |
* apcu_clear_cache() cannot be used, and instead, a list of all cache items | |
* belonging to this application need to be retrieved through this method | |
* instead. | |
* | |
* @param string $prefix | |
* (optional) A cache ID prefix to limit the result to. | |
* | |
* @return \APCUIterator | |
* An APCUIterator containing matched items. | |
*/ | |
protected function getAll($prefix = '') { | |
return $this->getIterator('/^' . preg_quote($this->getApcuKey($prefix), '/') . '/'); | |
} | |
/** | |
* Prepares a cached item. | |
* | |
* Checks that the item is either permanent or did not expire. | |
* | |
* @param \stdClass $cache | |
* An item loaded from cache_get() or cache_get_multiple(). | |
* @param bool $allow_invalid | |
* If TRUE, a cache item may be returned even if it is expired or has been | |
* invalidated. See ::get(). | |
* | |
* @return mixed | |
* The cache item or FALSE if the item expired. | |
*/ | |
protected function prepareItem($cache, $allow_invalid) { | |
if (!isset($cache->data)) { | |
return FALSE; | |
} | |
$cache->tags = $cache->tags ? explode(' ', $cache->tags) : array(); | |
// Check expire time. | |
$cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME; | |
// Check if invalidateTags() has been called with any of the entry's tags. | |
if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) { | |
$cache->valid = FALSE; | |
} | |
if (!$allow_invalid && !$cache->valid) { | |
return FALSE; | |
} | |
return $cache; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) { | |
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache tags must be strings.'); | |
$tags = array_unique($tags); | |
$cache = new \stdClass(); | |
$cache->cid = $cid; | |
$cache->created = round(microtime(TRUE), 3); | |
$cache->expire = $expire; | |
$cache->tags = implode(' ', $tags); | |
$cache->checksum = $this->checksumProvider->getCurrentChecksum($tags); | |
// APCu serializes/unserializes any structure itself. | |
$cache->serialized = 0; | |
$cache->data = $data; | |
// Expiration is handled by our own prepareItem(), not APCu. | |
apcu_store($this->getApcuKey($cid), $cache); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function setMultiple(array $items = array()) { | |
foreach ($items as $cid => $item) { | |
$this->set($cid, $item['data'], isset($item['expire']) ? $item['expire'] : CacheBackendInterface::CACHE_PERMANENT, isset($item['tags']) ? $item['tags'] : array()); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function delete($cid) { | |
apcu_delete($this->getApcuKey($cid)); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function deleteMultiple(array $cids) { | |
apcu_delete(array_map(array($this, 'getApcuKey'), $cids)); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function deleteAll() { | |
apcu_delete($this->getIterator('/^' . preg_quote($this->binPrefix, '/') . '/')); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function garbageCollection() { | |
// APCu performs garbage collection automatically. | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function removeBin() { | |
apcu_delete($this->getIterator('/^' . preg_quote($this->binPrefix, '/') . '/')); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function invalidate($cid) { | |
$this->invalidateMultiple(array($cid)); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function invalidateMultiple(array $cids) { | |
foreach ($this->getMultiple($cids) as $cache) { | |
$this->set($cache->cid, $cache, REQUEST_TIME - 1); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function invalidateAll() { | |
foreach ($this->getAll() as $data) { | |
$cid = str_replace($this->binPrefix, '', $data['key']); | |
$this->set($cid, $data['value'], REQUEST_TIME - 1); | |
} | |
} | |
/** | |
* Instantiates and returns the APCUIterator class. | |
* | |
* @param mixed $search | |
* A PCRE regular expression that matches against APC key names, either as a | |
* string for a single regular expression, or as an array of regular | |
* expressions. Or, optionally pass in NULL to skip the search. | |
* @param int $format | |
* The desired format, as configured with one or more of the APC_ITER_* | |
* constants. | |
* @param int $chunk_size | |
* The chunk size. Must be a value greater than 0. The default value is 100. | |
* @param int $list | |
* The type to list. Either pass in APC_LIST_ACTIVE or APC_LIST_DELETED. | |
* | |
* @return \APCUIterator | |
*/ | |
protected function getIterator($search = NULL, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) { | |
return new \APCUIterator($search, $format, $chunk_size, $list); | |
} | |
} |