Update dependencies

This commit is contained in:
Chris Hunt
2022-11-14 19:35:16 +00:00
parent 0966639699
commit ee77d09c58
677 changed files with 9253 additions and 65635 deletions

View File

@@ -49,15 +49,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
$item->key = $key;
$item->value = $v = $value;
$item->isHit = $isHit;
// Detect wrapped values that encode for their expiry and creation duration
// For compactness, these values are packed in the key of an array using
// magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
$item->value = $v[$k];
$v = unpack('Ve/Nc', substr($k, 1, -1));
$item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
$item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
}
$item->unpack();
return $item;
},
@@ -80,11 +72,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
$expiredIds[] = $getId($key);
continue;
}
if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
unset($metadata[CacheItem::METADATA_TAGS]);
}
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
$byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
$byLifetime[$ttl][$getId($key)] = $item->pack();
}
return $byLifetime;
@@ -98,10 +86,8 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
* Returns the best possible adapter that your runtime supports.
*
* Using ApcuAdapter makes system caches compatible with read-only filesystems.
*
* @return AdapterInterface
*/
public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null)
public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null): AdapterInterface
{
$opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true);
if (null !== $logger) {
@@ -132,7 +118,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
if (str_starts_with($dsn, 'memcached:')) {
return MemcachedAdapter::createConnection($dsn, $options);
}
if (0 === strpos($dsn, 'couchbase:')) {
if (str_starts_with($dsn, 'couchbase:')) {
if (CouchbaseBucketAdapter::isSupported()) {
return CouchbaseBucketAdapter::createConnection($dsn, $options);
}
@@ -145,13 +131,11 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
$ok = true;
$byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, \Closure::fromCallable([$this, 'getId']), $this->defaultLifetime);
$byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, $this->getId(...), $this->defaultLifetime);
$retry = $this->deferred = [];
if ($expiredIds) {

View File

@@ -56,7 +56,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
$item->isHit = $isHit;
// Extract value, tags and meta data from the cache value
$item->value = $value['value'];
$item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? [];
$item->metadata[CacheItem::METADATA_TAGS] = isset($value['tags']) ? array_combine($value['tags'], $value['tags']) : [];
if (isset($value['meta'])) {
// For compactness these values are packed, & expiry is offset to reduce size
$v = unpack('Ve/Nc', $value['meta']);
@@ -95,18 +95,19 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
if ($metadata) {
// For compactness, expiry and creation duration are packed, using magic numbers as separators
$value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]);
$value['meta'] = pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME]);
}
// Extract tag changes, these should be removed from values in doSave()
$value['tag-operations'] = ['add' => [], 'remove' => []];
$oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? [];
foreach (array_diff($value['tags'], $oldTags) as $addedTag) {
foreach (array_diff_key($value['tags'], $oldTags) as $addedTag) {
$value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag);
}
foreach (array_diff($oldTags, $value['tags']) as $removedTag) {
foreach (array_diff_key($oldTags, $value['tags']) as $removedTag) {
$value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag);
}
$value['tags'] = array_keys($value['tags']);
$byLifetime[$ttl][$getId($key)] = $value;
$item->metadata = $item->newMetadata;
@@ -135,10 +136,8 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
* Removes multiple items from the pool and their corresponding tags.
*
* @param array $ids An array of identifiers that should be removed from the pool
*
* @return bool
*/
abstract protected function doDelete(array $ids);
abstract protected function doDelete(array $ids): bool;
/**
* Removes relations between tags and deleted items.
@@ -172,7 +171,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
public function commit(): bool
{
$ok = true;
$byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, \Closure::fromCallable([$this, 'getId']), self::TAGS_PREFIX, $this->defaultLifetime);
$byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, $this->getId(...), self::TAGS_PREFIX, $this->defaultLifetime);
$retry = $this->deferred = [];
if ($expiredIds) {
@@ -254,7 +253,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
$tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id;
}
}
} catch (\Exception $e) {
} catch (\Exception) {
$ok = false;
}
@@ -262,7 +261,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) {
return true;
}
} catch (\Exception $e) {
} catch (\Exception) {
}
// When bulk-delete failed, retry each item individually
@@ -285,7 +284,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags)
public function invalidateTags(array $tags): bool
{
if (empty($tags)) {
return false;

View File

@@ -26,22 +26,18 @@ interface AdapterInterface extends CacheItemPoolInterface
{
/**
* {@inheritdoc}
*
* @return CacheItem
*/
public function getItem($key);
public function getItem(mixed $key): CacheItem;
/**
* {@inheritdoc}
*
* @return \Traversable<string, CacheItem>
* @return iterable<string, CacheItem>
*/
public function getItems(array $keys = []);
public function getItems(array $keys = []): iterable;
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '');
public function clear(string $prefix = ''): bool;
}

View File

