LICENSE000064400000002051144760115210005550 0ustar00Copyright (c) 2006-2015 Doctrine Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000064400000001617144760115210006031 0ustar00# Doctrine Cache [![Build Status](https://github.com/doctrine/cache/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/cache/actions) [![Code Coverage](https://codecov.io/gh/doctrine/cache/branch/1.10.x/graph/badge.svg)](https://codecov.io/gh/doctrine/cache/branch/1.10.x) [![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) [![Total Downloads](https://img.shields.io/packagist/dt/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) Cache component extracted from the Doctrine Common project. [Documentation](https://www.doctrine-project.org/projects/doctrine-cache/en/current/index.html) This library is deprecated and will no longer receive bug fixes from the Doctrine Project. Please use a different cache library, preferably PSR-6 or PSR-16 instead. UPGRADE-1.11.md000064400000001537144760115210006542 0ustar00# Upgrade to 1.11 doctrine/cache will no longer be maintained and all cache implementations have been marked as deprecated. These implementations will be removed in 2.0, which will only contain interfaces to provide a lightweight package for backward compatibility. There are two new classes to use in the `Doctrine\Common\Cache\Psr6` namespace: * The `CacheAdapter` class allows using any Doctrine Cache as PSR-6 cache. This is useful to provide a forward compatibility layer in libraries that accept Doctrine cache implementations and switch to PSR-6. * The `DoctrineProvider` class allows using any PSR-6 cache as Doctrine cache. This implementation is designed for libraries that leak the cache and want to switch to allowing PSR-6 implementations. This class is design to be used during the transition phase of sunsetting doctrine/cache support. UPGRADE-1.4.md000064400000001326144760115210006460 0ustar00# Upgrade to 1.4 ## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding the property in your own implementation. ## Minor BC Break: file based caches paths changed `Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and `Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. If you rely on warmed up caches for deployments, consider that caches generated with `doctrine/cache` `<1.4` are not compatible with the new directory structure, and will be ignored. composer.json000064400000003235144760115210007272 0ustar00{ "name": "doctrine/cache", "type": "library", "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", "keywords": [ "php", "cache", "caching", "abstraction", "redis", "memcached", "couchdb", "xcache", "apcu" ], "homepage": "https://www.doctrine-project.org/projects/cache.html", "license": "MIT", "authors": [ {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, {"name": "Roman Borschel", "email": "roman@code-factory.org"}, {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} ], "require": { "php": "~7.1 || ^8.0" }, "require-dev": { "alcaeus/mongo-php-adapter": "^1.1", "mongodb/mongodb": "^1.1", "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", "predis/predis": "~1.0", "doctrine/coding-standard": "^8.0", "psr/cache": "^1.0 || ^2.0", "cache/integration-tests": "dev-master", "symfony/cache": "^4.4 || ^5.2" }, "suggest": { "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "conflict": { "doctrine/common": ">2.2,<2.4", "psr/cache": ">=3" }, "autoload": { "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "autoload-dev": { "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine/Tests" } } } lib/Doctrine/Common/Cache/Cache.php000064400000005357144760115210013043 0ustar00hits * Number of keys that have been requested and found present. * * - misses * Number of items that have been requested and not found. * * - uptime * Time that the server is running. * * - memory_usage * Memory used by this server to store items. * * - memory_available * Memory allowed to use for storage. * * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise. */ public function getStats(); } lib/Doctrine/Common/Cache/CacheProvider.php000064400000020433144760115210014546 0ustar00namespace = (string) $namespace; $this->namespaceVersion = null; } /** * Retrieves the namespace that prefixes all cache ids. * * @return string */ public function getNamespace() { return $this->namespace; } /** * {@inheritdoc} */ public function fetch($id) { return $this->doFetch($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function fetchMultiple(array $keys) { if (empty($keys)) { return []; } // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys)); $items = $this->doFetchMultiple($namespacedKeys); $foundItems = []; // no internal array function supports this sort of mapping: needs to be iterative // this filters and combines keys in one pass foreach ($namespacedKeys as $requestedKey => $namespacedKey) { if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) { continue; } $foundItems[$requestedKey] = $items[$namespacedKey]; } return $foundItems; } /** * {@inheritdoc} */ public function saveMultiple(array $keysAndValues, $lifetime = 0) { $namespacedKeysAndValues = []; foreach ($keysAndValues as $key => $value) { $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; } return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); } /** * {@inheritdoc} */ public function contains($id) { return $this->doContains($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function save($id, $data, $lifeTime = 0) { return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); } /** * {@inheritdoc} */ public function deleteMultiple(array $keys) { return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys)); } /** * {@inheritdoc} */ public function delete($id) { return $this->doDelete($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function getStats() { return $this->doGetStats(); } /** * {@inheritDoc} */ public function flushAll() { return $this->doFlush(); } /** * {@inheritDoc} */ public function deleteAll() { $namespaceCacheKey = $this->getNamespaceCacheKey(); $namespaceVersion = $this->getNamespaceVersion() + 1; if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { $this->namespaceVersion = $namespaceVersion; return true; } return false; } /** * Prefixes the passed id with the configured namespace value. * * @param string $id The id to namespace. * * @return string The namespaced id. */ private function getNamespacedId(string $id): string { $namespaceVersion = $this->getNamespaceVersion(); return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); } /** * Returns the namespace cache key. */ private function getNamespaceCacheKey(): string { return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); } /** * Returns the namespace version. */ private function getNamespaceVersion(): int { if ($this->namespaceVersion !== null) { return $this->namespaceVersion; } $namespaceCacheKey = $this->getNamespaceCacheKey(); $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1; return $this->namespaceVersion; } /** * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. * * @param string[] $keys Array of keys to retrieve from cache * * @return mixed[] Array of values retrieved for the given keys. */ protected function doFetchMultiple(array $keys) { $returnValues = []; foreach ($keys as $key) { $item = $this->doFetch($key); if ($item === false && ! $this->doContains($key)) { continue; } $returnValues[$key] = $item; } return $returnValues; } /** * Fetches an entry from the cache. * * @param string $id The id of the cache entry to fetch. * * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id. */ abstract protected function doFetch($id); /** * Tests if an entry exists in the cache. * * @param string $id The cache id of the entry to check for. * * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. */ abstract protected function doContains($id); /** * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. * * @param mixed[] $keysAndValues Array of keys and values to save in cache * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these * cache entries (0 => infinite lifeTime). * * @return bool TRUE if the operation was successful, FALSE if it wasn't. */ protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) { $success = true; foreach ($keysAndValues as $key => $value) { if ($this->doSave($key, $value, $lifetime)) { continue; } $success = false; } return $success; } /** * Puts data into the cache. * * @param string $id The cache id. * @param string $data The cache entry/data. * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this * cache entry (0 => infinite lifeTime). * * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. */ abstract protected function doSave($id, $data, $lifeTime = 0); /** * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it. * * @param string[] $keys Array of keys to delete from cache * * @return bool TRUE if the operation was successful, FALSE if it wasn't */ protected function doDeleteMultiple(array $keys) { $success = true; foreach ($keys as $key) { if ($this->doDelete($key)) { continue; } $success = false; } return $success; } /** * Deletes a cache entry. * * @param string $id The cache id. * * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. */ abstract protected function doDelete($id); /** * Flushes all cache entries. * * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. */ abstract protected function doFlush(); /** * Retrieves cached information from the data store. * * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise. */ abstract protected function doGetStats(); } lib/Doctrine/Common/Cache/ClearableCache.php000064400000000765144760115210014634 0ustar00 infinite lifeTime). * * @return bool TRUE if the operation was successful, FALSE if it wasn't. */ public function saveMultiple(array $keysAndValues, $lifetime = 0); } lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php000064400000016413144760115210015171 0ustar00getPool(); } if ($cache instanceof SymfonyDoctrineProvider) { $getPool = function () { // phpcs:ignore Squiz.Scope.StaticThisUsage.Found return $this->pool; }; return $getPool->bindTo($cache, SymfonyDoctrineProvider::class)(); } return new self($cache); } private function __construct(Cache $cache) { $this->cache = $cache; } /** @internal */ public function getCache(): Cache { return $this->cache; } /** * {@inheritDoc} */ public function getItem($key): CacheItemInterface { assert(self::validKey($key)); if (isset($this->deferredItems[$key])) { $this->commit(); } $value = $this->cache->fetch($key); if ($value !== false) { return new CacheItem($key, $value, true); } return new CacheItem($key, null, false); } /** * {@inheritDoc} */ public function getItems(array $keys = []): array { if ($this->deferredItems) { $this->commit(); } assert(self::validKeys($keys)); $values = $this->doFetchMultiple($keys); $items = []; foreach ($keys as $key) { if (array_key_exists($key, $values)) { $items[$key] = new CacheItem($key, $values[$key], true); } else { $items[$key] = new CacheItem($key, null, false); } } return $items; } /** * {@inheritDoc} */ public function hasItem($key): bool { assert(self::validKey($key)); if (isset($this->deferredItems[$key])) { $this->commit(); } return $this->cache->contains($key); } public function clear(): bool { $this->deferredItems = []; if (! $this->cache instanceof ClearableCache) { return false; } return $this->cache->deleteAll(); } /** * {@inheritDoc} */ public function deleteItem($key): bool { assert(self::validKey($key)); unset($this->deferredItems[$key]); return $this->cache->delete($key); } /** * {@inheritDoc} */ public function deleteItems(array $keys): bool { foreach ($keys as $key) { assert(self::validKey($key)); unset($this->deferredItems[$key]); } return $this->doDeleteMultiple($keys); } public function save(CacheItemInterface $item): bool { return $this->saveDeferred($item) && $this->commit(); } public function saveDeferred(CacheItemInterface $item): bool { if (! $item instanceof CacheItem) { return false; } $this->deferredItems[$item->getKey()] = $item; return true; } public function commit(): bool { if (! $this->deferredItems) { return true; } $now = microtime(true); $itemsCount = 0; $byLifetime = []; $expiredKeys = []; foreach ($this->deferredItems as $key => $item) { $lifetime = ($item->getExpiry() ?? $now) - $now; if ($lifetime < 0) { $expiredKeys[] = $key; continue; } ++$itemsCount; $byLifetime[(int) $lifetime][$key] = $item->get(); } switch (count($expiredKeys)) { case 0: break; case 1: $this->cache->delete(current($expiredKeys)); break; default: $this->doDeleteMultiple($expiredKeys); break; } if ($itemsCount === 1) { return $this->cache->save($key, $item->get(), (int) $lifetime); } $success = true; foreach ($byLifetime as $lifetime => $values) { $success = $this->doSaveMultiple($values, $lifetime) && $success; } return $success; } public function __destruct() { $this->commit(); } /** * @param mixed $key */ private static function validKey($key): bool { if (! is_string($key)) { throw new InvalidArgument(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if ($key === '') { throw new InvalidArgument('Cache key length must be greater than zero.'); } if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) { throw new InvalidArgument(sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS)); } return true; } /** * @param mixed[] $keys */ private static function validKeys(array $keys): bool { foreach ($keys as $key) { self::validKey($key); } return true; } /** * @param mixed[] $keys */ private function doDeleteMultiple(array $keys): bool { if ($this->cache instanceof MultiDeleteCache) { return $this->cache->deleteMultiple($keys); } $success = true; foreach ($keys as $key) { $success = $this->cache->delete($key) && $success; } return $success; } /** * @param mixed[] $keys * * @return mixed[] */ private function doFetchMultiple(array $keys): array { if ($this->cache instanceof MultiGetCache) { return $this->cache->fetchMultiple($keys); } $values = []; foreach ($keys as $key) { $value = $this->cache->fetch($key); if (! $value) { continue; } $values[$key] = $value; } return $values; } /** * @param mixed[] $keysAndValues */ private function doSaveMultiple(array $keysAndValues, int $lifetime = 0): bool { if ($this->cache instanceof MultiPutCache) { return $this->cache->saveMultiple($keysAndValues, $lifetime); } $success = true; foreach ($keysAndValues as $key => $value) { $success = $this->cache->save($key, $value, $lifetime) && $success; } return $success; } } lib/Doctrine/Common/Cache/Psr6/CacheItem.php000064400000005006144760115210014503 0ustar00key = $key; $this->value = $data; $this->isHit = $isHit; } public function getKey(): string { return $this->key; } /** * {@inheritDoc} * * @return mixed */ public function get() { return $this->value; } public function isHit(): bool { return $this->isHit; } /** * {@inheritDoc} */ public function set($value): self { $this->value = $value; return $this; } /** * {@inheritDoc} */ public function expiresAt($expiration): self { if ($expiration === null) { $this->expiry = null; } elseif ($expiration instanceof DateTimeInterface) { $this->expiry = (float) $expiration->format('U.u'); } else { throw new TypeError(sprintf( 'Expected $expiration to be an instance of DateTimeInterface or null, got %s', is_object($expiration) ? get_class($expiration) : gettype($expiration) )); } return $this; } /** * {@inheritDoc} */ public function expiresAfter($time): self { if ($time === null) { $this->expiry = null; } elseif ($time instanceof DateInterval) { $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); } elseif (is_int($time)) { $this->expiry = $time + microtime(true); } else { throw new TypeError(sprintf( 'Expected $time to be either an integer, an instance of DateInterval or null, got %s', is_object($time) ? get_class($time) : gettype($time) )); } return $this; } /** * @internal */ public function getExpiry(): ?float { return $this->expiry; } } lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php000064400000005303144760115210016143 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Doctrine\Common\Cache\Psr6; use Doctrine\Common\Cache\Cache; use Doctrine\Common\Cache\CacheProvider; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\DoctrineAdapter as SymfonyDoctrineAdapter; use function rawurlencode; /** * This class was copied from the Symfony Framework, see the original copyright * notice above. The code is distributed subject to the license terms in * https://github.com/symfony/symfony/blob/ff0cf61278982539c49e467db9ab13cbd342f76d/LICENSE */ final class DoctrineProvider extends CacheProvider { /** @var CacheItemPoolInterface */ private $pool; public static function wrap(CacheItemPoolInterface $pool): Cache { if ($pool instanceof CacheAdapter) { return $pool->getCache(); } if ($pool instanceof SymfonyDoctrineAdapter) { $getCache = function () { // phpcs:ignore Squiz.Scope.StaticThisUsage.Found return $this->provider; }; return $getCache->bindTo($pool, SymfonyDoctrineAdapter::class)(); } return new self($pool); } private function __construct(CacheItemPoolInterface $pool) { $this->pool = $pool; } /** @internal */ public function getPool(): CacheItemPoolInterface { return $this->pool; } /** * {@inheritdoc} */ protected function doFetch($id) { $item = $this->pool->getItem(rawurlencode($id)); return $item->isHit() ? $item->get() : false; } /** * {@inheritdoc} * * @return bool */ protected function doContains($id) { return $this->pool->hasItem(rawurlencode($id)); } /** * {@inheritdoc} * * @return bool */ protected function doSave($id, $data, $lifeTime = 0) { $item = $this->pool->getItem(rawurlencode($id)); if (0 < $lifeTime) { $item->expiresAfter($lifeTime); } return $this->pool->save($item->set($data)); } /** * {@inheritdoc} * * @return bool */ protected function doDelete($id) { return $this->pool->deleteItem(rawurlencode($id)); } /** * {@inheritdoc} * * @return bool */ protected function doFlush() { return $this->pool->clear(); } /** * {@inheritdoc} * * @return array|null */ protected function doGetStats() { return null; } } lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php000064400000000421144760115210015746 0ustar00