Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/voku/cache/AdapterApc.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,26 @@ public function removeAll(): bool
return (bool) ($this->cacheClear('system') && $this->cacheClear('user'));
}

/**
* {@inheritdoc}
*/
public function getAllKeys(): array
{
$info = $this->cacheInfo('user');
if (empty($info['cache_list'])) {
return [];
}

$keys = [];
foreach ($info['cache_list'] as $entry) {
if (isset($entry['info'])) {
$keys[] = (string) $entry['info'];
}
}

return $keys;
}

/**
* {@inheritdoc}
*/
Expand Down
20 changes: 20 additions & 0 deletions src/voku/cache/AdapterApcu.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,26 @@ public function removeAll(): bool
return (bool) ($this->cacheClear('system') && $this->cacheClear('user'));
}

/**
* {@inheritdoc}
*/
public function getAllKeys(): array
{
$info = $this->cacheInfo();
if (empty($info['cache_list'])) {
return [];
}

$keys = [];
foreach ($info['cache_list'] as $entry) {
if (isset($entry['key'])) {
$keys[] = (string) $entry['key'];
}
}

return $keys;
}

/**
* {@inheritdoc}
*/
Expand Down
8 changes: 8 additions & 0 deletions src/voku/cache/AdapterArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ public function removeAll(): bool
return true;
}

/**
* {@inheritdoc}
*/
public function getAllKeys(): array
{
return \array_keys(self::$values);
}

/**
* {@inheritdoc}
*/
Expand Down
42 changes: 42 additions & 0 deletions src/voku/cache/AdapterFileAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,48 @@ public function removeAll(): bool
return \in_array(false, $return, true) === false;
}

/**
* {@inheritdoc}
*
* <p>Scans the cache directory and returns the store keys of all currently cached files
* by stripping CACHE_FILE_PREFIX and CACHE_FILE_SUBFIX from each filename.
* When used through the {@link Cache} class the keys will be MD5 hashes because
* {@link Cache::calculateStoreKey()} hashes the raw key for file-based adapters.</p>
*/
public function getAllKeys(): array
{
if (!$this->cacheDir || !\is_dir($this->cacheDir)) {
return [];
}

$prefix = self::CACHE_FILE_PREFIX;
$suffix = self::CACHE_FILE_SUBFIX;
$prefixLen = \strlen($prefix);
$suffixLen = \strlen($suffix);
$keys = [];

foreach (new \DirectoryIterator($this->cacheDir) as $fileInfo) {
if ($fileInfo->isDot() || !$fileInfo->isFile()) {
continue;
}

$filename = $fileInfo->getFilename();

if (
\str_starts_with($filename, $prefix)
&&
\str_ends_with($filename, $suffix)
) {
$key = \substr($filename, $prefixLen, -$suffixLen);
if ($key !== '') {
$keys[] = $key;
}
}
}

return $keys;
}

/**
* {@inheritdoc}
*/
Expand Down
91 changes: 88 additions & 3 deletions src/voku/cache/AdapterMemcache.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
*/
class AdapterMemcache implements iAdapter
{
/**
* Internal key used to persist the key registry inside Memcache.
* Not intended for use by application code.
*/
private const KEYS_REGISTRY_KEY = '__memcache_adapter_keys__';

/**
* @var bool
*/
Expand Down Expand Up @@ -77,17 +83,41 @@ public function installed(): bool
*/
public function remove(string $key): bool
{
return $this->memcache->delete($key);
$result = $this->memcache->delete($key);

$keys = $this->getKeysRegistry();
$filtered = \array_values(\array_diff($keys, [$key]));
if (\count($filtered) !== \count($keys)) {
$this->saveKeysRegistry($filtered);
}

return $result;
}

/**
* {@inheritdoc}
*
* <p>Calling flush() clears the entire Memcache backend, which includes the key
* registry stored under {@link KEYS_REGISTRY_KEY}. The registry is therefore
* implicitly empty after this call, consistent with the contract of getAllKeys().</p>
*/
public function removeAll(): bool
{
return $this->memcache->flush();
}

/**
* {@inheritdoc}
*
* <p>Returns the list of keys that have been stored through this adapter instance.
* The registry is maintained inside Memcache under an internal key and is updated
* on every {@link set()}, {@link setExpired()}, and {@link remove()} call.</p>
*/
public function getAllKeys(): array
{
return $this->getKeysRegistry();
}

/**
* {@inheritdoc}
*/
Expand All @@ -98,7 +128,17 @@ public function set(string $key, $value): bool
throw new InvalidArgumentException('The passed cache key is over 250 bytes:' . \print_r($key, true));
}