@@ -20,7 +20,7 @@ use Symfony\Component\Cache\Marshaller\MarshallerInterface;
*/
class ApcuAdapter extends AbstractAdapter
{
private $marshaller;
private ?MarshallerInterface $marshaller;
/**
* @throws CacheException if APCu is not enabled
@@ -55,19 +55,12 @@ class ApcuAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
try {
$values = [];
$ids = array_flip($ids);
foreach (apcu_fetch(array_keys($ids), $ok) ?: [] as $k => $v) {
if (!isset($ids[$k])) {
// work around https://github.com/krakjoe/apcu/issues/247
$k = key($ids);
}
unset($ids[$k]);
foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
if (null !== $v || $ok) {
$values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v;
}
@@ -84,7 +77,7 @@ class ApcuAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
protected function doHave(string $id): bool
{
return apcu_exists($id);
}
@@ -92,7 +85,7 @@ class ApcuAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))
? apcu_delete(new \APCUIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY))
@@ -102,7 +95,7 @@ class ApcuAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
protected function doDelete(array $ids): bool
{
foreach ($ids as $id) {
apcu_delete($id);
@@ -114,7 +107,7 @@ class ApcuAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) {
return $failed;

View File

@@ -30,14 +30,15 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
{
use LoggerAwareTrait;
private $storeSerialized;
private $values = [];
private $expiries = [];
private $defaultLifetime;
private $maxLifetime;
private $maxItems;
private bool $storeSerialized;
private array $values = [];
private array $tags = [];
private array $expiries = [];
private int $defaultLifetime;
private float $maxLifetime;
private int $maxItems;
private static $createCacheItem;
private static \Closure $createCacheItem;
/**
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
@@ -57,11 +58,14 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
$this->maxLifetime = $maxLifetime;
$this->maxItems = $maxItems;
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
static function ($key, $value, $isHit, $tags) {
$item = new CacheItem();
$item->key = $key;
$item->value = $value;
$item->isHit = $isHit;
if (null !== $tags) {
$item->metadata[CacheItem::METADATA_TAGS] = $tags;
}
return $item;
},
@@ -73,7 +77,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
$item = $this->getItem($key);
$metadata = $item->getMetadata();
@@ -100,10 +104,8 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
if ($this->maxItems) {
@@ -123,7 +125,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
if (!$isHit = $this->hasItem($key)) {
$value = null;
@@ -136,13 +138,13 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
}
return (self::$createCacheItem)($key, $value, $isHit);
return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null);
}
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
\assert(self::validateKeys($keys));
@@ -151,23 +153,19 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
\assert('' !== CacheItem::validateKey($key));
unset($this->values[$key], $this->expiries[$key]);
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
foreach ($keys as $key) {
$this->deleteItem($key);
@@ -178,10 +176,8 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
if (!$item instanceof CacheItem) {
return false;
@@ -213,7 +209,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
}
if ($this->maxItems) {
unset($this->values[$key]);
unset($this->values[$key], $this->tags[$key]);
// Iterate items and vacuum expired ones while we are at it
foreach ($this->values as $k => $v) {
@@ -221,49 +217,47 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
break;
}
unset($this->values[$k], $this->expiries[$k]);
unset($this->values[$k], $this->tags[$k], $this->expiries[$k]);
}
}
$this->values[$key] = $value;
$this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
if (null === $this->tags[$key] = $item["\0*\0newMetadata"][CacheItem::METADATA_TAGS] ?? null) {
unset($this->tags[$key]);
}
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
return $this->save($item);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
if ('' !== $prefix) {
$now = microtime(true);
foreach ($this->values as $key => $value) {
if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || 0 === strpos($key, $prefix)) {
unset($this->values[$key], $this->expiries[$key]);
if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) {
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
}
}
@@ -272,17 +266,15 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
}
}
$this->values = $this->expiries = [];
$this->values = $this->tags = $this->expiries = [];
return true;
}
/**
* Returns all cached values, with cache miss as null.
*
* @return array
*/
public function getValues()
public function getValues(): array
{
if (!$this->storeSerialized) {
return $this->values;
@@ -331,7 +323,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
}
unset($keys[$i]);
yield $key => $f($key, $value, $isHit);
yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null);
}
foreach ($keys as $key) {
@@ -353,7 +345,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
try {
$serialized = serialize($value);
} catch (\Exception $e) {
unset($this->values[$key]);
unset($this->values[$key], $this->tags[$key]);
$type = get_debug_type($value);
$message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);

View File

@@ -33,11 +33,11 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
{
use ContractsTrait;
private $adapters = [];
private $adapterCount;
private $defaultLifetime;
private array $adapters = [];
private int $adapterCount;
private int $defaultLifetime;
private static $syncItem;
private static \Closure $syncItem;
/**
* @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items
@@ -66,11 +66,10 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
$this->adapterCount = \count($this->adapters);
$this->defaultLifetime = $defaultLifetime;
self::$syncItem ?? self::$syncItem = \Closure::bind(
self::$syncItem ??= \Closure::bind(
static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) {
$sourceItem->isTaggable = false;
$sourceMetadata = $sourceMetadata ?? $sourceItem->metadata;
unset($sourceMetadata[CacheItem::METADATA_TAGS]);
$sourceMetadata ??= $sourceItem->metadata;
$item->value = $sourceItem->value;
$item->isHit = $sourceItem->isHit;
@@ -92,7 +91,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
$doSave = true;
$callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) {
@@ -116,7 +115,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
$value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
}
if (null !== $item) {
(self::$syncItem)($lastItem = $lastItem ?? $item, $item, $this->defaultLifetime, $metadata);
(self::$syncItem)($lastItem ??= $item, $item, $this->defaultLifetime, $metadata);
}
$save = $doSave;
@@ -129,7 +128,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
$syncItem = self::$syncItem;
$misses = [];
@@ -154,7 +153,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
return $this->generateItems($this->adapters[0]->getItems($keys), 0);
}
@@ -192,10 +191,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
foreach ($this->adapters as $adapter) {
if ($adapter->hasItem($key)) {
@@ -208,10 +205,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
$cleared = true;
$i = $this->adapterCount;
@@ -229,10 +224,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
$deleted = true;
$i = $this->adapterCount;
@@ -246,10 +239,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
$deleted = true;
$i = $this->adapterCount;
@@ -263,10 +254,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
$saved = true;
$i = $this->adapterCount;
@@ -280,10 +269,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
$saved = true;
$i = $this->adapterCount;
@@ -297,10 +284,8 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
$committed = true;
$i = $this->adapterCount;
@@ -315,7 +300,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function prune()
public function prune(): bool
{
$pruned = true;

View File

@@ -36,8 +36,8 @@ class CouchbaseBucketAdapter extends AbstractAdapter
'durabilityTimeout',
];
private $bucket;
private $marshaller;
private \CouchbaseBucket $bucket;
private MarshallerInterface $marshaller;
public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
@@ -54,15 +54,10 @@ class CouchbaseBucketAdapter extends AbstractAdapter
$this->marshaller = $marshaller ?? new DefaultMarshaller();
}
/**
* @param array|string $servers
*/
public static function createConnection($servers, array $options = []): \CouchbaseBucket
public static function createConnection(array|string $servers, array $options = []): \CouchbaseBucket
{
if (\is_string($servers)) {
$servers = [$servers];
} elseif (!\is_array($servers)) {
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($servers)));
}
if (!static::isSupported()) {
@@ -82,7 +77,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter
$password = $options['password'];
foreach ($servers as $dsn) {
if (0 !== strpos($dsn, 'couchbase:')) {
if (!str_starts_with($dsn, 'couchbase:')) {
throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $dsn));
}
@@ -164,7 +159,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
$resultsCouchbase = $this->bucket->get($ids);
@@ -221,7 +216,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
if (!$values = $this->marshaller->marshall($values, $failed)) {
return $failed;

View File

@@ -29,9 +29,8 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
{
private const MAX_KEY_LENGTH = 250;
/** @var Collection */
private $connection;
private $marshaller;
private Collection $connection;
private MarshallerInterface $marshaller;
public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
@@ -48,17 +47,10 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
$this->marshaller = $marshaller ?? new DefaultMarshaller();
}
/**
* @param array|string $dsn
*
* @return Bucket|Collection
*/
public static function createConnection($dsn, array $options = [])
public static function createConnection(array|string $dsn, array $options = []): Bucket|Collection
{
if (\is_string($dsn)) {
$dsn = [$dsn];
} elseif (!\is_array($dsn)) {
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($dsn)));
}
if (!static::isSupported()) {
@@ -78,7 +70,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
$password = $options['password'] ?? '';
foreach ($dsn as $server) {
if (0 !== strpos($server, 'couchbase:')) {
if (!str_starts_with($server, 'couchbase:')) {
throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $server));
}
@@ -148,7 +140,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
foreach ($ids as $id) {
try {
$resultCouchbase = $this->connection->get($id);
} catch (DocumentNotFoundException $exception) {
} catch (DocumentNotFoundException) {
continue;
}
@@ -189,7 +181,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
if (null === $result->mutationToken()) {
$idsErrors[] = $id;
}
} catch (DocumentNotFoundException $exception) {
} catch (DocumentNotFoundException) {
}
}
@@ -199,7 +191,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doSave(array $values, $lifetime)
protected function doSave(array $values, $lifetime): array|bool
{
if (!$values = $this->marshaller->marshall($values, $failed)) {
return $failed;
@@ -212,7 +204,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter
foreach ($values as $key => $value) {
try {
$this->connection->upsert($key, $value, $upsertOptions);
} catch (\Exception $exception) {
} catch (\Exception) {
$ko[$key] = '';
}
}

View File

@@ -1,110 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Cache\Adapter;
use Doctrine\Common\Cache\CacheProvider;
use Doctrine\Common\Cache\Psr6\CacheAdapter;
/**
* @author Nicolas Grekas <p@tchwork.com>
*
* @deprecated Since Symfony 5.4, use Doctrine\Common\Cache\Psr6\CacheAdapter instead
*/
class DoctrineAdapter extends AbstractAdapter
{
private $provider;
public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
{
trigger_deprecation('symfony/cache', '5.4', '"%s" is deprecated, use "%s" instead.', __CLASS__, CacheAdapter::class);
parent::__construct('', $defaultLifetime);
$this->provider = $provider;
$provider->setNamespace($namespace);
}
/**
* {@inheritdoc}
*/
public function reset()
{
parent::reset();
$this->provider->setNamespace($this->provider->getNamespace());
}
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
{
$unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback');
try {
return $this->provider->fetchMultiple($ids);
} catch (\Error $e) {
$trace = $e->getTrace();
if (isset($trace[0]['function']) && !isset($trace[0]['class'])) {
switch ($trace[0]['function']) {
case 'unserialize':
case 'apcu_fetch':
case 'apc_fetch':
throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
}
}
throw $e;
} finally {
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
}
}
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
{
return $this->provider->contains($id);
}
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
{
$namespace = $this->provider->getNamespace();
return isset($namespace[0])
? $this->provider->deleteAll()
: $this->provider->flushAll();
}
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
{
$ok = true;
foreach ($ids as $id) {
$ok = $this->provider->delete($id) && $ok;
}
return $ok;
}
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
{
return $this->provider->saveMultiple($values, $lifetime);
}
}

View File

@@ -27,16 +27,16 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
{
protected $maxIdLength = 255;
private $marshaller;
private $conn;
private $platformName;
private $serverVersion;
private $table = 'cache_items';
private $idCol = 'item_id';
private $dataCol = 'item_data';
private $lifetimeCol = 'item_lifetime';
private $timeCol = 'item_time';
private $namespace;
private MarshallerInterface $marshaller;
private Connection $conn;
private string $platformName;
private string $serverVersion;
private string $table = 'cache_items';
private string $idCol = 'item_id';
private string $dataCol = 'item_data';
private string $lifetimeCol = 'item_lifetime';
private string $timeCol = 'item_time';
private string $namespace;
/**
* You can either pass an existing database Doctrine DBAL Connection or
@@ -52,11 +52,9 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
* * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
* * db_time_col: The column where to store the timestamp [default: item_time]
*
* @param Connection|string $connOrDsn
*
* @throws InvalidArgumentException When namespace contains invalid characters
*/
public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
public function __construct(Connection|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
{
if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
@@ -64,13 +62,11 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
if ($connOrDsn instanceof Connection) {
$this->conn = $connOrDsn;
} elseif (\is_string($connOrDsn)) {
} else {
if (!class_exists(DriverManager::class)) {
throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $connOrDsn));
}
$this->conn = DriverManager::getConnection(['url' => $connOrDsn]);
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be "%s" or string, "%s" given.', __METHOD__, Connection::class, get_debug_type($connOrDsn)));
}
$this->table = $options['db_table'] ?? $this->table;
@@ -92,7 +88,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
*
* @throws DBALException When the table already exists
*/
public function createTable()
public function createTable(): void
{
$schema = new Schema();
$this->addTableToSchema($schema);
@@ -136,7 +132,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
try {
$this->conn->executeStatement($deleteSql, $params, $paramTypes);
} catch (TableNotFoundException $e) {
} catch (TableNotFoundException) {
}
return true;
@@ -213,7 +209,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
try {
$this->conn->executeStatement($sql);
} catch (TableNotFoundException $e) {
} catch (TableNotFoundException) {
}
return true;
@@ -227,7 +223,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
$sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)";
try {
$this->conn->executeStatement($sql, [array_values($ids)], [Connection::PARAM_STR_ARRAY]);
} catch (TableNotFoundException $e) {
} catch (TableNotFoundException) {
}
return true;
@@ -236,7 +232,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
if (!$values = $this->marshaller->marshall($values, $failed)) {
return $failed;
@@ -278,7 +274,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
$lifetime = $lifetime ?: null;
try {
$stmt = $this->conn->prepare($sql);
} catch (TableNotFoundException $e) {
} catch (TableNotFoundException) {
if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
$this->createTable();
}
@@ -316,7 +312,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
foreach ($values as $id => $data) {
try {
$rowCount = $stmt->executeStatement();
} catch (TableNotFoundException $e) {
} catch (TableNotFoundException) {
if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
$this->createTable();
}
@@ -325,7 +321,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
if (null === $platformName && 0 === $rowCount) {
try {
$insertStmt->executeStatement();
} catch (DBALException $e) {
} catch (DBALException) {
// A concurrent write won, let it be
}
}
@@ -342,28 +338,17 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
$platform = $this->conn->getDatabasePlatform();
switch (true) {
case $platform instanceof \Doctrine\DBAL\Platforms\MySQLPlatform:
case $platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform:
return $this->platformName = 'mysql';
case $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform:
return $this->platformName = 'sqlite';
case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform:
case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform:
return $this->platformName = 'pgsql';
case $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform:
return $this->platformName = 'oci';
case $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform:
case $platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform:
return $this->platformName = 'sqlsrv';
default:
return $this->platformName = \get_class($platform);
}
return match (true) {
$platform instanceof \Doctrine\DBAL\Platforms\MySQLPlatform,
$platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform => $this->platformName = 'mysql',
$platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform => $this->platformName = 'sqlite',
$platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform,
$platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform => $this->platformName = 'pgsql',
$platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => $this->platformName = 'oci',
$platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform,
$platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform => $this->platformName = 'sqlsrv',
default => $this->platformName = \get_class($platform),
};
}
private function getServerVersion(): string

View File

@@ -44,7 +44,7 @@ class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements Prune
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
$ok = $this->doClearCache($namespace);
@@ -140,7 +140,7 @@ class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements Prune
continue;
}
if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) {
if (!@unlink($file)) {
fclose($h);
continue;
}
@@ -159,16 +159,12 @@ class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements Prune
try {
yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta);
} catch (\Exception $e) {
} catch (\Exception) {
yield $id => [];
}
}
fclose($h);
if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) {
@unlink($file);
}
}
}

