aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/vendor/symfony/cache/Adapter
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/vendor/symfony/cache/Adapter')
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractAdapter.php203
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php323
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/AdapterInterface.php46
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/ApcuAdapter.php27
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/ArrayAdapter.php171
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/ChainAdapter.php332
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/DoctrineAdapter.php27
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemAdapter.php29
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php239
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/MemcachedAdapter.php37
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/NullAdapter.php156
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/PdoAdapter.php54
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpArrayAdapter.php332
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpFilesAdapter.php38
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/ProxyAdapter.php269
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/Psr16Adapter.php86
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisAdapter.php30
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php292
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php21
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapter.php429
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php33
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableAdapter.php302
-rw-r--r--srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php38
23 files changed, 3514 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractAdapter.php
new file mode 100644
index 0000000..98b42a4
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractAdapter.php
@@ -0,0 +1,203 @@
+<?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 Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ /**
+ * @internal
+ */
+ protected const NS_SEPARATOR = ':';
+
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
+ private static $apcuSupported;
+ private static $phpFilesSupported;
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
+ if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
+ throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace));
+ }
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) use ($defaultLifetime) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $v = $value;
+ $item->isHit = $isHit;
+ $item->defaultLifetime = $defaultLifetime;
+ // 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 = key($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'];
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $getId = \Closure::fromCallable([$this, 'getId']);
+ $this->mergeByLifetime = \Closure::bind(
+ static function ($deferred, $namespace, &$expiredIds) use ($getId) {
+ $byLifetime = [];
+ $now = microtime(true);
+ $expiredIds = [];
+
+ foreach ($deferred as $key => $item) {
+ $key = (string) $key;
+ if (null === $item->expiry) {
+ $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
+ $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;
+ }
+
+ return $byLifetime;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * Returns the best possible adapter that your runtime supports.
+ *
+ * Using ApcuAdapter makes system caches compatible with read-only filesystems.
+ *
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string $version
+ * @param string $directory
+ *
+ * @return AdapterInterface
+ */
+ public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
+ {
+ $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true);
+ if (null !== $logger) {
+ $opcache->setLogger($logger);
+ }
+
+ if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) {
+ return $opcache;
+ }
+
+ $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version);
+ if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
+ $apcu->setLogger(new NullLogger());
+ } elseif (null !== $logger) {
+ $apcu->setLogger($logger);
+ }
+
+ return new ChainAdapter([$apcu, $opcache]);
+ }
+
+ public static function createConnection($dsn, array $options = [])
+ {
+ if (!\is_string($dsn)) {
+ throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.', __METHOD__, \gettype($dsn)));
+ }
+ if (0 === strpos($dsn, 'redis:') || 0 === strpos($dsn, 'rediss:')) {
+ return RedisAdapter::createConnection($dsn, $options);
+ }
+ if (0 === strpos($dsn, 'memcached:')) {
+ return MemcachedAdapter::createConnection($dsn, $options);
+ }
+
+ throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $ok = true;
+ $byLifetime = $this->mergeByLifetime;
+ $byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds);
+ $retry = $this->deferred = [];
+
+ if ($expiredIds) {
+ $this->doDelete($expiredIds);
+ }
+ foreach ($byLifetime as $lifetime => $values) {
+ try {
+ $e = $this->doSave($values, $lifetime);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ if (\is_array($e) || 1 === \count($values)) {
+ foreach (\is_array($e) ? $e : array_keys($values) as $id) {
+ $ok = false;
+ $v = $values[$id];
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ } else {
+ foreach ($values as $id => $v) {
+ $retry[$lifetime][] = $id;
+ }
+ }
+ }
+
+ // When bulk-save failed, retry each item individually
+ foreach ($retry as $lifetime => $ids) {
+ foreach ($ids as $id) {
+ try {
+ $v = $byLifetime[$lifetime][$id];
+ $e = $this->doSave([$id => $v], $lifetime);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ $ok = false;
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ }
+
+ return $ok;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
new file mode 100644
index 0000000..10aca3b
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
@@ -0,0 +1,323 @@
+<?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 Psr\Log\LoggerAwareInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * Abstract for native TagAware adapters.
+ *
+ * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids
+ * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate().
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author André Rømcke <andre.romcke+symfony@gmail.com>
+ *
+ * @internal
+ */
+abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
+ private const TAGS_PREFIX = "\0tags\0";
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
+ if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
+ throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace));
+ }
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) use ($defaultLifetime) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->defaultLifetime = $defaultLifetime;
+ $item->isTaggable = true;
+ // If structure does not match what we expect return item as is (no value and not a hit)
+ if (!\is_array($value) || !\array_key_exists('value', $value)) {
+ return $item;
+ }
+ $item->isHit = $isHit;
+ // Extract value, tags and meta data from the cache value
+ $item->value = $value['value'];
+ $item->metadata[CacheItem::METADATA_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']);
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $getId = \Closure::fromCallable([$this, 'getId']);
+ $tagPrefix = self::TAGS_PREFIX;
+ $this->mergeByLifetime = \Closure::bind(
+ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
+ $byLifetime = [];
+ $now = microtime(true);
+ $expiredIds = [];
+
+ foreach ($deferred as $key => $item) {
+ $key = (string) $key;
+ if (null === $item->expiry) {
+ $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
+ $expiredIds[] = $getId($key);
+ continue;
+ }
+ // Store Value and Tags on the cache value
+ if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
+ $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]];
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ } else {
+ $value = ['value' => $item->value, 'tags' => []];
+ }
+
+ 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]);
+ }
+
+ // 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) {
+ $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag);
+ }
+ foreach (array_diff($oldTags, $value['tags']) as $removedTag) {
+ $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag);
+ }
+
+ $byLifetime[$ttl][$getId($key)] = $value;
+ }
+
+ return $byLifetime;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * Persists several cache items immediately.
+ *
+ * @param array $values The values to cache, indexed by their cache identifier
+ * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning
+ * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag
+ * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag
+ *
+ * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not
+ */
+ abstract protected function doSave(array $values, ?int $lifetime, array $addTagData = [], array $removeTagData = []): array;
+
+ /**
+ * 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 True if the items were successfully removed, false otherwise
+ */
+ abstract protected function doDelete(array $ids);
+
+ /**
+ * Removes relations between tags and deleted items.
+ *
+ * @param array $tagData Array of tag => key identifiers that should be removed from the pool
+ */
+ abstract protected function doDeleteTagRelations(array $tagData): bool;
+
+ /**
+ * Invalidates cached items using tags.
+ *
+ * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id
+ *
+ * @return bool True on success
+ */
+ abstract protected function doInvalidate(array $tagIds): bool;
+
+ /**
+ * Delete items and yields the tags they were bound to.
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($this->doFetch($ids) as $id => $value) {
+ yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : [];
+ }
+
+ $this->doDelete($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commit(): bool
+ {
+ $ok = true;
+ $byLifetime = $this->mergeByLifetime;
+ $byLifetime = $byLifetime($this->deferred, $expiredIds);
+ $retry = $this->deferred = [];
+
+ if ($expiredIds) {
+ // Tags are not cleaned up in this case, however that is done on invalidateTags().
+ $this->doDelete($expiredIds);
+ }
+ foreach ($byLifetime as $lifetime => $values) {
+ try {
+ $values = $this->extractTagData($values, $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ if (\is_array($e) || 1 === \count($values)) {
+ foreach (\is_array($e) ? $e : array_keys($values) as $id) {
+ $ok = false;
+ $v = $values[$id];
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ } else {
+ foreach ($values as $id => $v) {
+ $retry[$lifetime][] = $id;
+ }
+ }
+ }
+
+ // When bulk-save failed, retry each item individually
+ foreach ($retry as $lifetime => $ids) {
+ foreach ($ids as $id) {
+ try {
+ $v = $byLifetime[$lifetime][$id];
+ $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ $ok = false;
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItems(array $keys): bool
+ {
+ if (!$keys) {
+ return true;
+ }
+
+ $ok = true;
+ $ids = [];
+ $tagData = [];
+
+ foreach ($keys as $key) {
+ $ids[$key] = $this->getId($key);
+ unset($this->deferred[$key]);
+ }
+
+ try {
+ foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) {
+ foreach ($tags as $tag) {
+ $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id;
+ }
+ }
+ } catch (\Exception $e) {
+ $ok = false;
+ }
+
+ try {
+ if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ }
+
+ // When bulk-delete failed, retry each item individually
+ foreach ($ids as $key => $id) {
+ try {
+ $e = null;
+ if ($this->doDelete([$id])) {
+ continue;
+ }
+ } catch (\Exception $e) {
+ }
+ $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]);
+ $ok = false;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ if (empty($tags)) {
+ return false;
+ }
+
+ $tagIds = [];
+ foreach (array_unique($tags) as $tag) {
+ $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag);
+ }
+
+ if ($this->doInvalidate($tagIds)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it.
+ */
+ private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array
+ {
+ $addTagData = $removeTagData = [];
+ foreach ($values as $id => $value) {
+ foreach ($value['tag-operations']['add'] as $tag => $tagId) {
+ $addTagData[$tagId][] = $id;
+ }
+
+ foreach ($value['tag-operations']['remove'] as $tag => $tagId) {
+ $removeTagData[$tagId][] = $id;
+ }
+
+ unset($values[$id]['tag-operations']);
+ }
+
+ return $values;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AdapterInterface.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AdapterInterface.php
new file mode 100644
index 0000000..c40ae42
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/AdapterInterface.php
@@ -0,0 +1,46 @@
+<?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 Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+
+/**
+ * Interface for adapters managing instances of Symfony's CacheItem.
+ *
+ * @author Kévin Dunglas <dunglas@gmail.com>
+ */
+interface AdapterInterface extends CacheItemPoolInterface
+{
+ /**
+ * {@inheritdoc}
+ *
+ * @return CacheItem
+ */
+ public function getItem($key);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return \Traversable|CacheItem[]
+ */
+ public function getItems(array $keys = []);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/);
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ApcuAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ApcuAdapter.php
new file mode 100644
index 0000000..7db3956
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ApcuAdapter.php
@@ -0,0 +1,27 @@
+<?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 Symfony\Component\Cache\Traits\ApcuTrait;
+
+class ApcuAdapter extends AbstractAdapter
+{
+ use ApcuTrait;
+
+ /**
+ * @throws CacheException if APCu is not enabled
+ */
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null)
+ {
+ $this->init($namespace, $defaultLifetime, $version);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ArrayAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ArrayAdapter.php
new file mode 100644
index 0000000..d93dcbd
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ArrayAdapter.php
@@ -0,0 +1,171 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Psr\Log\LoggerAwareInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use ArrayTrait;
+
+ private $createCacheItem;
+
+ /**
+ * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
+ */
+ public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true)
+ {
+ $this->storeSerialized = $storeSerialized;
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) use ($defaultLifetime) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->isHit = $isHit;
+ $item->defaultLifetime = $defaultLifetime;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $item = $this->getItem($key);
+ $metadata = $item->getMetadata();
+
+ // ArrayAdapter works in memory, we don't care about stampede protection
+ if (INF === $beta || !$item->isHit()) {
+ $save = true;
+ $this->save($item->set($callback($item, $save)));
+ }
+
+ return $item->get();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ if (!$isHit = $this->hasItem($key)) {
+ $this->values[$key] = $value = null;
+ } else {
+ $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
+ }
+ $f = $this->createCacheItem;
+
+ return $f($key, $value, $isHit);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ foreach ($keys as $key) {
+ if (!\is_string($key) || !isset($this->expiries[$key])) {
+ CacheItem::validateKey($key);
+ }
+ }
+
+ return $this->generateItems($keys, microtime(true), $this->createCacheItem);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ foreach ($keys as $key) {
+ $this->deleteItem($key);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $item = (array) $item;
+ $key = $item["\0*\0key"];
+ $value = $item["\0*\0value"];
+ $expiry = $item["\0*\0expiry"];
+
+ if (null !== $expiry && $expiry <= microtime(true)) {
+ $this->deleteItem($key);
+
+ return true;
+ }
+ if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
+ return false;
+ }
+ if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
+ $expiry = microtime(true) + $item["\0*\0defaultLifetime"];
+ }
+
+ $this->values[$key] = $value;
+ $this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return $this->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ChainAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ChainAdapter.php
new file mode 100644
index 0000000..63e97a8
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ChainAdapter.php
@@ -0,0 +1,332 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * Chains several adapters together.
+ *
+ * Cached items are fetched from the first adapter having them in its data store.
+ * They are saved and deleted in all adapters at once.
+ *
+ * @author Kévin Dunglas <dunglas@gmail.com>
+ */
+class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ContractsTrait;
+
+ private $adapters = [];
+ private $adapterCount;
+ private $syncItem;
+
+ /**
+ * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items
+ * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones
+ */
+ public function __construct(array $adapters, int $defaultLifetime = 0)
+ {
+ if (!$adapters) {
+ throw new InvalidArgumentException('At least one adapter must be specified.');
+ }
+
+ foreach ($adapters as $adapter) {
+ if (!$adapter instanceof CacheItemPoolInterface) {
+ throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class));
+ }
+
+ if ($adapter instanceof AdapterInterface) {
+ $this->adapters[] = $adapter;
+ } else {
+ $this->adapters[] = new ProxyAdapter($adapter);
+ }
+ }
+ $this->adapterCount = \count($this->adapters);
+
+ $this->syncItem = \Closure::bind(
+ static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) {
+ $sourceItem->isTaggable = false;
+ $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata;
+ unset($sourceMetadata[CacheItem::METADATA_TAGS]);
+
+ $item->value = $sourceItem->value;
+ $item->expiry = $sourceMetadata[CacheItem::METADATA_EXPIRY] ?? $sourceItem->expiry;
+ $item->isHit = $sourceItem->isHit;
+ $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata;
+
+ if (0 < $sourceItem->defaultLifetime && $sourceItem->defaultLifetime < $defaultLifetime) {
+ $defaultLifetime = $sourceItem->defaultLifetime;
+ }
+ if (0 < $defaultLifetime && ($item->defaultLifetime <= 0 || $defaultLifetime < $item->defaultLifetime)) {
+ $item->defaultLifetime = $defaultLifetime;
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $lastItem = null;
+ $i = 0;
+ $wrap = function (CacheItem $item = null) use ($key, $callback, $beta, &$wrap, &$i, &$lastItem, &$metadata) {
+ $adapter = $this->adapters[$i];
+ if (isset($this->adapters[++$i])) {
+ $callback = $wrap;
+ $beta = INF === $beta ? INF : 0;
+ }
+ if ($adapter instanceof CacheInterface) {
+ $value = $adapter->get($key, $callback, $beta, $metadata);
+ } else {
+ $value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
+ }
+ if (null !== $item) {
+ ($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata);
+ }
+
+ return $value;
+ };
+
+ return $wrap();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $syncItem = $this->syncItem;
+ $misses = [];
+
+ foreach ($this->adapters as $i => $adapter) {
+ $item = $adapter->getItem($key);
+
+ if ($item->isHit()) {
+ while (0 <= --$i) {
+ $this->adapters[$i]->save($syncItem($item, $misses[$i]));
+ }
+
+ return $item;
+ }
+
+ $misses[$i] = $item;
+ }
+
+ return $item;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ return $this->generateItems($this->adapters[0]->getItems($keys), 0);
+ }
+
+ private function generateItems(iterable $items, int $adapterIndex)
+ {
+ $missing = [];
+ $misses = [];
+ $nextAdapterIndex = $adapterIndex + 1;
+ $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null;
+
+ foreach ($items as $k => $item) {
+ if (!$nextAdapter || $item->isHit()) {
+ yield $k => $item;
+ } else {
+ $missing[] = $k;
+ $misses[$k] = $item;
+ }
+ }
+
+ if ($missing) {
+ $syncItem = $this->syncItem;
+ $adapter = $this->adapters[$adapterIndex];
+ $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex);
+
+ foreach ($items as $k => $item) {
+ if ($item->isHit()) {
+ $adapter->save($syncItem($item, $misses[$k]));
+ }
+
+ yield $k => $item;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ foreach ($this->adapters as $adapter) {
+ if ($adapter->hasItem($key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/)
+ {
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
+ $cleared = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ if ($this->adapters[$i] instanceof AdapterInterface) {
+ $cleared = $this->adapters[$i]->clear($prefix) && $cleared;
+ } else {
+ $cleared = $this->adapters[$i]->clear() && $cleared;
+ }
+ }
+
+ return $cleared;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ $deleted = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $deleted = $this->adapters[$i]->deleteItem($key) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $deleted = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ $saved = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $saved = $this->adapters[$i]->save($item) && $saved;
+ }
+
+ return $saved;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ $saved = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $saved = $this->adapters[$i]->saveDeferred($item) && $saved;
+ }
+
+ return $saved;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $committed = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $committed = $this->adapters[$i]->commit() && $committed;
+ }
+
+ return $committed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ $pruned = true;
+
+ foreach ($this->adapters as $adapter) {
+ if ($adapter instanceof PruneableInterface) {
+ $pruned = $adapter->prune() && $pruned;
+ }
+ }
+
+ return $pruned;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ foreach ($this->adapters as $adapter) {
+ if ($adapter instanceof ResetInterface) {
+ $adapter->reset();
+ }
+ }
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/DoctrineAdapter.php
new file mode 100644
index 0000000..75ae4cb
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/DoctrineAdapter.php
@@ -0,0 +1,27 @@
+<?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 Symfony\Component\Cache\Traits\DoctrineTrait;
+
+class DoctrineAdapter extends AbstractAdapter
+{
+ use DoctrineTrait;
+
+ public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
+ {
+ parent::__construct('', $defaultLifetime);
+ $this->provider = $provider;
+ $provider->setNamespace($namespace);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemAdapter.php
new file mode 100644
index 0000000..7185dd4
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemAdapter.php
@@ -0,0 +1,29 @@
+<?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 Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemTrait;
+
+class FilesystemAdapter extends AbstractAdapter implements PruneableInterface
+{
+ use FilesystemTrait;
+
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
new file mode 100644
index 0000000..d9a1ad3
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
@@ -0,0 +1,239 @@
+<?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 Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author André Rømcke <andre.romcke+symfony@gmail.com>
+ */
+class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface
+{
+ use FilesystemTrait {
+ doClear as private doClearCache;
+ doSave as private doSaveCache;
+ }
+
+ /**
+ * Folder used for tag symlinks.
+ */
+ private const TAG_FOLDER = 'tags';
+
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = new TagAwareMarshaller($marshaller);
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear($namespace)
+ {
+ $ok = $this->doClearCache($namespace);
+
+ if ('' !== $namespace) {
+ return $ok;
+ }
+
+ set_error_handler(static function () {});
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ try {
+ foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) {
+ if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) {
+ $dir = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $dir .= \DIRECTORY_SEPARATOR;
+ $renamed = null;
+ }
+
+ for ($i = 0; $i < 38; ++$i) {
+ if (!file_exists($dir.$chars[$i])) {
+ continue;
+ }
+ for ($j = 0; $j < 38; ++$j) {
+ if (!file_exists($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) {
+ continue;
+ }
+ foreach (scandir($d, SCANDIR_SORT_NONE) ?: [] as $link) {
+ if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) {
+ unlink($d.\DIRECTORY_SEPARATOR.$link);
+ }
+ }
+ null === $renamed ?: rmdir($d);
+ }
+ null === $renamed ?: rmdir($dir.$chars[$i]);
+ }
+ null === $renamed ?: rmdir($renamed);
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, ?int $lifetime, array $addTagData = [], array $removeTagData = []): array
+ {
+ $failed = $this->doSaveCache($values, $lifetime);
+
+ // Add Tags as symlinks
+ foreach ($addTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ $file = $this->getFile($id);
+
+ if (!@symlink($file, $this->getFile($id, true, $tagFolder))) {
+ @unlink($file);
+ $failed[] = $id;
+ }
+ }
+ }
+
+ // Unlink removed Tags
+ foreach ($removeTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($ids as $id) {
+ $file = $this->getFile($id);
+ if (!file_exists($file) || !$h = @fopen($file, 'rb')) {
+ continue;
+ }
+
+ if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) {
+ fclose($h);
+ continue;
+ }
+
+ $meta = explode("\n", fread($h, 4096), 3)[2] ?? '';
+
+ // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) {
+ $meta[9] = "\0";
+ $tagLen = unpack('Nlen', $meta, 9)['len'];
+ $meta = substr($meta, 13, $tagLen);
+
+ if (0 < $tagLen -= \strlen($meta)) {
+ $meta .= fread($h, $tagLen);
+ }
+
+ try {
+ yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+
+ fclose($h);
+
+ if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) {
+ @unlink($file);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ foreach ($tagData as $tagId => $idList) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($idList as $id) {
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ foreach ($tagIds as $tagId) {
+ if (!file_exists($tagFolder = $this->getTagFolder($tagId))) {
+ continue;
+ }
+
+ set_error_handler(static function () {});
+
+ try {
+ if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) {
+ $tagFolder = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $renamed = null;
+ }
+
+ foreach ($this->scanHashDir($tagFolder) as $itemLink) {
+ unlink(realpath($itemLink) ?: $itemLink);
+ unlink($itemLink);
+ }
+
+ if (null === $renamed) {
+ continue;
+ }
+
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ for ($i = 0; $i < 38; ++$i) {
+ for ($j = 0; $j < 38; ++$j) {
+ rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]);
+ }
+ rmdir($tagFolder.$chars[$i]);
+ }
+ rmdir($renamed);
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ return true;
+ }
+
+ private function getTagFolder(string $tagId): string
+ {
+ return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/MemcachedAdapter.php
new file mode 100644
index 0000000..b678bb5
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/MemcachedAdapter.php
@@ -0,0 +1,37 @@
+<?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 Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Traits\MemcachedTrait;
+
+class MemcachedAdapter extends AbstractAdapter
+{
+ use MemcachedTrait;
+
+ protected $maxIdLength = 250;
+
+ /**
+ * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged.
+ * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that:
+ * - the Memcached::OPT_BINARY_PROTOCOL must be enabled
+ * (that's the default when using MemcachedAdapter::createConnection());
+ * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation;
+ * your Memcached memory should be large enough to never trigger LRU.
+ *
+ * Using a MemcachedAdapter as a pure items store is fine.
+ */
+ public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ $this->init($client, $namespace, $defaultLifetime, $marshaller);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/NullAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/NullAdapter.php
new file mode 100644
index 0000000..a2fdd36
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/NullAdapter.php
@@ -0,0 +1,156 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Titouan Galopin <galopintitouan@gmail.com>
+ */
+class NullAdapter implements AdapterInterface, CacheInterface
+{
+ private $createCacheItem;
+
+ public function __construct()
+ {
+ $this->createCacheItem = \Closure::bind(
+ function ($key) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->isHit = false;
+
+ return $item;
+ },
+ $this,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $save = true;
+
+ return $callback(($this->createCacheItem)($key), $save);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $f = $this->createCacheItem;
+
+ return $f($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ return $this->generateItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+
+ private function generateItems(array $keys)
+ {
+ $f = $this->createCacheItem;
+
+ foreach ($keys as $key) {
+ yield $key => $f($key);
+ }
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PdoAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PdoAdapter.php
new file mode 100644
index 0000000..d118736
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PdoAdapter.php
@@ -0,0 +1,54 @@
+<?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\DBAL\Connection;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\PdoTrait;
+
+class PdoAdapter extends AbstractAdapter implements PruneableInterface
+{
+ use PdoTrait;
+
+ protected $maxIdLength = 255;
+
+ /**
+ * You can either pass an existing database connection as PDO instance or
+ * a Doctrine DBAL Connection or a DSN string that will be used to
+ * lazy-connect to the database when the cache is actually used.
+ *
+ * When a Doctrine DBAL Connection is passed, the cache table is created
+ * automatically when possible. Otherwise, use the createTable() method.
+ *
+ * List of available options:
+ * * db_table: The name of the table [default: cache_items]
+ * * db_id_col: The column where to store the cache id [default: item_id]
+ * * db_data_col: The column where to store the cache data [default: item_data]
+ * * 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]
+ * * db_username: The username when lazy-connect [default: '']
+ * * db_password: The password when lazy-connect [default: '']
+ * * db_connection_options: An array of driver-specific connection options [default: []]
+ *
+ * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null
+ *
+ * @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)
+ {
+ $this->init($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
new file mode 100644
index 0000000..b4f13d1
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
@@ -0,0 +1,332 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Component\Cache\Traits\PhpArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
+ * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter.
+ *
+ * @author Titouan Galopin <galopintitouan@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use PhpArrayTrait;
+ use ContractsTrait;
+
+ private $createCacheItem;
+
+ /**
+ * @param string $file The PHP file were values are cached
+ * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit
+ */
+ public function __construct(string $file, AdapterInterface $fallbackPool)
+ {
+ $this->file = $file;
+ $this->pool = $fallbackPool;
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->isHit = $isHit;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * This adapter takes advantage of how PHP stores arrays in its latest versions.
+ *
+ * @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($file, CacheItemPoolInterface $fallbackPool)
+ {
+ if (!$fallbackPool instanceof AdapterInterface) {
+ $fallbackPool = new ProxyAdapter($fallbackPool);
+ }
+
+ return new static($file, $fallbackPool);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+ if (!isset($this->keys[$key])) {
+ get_from_pool:
+ if ($this->pool instanceof CacheInterface) {
+ return $this->pool->get($key, $callback, $beta, $metadata);
+ }
+
+ return $this->doGet($this->pool, $key, $callback, $beta, $metadata);
+ }
+ $value = $this->values[$this->keys[$key]];
+
+ if ('N;' === $value) {
+ return null;
+ }
+ try {
+ if ($value instanceof \Closure) {
+ return $value();
+ }
+ } catch (\Throwable $e) {
+ unset($this->keys[$key]);
+ goto get_from_pool;
+ }
+
+ return $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+ if (!isset($this->keys[$key])) {
+ return $this->pool->getItem($key);
+ }
+
+ $value = $this->values[$this->keys[$key]];
+ $isHit = true;
+
+ if ('N;' === $value) {
+ $value = null;
+ } elseif ($value instanceof \Closure) {
+ try {
+ $value = $value();
+ } catch (\Throwable $e) {
+ $value = null;
+ $isHit = false;
+ }
+ }
+
+ $f = $this->createCacheItem;
+
+ return $f($key, $value, $isHit);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ foreach ($keys as $key) {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
+ }
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return $this->generateItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return isset($this->keys[$key]) || $this->pool->hasItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$key]) && $this->pool->deleteItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $deleted = true;
+ $fallbackKeys = [];
+
+ foreach ($keys as $key) {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
+ }
+
+ if (isset($this->keys[$key])) {
+ $deleted = false;
+ } else {
+ $fallbackKeys[] = $key;
+ }
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ if ($fallbackKeys) {
+ $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$item->getKey()]) && $this->pool->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return $this->pool->commit();
+ }
+
+ private function generateItems(array $keys): \Generator
+ {
+ $f = $this->createCacheItem;
+ $fallbackKeys = [];
+
+ foreach ($keys as $key) {
+ if (isset($this->keys[$key])) {
+ $value = $this->values[$this->keys[$key]];
+
+ if ('N;' === $value) {
+ yield $key => $f($key, null, true);
+ } elseif ($value instanceof \Closure) {
+ try {
+ yield $key => $f($key, $value(), true);
+ } catch (\Throwable $e) {
+ yield $key => $f($key, null, false);
+ }
+ } else {
+ yield $key => $f($key, $value, true);
+ }
+ } else {
+ $fallbackKeys[] = $key;
+ }
+ }
+
+ if ($fallbackKeys) {
+ yield from $this->pool->getItems($fallbackKeys);
+ }
+ }
+
+ /**
+ * @throws \ReflectionException When $class is not found and is required
+ *
+ * @internal to be removed in Symfony 5.0
+ */
+ public static function throwOnRequiredClass($class)
+ {
+ $e = new \ReflectionException("Class $class does not exist");
+ $trace = debug_backtrace();
+ $autoloadFrame = [
+ 'function' => 'spl_autoload_call',
+ 'args' => [$class],
+ ];
+ $i = 1 + array_search($autoloadFrame, $trace, true);
+
+ if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) {
+ switch ($trace[$i]['function']) {
+ case 'get_class_methods':
+ case 'get_class_vars':
+ case 'get_parent_class':
+ case 'is_a':
+ case 'is_subclass_of':
+ case 'class_exists':
+ case 'class_implements':
+ case 'class_parents':
+ case 'trait_exists':
+ case 'defined':
+ case 'interface_exists':
+ case 'method_exists':
+ case 'property_exists':
+ case 'is_callable':
+ return;
+ }
+ }
+
+ throw $e;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
new file mode 100644
index 0000000..10938a0
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
@@ -0,0 +1,38 @@
+<?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 Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\PhpFilesTrait;
+
+class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
+{
+ use PhpFilesTrait;
+
+ /**
+ * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
+ * Doing so is encouraged because it fits perfectly OPcache's memory model.
+ *
+ * @throws CacheException if OPcache is not enabled
+ */
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false)
+ {
+ $this->appendOnly = $appendOnly;
+ self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ $this->includeHandler = static function ($type, $msg, $file, $line) {
+ throw new \ErrorException($msg, 0, $type, $file, $line);
+ };
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ProxyAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ProxyAdapter.php
new file mode 100644
index 0000000..bccafb3
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/ProxyAdapter.php
@@ -0,0 +1,269 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+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\CacheInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ProxyTrait;
+ use ContractsTrait;
+
+ private $namespace;
+ private $namespaceLen;
+ private $createCacheItem;
+ private $setInnerItem;
+ private $poolHash;
+
+ public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->pool = $pool;
+ $this->poolHash = $poolHash = spl_object_hash($pool);
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace);
+ $this->namespaceLen = \strlen($namespace);
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $innerItem) use ($defaultLifetime, $poolHash) {
+ $item = new CacheItem();
+ $item->key = $key;
+
+ if (null === $innerItem) {
+ return $item;
+ }
+
+ $item->value = $v = $innerItem->get();
+ $item->isHit = $innerItem->isHit();
+ $item->innerItem = $innerItem;
+ $item->defaultLifetime = $defaultLifetime;
+ $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 = key($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) {
+ $item->metadata = $innerItem->metadata;
+ }
+ $innerItem->set(null);
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->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);
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (!$this->pool instanceof CacheInterface) {
+ return $this->doGet($this, $key, $callback, $beta, $metadata);
+ }
+
+ return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
+ $item = ($this->createCacheItem)($key, $innerItem);
+ $item->set($value = $callback($item, $save));
+ ($this->setInnerItem)($innerItem, (array) $item);
+
+ return $value;
+ }, $beta, $metadata);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $f = $this->createCacheItem;
+ $item = $this->pool->getItem($this->getId($key));
+
+ return $f($key, $item);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ if ($this->namespaceLen) {
+ foreach ($keys as $i => $key) {
+ $keys[$i] = $this->getId($key);
+ }
+ }
+
+ return $this->generateItems($this->pool->getItems($keys));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ return $this->pool->hasItem($this->getId($key));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/)
+ {
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
+
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($this->namespace.$prefix);
+ }
+
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return $this->pool->deleteItem($this->getId($key));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ if ($this->namespaceLen) {
+ foreach ($keys as $i => $key) {
+ $keys[$i] = $this->getId($key);
+ }
+ }
+
+ return $this->pool->deleteItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ return $this->doSave($item, __FUNCTION__);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return $this->doSave($item, __FUNCTION__);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return $this->pool->commit();
+ }
+
+ private function doSave(CacheItemInterface $item, string $method)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $item = (array) $item;
+ if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) {
+ $item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"];
+ }
+
+ if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) {
+ $innerItem = $item["\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
+ $f = $this->createCacheItem;
+ $innerItem = $f($this->namespace.$item["\0*\0key"], null);
+ } else {
+ $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
+ }
+
+ ($this->setInnerItem)($innerItem, $item);
+
+ return $this->pool->$method($innerItem);
+ }
+
+ private function generateItems(iterable $items)
+ {
+ $f = $this->createCacheItem;
+
+ foreach ($items as $key => $item) {
+ if ($this->namespaceLen) {
+ $key = substr($key, $this->namespaceLen);
+ }
+
+ yield $key => $f($key, $item);
+ }
+ }
+
+ private function getId($key): string
+ {
+ CacheItem::validateKey($key);
+
+ return $this->namespace.$key;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/Psr16Adapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/Psr16Adapter.php
new file mode 100644
index 0000000..bb38871
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/Psr16Adapter.php
@@ -0,0 +1,86 @@
+<?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 Psr\SimpleCache\CacheInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+
+/**
+ * Turns a PSR-16 cache into a PSR-6 one.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
+{
+ /**
+ * @internal
+ */
+ protected const NS_SEPARATOR = '_';
+
+ use ProxyTrait;
+
+ private $miss;
+
+ public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0)
+ {
+ parent::__construct($namespace, $defaultLifetime);
+
+ $this->pool = $pool;
+ $this->miss = new \stdClass();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
+ if ($this->miss !== $value) {
+ yield $key => $value;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave($id)
+ {
+ return $this->pool->has($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear($namespace)
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ return $this->pool->deleteMultiple($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, $lifetime)
+ {
+ return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisAdapter.php
new file mode 100644
index 0000000..5c49f7a
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisAdapter.php
@@ -0,0 +1,30 @@
+<?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 Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Traits\RedisTrait;
+
+class RedisAdapter extends AbstractAdapter
+{
+ use RedisTrait;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
+ */
+ public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ $this->init($redisClient, $namespace, $defaultLifetime, $marshaller);
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
new file mode 100644
index 0000000..1dbce4b
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
@@ -0,0 +1,292 @@
+<?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 Predis\Connection\Aggregate\ClusterInterface;
+use Predis\Connection\Aggregate\PredisCluster;
+use Predis\Response\Status;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\Traits\RedisTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a Redis Set, lookup on invalidation using RENAME+SMEMBERS.
+ *
+ * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even
+ * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache
+ * relationship survives eviction (cache cleanup when Redis runs out of memory).
+ *
+ * Requirements:
+ * - Client: PHP Redis or Predis
+ * Note: Due to lack of RENAME support it is NOT recommended to use Cluster on Predis, instead use phpredis.
+ * - Server: Redis 2.8+
+ * Configured with any `volatile-*` eviction policy, OR `noeviction` if it will NEVER fill up memory
+ *
+ * Design limitations:
+ * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype.
+ * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also.
+ *
+ * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies.
+ * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author André Rømcke <andre.romcke+symfony@gmail.com>
+ */
+class RedisTagAwareAdapter extends AbstractTagAwareAdapter
+{
+ use RedisTrait;
+
+ /**
+ * Limits for how many keys are deleted in batch.
+ */
+ private const BULK_DELETE_LIMIT = 10000;
+
+ /**
+ * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are
+ * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements.
+ */
+ private const DEFAULT_CACHE_TTL = 8640000;
+
+ /**
+ * @var string|null detected eviction policy used on Redis server
+ */
+ private $redisEvictionPolicy;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
+ */
+ public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if ($redisClient instanceof \Predis\ClientInterface && $redisClient->getConnection() instanceof ClusterInterface && !$redisClient->getConnection() instanceof PredisCluster) {
+ throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, \get_class($redisClient->getConnection())));
+ }
+
+ if (\defined('Redis::OPT_COMPRESSION') && ($redisClient instanceof \Redis || $redisClient instanceof \RedisArray || $redisClient instanceof \RedisCluster)) {
+ $compression = $redisClient->getOption(\Redis::OPT_COMPRESSION);
+
+ foreach (\is_array($compression) ? $compression : [$compression] as $c) {
+ if (\Redis::COMPRESSION_NONE !== $c) {
+ throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', \get_class($this), DeflateMarshaller::class));
+ }
+ }
+ }
+
+ $this->init($redisClient, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, ?int $lifetime, array $addTagData = [], array $delTagData = []): array
+ {
+ $eviction = $this->getRedisEvictionPolicy();
+ if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) {
+ CacheItem::log($this->logger, sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies', $eviction));
+
+ return false;
+ }
+
+ // serialize values
+ if (!$serialized = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op
+ $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) {
+ // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one
+ foreach ($serialized as $id => $value) {
+ yield 'setEx' => [
+ $id,
+ 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime,
+ $value,
+ ];
+ }
+
+ // Add and Remove Tags
+ foreach ($addTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sAdd' => array_merge([$tagId], $ids);
+ }
+ }
+
+ foreach ($delTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sRem' => array_merge([$tagId], $ids);
+ }
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not
+ if (is_numeric($result)) {
+ continue;
+ }
+ // setEx results
+ if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
+ $failed[] = $id;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ $lua = <<<'EOLUA'
+ local v = redis.call('GET', KEYS[1])
+ redis.call('DEL', KEYS[1])
+
+ if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then
+ return ''
+ end
+
+ return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536)
+EOLUA;
+
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ $evalArgs = [$lua, 1, &$id];
+ } else {
+ $evalArgs = [$lua, [&$id], 1];
+ }
+
+ $results = $this->pipeline(function () use ($ids, &$id, $evalArgs) {
+ foreach ($ids as $id) {
+ yield 'eval' => $evalArgs;
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ try {
+ yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ $this->pipeline(static function () use ($tagData) {
+ foreach ($tagData as $tagId => $idList) {
+ array_unshift($idList, $tagId);
+ yield 'sRem' => $idList;
+ }
+ })->rewind();
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ if (!$this->redis instanceof \Predis\ClientInterface || !$this->redis->getConnection() instanceof PredisCluster) {
+ $movedTagSetIds = $this->renameKeys($this->redis, $tagIds);
+ } else {
+ $clusterConnection = $this->redis->getConnection();
+ $tagIdsByConnection = new \SplObjectStorage();
+ $movedTagSetIds = [];
+
+ foreach ($tagIds as $id) {
+ $connection = $clusterConnection->getConnectionByKey($id);
+ $slot = $tagIdsByConnection[$connection] ?? $tagIdsByConnection[$connection] = new \ArrayObject();
+ $slot[] = $id;
+ }
+
+ foreach ($tagIdsByConnection as $connection) {
+ $slot = $tagIdsByConnection[$connection];
+ $movedTagSetIds = array_merge($movedTagSetIds, $this->renameKeys(new $this->redis($connection, $this->redis->getOptions()), $slot->getArrayCopy()));
+ }
+ }
+
+ // No Sets found
+ if (!$movedTagSetIds) {
+ return false;
+ }
+
+ // Now safely take the time to read the keys in each set and collect ids we need to delete
+ $tagIdSets = $this->pipeline(static function () use ($movedTagSetIds) {
+ foreach ($movedTagSetIds as $movedTagId) {
+ yield 'sMembers' => [$movedTagId];
+ }
+ });
+
+ // Return combination of the temporary Tag Set ids and their values (cache ids)
+ $ids = array_merge($movedTagSetIds, ...iterator_to_array($tagIdSets, false));
+
+ // Delete cache in chunks to avoid overloading the connection
+ foreach (array_chunk(array_unique($ids), self::BULK_DELETE_LIMIT) as $chunkIds) {
+ $this->doDelete($chunkIds);
+ }
+
+ return true;
+ }
+
+ /**
+ * Renames several keys in order to be able to operate on them without risk of race conditions.
+ *
+ * Filters out keys that do not exist before returning new keys.
+ *
+ * @see https://redis.io/commands/rename
+ * @see https://redis.io/topics/cluster-spec#keys-hash-tags
+ *
+ * @return array Filtered list of the valid moved keys (only those that existed)
+ */
+ private function renameKeys($redis, array $ids): array
+ {
+ $newIds = [];
+ $uniqueToken = bin2hex(random_bytes(10));
+
+ $results = $this->pipeline(static function () use ($ids, $uniqueToken) {
+ foreach ($ids as $id) {
+ yield 'rename' => [$id, '{'.$id.'}'.$uniqueToken];
+ }
+ }, $redis);
+
+ foreach ($results as $id => $result) {
+ if (true === $result || ($result instanceof Status && Status::get('OK') === $result)) {
+ // Only take into account if ok (key existed), will be false on phpredis if it did not exist
+ $newIds[] = '{'.$id.'}'.$uniqueToken;
+ }
+ }
+
+ return $newIds;
+ }
+
+ private function getRedisEvictionPolicy(): string
+ {
+ if (null !== $this->redisEvictionPolicy) {
+ return $this->redisEvictionPolicy;
+ }
+
+ foreach ($this->getHosts() as $host) {
+ $info = $host->info('Memory');
+ $info = isset($info['Memory']) ? $info['Memory'] : $info;
+
+ return $this->redisEvictionPolicy = $info['maxmemory_policy'];
+ }
+
+ return $this->redisEvictionPolicy = '';
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php
new file mode 100644
index 0000000..d0d42e5
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php
@@ -0,0 +1,21 @@
+<?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;
+
+@trigger_error(sprintf('The "%s" class is @deprecated since Symfony 4.3, use "Psr16Adapter" instead.', SimpleCacheAdapter::class), E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use Psr16Adapter instead.
+ */
+class SimpleCacheAdapter extends Psr16Adapter
+{
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapter.php
new file mode 100644
index 0000000..7c0ee30
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapter.php
@@ -0,0 +1,429 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+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;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface
+{
+ const TAGS_PREFIX = "\0tags\0";
+
+ use ProxyTrait;
+ use ContractsTrait;
+
+ private $deferred = [];
+ private $createCacheItem;
+ private $setCacheItemTags;
+ private $getTagsByKey;
+ private $invalidateTags;
+ private $tags;
+ private $knownTagVersions = [];
+ private $knownTagVersionsTtl;
+
+ public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
+ {
+ $this->pool = $itemsPool;
+ $this->tags = $tagsPool ?: $itemsPool;
+ $this->knownTagVersionsTtl = $knownTagVersionsTtl;
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, CacheItem $protoItem) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->defaultLifetime = $protoItem->defaultLifetime;
+ $item->expiry = $protoItem->expiry;
+ $item->poolHash = $protoItem->poolHash;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->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;
+ }
+ unset($itemTags[$key]);
+ } else {
+ $item->value = null;
+ $item->isHit = false;
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->getTagsByKey = \Closure::bind(
+ static function ($deferred) {
+ $tagsByKey = [];
+ foreach ($deferred as $key => $item) {
+ $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? [];
+ }
+
+ return $tagsByKey;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->invalidateTags = \Closure::bind(
+ static function (AdapterInterface $tagsAdapter, array $tags) {
+ foreach ($tags as $v) {
+ $v->defaultLifetime = 0;
+ $v->expiry = null;
+ $tagsAdapter->saveDeferred($v);
+ }
+
+ return $tagsAdapter->commit();
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ $ok = true;
+ $tagsByKey = [];
+ $invalidatedTags = [];
+ foreach ($tags as $tag) {
+ CacheItem::validateKey($tag);
+ $invalidatedTags[$tag] = 0;
+ }
+
+ if ($this->deferred) {
+ $items = $this->deferred;
+ foreach ($items as $key => $item) {
+ if (!$this->pool->saveDeferred($item)) {
+ unset($this->deferred[$key]);
+ $ok = false;
+ }
+ }
+
+ $f = $this->getTagsByKey;
+ $tagsByKey = $f($items);
+ $this->deferred = [];
+ }
+
+ $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags);
+ $f = $this->createCacheItem;
+
+ foreach ($tagsByKey as $key => $tags) {
+ $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
+ }
+ $ok = $this->pool->commit() && $ok;
+
+ if ($invalidatedTags) {
+ $f = $this->invalidateTags;
+ $ok = $f($this->tags, $invalidatedTags) && $ok;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ if ($this->deferred) {
+ $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 && 1 !== $itemTags[$tag] - $version) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ foreach ($this->getItems([$key]) as $item) {
+ return $item;
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ if ($this->deferred) {
+ $this->commit();
+ }
+ $tagKeys = [];
+
+ foreach ($keys as $key) {
+ if ('' !== $key && \is_string($key)) {
+ $key = static::TAGS_PREFIX.$key;
+ $tagKeys[$key] = $key;
+ }
+ }
+
+ try {
+ $items = $this->pool->getItems($tagKeys + $keys);
+ } catch (InvalidArgumentException $e) {
+ $this->pool->getItems($keys); // Should throw an exception
+
+ throw $e;
+ }
+
+ return $this->generateItems($items, $tagKeys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/)
+ {
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
+
+ if ('' !== $prefix) {
+ foreach ($this->deferred as $key => $item) {
+ if (0 === strpos($key, $prefix)) {
+ unset($this->deferred[$key]);
+ }
+ }
+ } else {
+ $this->deferred = [];
+ }
+
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($prefix);
+ }
+
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return $this->deleteItems([$key]);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ foreach ($keys as $key) {
+ if ('' !== $key && \is_string($key)) {
+ $keys[] = static::TAGS_PREFIX.$key;
+ }
+ }
+
+ return $this->pool->deleteItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return $this->commit();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return $this->invalidateTags([]);
+ }
+
+ public function __sleep()
+ {
+ throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
+ }
+
+ public function __wakeup()
+ {
+ throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
+ }
+
+ public function __destruct()
+ {
+ $this->commit();
+ }
+
+ private function generateItems(iterable $items, array $tagKeys)
+ {
+ $bufferedItems = $itemTags = [];
+ $f = $this->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 && 1 !== $version - $tagVersions[$tag]) {
+ 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, array &$invalidatedTags = [])
+ {
+ $tagVersions = $invalidatedTags;
+
+ foreach ($tagsByKey as $tags) {
+ $tagVersions += $tags;
+ }
+
+ if (!$tagVersions) {
+ return [];
+ }
+
+ if (!$fetchTagVersions = 1 !== \func_num_args()) {
+ foreach ($tagsByKey as $tags) {
+ foreach ($tags as $tag => $version) {
+ if ($tagVersions[$tag] > $version) {
+ $tagVersions[$tag] = $version;
+ }
+ }
+ }
+ }
+
+ $now = microtime(true);
+ $tags = [];
+ foreach ($tagVersions as $tag => $version) {
+ $tags[$tag.static::TAGS_PREFIX] = $tag;
+ if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) {
+ $fetchTagVersions = true;
+ continue;
+ }
+ $version -= $this->knownTagVersions[$tag][1];
+ if ((0 !== $version && 1 !== $version) || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) {
+ // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises
+ $fetchTagVersions = true;
+ } else {
+ $this->knownTagVersions[$tag][1] += $version;
+ }
+ }
+
+ if (!$fetchTagVersions) {
+ return $tagVersions;
+ }
+
+ foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) {
+ $tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0;
+ if (isset($invalidatedTags[$tag])) {
+ $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]);
+ }
+ $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]];
+ }
+
+ return $tagVersions;
+ }
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php
new file mode 100644
index 0000000..340048c
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php
@@ -0,0 +1,33 @@
+<?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 Psr\Cache\InvalidArgumentException;
+
+/**
+ * Interface for invalidating cached items using tags.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface TagAwareAdapterInterface extends AdapterInterface
+{
+ /**
+ * Invalidates cached items using tags.
+ *
+ * @param string[] $tags An array of tags to invalidate
+ *
+ * @return bool True on success
+ *
+ * @throws InvalidArgumentException When $tags is not valid
+ */
+ public function invalidateTags(array $tags);
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableAdapter.php
new file mode 100644
index 0000000..7e9dac8
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableAdapter.php
@@ -0,0 +1,302 @@
+<?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 Psr\Cache\CacheItemInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * An adapter that collects data about all cache calls.
+ *
+ * @author Aaron Scherer <aequasi@gmail.com>
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ protected $pool;
+ private $calls = [];
+
+ public function __construct(AdapterInterface $pool)
+ {
+ $this->pool = $pool;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (!$this->pool instanceof CacheInterface) {
+ throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', \get_class($this->pool), CacheInterface::class));
+ }
+
+ $isHit = true;
+ $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) {
+ $isHit = $item->isHit();
+
+ return $callback($item, $save);
+ };
+
+ $event = $this->start(__FUNCTION__);
+ try {
+ $value = $this->pool->get($key, $callback, $beta, $metadata);
+ $event->result[$key] = \is_object($value) ? \get_class($value) : \gettype($value);
+ } finally {
+ $event->end = microtime(true);
+ }
+ if ($isHit) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+
+ return $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ $item = $this->pool->getItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ if ($event->result[$key] = $item->isHit()) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+
+ return $item;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->hasItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->deleteItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$item->getKey()] = $this->pool->save($item);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$item->getKey()] = $this->pool->saveDeferred($item);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ $result = $this->pool->getItems($keys);
+ } finally {
+ $event->end = microtime(true);
+ }
+ $f = function () use ($result, $event) {
+ $event->result = [];
+ foreach ($result as $key => $item) {
+ if ($event->result[$key] = $item->isHit()) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+ yield $key => $item;
+ }
+ };
+
+ return $f();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/*string $prefix = ''*/)
+ {
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
+ $event = $this->start(__FUNCTION__);
+ try {
+ if ($this->pool instanceof AdapterInterface) {
+ return $event->result = $this->pool->clear($prefix);
+ }
+
+ return $event->result = $this->pool->clear();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $event = $this->start(__FUNCTION__);
+ $event->result['keys'] = $keys;
+ try {
+ return $event->result['result'] = $this->pool->deleteItems($keys);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->commit();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ if (!$this->pool instanceof PruneableInterface) {
+ return false;
+ }
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->prune();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ if (!$this->pool instanceof ResetInterface) {
+ return;
+ }
+ $event = $this->start(__FUNCTION__);
+ try {
+ $this->pool->reset();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->deleteItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ public function getCalls()
+ {
+ return $this->calls;
+ }
+
+ public function clearCalls()
+ {
+ $this->calls = [];
+ }
+
+ protected function start($name)
+ {
+ $this->calls[] = $event = new TraceableAdapterEvent();
+ $event->name = $name;
+ $event->start = microtime(true);
+
+ return $event;
+ }
+}
+
+class TraceableAdapterEvent
+{
+ public $name;
+ public $start;
+ public $end;
+ public $result;
+ public $hits = 0;
+ public $misses = 0;
+}
diff --git a/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php
new file mode 100644
index 0000000..69461b8
--- /dev/null
+++ b/srcs/phpmyadmin/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php
@@ -0,0 +1,38 @@
+<?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 Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ */
+class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface
+{
+ public function __construct(TagAwareAdapterInterface $pool)
+ {
+ parent::__construct($pool);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->invalidateTags($tags);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+}