return $this->memcache->set($key, $value, $this->getCompressedFlag());
$result = $this->memcache->set($key, $value, $this->getCompressedFlag());

if ($result) {
$keys = $this->getKeysRegistry();
if (!\in_array($key, $keys, true)) {
$keys[] = $key;
$this->saveKeysRegistry($keys);
}
}

return $result;
}

/**
Expand All @@ -110,7 +150,17 @@ public function setExpired(string $key, $value, int $ttl = 0): bool
$ttl = 2592000;
}

return $this->memcache->set($key, $value, $this->getCompressedFlag(), $ttl);
$result = $this->memcache->set($key, $value, $this->getCompressedFlag(), $ttl);

if ($result) {
$keys = $this->getKeysRegistry();
if (!\in_array($key, $keys, true)) {
$keys[] = $key;
$this->saveKeysRegistry($keys);
}
}

return $result;
}

/**
Expand Down Expand Up @@ -142,4 +192,39 @@ public function setCompressed($value)
{
$this->compressed = (bool) $value;
}

/**
* Read the key registry stored inside Memcache.
*
* @return string[]
*/
private function getKeysRegistry(): array
{
$stored = $this->memcache->get(self::KEYS_REGISTRY_KEY);
if ($stored === false || !\is_string($stored)) {
return [];
}

$keys = @\unserialize($stored, ['allowed_classes' => false]);

return \is_array($keys) ? $keys : [];
}

/**
* Persist the key registry into Memcache (no TTL so it survives as long as the server allows).
*
* @param string[] $keys
*
* @return void
*/
private function saveKeysRegistry(array $keys): void
{
if (empty($keys)) {
$this->memcache->delete(self::KEYS_REGISTRY_KEY);

return;
}

$this->memcache->set(self::KEYS_REGISTRY_KEY, \serialize(\array_values($keys)), 0, 0);
}
}
13 changes: 13 additions & 0 deletions src/voku/cache/AdapterMemcached.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ public function removeAll(): bool
return $this->memcached->flush();
}

/**
* {@inheritdoc}
*/
public function getAllKeys(): array
{
$keys = $this->memcached->getAllKeys();
if ($keys === false) {
return [];
}

return $keys;
}

/**
* {@inheritdoc}
*/
Expand Down
44 changes: 44 additions & 0 deletions src/voku/cache/AdapterOpCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,48 @@

return $result;
}

/**
* {@inheritdoc}
*
* <p>Overrides the base implementation because {@link AdapterOpCache} stores files with a
* <code>.php</code> extension instead of the <code>.php.cache</code> extension used by
* the other file-based adapters.</p>
*/
public function getAllKeys(): array

Check warning on line 140 in src/voku/cache/AdapterOpCache.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/voku/cache/AdapterOpCache.php#L140

The method getAllKeys() has a Cyclomatic Complexity of 10. The configured cyclomatic complexity threshold is 10.
{
if (!$this->cacheDir || !\is_dir($this->cacheDir)) {
return [];
}

$prefix = static::CACHE_FILE_PREFIX;
$suffix = '.php';
$prefixLen = \strlen($prefix);
$suffixLen = \strlen($suffix);
$keys = [];

foreach (new \DirectoryIterator($this->cacheDir) as $fileInfo) {
if ($fileInfo->isDot() || !$fileInfo->isFile()) {
continue;
}

$filename = $fileInfo->getFilename();

// Match __simple_KEY.php but not __simple_KEY.php.cache
if (
\str_starts_with($filename, $prefix)
&&
\str_ends_with($filename, $suffix)
&&
!\str_ends_with($filename, '.php.cache')
) {
$key = \substr($filename, $prefixLen, -$suffixLen);
if ($key !== '') {
$keys[] = $key;
}
}
}

return $keys;
}
}
11 changes: 11 additions & 0 deletions src/voku/cache/AdapterPredis.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ public function removeAll(): bool
return (bool) $this->client->flushall();
}

/**
* {@inheritdoc}
*
* <p>Uses the Redis <code>KEYS *</code> command, which scans the entire keyspace.
* This may have performance implications on large Redis datasets.</p>
*/
public function getAllKeys(): array
{
return (array) $this->client->keys('*');
}

/**
* {@inheritdoc}
*/
Expand Down
Loading