View File

@@ -39,9 +39,9 @@ class MemcachedAdapter extends AbstractAdapter
\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP,
];
private $marshaller;
private $client;
private $lazyClient;
private MarshallerInterface $marshaller;
private \Memcached $client;
private \Memcached $lazyClient;
/**
* Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged.
@@ -90,11 +90,9 @@ class MemcachedAdapter extends AbstractAdapter
*
* @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs
*
* @return \Memcached
*
* @throws \ErrorException When invalid options or servers are provided
*/
public static function createConnection($servers, array $options = [])
public static function createConnection(array|string $servers, array $options = []): \Memcached
{
if (\is_string($servers)) {
$servers = [$servers];
@@ -242,7 +240,7 @@ class MemcachedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
if (!$values = $this->marshaller->marshall($values, $failed)) {
return $failed;
@@ -263,7 +261,7 @@ class MemcachedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
try {
$encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
@@ -284,7 +282,7 @@ class MemcachedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
protected function doHave(string $id): bool
{
return false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
}
@@ -292,7 +290,7 @@ class MemcachedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
protected function doDelete(array $ids): bool
{
$ok = true;
$encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
@@ -308,12 +306,12 @@ class MemcachedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
return '' === $namespace && $this->getClient()->flush();
}
private function checkResultCode($result)
private function checkResultCode(mixed $result)
{
$code = $this->client->getResultCode();
@@ -326,7 +324,7 @@ class MemcachedAdapter extends AbstractAdapter
private function getClient(): \Memcached
{
if ($this->client) {
if (isset($this->client)) {
return $this->client;
}

View File

@@ -40,7 +40,7 @@ class NullAdapter implements AdapterInterface, CacheInterface
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
$save = true;
@@ -50,7 +50,7 @@ class NullAdapter implements AdapterInterface, CacheInterface
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
return (self::$createCacheItem)($key);
}
@@ -58,77 +58,63 @@ class NullAdapter implements AdapterInterface, CacheInterface
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
return $this->generateItems($keys);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
return false;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
return true;
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
return true;
}

View File

@@ -12,9 +12,6 @@
namespace Symfony\Component\Cache\Adapter;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
use Psr\Cache\CacheItemInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
@@ -24,22 +21,20 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
{
protected $maxIdLength = 255;
private $marshaller;
private $conn;
private $dsn;
private $driver;
private $serverVersion;
private $table = 'cache_items';
private $idCol = 'item_id';
private $dataCol = 'item_data';
private $lifetimeCol = 'item_lifetime';
private $timeCol = 'item_time';
private $username = '';
private $password = '';
private $connectionOptions = [];
private $namespace;
private $dbalAdapter;
private MarshallerInterface $marshaller;
private \PDO|Connection $conn;
private string $dsn;
private string $driver;
private string $serverVersion;
private mixed $table = 'cache_items';
private mixed $idCol = 'item_id';
private mixed $dataCol = 'item_data';
private mixed $lifetimeCol = 'item_lifetime';
private mixed $timeCol = 'item_time';
private mixed $username = '';
private mixed $password = '';
private mixed $connectionOptions = [];
private string $namespace;
/**
* You can either pass an existing database connection as PDO instance or
@@ -56,19 +51,14 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
* * db_password: The password when lazy-connect [default: '']
* * db_connection_options: An array of driver-specific connection options [default: []]
*
* @param \PDO|string $connOrDsn
*
* @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
* @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
* @throws InvalidArgumentException When namespace contains invalid characters
*/
public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
public function __construct(\PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
{
if ($connOrDsn instanceof Connection || (\is_string($connOrDsn) && str_contains($connOrDsn, '://'))) {
trigger_deprecation('symfony/cache', '5.4', 'Usage of a DBAL Connection with "%s" is deprecated and will be removed in symfony 6.0. Use "%s" instead.', __CLASS__, DoctrineDbalAdapter::class);
$this->dbalAdapter = new DoctrineDbalAdapter($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller);
return;
if (\is_string($connOrDsn) && str_contains($connOrDsn, '://')) {
throw new InvalidArgumentException(sprintf('Usage of Doctrine DBAL URL with "%s" is not supported. Use a PDO DSN or "%s" instead. Got "%s".', __CLASS__, DoctrineDbalAdapter::class, $connOrDsn));
}
if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
@@ -81,10 +71,8 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
}
$this->conn = $connOrDsn;
} elseif (\is_string($connOrDsn)) {
$this->dsn = $connOrDsn;
} else {
throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, get_debug_type($connOrDsn)));
$this->dsn = $connOrDsn;
}
$this->table = $options['db_table'] ?? $this->table;
@@ -101,166 +89,6 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
parent::__construct($namespace, $defaultLifetime);
}
/**
* {@inheritDoc}
*/
public function getItem($key)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->getItem($key);
}
return parent::getItem($key);
}
/**
* {@inheritDoc}
*/
public function getItems(array $keys = [])
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->getItems($keys);
}
return parent::getItems($keys);
}
/**
* {@inheritDoc}
*/
public function hasItem($key)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->hasItem($key);
}
return parent::hasItem($key);
}
/**
* {@inheritDoc}
*/
public function deleteItem($key)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->deleteItem($key);
}
return parent::deleteItem($key);
}
/**
* {@inheritDoc}
*/
public function deleteItems(array $keys)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->deleteItems($keys);
}
return parent::deleteItems($keys);
}
/**
* {@inheritDoc}
*/
public function clear(string $prefix = '')
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->clear($prefix);
}
return parent::clear($prefix);
}
/**
* {@inheritDoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->get($key, $callback, $beta, $metadata);
}
return parent::get($key, $callback, $beta, $metadata);
}
/**
* {@inheritDoc}
*/
public function delete(string $key): bool
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->delete($key);
}
return parent::delete($key);
}
/**
* {@inheritDoc}
*/
public function save(CacheItemInterface $item)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->save($item);
}
return parent::save($item);
}
/**
* {@inheritDoc}
*/
public function saveDeferred(CacheItemInterface $item)
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->saveDeferred($item);
}
return parent::saveDeferred($item);
}
/**
* {@inheritDoc}
*/
public function setLogger(LoggerInterface $logger): void
{
if (isset($this->dbalAdapter)) {
$this->dbalAdapter->setLogger($logger);
return;
}
parent::setLogger($logger);
}
/**
* {@inheritDoc}
*/
public function commit()
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->commit();
}
return parent::commit();
}
/**
* {@inheritDoc}
*/
public function reset()
{
if (isset($this->dbalAdapter)) {
$this->dbalAdapter->reset();
return;
}
parent::reset();
}
/**
* Creates the table to store cache items which can be called once for setup.
*
@@ -272,64 +100,31 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
*/
public function createTable()
{
if (isset($this->dbalAdapter)) {
$this->dbalAdapter->createTable();
return;
}
// connect if we are not yet
$conn = $this->getConnection();
switch ($this->driver) {
case 'mysql':
// We use varbinary for the ID column because it prevents unwanted conversions:
// - character set conversions between server and client
// - trailing space removal
// - case-insensitivity
// - language processing like é == e
$sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB";
break;
case 'sqlite':
$sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
break;
case 'pgsql':
$sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
break;
case 'oci':
$sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
break;
case 'sqlsrv':
$sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
break;
default:
throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver));
}
$sql = match ($this->driver) {
// We use varbinary for the ID column because it prevents unwanted conversions:
// - character set conversions between server and client
// - trailing space removal
// - case-insensitivity
// - language processing like é == e
'mysql' => "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB",
'sqlite' => "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)",
'pgsql' => "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)",
'oci' => "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)",
'sqlsrv' => "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)",
default => throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)),
};
$conn->exec($sql);
}
/**
* Adds the Table to the Schema if the adapter uses this Connection.
*
* @deprecated since symfony/cache 5.4 use DoctrineDbalAdapter instead
*/
public function configureSchema(Schema $schema, Connection $forConnection): void
{
if (isset($this->dbalAdapter)) {
$this->dbalAdapter->configureSchema($schema, $forConnection);
}
}
/**
* {@inheritdoc}
*/
public function prune()
public function prune(): bool
{
if (isset($this->dbalAdapter)) {
return $this->dbalAdapter->prune();
}
$deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time";
if ('' !== $this->namespace) {
@@ -340,7 +135,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
try {
$delete = $connection->prepare($deleteSql);
} catch (\PDOException $e) {
} catch (\PDOException) {
return true;
}
$delete->bindValue(':time', time(), \PDO::PARAM_INT);
@@ -350,7 +145,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
}
try {
return $delete->execute();
} catch (\PDOException $e) {
} catch (\PDOException) {
return true;
}
}
@@ -358,7 +153,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
$connection = $this->getConnection();
@@ -404,7 +199,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
protected function doHave(string $id): bool
{
$connection = $this->getConnection();
@@ -421,7 +216,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
$conn = $this->getConnection();
@@ -437,7 +232,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
try {
$conn->exec($sql);
} catch (\PDOException $e) {
} catch (\PDOException) {
}
return true;
@@ -446,14 +241,14 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
protected function doDelete(array $ids): bool
{
$sql = str_pad('', (\count($ids) << 1) - 1, '?,');
$sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)";
try {
$stmt = $this->getConnection()->prepare($sql);
$stmt->execute(array_values($ids));
} catch (\PDOException $e) {
} catch (\PDOException) {
}
return true;
@@ -462,7 +257,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
if (!$values = $this->marshaller->marshall($values, $failed)) {
return $failed;
@@ -506,7 +301,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
$lifetime = $lifetime ?: null;
try {
$stmt = $conn->prepare($sql);
} catch (\PDOException $e) {
} catch (\PDOException) {
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
$this->createTable();
}
@@ -541,7 +336,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
foreach ($values as $id => $data) {
try {
$stmt->execute();
} catch (\PDOException $e) {
} catch (\PDOException) {
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
$this->createTable();
}
@@ -550,7 +345,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
if (null === $driver && !$stmt->rowCount()) {
try {
$insertStmt->execute();
} catch (\PDOException $e) {
} catch (\PDOException) {
// A concurrent write won, let it be
}
}
@@ -561,23 +356,17 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
private function getConnection(): \PDO
{
if (null === $this->conn) {
if (!isset($this->conn)) {
$this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions);
$this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
if (null === $this->driver) {
$this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME);
}
$this->driver ??= $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME);
return $this->conn;
}
private function getServerVersion(): string
{
if (null === $this->serverVersion) {
$this->serverVersion = $this->conn->getAttribute(\PDO::ATTR_SERVER_VERSION);
}
return $this->serverVersion;
return $this->serverVersion ??= $this->conn->getAttribute(\PDO::ATTR_SERVER_VERSION);
}
}

View File

@@ -34,12 +34,12 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
use ContractsTrait;
use ProxyTrait;
private $file;
private $keys;
private $values;
private string $file;
private array $keys;
private array $values;
private static $createCacheItem;
private static $valuesCache = [];
private static \Closure $createCacheItem;
private static array $valuesCache = [];
/**
* @param string $file The PHP file were values are cached
@@ -68,10 +68,8 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
*
* @param string $file The PHP file were values are cached
* @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit
*
* @return CacheItemPoolInterface
*/
public static function create(string $file, CacheItemPoolInterface $fallbackPool)
public static function create(string $file, CacheItemPoolInterface $fallbackPool): CacheItemPoolInterface
{
if (!$fallbackPool instanceof AdapterInterface) {
$fallbackPool = new ProxyAdapter($fallbackPool);
@@ -83,9 +81,9 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
if (!isset($this->keys[$key])) {
@@ -105,7 +103,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
if ($value instanceof \Closure) {
return $value();
}
} catch (\Throwable $e) {
} catch (\Throwable) {
unset($this->keys[$key]);
goto get_from_pool;
}
@@ -116,12 +114,12 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
if (!\is_string($key)) {
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
}
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
if (!isset($this->keys[$key])) {
@@ -136,7 +134,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
} elseif ($value instanceof \Closure) {
try {
$value = $value();
} catch (\Throwable $e) {
} catch (\Throwable) {
$value = null;
$isHit = false;
}
@@ -148,14 +146,14 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
foreach ($keys as $key) {
if (!\is_string($key)) {
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
}
}
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -164,15 +162,13 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
if (!\is_string($key)) {
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
}
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -181,15 +177,13 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
if (!\is_string($key)) {
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
}
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -198,10 +192,8 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
$deleted = true;
$fallbackKeys = [];
@@ -217,7 +209,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
$fallbackKeys[] = $key;
}
}
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -230,12 +222,10 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -244,12 +234,10 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
if (null === $this->values) {
if (!isset($this->values)) {
$this->initialize();
}
@@ -258,20 +246,16 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
return $this->pool->commit();
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
$this->keys = $this->values = [];
@@ -292,7 +276,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
*
* @return string[] A list of classes to preload on PHP 7.4+
*/
public function warmUp(array $values)
public function warmUp(array $values): array
{
if (file_exists($this->file)) {
if (!is_file($this->file)) {
@@ -417,7 +401,7 @@ EOF;
} elseif ($value instanceof \Closure) {
try {
yield $key => $f($key, $value(), true);
} catch (\Throwable $e) {
} catch (\Throwable) {
yield $key => $f($key, null, false);
}
} else {

View File

@@ -29,13 +29,13 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
doDelete as private doCommonDelete;
}
private $includeHandler;
private $appendOnly;
private $values = [];
private $files = [];
private \Closure $includeHandler;
private bool $appendOnly;
private array $values = [];
private array $files = [];
private static $startTime;
private static $valuesCache = [];
private static int $startTime;
private static array $valuesCache = [];
/**
* @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
@@ -61,10 +61,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN));
}
/**
* @return bool
*/
public function prune()
public function prune(): bool
{
$time = time();
$pruned = true;
@@ -95,7 +92,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
if ($this->appendOnly) {
$now = 0;
@@ -138,7 +135,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
foreach ($missingIds as $k => $id) {
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
$file = $this->files[$id] ??= $this->getFile($id);
if (isset(self::$valuesCache[$file])) {
[$expiresAt, $this->values[$id]] = self::$valuesCache[$file];
@@ -171,7 +168,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
protected function doHave(string $id): bool
{
if ($this->appendOnly && isset($this->values[$id])) {
return true;
@@ -179,7 +176,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
set_error_handler($this->includeHandler);
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
$file = $this->files[$id] ??= $this->getFile($id);
$getExpiry = true;
if (isset(self::$valuesCache[$file])) {
@@ -193,7 +190,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
} elseif ($this->appendOnly) {
$value = new LazyValue($file);
}
} catch (\ErrorException $e) {
} catch (\ErrorException) {
return false;
} finally {
restore_error_handler();
@@ -211,7 +208,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
$ok = true;
$expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX';
@@ -273,7 +270,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
$this->values = [];
@@ -283,7 +280,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
protected function doDelete(array $ids): bool
{
foreach ($ids as $id) {
unset($this->values[$id]);
@@ -321,7 +318,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
*/
class LazyValue
{
public $file;
public string $file;
public function __construct(string $file)
{

View File

@@ -28,25 +28,25 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
use ContractsTrait;
use ProxyTrait;
private $namespace = '';
private $namespaceLen;
private $poolHash;
private $defaultLifetime;
private string $namespace = '';
private int $namespaceLen;
private string $poolHash;
private int $defaultLifetime;
private static $createCacheItem;
private static $setInnerItem;
private static \Closure $createCacheItem;
private static \Closure $setInnerItem;
public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
{
$this->pool = $pool;
$this->poolHash = $poolHash = spl_object_hash($pool);
$this->poolHash = spl_object_hash($pool);
if ('' !== $namespace) {
\assert('' !== CacheItem::validateKey($namespace));
$this->namespace = $namespace;
}
$this->namespaceLen = \strlen($namespace);
$this->defaultLifetime = $defaultLifetime;
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
self::$createCacheItem ??= \Closure::bind(
static function ($key, $innerItem, $poolHash) {
$item = new CacheItem();
$item->key = $key;
@@ -55,20 +55,12 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
return $item;
}
$item->value = $v = $innerItem->get();
$item->value = $innerItem->get();
$item->isHit = $innerItem->isHit();
$item->innerItem = $innerItem;
$item->poolHash = $poolHash;
// Detect wrapped values that encode for their expiry and creation duration
// For compactness, these values are packed in the key of an array using
// magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
$item->value = $v[$k];
$v = unpack('Ve/Nc', substr($k, 1, -1));
$item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
$item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
} elseif ($innerItem instanceof CacheItem) {
if (!$item->unpack() && $innerItem instanceof CacheItem) {
$item->metadata = $innerItem->metadata;
}
$innerItem->set(null);
@@ -78,21 +70,10 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
null,
CacheItem::class
);
self::$setInnerItem ?? self::$setInnerItem = \Closure::bind(
/**
* @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix
*/
static function (CacheItemInterface $innerItem, array $item) {
// Tags are stored separately, no need to account for them when considering this item's newly set metadata
if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) {
unset($metadata[CacheItem::METADATA_TAGS]);
}
if ($metadata) {
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
$item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
}
$innerItem->set($item["\0*\0value"]);
$innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null);
self::$setInnerItem ??= \Closure::bind(
static function (CacheItemInterface $innerItem, CacheItem $item, $expiry = null) {
$innerItem->set($item->pack());
$innerItem->expiresAt(($expiry ?? $item->expiry) ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $expiry ?? $item->expiry)) : null);
},
null,
CacheItem::class
@@ -102,7 +83,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
if (!$this->pool instanceof CacheInterface) {
return $this->doGet($this, $key, $callback, $beta, $metadata);
@@ -111,7 +92,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
$item = (self::$createCacheItem)($key, $innerItem, $this->poolHash);
$item->set($value = $callback($item, $save));
(self::$setInnerItem)($innerItem, (array) $item);
(self::$setInnerItem)($innerItem, $item);
return $value;
}, $beta, $metadata);
@@ -120,7 +101,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
$item = $this->pool->getItem($this->getId($key));
@@ -130,7 +111,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
if ($this->namespaceLen) {
foreach ($keys as $i => $key) {
@@ -143,20 +124,16 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
return $this->pool->hasItem($this->getId($key));
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
if ($this->pool instanceof AdapterInterface) {
return $this->pool->clear($this->namespace.$prefix);
@@ -167,20 +144,16 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
return $this->pool->deleteItem($this->getId($key));
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
if ($this->namespaceLen) {
foreach ($keys as $i => $key) {
@@ -193,55 +166,50 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
return $this->doSave($item, __FUNCTION__);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
return $this->doSave($item, __FUNCTION__);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
return $this->pool->commit();
}
private function doSave(CacheItemInterface $item, string $method)
private function doSave(CacheItemInterface $item, string $method): bool
{
if (!$item instanceof CacheItem) {
return false;
}
$item = (array) $item;
if (null === $item["\0*\0expiry"] && 0 < $this->defaultLifetime) {
$item["\0*\0expiry"] = microtime(true) + $this->defaultLifetime;
$castItem = (array) $item;
if (null === $castItem["\0*\0expiry"] && 0 < $this->defaultLifetime) {
$castItem["\0*\0expiry"] = microtime(true) + $this->defaultLifetime;
}
if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) {
$innerItem = $item["\0*\0innerItem"];
if ($castItem["\0*\0poolHash"] === $this->poolHash && $castItem["\0*\0innerItem"]) {
$innerItem = $castItem["\0*\0innerItem"];
} elseif ($this->pool instanceof AdapterInterface) {
// this is an optimization specific for AdapterInterface implementations
// so we can save a round-trip to the backend by just creating a new item
$innerItem = (self::$createCacheItem)($this->namespace.$item["\0*\0key"], null, $this->poolHash);
$innerItem = (self::$createCacheItem)($this->namespace.$castItem["\0*\0key"], null, $this->poolHash);
} else {
$innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
$innerItem = $this->pool->getItem($this->namespace.$castItem["\0*\0key"]);
}
(self::$setInnerItem)($innerItem, $item);
(self::$setInnerItem)($innerItem, $item, $castItem["\0*\0expiry"]);
return $this->pool->$method($innerItem);
}
@@ -259,7 +227,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
}
}
private function getId($key): string
private function getId(mixed $key): string
{
\assert('' !== CacheItem::validateKey($key));

View File

@@ -30,7 +30,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
*/
protected const NS_SEPARATOR = '_';
private $miss;
private object $miss;
public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0)
{
@@ -43,7 +43,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
/**
* {@inheritdoc}
*/
protected function doFetch(array $ids)
protected function doFetch(array $ids): iterable
{
foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
if ($this->miss !== $value) {
@@ -55,7 +55,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
/**
* {@inheritdoc}
*/
protected function doHave(string $id)
protected function doHave(string $id): bool
{
return $this->pool->has($id);
}
@@ -63,7 +63,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
/**
* {@inheritdoc}
*/
protected function doClear(string $namespace)
protected function doClear(string $namespace): bool
{
return $this->pool->clear();
}
@@ -71,7 +71,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
/**
* {@inheritdoc}
*/
protected function doDelete(array $ids)
protected function doDelete(array $ids): bool
{
return $this->pool->deleteMultiple($ids);
}
@@ -79,7 +79,7 @@ class Psr16Adapter extends AbstractAdapter implements PruneableInterface, Resett
/**
* {@inheritdoc}
*/
protected function doSave(array $values, int $lifetime)
protected function doSave(array $values, int $lifetime): array|bool
{
return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
}

View File

@@ -20,12 +20,7 @@ class RedisAdapter extends AbstractAdapter
{
use RedisTrait;
/**
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
* @param string $namespace The default namespace
* @param int $defaultLifetime The default lifetime
*/
public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
public function __construct(\Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
$this->init($redis, $namespace, $defaultLifetime, $marshaller);
}

View File

@@ -56,17 +56,12 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter
private const DEFAULT_CACHE_TTL = 8640000;
/**
* @var string|null detected eviction policy used on Redis server
* detected eviction policy used on Redis server.
*/
private $redisEvictionPolicy;
private $namespace;
private string $redisEvictionPolicy;
private string $namespace;
/**
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
* @param string $namespace The default namespace
* @param int $defaultLifetime The default lifetime
*/
public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
public function __construct(\Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) {
throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection())));
@@ -175,7 +170,7 @@ EOLUA;
try {
yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
} catch (\Exception $e) {
} catch (\Exception) {
yield $id => [];
}
}
@@ -297,7 +292,7 @@ EOLUA;
private function getRedisEvictionPolicy(): string
{
if (null !== $this->redisEvictionPolicy) {
if (isset($this->redisEvictionPolicy)) {
return $this->redisEvictionPolicy;
}

View File

@@ -19,70 +19,73 @@ use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ContractsTrait;
use Symfony\Component\Cache\Traits\ProxyTrait;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
* Implements simple and robust tag-based invalidation suitable for use with volatile caches.
*
* This adapter works by storing a version for each tags. When saving an item, it is stored together with its tags and
* their corresponding versions. When retrieving an item, those tag versions are compared to the current version of
* each tags. Invalidation is achieved by deleting tags, thereby ensuring that their versions change even when the
* storage is out of space. When versions of non-existing tags are requested for item commits, this adapter assigns a
* new random version to them.
*
* @author Nicolas Grekas <p@tchwork.com>
* @author Sergey Belyshkin <sbelyshkin@gmail.com>
*/
class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface
{
use ContractsTrait;
use LoggerAwareTrait;
use ProxyTrait;
public const TAGS_PREFIX = "\0tags\0";
private $deferred = [];
private $tags;
private $knownTagVersions = [];
private $knownTagVersionsTtl;
private array $deferred = [];
private AdapterInterface $pool;
private AdapterInterface $tags;
private array $knownTagVersions = [];
private float $knownTagVersionsTtl;
private static $createCacheItem;
private static $setCacheItemTags;
private static $getTagsByKey;
private static $saveTags;
private static \Closure $setCacheItemTags;
private static \Closure $setTagVersions;
private static \Closure $getTagsByKey;
private static \Closure $saveTags;
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
{
$this->pool = $itemsPool;
$this->tags = $tagsPool ?: $itemsPool;
$this->tags = $tagsPool ?? $itemsPool;
$this->knownTagVersionsTtl = $knownTagVersionsTtl;
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, CacheItem $protoItem) {
$item = new CacheItem();
$item->key = $key;
$item->value = $value;
$item->expiry = $protoItem->expiry;
$item->poolHash = $protoItem->poolHash;
self::$setCacheItemTags ??= \Closure::bind(
static function (array $items, array $itemTags) {
foreach ($items as $key => $item) {
$item->isTaggable = true;
return $item;
},
null,
CacheItem::class
);
self::$setCacheItemTags ?? self::$setCacheItemTags = \Closure::bind(
static function (CacheItem $item, $key, array &$itemTags) {
$item->isTaggable = true;
if (!$item->isHit) {
return $item;
}
if (isset($itemTags[$key])) {
foreach ($itemTags[$key] as $tag => $version) {
$item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag;
if (isset($itemTags[$key])) {
$tags = array_keys($itemTags[$key]);
$item->metadata[CacheItem::METADATA_TAGS] = array_combine($tags, $tags);
} else {
$item->value = null;
$item->isHit = false;
$item->metadata = [];
}
unset($itemTags[$key]);
} else {
$item->value = null;
$item->isHit = false;
}
return $item;
return $items;
},
null,
CacheItem::class
);
self::$getTagsByKey ?? self::$getTagsByKey = \Closure::bind(
self::$setTagVersions ??= \Closure::bind(
static function (array $items, array $tagVersions) {
foreach ($items as $item) {
$item->newMetadata[CacheItem::METADATA_TAGS] = array_intersect_key($tagVersions, $item->newMetadata[CacheItem::METADATA_TAGS] ?? []);
}
},
null,
CacheItem::class
);
self::$getTagsByKey ??= \Closure::bind(
static function ($deferred) {
$tagsByKey = [];
foreach ($deferred as $key => $item) {
@@ -95,7 +98,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
null,
CacheItem::class
);
self::$saveTags ?? self::$saveTags = \Closure::bind(
self::$saveTags ??= \Closure::bind(
static function (AdapterInterface $tagsAdapter, array $tags) {
ksort($tags);
@@ -114,7 +117,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags)
public function invalidateTags(array $tags): bool
{
$ids = [];
foreach ($tags as $tag) {
@@ -128,54 +131,26 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
if (\is_string($key) && isset($this->deferred[$key])) {
$this->commit();
}
if (!$this->pool->hasItem($key)) {
return false;
}
$itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key);
if (!$itemTags->isHit()) {
return false;
}
if (!$itemTags = $itemTags->get()) {
return true;
}
foreach ($this->getTagVersions([$itemTags]) as $tag => $version) {
if ($itemTags[$tag] !== $version) {
return false;
}
}
return true;
return $this->getItem($key)->isHit();
}
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
foreach ($this->getItems([$key]) as $item) {
return $item;
}
return null;
}
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
$tagKeys = [];
$commit = false;
@@ -184,7 +159,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
if ('' !== $key && \is_string($key)) {
$commit = $commit || isset($this->deferred[$key]);
$key = static::TAGS_PREFIX.$key;
$tagKeys[$key] = $key;
$tagKeys[$key] = $key; // BC with pools populated before v6.1
}
}
@@ -200,15 +175,41 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
throw $e;
}
return $this->generateItems($items, $tagKeys);
$bufferedItems = $itemTags = [];
foreach ($items as $key => $item) {
if (isset($tagKeys[$key])) { // BC with pools populated before v6.1
if ($item->isHit()) {
$itemTags[substr($key, \strlen(static::TAGS_PREFIX))] = $item->get() ?: [];
}
continue;
}
if (null !== $tags = $item->getMetadata()[CacheItem::METADATA_TAGS] ?? null) {
$itemTags[$key] = $tags;
}
$bufferedItems[$key] = $item;
}
$tagVersions = $this->getTagVersions($itemTags, false);
foreach ($itemTags as $key => $tags) {
foreach ($tags as $tag => $version) {
if ($tagVersions[$tag] !== $version) {
unset($itemTags[$key]);
continue 2;
}
}
}
$tagVersions = null;
return (self::$setCacheItemTags)($bufferedItems, $itemTags);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
if ('' !== $prefix) {
foreach ($this->deferred as $key => $item) {
@@ -229,24 +230,20 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
return $this->deleteItems([$key]);
}
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
foreach ($keys as $key) {
if ('' !== $key && \is_string($key)) {
$keys[] = static::TAGS_PREFIX.$key;
$keys[] = static::TAGS_PREFIX.$key; // BC with pools populated before v6.1
}
}
@@ -255,10 +252,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
if (!$item instanceof CacheItem) {
return false;
@@ -270,10 +265,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
if (!$item instanceof CacheItem) {
return false;
@@ -285,41 +278,52 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
if (!$this->deferred) {
if (!$items = $this->deferred) {
return true;
}
$tagVersions = $this->getTagVersions((self::$getTagsByKey)($items), true);
(self::$setTagVersions)($items, $tagVersions);
$ok = true;
foreach ($this->deferred as $key => $item) {
if (!$this->pool->saveDeferred($item)) {
foreach ($items as $key => $item) {
if ($this->pool->saveDeferred($item)) {
unset($this->deferred[$key]);
} else {
$ok = false;
}
}
$ok = $this->pool->commit() && $ok;
$items = $this->deferred;
$tagsByKey = (self::$getTagsByKey)($items);
$this->deferred = [];
$tagVersions = array_keys($tagVersions);
(self::$setTagVersions)($items, array_combine($tagVersions, $tagVersions));
$tagVersions = $this->getTagVersions($tagsByKey);
$f = self::$createCacheItem;
foreach ($tagsByKey as $key => $tags) {
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
}
return $this->pool->commit() && $ok;
return $ok;
}
/**
* @return array
* {@inheritdoc}
*/
public function __sleep()
public function prune(): bool
{
return $this->pool instanceof PruneableInterface && $this->pool->prune();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->commit();
$this->knownTagVersions = [];
$this->pool instanceof ResettableInterface && $this->pool->reset();
$this->tags instanceof ResettableInterface && $this->tags->reset();
}
public function __sleep(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
@@ -334,59 +338,19 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
$this->commit();
}
private function generateItems(iterable $items, array $tagKeys): \Generator
{
$bufferedItems = $itemTags = [];
$f = self::$setCacheItemTags;
foreach ($items as $key => $item) {
if (!$tagKeys) {
yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags);
continue;
}
if (!isset($tagKeys[$key])) {
$bufferedItems[$key] = $item;
continue;
}
unset($tagKeys[$key]);
if ($item->isHit()) {
$itemTags[$key] = $item->get() ?: [];
}
if (!$tagKeys) {
$tagVersions = $this->getTagVersions($itemTags);
foreach ($itemTags as $key => $tags) {
foreach ($tags as $tag => $version) {
if ($tagVersions[$tag] !== $version) {
unset($itemTags[$key]);
continue 2;
}
}
}
$tagVersions = $tagKeys = null;
foreach ($bufferedItems as $key => $item) {
yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags);
}
$bufferedItems = null;
}
}
}
private function getTagVersions(array $tagsByKey)
private function getTagVersions(array $tagsByKey, bool $persistTags): array
{
$tagVersions = [];
$fetchTagVersions = false;
$fetchTagVersions = $persistTags;
foreach ($tagsByKey as $tags) {
$tagVersions += $tags;
if ($fetchTagVersions) {
continue;
}
foreach ($tags as $tag => $version) {
if ($tagVersions[$tag] !== $version) {
unset($this->knownTagVersions[$tag]);
$fetchTagVersions = true;
}
}
}
@@ -399,8 +363,9 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
$tags = [];
foreach ($tagVersions as $tag => $version) {
$tags[$tag.static::TAGS_PREFIX] = $tag;
if ($fetchTagVersions || ($this->knownTagVersions[$tag][1] ?? null) !== $version || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) {
// reuse previously fetched tag versions up to the ttl
$knownTagVersion = $this->knownTagVersions[$tag] ?? [0, null];
if ($fetchTagVersions || $now > $knownTagVersion[0] || $knownTagVersion[1] !== $version) {
// reuse previously fetched tag versions until the expiration
$fetchTagVersions = true;
}
}
@@ -411,18 +376,26 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
$newTags = [];
$newVersion = null;
$expiration = $now + $this->knownTagVersionsTtl;
foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) {
if (!$version->isHit()) {
$newTags[$tag] = $version->set($newVersion ?? $newVersion = random_int(\PHP_INT_MIN, \PHP_INT_MAX));
unset($this->knownTagVersions[$tag = $tags[$tag]]); // update FIFO
if (null !== $tagVersions[$tag] = $version->get()) {
$this->knownTagVersions[$tag] = [$expiration, $tagVersions[$tag]];
} elseif ($persistTags) {
$newTags[$tag] = $version->set($newVersion ??= random_bytes(6));
$tagVersions[$tag] = $newVersion;
$this->knownTagVersions[$tag] = [$expiration, $newVersion];
}
$tagVersions[$tag = $tags[$tag]] = $version->get();
$this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]];
}
if ($newTags) {
(self::$saveTags)($this->tags, $newTags);
}
while ($now > ($this->knownTagVersions[$tag = array_key_first($this->knownTagVersions)][0] ?? \INF)) {
unset($this->knownTagVersions[$tag]);
}
return $tagVersions;
}
}

View File

@@ -25,9 +25,7 @@ interface TagAwareAdapterInterface extends AdapterInterface
*
* @param string[] $tags An array of tags to invalidate
*
* @return bool
*
* @throws InvalidArgumentException When $tags is not valid
*/
public function invalidateTags(array $tags);
public function invalidateTags(array $tags): bool;
}

View File

@@ -28,7 +28,7 @@ use Symfony\Contracts\Service\ResetInterface;
class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
protected $pool;
private $calls = [];
private array $calls = [];
public function __construct(AdapterInterface $pool)
{
@@ -38,7 +38,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed
{
if (!$this->pool instanceof CacheInterface) {
throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class));
@@ -70,7 +70,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*/
public function getItem($key)
public function getItem(mixed $key): CacheItem
{
$event = $this->start(__FUNCTION__);
try {
@@ -89,10 +89,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function hasItem($key)
public function hasItem(mixed $key): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -104,10 +102,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItem($key)
public function deleteItem(mixed $key): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -119,10 +115,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function save(CacheItemInterface $item)
public function save(CacheItemInterface $item): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -134,10 +128,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function saveDeferred(CacheItemInterface $item)
public function saveDeferred(CacheItemInterface $item): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -150,7 +142,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
public function getItems(array $keys = []): iterable
{
$event = $this->start(__FUNCTION__);
try {
@@ -175,10 +167,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function clear(string $prefix = '')
public function clear(string $prefix = ''): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -194,10 +184,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function deleteItems(array $keys)
public function deleteItems(array $keys): bool
{
$event = $this->start(__FUNCTION__);
$event->result['keys'] = $keys;
@@ -210,10 +198,8 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*
* @return bool
*/
public function commit()
public function commit(): bool
{
$event = $this->start(__FUNCTION__);
try {
@@ -226,7 +212,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
/**
* {@inheritdoc}
*/
public function prune()
public function prune(): bool
{
if (!$this->pool instanceof PruneableInterface) {
return false;
@@ -284,12 +270,15 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt
}
}
/**
* @internal
*/
class TraceableAdapterEvent
{
public $name;
public $start;
public $end;
public $result;
public $hits = 0;
public $misses = 0;
public string $name;
public float $start;
public float $end;
public array|bool $result;
public int $hits = 0;
public int $misses = 0;
}

View File

@@ -26,7 +26,7 @@ class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapt
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags)
public function invalidateTags(array $tags): bool
{
$event = $this->start(__FUNCTION__);
try {