From 73e58dc71cac5606b62a9387901300ab09444c3a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 19 May 2021 15:18:37 +0200 Subject: [PATCH 01/20] Bump Symfony 6 to PHP 8 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0f69892..81cac20 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "psr/cache": "^1.0|^2.0|^3.0" }, "suggest": { From 0fbbf3d935d236659db46a1c0a16c4577e37615e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 9 Jun 2021 12:09:37 +0200 Subject: [PATCH 02/20] Bump Contracts to 2.5 --- ItemInterface.php | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ItemInterface.php b/ItemInterface.php index 10c0488..9795262 100644 --- a/ItemInterface.php +++ b/ItemInterface.php @@ -54,7 +54,7 @@ interface ItemInterface extends CacheItemInterface * @throws InvalidArgumentException When $tag is not valid * @throws CacheException When the item comes from a pool that is not tag-aware */ - public function tag($tags): self; + public function tag(string|iterable $tags): self; /** * Returns a list of metadata info that were saved alongside with the cached value. diff --git a/composer.json b/composer.json index 81cac20..f613e8a 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", From 7ce2310bdc72c4115509256f341f7d05772f62eb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 13 Jul 2021 13:47:05 +0200 Subject: [PATCH 03/20] [Contracts] add return types and bump to v3 --- CacheInterface.php | 2 +- CacheTrait.php | 6 ++---- CallbackInterface.php | 2 +- ItemInterface.php | 2 +- TagAwareCacheInterface.php | 2 +- composer.json | 4 ++-- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CacheInterface.php b/CacheInterface.php index 4b1686b..419bc90 100644 --- a/CacheInterface.php +++ b/CacheInterface.php @@ -42,7 +42,7 @@ interface CacheInterface * * @throws InvalidArgumentException When $key is not valid or when $beta is negative */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null); + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed; /** * Removes an item from the pool. diff --git a/CacheTrait.php b/CacheTrait.php index d340e06..d245df6 100644 --- a/CacheTrait.php +++ b/CacheTrait.php @@ -27,10 +27,8 @@ trait CacheTrait { /** * {@inheritdoc} - * - * @return mixed */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed { return $this->doGet($this, $key, $callback, $beta, $metadata); } @@ -43,7 +41,7 @@ public function delete(string $key): bool return $this->deleteItem($key); } - private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null) + private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null): mixed { if (0 > $beta = $beta ?? 1.0) { throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { }; diff --git a/CallbackInterface.php b/CallbackInterface.php index 7dae2aa..437a3c9 100644 --- a/CallbackInterface.php +++ b/CallbackInterface.php @@ -26,5 +26,5 @@ interface CallbackInterface * * @return mixed The computed value for the passed item */ - public function __invoke(CacheItemInterface $item, bool &$save); + public function __invoke(CacheItemInterface $item, bool &$save): mixed; } diff --git a/ItemInterface.php b/ItemInterface.php index 9795262..8c4c512 100644 --- a/ItemInterface.php +++ b/ItemInterface.php @@ -54,7 +54,7 @@ interface ItemInterface extends CacheItemInterface * @throws InvalidArgumentException When $tag is not valid * @throws CacheException When the item comes from a pool that is not tag-aware */ - public function tag(string|iterable $tags): self; + public function tag(string|iterable $tags): static; /** * Returns a list of metadata info that were saved alongside with the cached value. diff --git a/TagAwareCacheInterface.php b/TagAwareCacheInterface.php index 7c4cf11..8e0b6be 100644 --- a/TagAwareCacheInterface.php +++ b/TagAwareCacheInterface.php @@ -34,5 +34,5 @@ interface TagAwareCacheInterface extends CacheInterface * * @throws InvalidArgumentException When $tags is not valid */ - public function invalidateTags(array $tags); + public function invalidateTags(array $tags): bool; } diff --git a/composer.json b/composer.json index f613e8a..1523e06 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "psr/cache": "^1.0|^2.0|^3.0" + "psr/cache": "^3.0" }, "suggest": { "symfony/cache-implementation": "" @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", From d0c92a783eb68478d25f17e5ad9385357b93b28b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Nov 2021 19:10:03 +0100 Subject: [PATCH 04/20] [Contracts] update branch-alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1523e06..55769fe 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.1-dev" }, "thanks": { "name": "symfony/contracts", From d1b0b26679d193d779803e3208f9a8bb637cdd28 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 16 Dec 2021 11:11:51 +0100 Subject: [PATCH 05/20] Add more nullsafe operators --- CacheTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CacheTrait.php b/CacheTrait.php index d245df6..9ac5a6d 100644 --- a/CacheTrait.php +++ b/CacheTrait.php @@ -43,7 +43,7 @@ public function delete(string $key): bool private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null): mixed { - if (0 > $beta = $beta ?? 1.0) { + if (0 > $beta ??= 1.0) { throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { }; } @@ -58,7 +58,7 @@ private function doGet(CacheItemPoolInterface $pool, string $key, callable $call if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) { // force applying defaultLifetime to expiry $item->expiresAt(null); - $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ + $logger?->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ 'key' => $key, 'delta' => sprintf('%.1f', $expiry - $now), ]); From 2eab7fa459af6d75c6463e63e633b667a9b761d3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 9 Feb 2022 15:00:38 +0100 Subject: [PATCH 06/20] Bump minimum version of PHP to 8.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 55769fe..2582e5a 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/cache": "^3.0" }, "suggest": { From aa79ac322ca42cfed7d744cb55777b9425a93d2d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 20 May 2022 15:56:22 +0200 Subject: [PATCH 07/20] Update branch alias for contracts --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2582e5a..27b2c84 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.1-dev" + "dev-main": "3.2-dev" }, "thanks": { "name": "symfony/contracts", From 2eeee072bf0befcea7322a665a28d6618a39f998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Wed, 27 Jul 2022 15:32:56 +0200 Subject: [PATCH 08/20] Remove .gitignore file from dist package --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3a01b37 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/.gitattributes export-ignore +/.gitignore export-ignore From a74b8f61671cf3e4ea1fb216132cb08e103a16dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 25 Aug 2022 16:59:21 +0200 Subject: [PATCH 09/20] [CS] Remove @inheritdoc PHPDoc --- CacheTrait.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CacheTrait.php b/CacheTrait.php index 9ac5a6d..b4fddfa 100644 --- a/CacheTrait.php +++ b/CacheTrait.php @@ -25,17 +25,11 @@ class_exists(InvalidArgumentException::class); */ trait CacheTrait { - /** - * {@inheritdoc} - */ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed { return $this->doGet($this, $key, $callback, $beta, $metadata); } - /** - * {@inheritdoc} - */ public function delete(string $key): bool { return $this->deleteItem($key); From f7d00057552710222fd787b1f9d1f836a1716989 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Sep 2022 16:55:07 +0200 Subject: [PATCH 10/20] CS fixes --- CacheInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CacheInterface.php b/CacheInterface.php index 0840a8f..0d4f403 100644 --- a/CacheInterface.php +++ b/CacheInterface.php @@ -47,9 +47,9 @@ public function get(string $key, callable $callback, float $beta = null, array & * * @param string $key The key to delete * - * @throws InvalidArgumentException When $key is not valid - * * @return bool True if the item was successfully removed, false if there was any error + * + * @throws InvalidArgumentException When $key is not valid */ public function delete(string $key): bool; } From e8d1a5fc43534063204b74c080ebe36307d12271 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Nov 2022 11:21:52 +0100 Subject: [PATCH 11/20] [Contracts] update branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 27b2c84..770e20e 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", From 13769aac94f0c582cfd9f9ac0b5832006654e633 Mon Sep 17 00:00:00 2001 From: Jack Worman Date: Thu, 26 Jan 2023 12:56:19 -0500 Subject: [PATCH 12/20] Add cache contracts template annotations --- CacheInterface.php | 20 ++++++++++++-------- CallbackInterface.php | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CacheInterface.php b/CacheInterface.php index 0d4f403..a4fcea7 100644 --- a/CacheInterface.php +++ b/CacheInterface.php @@ -29,14 +29,18 @@ interface CacheInterface * requested key, that could be used e.g. for expiration control. It could also * be an ItemInterface instance when its additional features are needed. * - * @param string $key The key of the item to retrieve from the cache - * @param callable|CallbackInterface $callback Should return the computed value for the given key/item - * @param float|null $beta A float that, as it grows, controls the likeliness of triggering - * early expiration. 0 disables it, INF forces immediate expiration. - * The default (or providing null) is implementation dependent but should - * typically be 1.0, which should provide optimal stampede protection. - * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration - * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} + * @template T + * + * @param string $key The key of the item to retrieve from the cache + * @param (callable(CacheItemInterface,bool):T)|(callable(ItemInterface,bool):T)|CallbackInterface $callback + * @param float|null $beta A float that, as it grows, controls the likeliness of triggering + * early expiration. 0 disables it, INF forces immediate expiration. + * The default (or providing null) is implementation dependent but should + * typically be 1.0, which should provide optimal stampede protection. + * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration + * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} + * + * @return T * * @throws InvalidArgumentException When $key is not valid or when $beta is negative */ diff --git a/CallbackInterface.php b/CallbackInterface.php index 437a3c9..15941e9 100644 --- a/CallbackInterface.php +++ b/CallbackInterface.php @@ -17,6 +17,8 @@ * Computes and returns the cached value of an item. * * @author Nicolas Grekas + * + * @template T */ interface CallbackInterface { @@ -24,7 +26,7 @@ interface CallbackInterface * @param CacheItemInterface|ItemInterface $item The item to compute the value for * @param bool &$save Should be set to false when the value should not be saved in the pool * - * @return mixed The computed value for the passed item + * @return T The computed value for the passed item */ public function __invoke(CacheItemInterface $item, bool &$save): mixed; } From eeb71f04b6f7f34ca6d15633df82e014528b1632 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Mar 2023 11:32:47 +0100 Subject: [PATCH 13/20] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7085a69..ffe0833 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Symfony Cache Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful - and +Can be used to build on semantics that the Symfony components proved useful and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. From d2fa225c522be4c83ca06522d2b4cdc664191154 Mon Sep 17 00:00:00 2001 From: Artyum Petrov <17199757+artyuum@users.noreply.github.com> Date: Thu, 20 Apr 2023 19:24:19 +0400 Subject: [PATCH 14/20] Add "composer require..." in all exception messages when needed --- composer.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/composer.json b/composer.json index 770e20e..79a1d2d 100644 --- a/composer.json +++ b/composer.json @@ -19,9 +19,6 @@ "php": ">=8.1", "psr/cache": "^3.0" }, - "suggest": { - "symfony/cache-implementation": "" - }, "autoload": { "psr-4": { "Symfony\\Contracts\\Cache\\": "" } }, From ad945640ccc0ae6e208bcea7d7de4b39b569896b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 23 May 2023 16:45:45 +0200 Subject: [PATCH 15/20] Bump contracts to 3.4-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 79a1d2d..f80d0b5 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", From 1d74b127da04ffa87aa940abe15446fa89653778 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 25 Sep 2023 14:52:38 +0200 Subject: [PATCH 16/20] Minor CS fixes --- CacheTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CacheTrait.php b/CacheTrait.php index b4fddfa..8a4b0bd 100644 --- a/CacheTrait.php +++ b/CacheTrait.php @@ -38,7 +38,7 @@ public function delete(string $key): bool private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null): mixed { if (0 > $beta ??= 1.0) { - throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { }; + throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; } $item = $pool->getItem($key); From b0393e376d6137fe2abf9e0e89cf74f4e91b5790 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Wed, 20 Dec 2023 13:09:40 -0500 Subject: [PATCH 17/20] [DependencyInjection] Add `ServiceCollectionInterface` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f80d0b5..fe261d1 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", From b26d00fe210cf412459379658228c70cfbf6b469 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 20 Jun 2024 17:52:34 +0200 Subject: [PATCH 18/20] Prefix all sprintf() calls --- CacheTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CacheTrait.php b/CacheTrait.php index c2f6580..4c5449b 100644 --- a/CacheTrait.php +++ b/CacheTrait.php @@ -38,7 +38,7 @@ public function delete(string $key): bool private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null, ?LoggerInterface $logger = null): mixed { if (0 > $beta ??= 1.0) { - throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; + throw new class(\sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; } $item = $pool->getItem($key); @@ -54,7 +54,7 @@ private function doGet(CacheItemPoolInterface $pool, string $key, callable $call $item->expiresAt(null); $logger?->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ 'key' => $key, - 'delta' => sprintf('%.1f', $expiry - $now), + 'delta' => \sprintf('%.1f', $expiry - $now), ]); } } From bed7d6f5ff06465e7c9b27b5f3e008e5560d5f13 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 5 Sep 2024 11:40:18 +0200 Subject: [PATCH 19/20] make test case classes compatible with PHPUnit 10+ --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fe261d1..b713c29 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" }, "thanks": { "name": "symfony/contracts", From 5d68a57d66910405e5c0b63d6f0af941e66fc868 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 19 Feb 2025 15:04:36 +0100 Subject: [PATCH 20/20] [Cache] Enable namespace-based invalidation by prefixing keys with backend-native namespace separators --- NamespacedPoolInterface.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 NamespacedPoolInterface.php diff --git a/NamespacedPoolInterface.php b/NamespacedPoolInterface.php new file mode 100644 index 0000000..cd67bc0 --- /dev/null +++ b/NamespacedPoolInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\InvalidArgumentException; + +/** + * Enables namespace-based invalidation by prefixing keys with backend-native namespace separators. + * + * Note that calling `withSubNamespace()` MUST NOT mutate the pool, but return a new instance instead. + * + * When tags are used, they MUST ignore sub-namespaces. + * + * @author Nicolas Grekas + */ +interface NamespacedPoolInterface +{ + /** + * @throws InvalidArgumentException If the namespace contains characters found in ItemInterface's RESERVED_CHARACTERS + */ + public function withSubNamespace(string $namespace): static; +}