diff --git a/.gitattributes b/.gitattributes index fe524d08..568685da 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ /.gitignore export-ignore /.travis.yml export-ignore /benchmark/ export-ignore +/dev-implementation/ export-ignore /docs/ export-ignore /mkdocs.yml export-ignore /phpbench.json export-ignore diff --git a/.laminas-ci.json b/.laminas-ci.json index 38b147d9..18707e20 100644 --- a/.laminas-ci.json +++ b/.laminas-ci.json @@ -1,10 +1,3 @@ { - "extensions": [ - "apcu" - ], - "ini": [ - "apc.enabled=1", - "apc.enable_cli=1" - ], "backwardCompatibilityCheck": true } diff --git a/.laminas-ci/install-apcu-extension-via-pecl.sh b/.laminas-ci/install-apcu-extension-via-pecl.sh deleted file mode 100755 index 0f2e221f..00000000 --- a/.laminas-ci/install-apcu-extension-via-pecl.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -PHP_VERSION="$1" - -if ! [[ "${PHP_VERSION}" =~ 8\.2 ]]; then - echo "APCu is only installed from pecl for PHP 8.2, ${PHP_VERSION} detected." - exit 0; -fi - -set +e - -pecl install --configureoptions 'enable-apcu-debug="no"' apcu -echo "extension=apcu.so" > /etc/php/${PHP_VERSION}/mods-available/apcu.ini -phpenmod -v ${PHP} -s cli apcu diff --git a/.laminas-ci/pre-install.sh b/.laminas-ci/pre-install.sh index 73c63187..25ed8129 100755 --- a/.laminas-ci/pre-install.sh +++ b/.laminas-ci/pre-install.sh @@ -14,5 +14,3 @@ if [ ! -z "$GITHUB_BASE_REF" ] && [[ "$GITHUB_BASE_REF" =~ ^[0-9]+\.[0-9] ]]; th export COMPOSER_ROOT_VERISON="${MAJOR_OF_TARGET_BRANCH}.${MINOR_OF_TARGET_BRANCH}.99" echo "Exported COMPOSER_ROOT_VERISON as ${COMPOSER_ROOT_VERISON}" fi - -${WORKING_DIRECTORY}/.laminas-ci/install-apcu-extension-via-pecl.sh "${PHP_VERSION}" || exit 1 diff --git a/benchmark/AbstractCommonStorageAdapterBench.php b/benchmark/AbstractCommonStorageAdapterBench.php deleted file mode 100644 index 27f70dc1..00000000 --- a/benchmark/AbstractCommonStorageAdapterBench.php +++ /dev/null @@ -1,353 +0,0 @@ - - */ - protected $warmItems = []; - - /** - * Key-Value-Pairs of missing items - * - * @var array - */ - protected $coldItems = []; - - public function __construct() - { - // generate warm items - for ($i = 0; $i < 10; $i++) { - $this->warmItems['warm' . $i] = $i; - } - - // generate cold items - for ($i = 0; $i < 10; $i++) { - $this->coldItems['cold' . $i] = $i; - } - } - - public function setUp() - { - $this->storage->setItems($this->warmItems); - } - - public function tearDown() - { - $this->storage->removeItems(array_keys($this->coldItems)); - } - - /** - * Has missing items with single operations - */ - public function benchHasMissingItemsSingle() - { - foreach ($this->coldItems as $k => $_) { - $this->storage->hasItem($k); - } - } - - /** - * Has missing items at once - */ - public function benchHasMissingItemsBulk() - { - $this->storage->hasItems(array_keys($this->coldItems)); - } - - /** - * Has existing items with single operations - */ - public function benchHasExistingItemsSingle() - { - foreach ($this->warmItems as $k => $_) { - $this->storage->hasItem($k); - } - } - - /** - * Has existing items at once - */ - public function benchHasExistingItemsBulk() - { - $this->storage->hasItems(array_keys($this->warmItems)); - } - - /** - * Set existing items with single operations - */ - public function benchSetExistingItemsSingle() - { - foreach ($this->warmItems as $k => $v) { - $this->storage->setItem($k, $v); - } - } - - /** - * Set existingn items at once - */ - public function benchSetExistingItemsBulk() - { - $this->storage->setItems($this->warmItems); - } - - /** - * Set missing items with single operations - */ - public function benchSetMissingItemsSingle() - { - foreach ($this->coldItems as $k => $v) { - $this->storage->setItem($k, $k . $v); - } - } - - /** - * Set missing items at once - */ - public function benchSetMissingItemsBulk() - { - $this->storage->setItems($this->coldItems); - } - - /** - * Add items with single operations - */ - public function benchAddItemsSingle() - { - foreach ($this->coldItems as $k => $v) { - $this->storage->addItem($k, $k . $v); - } - } - - /** - * Add items at once - */ - public function benchAddItemsBulk() - { - $this->storage->addItems($this->coldItems); - } - - /** - * Replace items with single operations - */ - public function benchReplaceItemsSingle() - { - foreach ($this->warmItems as $k => $v) { - $this->storage->replaceItem($k, $k . $v); - } - } - - /** - * Replace items at once - */ - public function benchReplaceItemsBulk() - { - $this->storage->replaceItems($this->coldItems); - } - - /** - * Get, check and set items with single operations - */ - public function benchGetCheckAndSetItemsSingle() - { - foreach ($this->warmItems as $k => $v) { - $this->storage->getItem($k, $success, $token); - $this->storage->checkAndSetItem($token, $k, $k . $v); - } - } - - /** - * Touch missing items with single operations - */ - public function benchTouchMissingItemsSingle() - { - foreach ($this->coldItems as $k => $_) { - $this->storage->touchItem($k); - } - } - - /** - * Touch missing items at once - */ - public function benchTouchMissingItemsBulk() - { - $this->storage->touchItems(array_keys($this->coldItems)); - } - - /** - * Touch existing items with single operations - */ - public function benchTouchExistingItemsSingle() - { - foreach ($this->warmItems as $k => $_) { - $this->storage->touchItem($k); - } - } - - /** - * Touch existing items at once - */ - public function benchTouchExistingItemsBulk() - { - $this->storage->touchItems(array_keys($this->warmItems)); - } - - /** - * Get missing items with single operations - */ - public function benchGetMissingItemsSingle() - { - foreach ($this->coldItems as $k => $_) { - $this->storage->getItem($k); - } - } - - /** - * Get missing items at once - */ - public function benchGetMissingItemsBulk() - { - $this->storage->getItems(array_keys($this->coldItems)); - } - - /** - * Get existing items with single operations - */ - public function benchGetExistingItemsSingle() - { - foreach ($this->warmItems as $k => $_) { - $this->storage->getItem($k); - } - } - - /** - * Get existing items at once - */ - public function benchGetExistingItemsBulk() - { - $this->storage->getItems(array_keys($this->warmItems)); - } - - /** - * Remove missing items with single operations - */ - public function benchRemoveMissingItemsSingle() - { - foreach ($this->coldItems as $k => $_) { - $this->storage->removeItem($k); - } - } - - /** - * Remove missing items at once - */ - public function benchRemoveMissingItemsBulk() - { - $this->storage->removeItems(array_keys($this->coldItems)); - } - - /** - * Remove exisint items with single operations - */ - public function benchRemoveExistingItemsSingle() - { - foreach ($this->warmItems as $k => $_) { - $this->storage->removeItem($k); - } - } - - /** - * Remove existing items at once - */ - public function benchRemoveExistingItemsBulk() - { - $this->storage->removeItems(array_keys($this->warmItems)); - } - - /** - * Increment missing items with single operations - */ - public function benchIncrementMissingItemsSingle() - { - foreach ($this->coldItems as $k => $v) { - $this->storage->incrementItem($k, $v); - } - } - - /** - * Increment missing items at once - */ - public function benchIncrementMissingItemsBulk() - { - $this->storage->incrementItems($this->coldItems); - } - - /** - * Increment exisint items with single operations - */ - public function benchIncrementExistingItemsSingle() - { - foreach ($this->warmItems as $k => $v) { - $this->storage->incrementItem($k, $v); - } - } - - /** - * Increment existing items at once - */ - public function benchIncrementExistingItemsBulk() - { - $this->storage->incrementItems($this->warmItems); - } - - /** - * Decrement missing items with single operations - */ - public function benchDecrementMissingItemsSingle() - { - foreach ($this->coldItems as $k => $v) { - $this->storage->decrementItem($k, $v); - } - } - - /** - * Decrement missing items at once - */ - public function benchDecrementMissingItemsBulk() - { - $this->storage->decrementItems($this->coldItems); - } - - /** - * Decrement exisint items with single operations - */ - public function benchDecrementExistingItemsSingle() - { - foreach ($this->warmItems as $k => $v) { - $this->storage->decrementItem($k, $v); - } - } - - /** - * Decrement existing items at once - */ - public function benchDecrementExistingItemsBulk() - { - $this->storage->decrementItems($this->warmItems); - } -} diff --git a/benchmark/FilesystemStorageAdapterBench.php b/benchmark/FilesystemStorageAdapterBench.php deleted file mode 100644 index 937b82dc..00000000 --- a/benchmark/FilesystemStorageAdapterBench.php +++ /dev/null @@ -1,74 +0,0 @@ -tmpCacheDir = (string) @tempnam(sys_get_temp_dir(), 'laminas_cache_test_'); - if (! $this->tmpCacheDir) { - $err = error_get_last(); - $this->fail("Can't create temporary cache directory-file: {$err['message']}"); - } elseif (! @unlink($this->tmpCacheDir)) { - $err = error_get_last(); - $this->fail("Can't remove temporary cache directory-file: {$err['message']}"); - } elseif (! @mkdir($this->tmpCacheDir, 0777)) { - $err = error_get_last(); - $this->fail("Can't create temporary cache directory: {$err['message']}"); - } - - $this->storage = new Filesystem([ - 'cache_dir' => $this->tmpCacheDir, - ]); - - parent::__construct(); - } - - public function __destruct() - { - $this->removeRecursive($this->tmpCacheDir); - } - - private function removeRecursive(string $dir): void - { - if (file_exists($dir)) { - $dirIt = new DirectoryIterator($dir); - foreach ($dirIt as $entry) { - $fname = $entry->getFilename(); - if ($fname === '.' || $fname === '..') { - continue; - } - - if ($entry->isFile()) { - unlink($entry->getPathname()); - } else { - $this->removeRecursive($entry->getPathname()); - } - } - - rmdir($dir); - } - } -} diff --git a/benchmark/MemoryStorageAdapterBench.php b/benchmark/MemoryStorageAdapterBench.php deleted file mode 100644 index 8ae937a7..00000000 --- a/benchmark/MemoryStorageAdapterBench.php +++ /dev/null @@ -1,23 +0,0 @@ -storage = new Memory(); - - parent::__construct(); - } -} diff --git a/composer.json b/composer.json index 5eb0e22d..a2a86ef0 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ }, "require": { "php": "~8.1.0 || ~8.2.0", - "laminas/laminas-cache-storage-implementation": "1.0", + "laminas/laminas-cache-storage-implementation": "2.0", "laminas/laminas-eventmanager": "^3.4", "laminas/laminas-servicemanager": "^3.21", "laminas/laminas-stdlib": "^3.6", @@ -45,17 +45,12 @@ "webmozart/assert": "^1.9" }, "require-dev": { - "laminas/laminas-cache-storage-adapter-apcu": "^2.4", - "laminas/laminas-cache-storage-adapter-blackhole": "^2.3", - "laminas/laminas-cache-storage-adapter-filesystem": "^2.3", - "laminas/laminas-cache-storage-adapter-memory": "^2.2", - "laminas/laminas-cache-storage-adapter-test": "^2.4", + "laminas/laminas-cache-storage-adapter-dev": "@dev", "laminas/laminas-cli": "^1.7", "laminas/laminas-coding-standard": "~2.5.0", "laminas/laminas-config-aggregator": "^1.13", "laminas/laminas-feed": "^2.20", "laminas/laminas-serializer": "^2.14", - "phpbench/phpbench": "^1.2.7", "phpunit/phpunit": "^9.5.27", "psalm/plugin-phpunit": "^0.18.4", "vimeo/psalm": "^5.4" @@ -87,12 +82,16 @@ }, "autoload-dev": { "psr-4": { - "LaminasTest\\Cache\\": "test/", - "LaminasBench\\Cache\\": "benchmark/" + "LaminasTest\\Cache\\": "test/" } }, + "repositories": [ + { + "type": "path", + "url": "./dev-implementation" + } + ], "scripts": { - "benchmark": "phpbench run --revs=2 --iterations=2 --report=aggregate", "check": [ "@cs-check", "@static-analysis", diff --git a/composer.lock b/composer.lock index f33367e2..6fe387e2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,74 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "295bfbb0011bdabd9ee9e7ab205903e7", + "content-hash": "9d8cf830e8f7a3851a59b082359a99e0", "packages": [ { - "name": "laminas/laminas-cache-storage-adapter-memory", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-cache-storage-adapter-memory.git", - "reference": "e002c7d3fa0d4723589b550d7ab4586befa72366" - }, + "name": "laminas/laminas-cache-storage-adapter-dev", + "version": "4.0.x-dev", "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cache-storage-adapter-memory/zipball/e002c7d3fa0d4723589b550d7ab4586befa72366", - "reference": "e002c7d3fa0d4723589b550d7ab4586befa72366", - "shasum": "" - }, - "require": { - "laminas/laminas-cache": "^3.0", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0" - }, - "conflict": { - "laminas/laminas-servicemanager": "<3.11" + "type": "path", + "url": "./dev-implementation", + "reference": "8b617656868665bd6cb5e9a99918126bdb015a89" }, "provide": { - "laminas/laminas-cache-storage-implementation": "1.0" - }, - "require-dev": { - "laminas/laminas-cache-storage-adapter-benchmark": "^1.0", - "laminas/laminas-cache-storage-adapter-test": "^2.0", - "laminas/laminas-coding-standard": "~2.4.0", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.9" + "laminas/laminas-cache-storage-implementation": "2.0" }, "type": "library", - "extra": { - "laminas": { - "config-provider": "Laminas\\Cache\\Storage\\Adapter\\Memory\\ConfigProvider", - "module": "Laminas\\Cache\\Storage\\Adapter\\Memory" - } - }, "autoload": { "psr-4": { - "Laminas\\Cache\\Storage\\Adapter\\": "src/" + "Laminas\\Cache\\Storage\\Adapter\\Dev\\": "." } }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas cache adapter for memory", - "keywords": [ - "cache", - "laminas" - ], - "support": { - "docs": "https://docs.laminas.dev/laminas-cache-storage-adapter-memory/", - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-cache-storage-adapter-memory/issues", - "rss": "https://github.com/laminas/laminas-cache-storage-adapter-memory/releases.atom", - "source": "https://github.com/laminas/laminas-cache-storage-adapter-memory" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-10-22T14:38:52+00:00" + "transport-options": { + "relative": true + } }, { "name": "laminas/laminas-eventmanager", @@ -1165,82 +1119,6 @@ }, "time": "2019-12-04T15:06:13+00:00" }, - { - "name": "doctrine/annotations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "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" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" - }, - "time": "2023-02-02T22:02:53+00:00" - }, { "name": "doctrine/instantiator", "version": "2.0.0", @@ -1311,83 +1189,6 @@ ], "time": "2022-12-30T00:23:10+00:00" }, - { - "name": "doctrine/lexer", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "84a527db05647743d50373e0ec53a152f2cde568" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", - "reference": "84a527db05647743d50373e0ec53a152f2cde568", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-12-15T16:57:16+00:00" - }, { "name": "felixfbecker/advanced-json-rpc", "version": "v3.2.1", @@ -1550,263 +1351,6 @@ ], "time": "2022-12-24T12:35:10+00:00" }, - { - "name": "laminas/laminas-cache-storage-adapter-apcu", - "version": "2.4.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-cache-storage-adapter-apcu.git", - "reference": "89561dee942fbdb76647ec939f0dfa6a1db6f9f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cache-storage-adapter-apcu/zipball/89561dee942fbdb76647ec939f0dfa6a1db6f9f4", - "reference": "89561dee942fbdb76647ec939f0dfa6a1db6f9f4", - "shasum": "" - }, - "require": { - "ext-apcu": "^5.1.10", - "laminas/laminas-cache": "^3.0", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0" - }, - "provide": { - "laminas/laminas-cache-storage-implementation": "1.0" - }, - "require-dev": { - "laminas/laminas-cache-storage-adapter-test": "^2.0", - "laminas/laminas-coding-standard": "~2.4.0", - "psalm/plugin-phpunit": "^0.18.0", - "vimeo/psalm": "^5.0.0" - }, - "type": "library", - "extra": { - "laminas": { - "config-provider": "Laminas\\Cache\\Storage\\Adapter\\Apcu\\ConfigProvider", - "module": "Laminas\\Cache\\Storage\\Adapter\\Apcu" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Cache\\Storage\\Adapter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas cache adapter for apcu", - "keywords": [ - "cache", - "laminas" - ], - "support": { - "docs": "https://docs.laminas.dev/laminas-cache-storage-adapter-apcu/", - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-cache-storage-adapter-apcu/issues", - "rss": "https://github.com/laminas/laminas-cache-storage-adapter-apcu/releases.atom", - "source": "https://github.com/laminas/laminas-cache-storage-adapter-apcu" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-12-05T11:22:35+00:00" - }, - { - "name": "laminas/laminas-cache-storage-adapter-blackhole", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-cache-storage-adapter-blackhole.git", - "reference": "8730402201904784e6b28a1014908c6123c12d02" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cache-storage-adapter-blackhole/zipball/8730402201904784e6b28a1014908c6123c12d02", - "reference": "8730402201904784e6b28a1014908c6123c12d02", - "shasum": "" - }, - "require": { - "laminas/laminas-cache": "^3.0", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0" - }, - "conflict": { - "laminas/laminas-servicemanager": "<3.11" - }, - "provide": { - "laminas/laminas-cache-storage-implementation": "1.0" - }, - "require-dev": { - "laminas/laminas-cache-storage-adapter-test": "^2.4", - "laminas/laminas-coding-standard": "~2.4.0", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.2" - }, - "type": "library", - "extra": { - "laminas": { - "config-provider": "Laminas\\Cache\\Storage\\Adapter\\BlackHole\\ConfigProvider", - "module": "Laminas\\Cache\\Storage\\Adapter\\BlackHole" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Cache\\Storage\\Adapter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas cache adapter for blackhole", - "keywords": [ - "cache", - "laminas" - ], - "support": { - "docs": "https://docs.laminas.dev/laminas-cache-storage-adapter-blackhole/", - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-cache-storage-adapter-blackhole/issues", - "rss": "https://github.com/laminas/laminas-cache-storage-adapter-blackhole/releases.atom", - "source": "https://github.com/laminas/laminas-cache-storage-adapter-blackhole" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-12-31T16:03:12+00:00" - }, - { - "name": "laminas/laminas-cache-storage-adapter-filesystem", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-cache-storage-adapter-filesystem.git", - "reference": "9881529cacc26823dc1530e8b850fd9e467ccd05" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cache-storage-adapter-filesystem/zipball/9881529cacc26823dc1530e8b850fd9e467ccd05", - "reference": "9881529cacc26823dc1530e8b850fd9e467ccd05", - "shasum": "" - }, - "require": { - "laminas/laminas-cache": "^3.0", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0" - }, - "provide": { - "laminas/laminas-cache-storage-implementation": "1.0" - }, - "require-dev": { - "ext-pcntl": "*", - "ext-posix": "*", - "laminas/laminas-cache-storage-adapter-benchmark": "^1.0", - "laminas/laminas-cache-storage-adapter-test": "^2.0 || 2.0.x-dev", - "laminas/laminas-coding-standard": "~2.4", - "laminas/laminas-serializer": "^2.14.0", - "phpunit/phpunit": "^9.5.25", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.29.0" - }, - "type": "library", - "extra": { - "laminas": { - "config-provider": "Laminas\\Cache\\Storage\\Adapter\\Filesystem\\ConfigProvider", - "module": "Laminas\\Cache\\Storage\\Adapter\\Filesystem" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Cache\\Storage\\Adapter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas cache adapter for filesystem", - "keywords": [ - "cache", - "laminas" - ], - "support": { - "docs": "https://docs.laminas.dev/laminas-cache-storage-adapter-filesystem/", - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-cache-storage-adapter-filesystem/issues", - "rss": "https://github.com/laminas/laminas-cache-storage-adapter-filesystem/releases.atom", - "source": "https://github.com/laminas/laminas-cache-storage-adapter-filesystem" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-10-22T15:00:05+00:00" - }, - { - "name": "laminas/laminas-cache-storage-adapter-test", - "version": "2.4.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-cache-storage-adapter-test.git", - "reference": "cf8dbad341f93fa1bee326cdaca488182fc68e96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cache-storage-adapter-test/zipball/cf8dbad341f93fa1bee326cdaca488182fc68e96", - "reference": "cf8dbad341f93fa1bee326cdaca488182fc68e96", - "shasum": "" - }, - "require": { - "container-interop/container-interop": "^1.2", - "laminas/laminas-cache": "^3.1", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", - "phpunit/phpunit": "^9.5.20", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "laminas/laminas-cache-storage-adapter-apcu": "^2.0", - "laminas/laminas-cache-storage-adapter-memory": "^2.0", - "laminas/laminas-coding-standard": "~2.4.0", - "psalm/plugin-phpunit": "^0.18.0", - "vimeo/psalm": "^5.0.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "LaminasTest\\Cache\\Storage\\Adapter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas cache storage adapter shared test dependency", - "keywords": [ - "cache", - "laminas", - "test" - ], - "support": { - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-cache-storage-adapter-test/issues", - "rss": "https://github.com/laminas/laminas-cache-storage-adapter-test/releases.atom", - "source": "https://github.com/laminas/laminas-cache-storage-adapter-test" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-12-09T09:20:01+00:00" - }, { "name": "laminas/laminas-cli", "version": "1.8.0", @@ -2385,16 +1929,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.16.0", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -2435,9 +1979,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-06-25T14:52:30+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -2534,213 +2078,21 @@ }, { "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpbench/container", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "shasum": "" - }, - "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "Simple, configurable, service container.", - "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.1" - }, - "time": "2022-01-25T10:17:35+00:00" - }, - { - "name": "phpbench/dom", - "version": "0.3.3", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "786a96db538d0def931f5b19225233ec42ec7a72" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/786a96db538d0def931f5b19225233ec42ec7a72", - "reference": "786a96db538d0def931f5b19225233ec42ec7a72", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.3||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.14", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.3" - }, - "time": "2023-03-06T23:46:57+00:00" - }, - { - "name": "phpbench/phpbench", - "version": "1.2.14", - "source": { - "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e", - "reference": "edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.13 || ^2.0", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "phpbench/container": "^2.1", - "phpbench/dom": "~0.3.3", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0", - "webmozart/glob": "^4.6" - }, - "require-dev": { - "dantleech/invoke": "^2.0", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "^1.12", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.0", - "symfony/error-handler": "^5.2 || ^6.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], - "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "PHP Benchmarking Framework", + "description": "Library for handling version information and constraints", "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.14" + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "funding": [ - { - "url": "https://github.com/dantleech", - "type": "github" - } - ], - "time": "2023-07-09T09:16:08+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -3272,16 +2624,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.10", + "version": "9.6.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0", "shasum": "" }, "require": { @@ -3355,7 +2707,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" }, "funding": [ { @@ -3371,7 +2723,7 @@ "type": "tidelift" } ], - "time": "2023-07-10T04:04:23+00:00" + "time": "2023-08-19T07:10:56+00:00" }, { "name": "psalm/plugin-phpunit", @@ -4039,16 +3391,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -4091,7 +3443,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -4099,7 +3451,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -4497,70 +3849,6 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "seld/jsonlint", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/594fd6462aad8ecee0b45ca5045acea4776667f1", - "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.10.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2023-05-11T13:16:46+00:00" - }, { "name": "slevomat/coding-standard", "version": "7.2.1", @@ -4744,16 +4032,16 @@ }, { "name": "symfony/console", - "version": "v6.3.0", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", - "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { @@ -4814,7 +4102,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.0" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -4830,7 +4118,7 @@ "type": "tidelift" } ], - "time": "2023-05-29T12:49:39+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4901,16 +4189,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.3.0", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa" + "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", - "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", "shasum": "" }, "require": { @@ -4961,7 +4249,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" }, "funding": [ { @@ -4977,7 +4265,7 @@ "type": "tidelift" } ], - "time": "2023-04-21T14:41:17+00:00" + "time": "2023-07-06T06:56:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -5118,137 +4406,6 @@ ], "time": "2023-06-01T08:30:39+00:00" }, - { - "name": "symfony/finder", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2", - "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/filesystem": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-04-02T01:25:41+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-12T14:21:09+00:00" - }, { "name": "symfony/polyfill-ctype", "version": "v1.27.0", @@ -5662,67 +4819,6 @@ ], "time": "2022-11-03T14:55:06+00:00" }, - { - "name": "symfony/process", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628", - "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-19T08:06:44+00:00" - }, { "name": "symfony/service-contracts", "version": "v2.5.2", @@ -5808,16 +4904,16 @@ }, { "name": "symfony/string", - "version": "v6.3.0", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f" + "reference": "53d1a83225002635bca3482fcbf963001313fb68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f", - "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", + "reference": "53d1a83225002635bca3482fcbf963001313fb68", "shasum": "" }, "require": { @@ -5874,7 +4970,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.0" + "source": "https://github.com/symfony/string/tree/v6.3.2" }, "funding": [ { @@ -5890,7 +4986,7 @@ "type": "tidelift" } ], - "time": "2023-03-21T21:06:29+00:00" + "time": "2023-07-05T08:41:27+00:00" }, { "name": "theseer/tokenizer", @@ -5944,16 +5040,16 @@ }, { "name": "vimeo/psalm", - "version": "5.13.1", + "version": "5.15.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "086b94371304750d1c673315321a55d15fc59015" + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/086b94371304750d1c673315321a55d15fc59015", - "reference": "086b94371304750d1c673315321a55d15fc59015", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", "shasum": "" }, "require": { @@ -5974,13 +5070,16 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", "symfony/filesystem": "^5.4 || ^6.0" }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, "provide": { "psalm/psalm": "self.version" }, @@ -6044,9 +5143,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.13.1" + "source": "https://github.com/vimeo/psalm/tree/5.15.0" }, - "time": "2023-06-27T16:39:49+00:00" + "time": "2023-08-20T23:07:30+00:00" }, { "name": "webimpress/coding-standard", @@ -6161,60 +5260,13 @@ } ], "time": "2021-04-19T16:34:45+00:00" - }, - { - "name": "webmozart/glob", - "version": "4.6.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/glob.git", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.5", - "symfony/filesystem": "^5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Glob\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A PHP implementation of Ant's glob.", - "support": { - "issues": "https://github.com/webmozarts/glob/issues", - "source": "https://github.com/webmozarts/glob/tree/4.6.0" - }, - "time": "2022-05-24T19:45:58+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "laminas/laminas-cache-storage-adapter-dev": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/dev-implementation/README.md b/dev-implementation/README.md new file mode 100644 index 00000000..9a3a596e --- /dev/null +++ b/dev-implementation/README.md @@ -0,0 +1,4 @@ +# README + +This package is meant to provide a cache implementation for development. +By adding this as a dev-dependency, we get rid of the circular dependencies. diff --git a/dev-implementation/VoidAdapter.php b/dev-implementation/VoidAdapter.php new file mode 100644 index 00000000..4a907c9f --- /dev/null +++ b/dev-implementation/VoidAdapter.php @@ -0,0 +1,36 @@ + src test - benchmark + dev-implementation diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 0ee001c6..81a453f2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,17 +1,10 @@ - + $cacheConfiguration $configuration - - $cache - $cacheConfiguration - $caches - $caches - $configuration - $projectConfiguration @@ -66,11 +59,6 @@ $result[0] $result[1] - - $object - $result - $ret - __call @@ -126,13 +114,6 @@ $property $property - - $property - $property - $property - $property - $value - bool void @@ -158,24 +139,12 @@ $object $object - - __get - __set - $data $key - - $data - $key - - - end - start - (string) $key @@ -220,12 +189,6 @@ validateKeys validateStorage - - $cleared - $key - $value - $value - flush @@ -238,14 +201,6 @@ $key $key - - $key - $key - $result - $result - $results[$key] - $value - $ttl $ttl @@ -319,7 +274,6 @@ $normalizedKey $normalizedKey $normalizedKey - $normalizedKey $value $value @@ -331,50 +285,6 @@ $normalizedKey $normalizedKey - - $handle - $normalizedKey - $normalizedKey - $normalizedKey - $normalizedKey - $normalizedKey - $normalizedKeyValuePairs[$key] - $oldValue - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result - $result[$normalizedKey] - $value - $value - $value - $value - $value - $value - $value - $value - AdapterOptions Capabilities @@ -387,8 +297,6 @@ array array array - array - array|bool bool bool bool @@ -427,10 +335,6 @@ triggerException(__FUNCTION__, $args, $result, $e)]]> triggerException(__FUNCTION__, $args, $result, $e)]]> triggerException(__FUNCTION__, $args, $result, $e)]]> - triggerException(__FUNCTION__, $args, $result, $e)]]> - triggerException(__FUNCTION__, $args, $result, $e)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> triggerPost(__FUNCTION__, $args, $result)]]> triggerPost(__FUNCTION__, $args, $result)]]> triggerPost(__FUNCTION__, $args, $result)]]> @@ -464,9 +368,6 @@ getCaching setCaching - - $pluginRegistry - (bool) $flag (int) $value @@ -478,6 +379,12 @@ is_array($options) + + $array + + + array + $letters @@ -486,12 +393,6 @@ $letter $letters - - $array[$normalizedKey] - $key - $letter - $value - $this @@ -518,18 +419,10 @@ - - is_string($name) - $name - - $toType - $value - - array array bool bool @@ -559,14 +452,12 @@ 'object' => false, 'resource' => false, ])]]> - getCapability('supportedMetadata', [])]]> getCapability('ttlPrecision', 1)]]> getCapability('useRequestTime', false)]]> getNamespaceIsPrefix getNamespaceSeparator - getSupportedMetadata getTtlPrecision setLockOnExpire setMaxKeyLength @@ -575,7 +466,6 @@ setNamespaceSeparator setStaticTtl setSupportedDatatypes - setSupportedMetadata setTtlPrecision setUseRequestTime @@ -588,7 +478,6 @@ $namespaceSeparator $staticTtl $supportedDatatypes - $supportedMetadata $ttlPrecision $useRequestTime @@ -675,9 +564,6 @@ SerializerAdapter - - serializerOptions]]> - setExitOnAbort setOptimizingFactor @@ -716,29 +602,6 @@ $keyValuePairs[$key] $keyValuePairs[$key] - - $baseCapabilities - $failedKey - $failedKey - $key - $key - $keyValuePairs[$key] - $keyValuePairs[$key] - $keyValuePairs[$key] - $keyValuePairs[$key] - $newValue - $newValue - $oldValue - $oldValue - $result - $result - $result - $value - $value - $value - $value - $value - getAdapter @@ -814,41 +677,9 @@ - - $event - - - $key - - - - - - $generatedKey - $key - $params - $return - $return - $usedKey - - - attach - getParams - getCommonPatternNamesProvider - - call - call - call - call - call - call - generateKey - generateKey - getEventManager - @@ -874,31 +705,6 @@ - - $event - - - - - - $generatedKey - $params - $return - $return - $usedKey - - - attach - getParams - - - pattern->property]]> - pattern->property]]> - pattern->property]]> - pattern->property]]> - pattern->property]]> - pattern->unknownProperty]]> - options->getObject()->property]]> options->getObject()->property]]> @@ -906,40 +712,17 @@ getCommonPatternNamesProvider - - call - generateKey - getEventManager - - - getItem - setItem - getCommonPatternNamesProvider - - end - start - start - start - TestCachePattern - - - emptyMethod - - - emptyMethod - - emptyMethod @@ -968,11 +751,6 @@ $key $key - - $item - $item - $item - get get @@ -1030,9 +808,6 @@ setCapabilities - - TtlStorage - @@ -1068,32 +843,11 @@ - - $event - - - static function ($event) use ($retVal) { - $success - - $eventList[] - $eventList[] - $eventList[] - - - $result - $result - $rs - $v - - - array - getResult - stopPropagation null @@ -1113,6 +867,9 @@ $success + + simpleEventHandlingMethodDefinitions + @@ -1159,10 +916,6 @@ $eventArg - - $em - $event - attach @@ -1282,9 +1035,6 @@ - - $values - onDecrementItemPre onReadItemPost @@ -1301,9 +1051,6 @@ clearExpired - - ClearExpiredMockAdapter - @@ -1311,9 +1058,6 @@ internalRemoveItem internalSetItem - - MockAdapter - @@ -1335,8 +1079,5 @@ optimize - - OptimizableMockAdapter - diff --git a/psalm.xml b/psalm.xml index f3f9362e..3b13db86 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,11 +13,13 @@ + + diff --git a/src/Psr/CacheItemPool/CacheItemPoolDecorator.php b/src/Psr/CacheItemPool/CacheItemPoolDecorator.php index 12cdddaf..e3b32f31 100644 --- a/src/Psr/CacheItemPool/CacheItemPoolDecorator.php +++ b/src/Psr/CacheItemPool/CacheItemPoolDecorator.php @@ -417,8 +417,7 @@ private function saveMultipleItems(array $items, ?int $itemTtl): array $keyValuePair = []; foreach ($items as $item) { - $key = $item->getKey(); - /** @psalm-suppress MixedAssignment */ + $key = $item->getKey(); $keyValuePair[$key] = $item->get(); } diff --git a/src/Psr/SimpleCache/SimpleCacheDecorator.php b/src/Psr/SimpleCache/SimpleCacheDecorator.php index 20d0eb48..7d945363 100644 --- a/src/Psr/SimpleCache/SimpleCacheDecorator.php +++ b/src/Psr/SimpleCache/SimpleCacheDecorator.php @@ -442,7 +442,6 @@ private function convertIterableToKeyValueMap(iterable $values): array $this->validateKey($key); - /** @psalm-suppress MixedAssignment */ $keyValueMap[$key] = $value; } diff --git a/src/Storage/AbstractMetadataCapableAdapter.php b/src/Storage/AbstractMetadataCapableAdapter.php new file mode 100644 index 00000000..3e68ccca --- /dev/null +++ b/src/Storage/AbstractMetadataCapableAdapter.php @@ -0,0 +1,151 @@ + + */ +abstract class AbstractMetadataCapableAdapter extends AbstractAdapter implements MetadataCapableInterface +{ + public function getMetadata(string $key): ?object + { + if (! $this->getOptions()->getReadable()) { + return null; + } + + $this->normalizeKey($key); + $args = new ArrayObject([ + 'key' => &$key, + ]); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + Assert::string($args['key']); + + $result = $eventRs->stopped() + ? $eventRs->last() + : $this->internalGetMetadata($args['key']); + + $result = $this->triggerPost(__FUNCTION__, $args, $result); + if ($result !== null && ! is_object($result)) { + return null; + } + + /** + * NOTE: We do trust the event handling here and assume that it will return an instance of Metadata + * and thus does not modify the type. + * + * @var TMetadata|null $result + */ + return $result; + } catch (Exception $exception) { + $result = null; + $result = $this->triggerException(__FUNCTION__, $args, $result, $exception); + Assert::nullOrObject($result); + + /** + * NOTE: We do trust the event handling here and assume that it will return an instance of Metadata + * and thus does not modify the type. + * + * @var TMetadata|null $result + */ + return $result; + } + } + + /** + * Internal method to get metadata of an item. + * + * @return TMetadata|null Metadata on success, null on failure or in case metadata is not accessible. + * @throws ExceptionInterface + */ + abstract protected function internalGetMetadata(string $normalizedKey): ?object; + + public function getMetadatas(array $keys): array + { + if (! $this->getOptions()->getReadable()) { + return []; + } + + $this->normalizeKeys($keys); + $args = new ArrayObject([ + 'keys' => &$keys, + ]); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + Assert::isArray($args['keys']); + Assert::allString($args['keys']); + + $result = $eventRs->stopped() + ? $eventRs->last() + : $this->internalGetMetadatas($args['keys']); + + if (! is_array($result)) { + return []; + } + + $result = $this->triggerPost(__FUNCTION__, $args, $result); + Assert::isMap($result); + Assert::allObject($result); + + /** + * NOTE: We do trust the event handling here and assume that it will return a map of instances of Metadata + * and thus does not modify the type. + * + * @var array $result + */ + return $result; + } catch (Exception $exception) { + $result = []; + $result = $this->triggerException(__FUNCTION__, $args, $result, $exception); + Assert::isArray($result); + Assert::allObject($result); + + /** + * NOTE: We do trust the event handling here and assume that it will return a map of instances of Metadata + * and thus does not modify the type. + * + * @var array $result + */ + return $result; + } + } + + /** + * Internal method to get multiple metadata + * + * @param array $normalizedKeys + * @return array Associative array of keys and metadata + * @throws ExceptionInterface + */ + protected function internalGetMetadatas(array $normalizedKeys): array + { + $result = []; + foreach ($normalizedKeys as $normalizedKey) { + $metadata = $this->internalGetMetadata($normalizedKey); + if ($metadata === null) { + continue; + } + + $result[$normalizedKey] = $metadata; + } + + return $result; + } +} diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 951feb17..1c632a33 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -45,7 +45,7 @@ abstract class AbstractAdapter implements StorageInterface, PluginAwareInterface /** * The plugin registry * - * @var SplObjectStorage Registered plugins + * @var SplObjectStorage|null Registered plugins */ protected $pluginRegistry; @@ -527,110 +527,6 @@ protected function internalHasItems(array &$normalizedKeys) return $result; } - /** - * Get metadata of an item. - * - * @param string $key - * @return array|bool Metadata on success, false on failure - * @throws Exception\ExceptionInterface - * @triggers getMetadata.pre(PreEvent) - * @triggers getMetadata.post(PostEvent) - * @triggers getMetadata.exception(ExceptionEvent) - */ - public function getMetadata($key) - { - if (! $this->getOptions()->getReadable()) { - return false; - } - - $this->normalizeKey($key); - $args = new ArrayObject([ - 'key' => &$key, - ]); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - - $result = $eventRs->stopped() - ? $eventRs->last() - : $this->internalGetMetadata($args['key']); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to get metadata of an item. - * - * @param string $normalizedKey - * @return array|bool Metadata on success, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetMetadata(&$normalizedKey) - { - if (! $this->internalHasItem($normalizedKey)) { - return false; - } - - return []; - } - - /** - * Get multiple metadata - * - * @param array $keys - * @return array Associative array of keys and metadata - * @throws Exception\ExceptionInterface - * @triggers getMetadatas.pre(PreEvent) - * @triggers getMetadatas.post(PostEvent) - * @triggers getMetadatas.exception(ExceptionEvent) - */ - public function getMetadatas(array $keys) - { - if (! $this->getOptions()->getReadable()) { - return []; - } - - $this->normalizeKeys($keys); - $args = new ArrayObject([ - 'keys' => &$keys, - ]); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - - $result = $eventRs->stopped() - ? $eventRs->last() - : $this->internalGetMetadatas($args['keys']); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = []; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to get multiple metadata - * - * @return array Associative array of keys and metadata - * @throws Exception\ExceptionInterface - */ - protected function internalGetMetadatas(array &$normalizedKeys) - { - $result = []; - foreach ($normalizedKeys as $normalizedKey) { - $metadata = $this->internalGetMetadata($normalizedKey); - if ($metadata !== false) { - $result[$normalizedKey] = $metadata; - } - } - return $result; - } - /* writing */ /** diff --git a/src/Storage/Adapter/KeyListIterator.php b/src/Storage/Adapter/KeyListIterator.php index c62cf1df..41b35774 100644 --- a/src/Storage/Adapter/KeyListIterator.php +++ b/src/Storage/Adapter/KeyListIterator.php @@ -96,10 +96,6 @@ public function current() $key = $this->key(); - if ($this->mode === IteratorInterface::CURRENT_AS_METADATA) { - return $this->storage->getMetadata($key); - } - if ($this->mode === IteratorInterface::CURRENT_AS_VALUE) { return $this->storage->getItem($key); } diff --git a/src/Storage/Capabilities.php b/src/Storage/Capabilities.php index 5682062b..82844dd6 100644 --- a/src/Storage/Capabilities.php +++ b/src/Storage/Capabilities.php @@ -102,16 +102,6 @@ class Capabilities */ protected $supportedDatatypes; - /** - * Supported metadata - * - * If it's NULL the capability isn't set and the getter - * returns the base capability or the default value. - * - * @var null|array - */ - protected $supportedMetadata; - /** * TTL precision * @@ -222,33 +212,6 @@ public function setSupportedDatatypes(stdClass $marker, array $datatypes) return $this->setCapability($marker, 'supportedDatatypes', $datatypes); } - /** - * Get supported metadata - * - * @return array - */ - public function getSupportedMetadata() - { - return $this->getCapability('supportedMetadata', []); - } - - /** - * Set supported metadata - * - * @param string[] $metadata - * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface - */ - public function setSupportedMetadata(stdClass $marker, array $metadata) - { - foreach ($metadata as $name) { - if (! is_string($name)) { - throw new Exception\InvalidArgumentException('$metadata must be an array of strings'); - } - } - return $this->setCapability($marker, 'supportedMetadata', $metadata); - } - /** * Get minimum supported time-to-live * diff --git a/src/Storage/IteratorInterface.php b/src/Storage/IteratorInterface.php index 386e865e..69d11796 100644 --- a/src/Storage/IteratorInterface.php +++ b/src/Storage/IteratorInterface.php @@ -11,10 +11,9 @@ */ interface IteratorInterface extends Iterator { - public const CURRENT_AS_SELF = 0; - public const CURRENT_AS_KEY = 1; - public const CURRENT_AS_VALUE = 2; - public const CURRENT_AS_METADATA = 3; + public const CURRENT_AS_SELF = 0; + public const CURRENT_AS_KEY = 1; + public const CURRENT_AS_VALUE = 2; /** * Get storage instance diff --git a/src/Storage/MetadataCapableInterface.php b/src/Storage/MetadataCapableInterface.php new file mode 100644 index 00000000..664e1590 --- /dev/null +++ b/src/Storage/MetadataCapableInterface.php @@ -0,0 +1,30 @@ + $keys + * @return array Associative array of keys and metadata + * @throws ExceptionInterface + */ + public function getMetadatas(array $keys): array; +} diff --git a/src/Storage/PluginManager.php b/src/Storage/PluginManager.php index 4cb033e9..916773e8 100644 --- a/src/Storage/PluginManager.php +++ b/src/Storage/PluginManager.php @@ -15,7 +15,6 @@ * plugins available. * * @extends AbstractPluginManager - * @final */ final class PluginManager extends AbstractPluginManager { @@ -64,8 +63,7 @@ final class PluginManager extends AbstractPluginManager public function build($name, ?array $options = null) { $options ??= []; - /** @psalm-suppress MixedAssignment */ - $plugin = parent::build($name); + $plugin = parent::build($name); if ($options !== [] && $plugin instanceof PluginInterface) { $plugin->setOptions(new PluginOptions($options)); } diff --git a/src/Storage/StorageInterface.php b/src/Storage/StorageInterface.php index a22a8bfa..518ed855 100644 --- a/src/Storage/StorageInterface.php +++ b/src/Storage/StorageInterface.php @@ -58,23 +58,6 @@ public function hasItem($key); */ public function hasItems(array $keys); - /** - * Get metadata of an item. - * - * @param string $key - * @return array|bool Metadata on success, false on failure - * @throws ExceptionInterface - */ - public function getMetadata($key); - - /** - * Get multiple metadata - * - * @return array Associative array of keys and metadata - * @throws ExceptionInterface - */ - public function getMetadatas(array $keys); - /* writing */ /** * Store an item. diff --git a/test/Pattern/AbstractCommonStoragePatternTest.php b/test/Pattern/AbstractCommonStoragePatternTest.php index 7c55455b..586330b0 100644 --- a/test/Pattern/AbstractCommonStoragePatternTest.php +++ b/test/Pattern/AbstractCommonStoragePatternTest.php @@ -7,18 +7,20 @@ use Laminas\Cache\Pattern\PatternInterface; use Laminas\Cache\Pattern\StorageCapableInterface; use Laminas\Cache\Storage\StorageInterface; +use PHPUnit\Framework\MockObject\MockObject; use function sprintf; /** * @psalm-suppress MissingConstructor + * @template TPattern of PatternInterface&StorageCapableInterface */ abstract class AbstractCommonStoragePatternTest extends AbstractCommonPatternTest { - /** @var StorageInterface */ + /** @var StorageInterface&MockObject */ protected $storage; - /** @var PatternInterface&StorageCapableInterface */ + /** @var TPattern */ protected $pattern; protected function setUp(): void diff --git a/test/Pattern/CallbackCacheTest.php b/test/Pattern/CallbackCacheTest.php index 95e53f90..a6c8fd93 100644 --- a/test/Pattern/CallbackCacheTest.php +++ b/test/Pattern/CallbackCacheTest.php @@ -4,8 +4,8 @@ namespace LaminasTest\Cache\Pattern; -use Laminas\Cache; -use Laminas\Cache\Exception\InvalidArgumentException; +use Laminas\Cache\Pattern\CallbackCache; +use Laminas\Cache\Storage\StorageInterface; use LaminasTest\Cache\Pattern\TestAsset\FailableCallback; use LaminasTest\Cache\Pattern\TestAsset\TestCallbackCache; @@ -26,16 +26,15 @@ function bar(): string /** * @group Laminas_Cache + * @template-extends AbstractCommonStoragePatternTest */ class CallbackCacheTest extends AbstractCommonStoragePatternTest { protected function setUp(): void { - $this->storage = new Cache\Storage\Adapter\Memory([ - 'memory_limit' => 0, - ]); + $this->storage = $this->createMock(StorageInterface::class); - $this->pattern = new Cache\Pattern\CallbackCache($this->storage); + $this->pattern = new CallbackCache($this->storage); parent::setUp(); } @@ -80,40 +79,36 @@ public function testGenerateKey(): void $args = ['arg1', 2, 3.33, null]; $generatedKey = $this->pattern->generateKey($callback, $args); - $usedKey = null; - $this->storage->getEventManager()->attach('setItem.pre', static function ($event) use (&$usedKey): void { - $params = $event->getParams(); - $usedKey = $params['key']; - }); - $this->pattern->call($callback, $args); - self::assertEquals($generatedKey, $usedKey); - } + $this->storage + ->expects(self::once()) + ->method('getItem') + ->with($generatedKey, null) + ->willReturn(null); - public function testCallInvalidCallbackException(): void - { - $this->expectException(InvalidArgumentException::class); - $this->pattern->call(1); - } + $this->storage + ->expects(self::once()) + ->method('setItem') + ->with($generatedKey, self::anything()) + ->willReturn(true); - public function testCallUnknownCallbackException(): void - { - $this->expectException(InvalidArgumentException::class); - $this->pattern->call('notExiststingFunction'); + $this->pattern->call($callback, $args); } /** * Running tests calling {@see \LaminasTest\Cache\Pattern\TestCallbackCache::bar} * using different callbacks resulting in this method call * - * @param callable $callback + * @param callable():string $callback + * @param array $args */ - protected function executeCallbackAndMakeAssertions($callback, array $args): void + protected function executeCallbackAndMakeAssertions(callable $callback, array $args): void { - /** @psalm-suppress MixedArgumentTypeCoercion */ - $imploded = implode(', ', $args); - $returnSpec = 'foobar_return(' . $imploded . ') : '; - $outputSpec = 'foobar_output(' . $imploded . ') : '; + $options = $this->pattern->getOptions(); + $cacheOutput = $options->getCacheOutput(); + $imploded = implode(', ', $args); + $returnSpec = 'foobar_return(' . $imploded . ') : '; + $outputSpec = 'foobar_output(' . $imploded . ') : '; // first call - not cached $firstCounter = TestCallbackCache::$fooCounter + 1; @@ -121,13 +116,45 @@ protected function executeCallbackAndMakeAssertions($callback, array $args): voi ob_start(); ob_implicit_flush(false); + $expectedKey = $this->pattern->generateKey($callback, $args); + $this->storage + ->expects(self::exactly(2)) + ->method('getItem') + ->with($expectedKey, null) + ->willReturnCallback( + function ( + string $key, + bool|null &$success = null + ) use ( + $returnSpec, + $outputSpec, + $firstCounter, + $cacheOutput, + ): ?array { + static $called = false; + if ($called === true) { + $success = true; + + $cached = [$returnSpec . $firstCounter]; + if ($cacheOutput) { + $cached[] = $outputSpec . $firstCounter; + } + + return $cached; + } + + $called = true; + return null; + } + ); + $return = $this->pattern->call($callback, $args); $data = ob_get_clean(); self::assertEquals($returnSpec . $firstCounter, $return); self::assertEquals($outputSpec . $firstCounter, $data); - // second call - cached + // second call - "cached" ob_start(); ob_implicit_flush(false); @@ -135,8 +162,7 @@ protected function executeCallbackAndMakeAssertions($callback, array $args): voi $data = ob_get_clean(); self::assertEquals($returnSpec . $firstCounter, $return); - $options = $this->pattern->getOptions(); - if ($options->getCacheOutput()) { + if ($cacheOutput) { self::assertEquals($outputSpec . $firstCounter, $data); } else { self::assertEquals('', $data); @@ -150,7 +176,15 @@ public function testCallCanReturnCachedNullValues(): void { $callback = new FailableCallback(); $key = $this->pattern->generateKey($callback, []); - $this->storage->setItem($key, [null]); + $this->storage + ->expects(self::once()) + ->method('getItem') + ->with($key, null) + ->willReturnCallback(function (string $key, ?bool &$success = null): array { + $success = true; + return [null]; + }); + $value = $this->pattern->call($callback); self::assertNull($value); } diff --git a/test/Pattern/ObjectCacheTest.php b/test/Pattern/ObjectCacheTest.php index 809c5a41..c1e0772c 100644 --- a/test/Pattern/ObjectCacheTest.php +++ b/test/Pattern/ObjectCacheTest.php @@ -5,7 +5,9 @@ namespace LaminasTest\Cache\Pattern; use Laminas\Cache; +use Laminas\Cache\Pattern\ObjectCache; use Laminas\Cache\Pattern\PatternOptions; +use Laminas\Cache\Storage\StorageInterface; use LaminasTest\Cache\Pattern\TestAsset\TestObjectCache; use function implode; @@ -16,6 +18,7 @@ /** * @group Laminas_Cache + * @template-extends AbstractCommonStoragePatternTest */ class ObjectCacheTest extends AbstractCommonStoragePatternTest { @@ -24,13 +27,11 @@ class ObjectCacheTest extends AbstractCommonStoragePatternTest protected function setUp(): void { - $this->storage = new Cache\Storage\Adapter\Memory([ - 'memory_limit' => 0, - ]); + $this->storage = $this->createMock(StorageInterface::class); $this->options = new Cache\Pattern\PatternOptions([ 'object' => new TestObjectCache(), ]); - $this->pattern = new Cache\Pattern\ObjectCache($this->storage, $this->options); + $this->pattern = new ObjectCache($this->storage, $this->options); parent::setUp(); } @@ -71,14 +72,20 @@ public function testGenerateKey(): void $args = ['arg1', 2, 3.33, null]; $generatedKey = $this->pattern->generateKey('emptyMethod', $args); - $usedKey = null; - $this->storage->getEventManager()->attach('setItem.pre', static function ($event) use (&$usedKey): void { - $params = $event->getParams(); - $usedKey = $params['key']; - }); + + $this->storage + ->expects(self::once()) + ->method('getItem') + ->with($generatedKey, null) + ->willReturn(null); + + $this->storage + ->expects(self::once()) + ->method('setItem') + ->with($generatedKey, self::anything()) + ->willReturn(true); $this->pattern->call('emptyMethod', $args); - self::assertEquals($generatedKey, $usedKey); } public function testSetProperty(): void @@ -119,17 +126,53 @@ public function testEmptyObjectKeys(): void self::assertSame($this->options->getObject()::class, $this->options->getObjectKey()); } + /** + * @param array $args + */ protected function executeMethodAndMakeAssertions(string $method, array $args): void { - /** @psalm-suppress MixedArgumentTypeCoercion */ - $imploded = implode(', ', $args); - $returnSpec = 'foobar_return(' . $imploded . ') : '; - $outputSpec = 'foobar_output(' . $imploded . ') : '; - $callback = [$this->pattern, $method]; + $options = $this->pattern->getOptions(); + $cacheOutput = $options->getCacheOutput(); + $imploded = implode(', ', $args); + $returnSpec = 'foobar_return(' . $imploded . ') : '; + $outputSpec = 'foobar_output(' . $imploded . ') : '; + $callback = [$this->pattern, $method]; // first call - not cached $firstCounter = TestObjectCache::$fooCounter + 1; + $expectedKey = $this->pattern->generateKey($method, $args); + $this->storage + ->expects(self::exactly(2)) + ->method('getItem') + ->with($expectedKey, null) + ->willReturnCallback( + function ( + string $key, + bool|null &$success = null + ) use ( + $returnSpec, + $outputSpec, + $firstCounter, + $cacheOutput, + ): ?array { + static $called = false; + if ($called === true) { + $success = true; + + $cached = [$returnSpec . $firstCounter]; + if ($cacheOutput) { + $cached[] = $outputSpec . $firstCounter; + } + + return $cached; + } + + $called = true; + return null; + } + ); + ob_start(); ob_implicit_flush(false); @@ -149,7 +192,7 @@ protected function executeMethodAndMakeAssertions(string $method, array $args): ob_end_clean(); self::assertEquals($returnSpec . $firstCounter, $return); - if ($this->options->getCacheOutput()) { + if ($cacheOutput) { self::assertEquals($outputSpec . $firstCounter, $data); } else { self::assertEquals('', $data); diff --git a/test/Pattern/OutputCacheTest.php b/test/Pattern/OutputCacheTest.php index a2724fa3..0c468f91 100644 --- a/test/Pattern/OutputCacheTest.php +++ b/test/Pattern/OutputCacheTest.php @@ -4,8 +4,9 @@ namespace LaminasTest\Cache\Pattern; -use Laminas\Cache; use Laminas\Cache\Exception\MissingKeyException; +use Laminas\Cache\Pattern\OutputCache; +use Laminas\Cache\Storage\StorageInterface; use function ob_end_clean; use function ob_get_clean; @@ -15,6 +16,7 @@ /** * @group Laminas_Cache * @covers \Laminas\Cache\Pattern\OutputCache + * @template-extends AbstractCommonStoragePatternTest */ class OutputCacheTest extends AbstractCommonStoragePatternTest { @@ -27,11 +29,9 @@ class OutputCacheTest extends AbstractCommonStoragePatternTest public function setUp(): void { - $this->storage = new Cache\Storage\Adapter\Memory([ - 'memory_limit' => 0, - ]); + $this->storage = $this->createMock(StorageInterface::class); - $this->pattern = new Cache\Pattern\OutputCache($this->storage); + $this->pattern = new OutputCache($this->storage); // used to reset the level on tearDown $this->obLevel = ob_get_level(); @@ -69,6 +69,12 @@ public function testStartEndCacheMiss(): void $output = 'foobar'; $key = 'testStartEndCacheMiss'; + $this->storage + ->expects(self::once()) + ->method('setItem') + ->with($key, $output) + ->willReturn(true); + ob_start(); self::assertFalse($this->pattern->start($key)); echo $output; @@ -76,7 +82,6 @@ public function testStartEndCacheMiss(): void $data = ob_get_clean(); self::assertEquals($output, $data); - self::assertEquals($output, $this->pattern->getStorage()->getItem($key)); } public function testStartEndCacheHit(): void @@ -84,9 +89,18 @@ public function testStartEndCacheHit(): void $output = 'foobar'; $key = 'testStartEndCacheHit'; - // fill cache - $storage = $this->pattern->getStorage(); - $storage->setItem($key, $output); + $this->storage + ->expects(self::never()) + ->method('setItem'); + + $this->storage + ->expects(self::once()) + ->method('getItem') + ->with($key, null) + ->willReturnCallback(function (string $key, ?bool &$success = null) use ($output): string { + $success = true; + return $output; + }); ob_start(); self::assertTrue($this->pattern->start($key)); diff --git a/test/Pattern/TestAsset/TestCallbackCache.php b/test/Pattern/TestAsset/TestCallbackCache.php index 565b99ee..8e1abbba 100644 --- a/test/Pattern/TestAsset/TestCallbackCache.php +++ b/test/Pattern/TestAsset/TestCallbackCache.php @@ -14,10 +14,8 @@ final class TestCallbackCache { /** * A counter how oftern the method "foo" was called - * - * @var int */ - public static $fooCounter = 0; + public static int $fooCounter = 0; public static function bar(): string { @@ -30,7 +28,7 @@ public static function bar(): string return 'foobar_return(' . $imploded . ') : ' . static::$fooCounter; } - public static function emptyMethod() + public static function emptyMethod(): void { } } diff --git a/test/Psr/CacheItemPool/CacheItemPoolIntegrationTest.php b/test/Psr/CacheItemPool/CacheItemPoolIntegrationTest.php deleted file mode 100644 index 0b3e5510..00000000 --- a/test/Psr/CacheItemPool/CacheItemPoolIntegrationTest.php +++ /dev/null @@ -1,22 +0,0 @@ -addPlugin($serializer); - - return $storage; - } -} diff --git a/test/Psr/SimpleCache/SimpleCacheIntegrationTest.php b/test/Psr/SimpleCache/SimpleCacheIntegrationTest.php deleted file mode 100644 index 2a14c579..00000000 --- a/test/Psr/SimpleCache/SimpleCacheIntegrationTest.php +++ /dev/null @@ -1,22 +0,0 @@ -addPlugin($serializer); - - return $storage; - } -} diff --git a/test/StaticAnalysis/AdapterPluginManagerTypes.php b/test/StaticAnalysis/AdapterPluginManagerTypes.php index 4aa3ec9f..b2e9d150 100644 --- a/test/StaticAnalysis/AdapterPluginManagerTypes.php +++ b/test/StaticAnalysis/AdapterPluginManagerTypes.php @@ -4,7 +4,7 @@ namespace LaminasTest\Cache\StaticAnalysis; -use Laminas\Cache\Storage\Adapter\Memory; +use Laminas\Cache\Storage\Adapter\Dev\VoidAdapter; use Laminas\Cache\Storage\AdapterPluginManager; use Laminas\Cache\Storage\StorageInterface; @@ -12,7 +12,7 @@ final class AdapterPluginManagerTypes { public function willReturnAnAdapterUsingFQCN(AdapterPluginManager $manager): StorageInterface { - return $manager->get(Memory::class); + return $manager->get(VoidAdapter::class); } public function validateWillAssertInstanceType(AdapterPluginManager $manager, object $instance): StorageInterface @@ -24,6 +24,6 @@ public function validateWillAssertInstanceType(AdapterPluginManager $manager, ob public function buildWillReturnAdapterUsingFQCN(AdapterPluginManager $manager): StorageInterface { - return $manager->build(Memory::class); + return $manager->build(VoidAdapter::class); } } diff --git a/test/StaticAnalysis/MetadataCapableAdapter.php b/test/StaticAnalysis/MetadataCapableAdapter.php new file mode 100644 index 00000000..0f222bbd --- /dev/null +++ b/test/StaticAnalysis/MetadataCapableAdapter.php @@ -0,0 +1,68 @@ + + */ +final class MetadataCapableAdapter extends AbstractMetadataCapableAdapter +{ + /** + * {@inheritDoc} + */ + protected function internalHasItem(&$normalizedKey) + { + return true; + } + + /** + * {@inheritDoc} + */ + protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$casToken = null) + { + return null; + } + + /** + * {@inheritDoc} + */ + protected function internalSetItem(&$normalizedKey, mixed &$value) + { + return false; + } + + /** + * {@inheritDoc} + */ + protected function internalRemoveItem(&$normalizedKey) + { + return false; + } + + /** + * {@inheritDoc} + */ + protected function internalGetMetadata(string $normalizedKey): ?object + { + return null; + } + + /** + * @psalm-api Mark method as API method to prevent psalm from detecting this method as unused. + */ + public function whatever(): string + { + $adapter = new MetadataCapableAdapter(); + $metadata = $adapter->getMetadata('foo'); + + if ($metadata === null) { + return ''; + } + + return $metadata->meta; + } +} diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index 30ba7dbc..8b5c0fd4 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -24,7 +24,6 @@ use stdClass; use function array_keys; -use function array_map; use function array_merge; use function array_unique; use function assert; @@ -377,8 +376,6 @@ public function simpleEventHandlingMethodDefinitions(): array ['hasItems', 'internalHasItems', [['k1', 'k2']], ['v1', 'v2']], ['getItem', 'internalGetItem', ['k'], 'v'], ['getItems', 'internalGetItems', [['k1', 'k2']], ['k1' => 'v1', 'k2' => 'v2']], - ['getMetadata', 'internalGetMetadata', ['k'], []], - ['getMetadatas', 'internalGetMetadatas', [['k1', 'k2']], ['k1' => [], 'k2' => []]], ['setItem', 'internalSetItem', ['k', 'v'], true], ['setItems', 'internalSetItems', [['k1' => 'v1', 'k2' => 'v2']], []], ['replaceItem', 'internalReplaceItem', ['k', 'v'], true], @@ -398,161 +395,6 @@ public function simpleEventHandlingMethodDefinitions(): array ]; } - /** - * @psalm-param non-empty-string $methodName - * @psalm-param non-empty-string $internalMethodName - * @dataProvider simpleEventHandlingMethodDefinitions - */ - public function testEventHandlingSimple( - string $methodName, - string $internalMethodName, - array $methodArgs, - mixed $retVal - ): void { - $storage = $this->getMockForAbstractAdapter([$internalMethodName]); - - $eventList = []; - $eventHandler = static function (Event $event) use (&$eventList): void { - $eventList[] = $event->getName(); - }; - $eventManager = $storage->getEventManager(); - $eventManager->attach($methodName . '.pre', $eventHandler); - $eventManager->attach($methodName . '.post', $eventHandler); - $eventManager->attach($methodName . '.exception', $eventHandler); - - $storage - ->expects($this->once()) - ->method($internalMethodName) - ->with(...array_map([$this, 'equalTo'], $methodArgs)) - ->willReturn($retVal); - - call_user_func_array([$storage, $methodName], $methodArgs); - - $expectedEventList = [ - $methodName . '.pre', - $methodName . '.post', - ]; - - self::assertSame($expectedEventList, $eventList); - } - - /** - * @psalm-param non-empty-string $methodName - * @psalm-param non-empty-string $internalMethodName - * @dataProvider simpleEventHandlingMethodDefinitions - */ - public function testEventHandlingCatchException( - string $methodName, - string $internalMethodName, - array $methodArgs - ): void { - $storage = $this->getMockForAbstractAdapter([$internalMethodName]); - - $eventList = []; - $eventHandler = static function (Event $event) use (&$eventList): void { - $eventList[] = $event->getName(); - if ($event instanceof Cache\Storage\ExceptionEvent) { - $event->setThrowException(false); - } - }; - $eventManager = $storage->getEventManager(); - $eventManager->attach($methodName . '.pre', $eventHandler); - $eventManager->attach($methodName . '.post', $eventHandler); - $eventManager->attach($methodName . '.exception', $eventHandler); - - $storage - ->expects($this->once()) - ->method($internalMethodName) - ->with(...array_map([$this, 'equalTo'], $methodArgs)) - ->willThrowException(new \Exception('test')); - - call_user_func_array([$storage, $methodName], $methodArgs); - - $expectedEventList = [ - $methodName . '.pre', - $methodName . '.exception', - ]; - self::assertSame($expectedEventList, $eventList); - } - - /** - * @psalm-param non-empty-string $methodName - * @psalm-param non-empty-string $internalMethodName - * @dataProvider simpleEventHandlingMethodDefinitions - */ - public function testEventHandlingStopInPre( - string $methodName, - string $internalMethodName, - array $methodArgs, - mixed $retVal - ): void { - $storage = $this->getMockForAbstractAdapter([$internalMethodName]); - - $eventList = []; - $eventHandler = static function (Event $event) use (&$eventList): void { - $eventList[] = $event->getName(); - }; - $eventManager = $storage->getEventManager(); - $eventManager->attach($methodName . '.pre', $eventHandler); - $eventManager->attach($methodName . '.post', $eventHandler); - $eventManager->attach($methodName . '.exception', $eventHandler); - - $eventManager->attach($methodName . '.pre', static function ($event) use ($retVal) { - $event->stopPropagation(); - return $retVal; - }); - - // the internal method should never be called - $storage->expects($this->never())->method($internalMethodName); - - // the return vaue should be available by pre-event - $result = call_user_func_array([$storage, $methodName], $methodArgs); - self::assertSame($retVal, $result); - - // after the triggered pre-event the post-event should be triggered as well - $expectedEventList = [ - $methodName . '.pre', - $methodName . '.post', - ]; - self::assertSame($expectedEventList, $eventList); - } - - public function testGetMetadatas(): void - { - $storage = $this->getMockForAbstractAdapter(['getMetadata', 'internalGetMetadata']); - - $meta = ['meta' => 'data']; - $items = [ - 'key1' => $meta, - 'key2' => $meta, - ]; - - // foreach item call 'internalGetMetadata' instead of 'getMetadata' - $storage->expects($this->never())->method('getMetadata'); - $storage->expects($this->exactly(count($items))) - ->method('internalGetMetadata') - ->with($this->stringContains('key')) - ->willReturn($meta); - - self::assertSame($items, $storage->getMetadatas(array_keys($items))); - } - - public function testGetMetadatasFail(): void - { - $storage = $this->getMockForAbstractAdapter(['internalGetMetadata']); - - $items = ['key1', 'key2']; - - // return false to indicate that the operation failed - $storage - ->expects($this->exactly(count($items))) - ->method('internalGetMetadata') - ->with($this->stringContains('key')) - ->willReturn(false); - - self::assertSame([], $storage->getMetadatas($items)); - } - public function testSetItems(): void { $storage = $this->getMockForAbstractAdapter(['setItem', 'internalSetItem']); @@ -954,19 +796,6 @@ public function testPreEventsCanChangeArguments(): void 'keys' => ['changedKey'], ]); - // getMetadata(s) - $this->checkPreEventCanChangeArguments('getMetadata', [ - 'key' => 'key', - ], [ - 'key' => 'changedKey', - ]); - - $this->checkPreEventCanChangeArguments('getMetadatas', [ - 'keys' => ['key'], - ], [ - 'keys' => ['changedKey'], - ]); - // setItem(s) $this->checkPreEventCanChangeArguments('setItem', [ 'key' => 'key', @@ -1111,14 +940,11 @@ protected function checkPreEventCanChangeArguments(string $method, array $args, * Also sets the adapter options * * @psalm-param list $methods - * @return AbstractAdapter&MockObject */ - protected function getMockForAbstractAdapter(array $methods = []): AbstractAdapter + protected function getMockForAbstractAdapter(array $methods = []): MockObject&AbstractAdapter { - $class = AbstractAdapter::class; - if (! $methods) { - $adapter = $this->getMockForAbstractClass($class); + $adapter = $this->getMockForAbstractClass(AbstractAdapter::class); } else { $reflection = new ReflectionClass(AbstractAdapter::class); foreach ($reflection->getMethods() as $method) { @@ -1126,7 +952,7 @@ protected function getMockForAbstractAdapter(array $methods = []): AbstractAdapt $methods[] = $method->getName(); } } - $adapter = $this->getMockBuilder($class) + $adapter = $this->getMockBuilder(AbstractAdapter::class) ->onlyMethods(array_unique($methods)) ->disableArgumentCloning() ->getMock(); diff --git a/test/Storage/Adapter/AbstractMetadataCapableAdapterTest.php b/test/Storage/Adapter/AbstractMetadataCapableAdapterTest.php new file mode 100644 index 00000000..3af0775f --- /dev/null +++ b/test/Storage/Adapter/AbstractMetadataCapableAdapterTest.php @@ -0,0 +1,287 @@ +options = new AdapterOptions(); + } + + /** + * @return list + */ + public function simpleEventHandlingMethodDefinitions(): array + { + return [ + // name, internalName, args, returnValue + ['getMetadata', 'internalGetMetadata', ['k'], null], + ['getMetadatas', 'internalGetMetadatas', [['k1', 'k2']], []], + ]; + } + + /** + * Generates a mock of the abstract metadata capable storage adapter by mocking all abstract and the given methods + * Also sets the adapter options + * + * @psalm-param list $methods + */ + private function getMockForAbstractMetadataCapableAdapter( + array $methods = [] + ): MockObject&AbstractMetadataCapableAdapter { + if (! $methods) { + $adapter = $this->getMockForAbstractClass(AbstractMetadataCapableAdapter::class); + } else { + $reflection = new ReflectionClass(AbstractMetadataCapableAdapter::class); + foreach ($reflection->getMethods() as $method) { + if ($method->isAbstract()) { + $methods[] = $method->getName(); + } + } + $adapter = $this->getMockBuilder(AbstractMetadataCapableAdapter::class) + ->onlyMethods(array_unique($methods)) + ->disableArgumentCloning() + ->getMock(); + } + + $adapter->setOptions($this->options ?? new AdapterOptions()); + + return $adapter; + } + + /** + * @psalm-param non-empty-string $methodName + * @psalm-param non-empty-string $internalMethodName + * @dataProvider simpleEventHandlingMethodDefinitions + */ + public function testEventHandlingSimple( + string $methodName, + string $internalMethodName, + array $methodArgs, + mixed $retVal + ): void { + $storage = $this->getMockForAbstractMetadataCapableAdapter([$internalMethodName]); + + $eventList = []; + $eventHandler = static function (Event $event) use (&$eventList): void { + assert(is_array($eventList)); + $eventList[] = $event->getName(); + }; + $eventManager = $storage->getEventManager(); + $eventManager->attach($methodName . '.pre', $eventHandler); + $eventManager->attach($methodName . '.post', $eventHandler); + $eventManager->attach($methodName . '.exception', $eventHandler); + + $storage + ->expects($this->once()) + ->method($internalMethodName) + ->with(...array_map([$this, 'equalTo'], $methodArgs)) + ->willReturn($retVal); + + call_user_func_array([$storage, $methodName], $methodArgs); + + $expectedEventList = [ + $methodName . '.pre', + $methodName . '.post', + ]; + + self::assertSame($expectedEventList, $eventList); + } + + /** + * @psalm-param non-empty-string $methodName + * @psalm-param non-empty-string $internalMethodName + * @dataProvider simpleEventHandlingMethodDefinitions + */ + public function testEventHandlingCatchException( + string $methodName, + string $internalMethodName, + array $methodArgs + ): void { + $storage = $this->getMockForAbstractMetadataCapableAdapter([$internalMethodName]); + + $eventList = []; + $eventHandler = static function (Event $event) use (&$eventList): void { + assert(is_array($eventList)); + $eventList[] = $event->getName(); + if ($event instanceof Cache\Storage\ExceptionEvent) { + $event->setThrowException(false); + } + }; + $eventManager = $storage->getEventManager(); + $eventManager->attach($methodName . '.pre', $eventHandler); + $eventManager->attach($methodName . '.post', $eventHandler); + $eventManager->attach($methodName . '.exception', $eventHandler); + + $storage + ->expects($this->once()) + ->method($internalMethodName) + ->with(...array_map([self::class, 'equalTo'], $methodArgs)) + ->willThrowException(new Exception('test')); + + call_user_func_array([$storage, $methodName], $methodArgs); + + $expectedEventList = [ + $methodName . '.pre', + $methodName . '.exception', + ]; + self::assertSame($expectedEventList, $eventList); + } + + /** + * @psalm-param non-empty-string $methodName + * @psalm-param non-empty-string $internalMethodName + * @dataProvider simpleEventHandlingMethodDefinitions + */ + public function testEventHandlingStopInPre( + string $methodName, + string $internalMethodName, + array $methodArgs, + mixed $retVal + ): void { + $storage = $this->getMockForAbstractMetadataCapableAdapter([$internalMethodName]); + + $eventList = []; + $eventHandler = static function (Event $event) use (&$eventList): void { + assert(is_array($eventList)); + $eventList[] = $event->getName(); + }; + $eventManager = $storage->getEventManager(); + $eventManager->attach($methodName . '.pre', $eventHandler); + $eventManager->attach($methodName . '.post', $eventHandler); + $eventManager->attach($methodName . '.exception', $eventHandler); + + $eventManager->attach($methodName . '.pre', static function (EventInterface $event) use ($retVal): mixed { + $event->stopPropagation(); + return $retVal; + }); + + // the internal method should never be called + $storage->expects($this->never())->method($internalMethodName); + + // the return value should be available by pre-event + $result = call_user_func_array([$storage, $methodName], $methodArgs); + self::assertSame($retVal, $result); + + // after the triggered pre-event the post-event should be triggered as well + $expectedEventList = [ + $methodName . '.pre', + $methodName . '.post', + ]; + self::assertSame($expectedEventList, $eventList); + } + + public function testGetMetadatas(): void + { + $storage = $this->getMockForAbstractMetadataCapableAdapter(['getMetadata', 'internalGetMetadata']); + + $meta = new class { + public string $meta = 'data'; + }; + + $items = [ + 'key1' => $meta, + 'key2' => $meta, + ]; + + // foreach item call 'internalGetMetadata' instead of 'getMetadata' + $storage->expects($this->never())->method('getMetadata'); + $storage->expects($this->exactly(count($items))) + ->method('internalGetMetadata') + ->with($this->stringContains('key')) + ->willReturn($meta); + + self::assertSame($items, $storage->getMetadatas(array_keys($items))); + } + + public function testGetMetadatasFail(): void + { + $storage = $this->getMockForAbstractMetadataCapableAdapter(['internalGetMetadata']); + + $items = ['key1', 'key2']; + + // return false to indicate that the operation failed + $storage + ->expects($this->exactly(count($items))) + ->method('internalGetMetadata') + ->with($this->stringContains('key')) + ->willReturn(null); + + self::assertSame([], $storage->getMetadatas($items)); + } + + public function testFoo(): void + { + // getMetadata(s) + $this->checkPreEventCanChangeArguments('getMetadata', [ + 'key' => 'key', + ], [ + 'key' => 'changedKey', + ]); + + $this->checkPreEventCanChangeArguments('getMetadatas', [ + 'keys' => ['key'], + ], [ + 'keys' => ['changedKey'], + ]); + } + + /** + * @param non-empty-string $method + * @param array>|array $args + * @param array>|array $expectedArgs + */ + protected function checkPreEventCanChangeArguments(string $method, array $args, array $expectedArgs): void + { + $internalMethod = 'internal' . ucfirst($method); + $eventName = $method . '.pre'; + + // init mock + $storage = $this->getMockForAbstractMetadataCapableAdapter([$internalMethod]); + $storage->getEventManager()->attach($eventName, static function (Event $event) use ($expectedArgs): void { + $params = $event->getParams(); + $params->exchangeArray(array_merge($params->getArrayCopy(), $expectedArgs)); + }); + + // set expected arguments of internal method call + $tmp = $storage->expects($this->once())->method($internalMethod); + $equals = []; + foreach ($expectedArgs as $v) { + $equals[] = $this->equalTo($v); + } + call_user_func_array([$tmp, 'with'], $equals); + + // run + call_user_func_array([$storage, $method], $args); + } +} diff --git a/test/Storage/CapabilitiesTest.php b/test/Storage/CapabilitiesTest.php index 25c32b84..c3f3c334 100644 --- a/test/Storage/CapabilitiesTest.php +++ b/test/Storage/CapabilitiesTest.php @@ -4,7 +4,7 @@ namespace LaminasTest\Cache\Storage; -use Laminas\Cache\Storage\Adapter\Memory as MemoryAdapter; +use Laminas\Cache\Storage\Adapter\Dev\VoidAdapter; use Laminas\Cache\Storage\Capabilities; use Laminas\EventManager\Event; use PHPUnit\Framework\TestCase; @@ -40,14 +40,14 @@ class CapabilitiesTest extends TestCase /** * The storage adapter * - * @var MemoryAdapter + * @var VoidAdapter */ protected $adapter; public function setUp(): void { $this->marker = new stdClass(); - $this->adapter = new MemoryAdapter(); + $this->adapter = new VoidAdapter(); $this->baseCapabilities = new Capabilities($this->adapter, $this->marker); $this->capabilities = new Capabilities($this->adapter, $this->marker, [], $this->baseCapabilities);