diff --git a/.gitignore b/.gitignore index ee18513c..7fbb080a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /vendor/ /.phpunit.result.cache /.phpcs-cache +/psalm.xml diff --git a/composer.lock b/composer.lock index 01c8d54b..9835de86 100644 --- a/composer.lock +++ b/composer.lock @@ -1271,16 +1271,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.0.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "85193c0b0cb5c47894b5eaec906e946f054e7077" + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/85193c0b0cb5c47894b5eaec906e946f054e7077", - "reference": "85193c0b0cb5c47894b5eaec906e946f054e7077", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", "shasum": "" }, "require": { @@ -1320,7 +1320,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.0.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" }, "funding": [ { @@ -1328,7 +1328,7 @@ "type": "github" } ], - "time": "2023-09-17T21:38:23+00:00" + "time": "2024-02-07T09:43:46+00:00" }, { "name": "laminas/laminas-cli", @@ -1715,16 +1715,16 @@ }, { "name": "netresearch/jsonmapper", - "version": "v4.2.0", + "version": "v4.4.1", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", "shasum": "" }, "require": { @@ -1735,7 +1735,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", "squizlabs/php_codesniffer": "~3.5" }, "type": "library", @@ -1760,9 +1760,9 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" }, - "time": "2023-04-09T17:37:40+00:00" + "time": "2024-01-31T06:18:54+00:00" }, { "name": "nikic/php-parser", @@ -3022,16 +3022,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -3076,7 +3076,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -3084,7 +3084,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -3749,16 +3749,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.2.2", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "96be97e664c87613121d073ea39af4c74e57a7f8" + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/96be97e664c87613121d073ea39af4c74e57a7f8", - "reference": "96be97e664c87613121d073ea39af4c74e57a7f8", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/c95fd4db94ec199f798d4b5b4a81757bd20d88ab", + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab", "shasum": "" }, "require": { @@ -3796,7 +3796,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.2" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.3" }, "funding": [ { @@ -3808,7 +3808,7 @@ "type": "github" } ], - "time": "2023-11-14T14:08:51+00:00" + "time": "2024-02-07T10:39:02+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -3883,16 +3883,16 @@ }, { "name": "symfony/console", - "version": "v6.4.2", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", + "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", "shasum": "" }, "require": { @@ -3957,7 +3957,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.2" + "source": "https://github.com/symfony/console/tree/v6.4.4" }, "funding": [ { @@ -3973,7 +3973,7 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2024-02-22T20:27:10+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4200,16 +4200,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" + "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", + "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", "shasum": "" }, "require": { @@ -4243,7 +4243,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.0" + "source": "https://github.com/symfony/filesystem/tree/v6.4.3" }, "funding": [ { @@ -4259,20 +4259,20 @@ "type": "tidelift" } ], - "time": "2023-07-26T17:27:13+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -4286,9 +4286,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4325,7 +4322,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -4341,20 +4338,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -4365,9 +4362,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4406,7 +4400,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -4422,20 +4416,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -4446,9 +4440,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4490,7 +4481,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -4506,20 +4497,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -4533,9 +4524,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4573,7 +4561,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -4589,20 +4577,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { @@ -4610,9 +4598,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4656,7 +4641,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" }, "funding": [ { @@ -4672,7 +4657,7 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/service-contracts", @@ -4758,16 +4743,16 @@ }, { "name": "symfony/string", - "version": "v6.4.2", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "shasum": "" }, "require": { @@ -4824,7 +4809,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.2" + "source": "https://github.com/symfony/string/tree/v6.4.4" }, "funding": [ { @@ -4840,7 +4825,7 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2024-02-01T13:16:41+00:00" }, { "name": "theseer/tokenizer", @@ -4894,16 +4879,16 @@ }, { "name": "vimeo/psalm", - "version": "5.20.0", + "version": "5.22.2", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "3f284e96c9d9be6fe6b15c79416e1d1903dcfef4" + "reference": "d768d914152dbbf3486c36398802f74e80cfde48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/3f284e96c9d9be6fe6b15c79416e1d1903dcfef4", - "reference": "3f284e96c9d9be6fe6b15c79416e1d1903dcfef4", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d768d914152dbbf3486c36398802f74e80cfde48", + "reference": "d768d914152dbbf3486c36398802f74e80cfde48", "shasum": "" }, "require": { @@ -4926,7 +4911,7 @@ "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.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", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" @@ -5000,7 +4985,7 @@ "issues": "https://github.com/vimeo/psalm/issues", "source": "https://github.com/vimeo/psalm" }, - "time": "2024-01-18T12:15:06+00:00" + "time": "2024-02-22T23:39:07+00:00" }, { "name": "webimpress/coding-standard", diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5a01a471..4c10c329 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,196 +1,141 @@ - + - $cacheConfiguration - $configuration + + - $projectConfiguration + - BadMethodCallException + - MissingDependencyException + - OutOfSpaceException + - UnexpectedValueException + - UnsupportedMethodCallException + - Module + - PatternOptions + options]]> - - $function - - $result + - $result[0] - $result[1] + + - __call + - $content + - - clearByGlob - set - - $content + - isFile + - $publicDir + - clearByGlob - start + + - bool - bool - string|null + + + - - $method - $method - - - $callback[1] - - - call('__set', [$name, $value])]]> - call('__unset', [$name])]]> - - $callback[1] - $property - $property - $property - $property + + + + - bool - void - void + - - $method - call('__isset', [$name])]]> - - $method - $method - - - $object - $object - $object - $object - $object - $object - $object - $object - + + + - $data - $key + + - - (string) $key - - $array + - $dirPermission - $filePermission - $umask + + + - setCacheByDefault - setDirPermission - setFileLocking - setFilePermission - setObject - setObjectCacheMagicProperties - setObjectCacheMethods - setObjectNonCacheMethods - setPublicDir - setUmask + + + + + + + + + + - - (bool) $cacheOutput - (bool) $fileLocking - (bool) $objectCacheMagicProperties - (string) $indexFilename - (string) $objectKey - (string) $publicDir - - - - - is_array($result) - - - $key - $key - - - storage->removeItem($key)]]> - + + + - $pluginConfiguration + @@ -202,17 +147,17 @@ get(StoragePluginFactoryInterface::class)]]> - StorageAdapterFactory + - object + - StorageInterface + @@ -220,216 +165,133 @@ get(PluginManager::class)]]> - StoragePluginFactory + - $args - $args - $args - $args - $args - $args + + + + + + - $plugin + - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - $args - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - bool - - - - - $handle - $keyValuePairs - $keyValuePairs - $keyValuePairs - $normalizedKey - $normalizedKey - $normalizedKey - $normalizedKey + - - $key - $normalizedKey - $normalizedKey - $normalizedKey - - - AdapterOptions - Capabilities - array - array - array - array - array - array - array - bool - bool - bool - bool - bool - bool - bool - - - setAdapter - - - options]]> - triggerException(__FUNCTION__, $args, $keys, $e)]]> - triggerException(__FUNCTION__, $args, $keys, $e)]]> - 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)]]> - 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)]]> - 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)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - triggerPost(__FUNCTION__, $args, $result)]]> - - - $success - + + + + + + + + + - getCaching - setCaching + + + + - - (bool) $flag - (string) $key - + + + + + + + - is_array($options) + $optionValue])]]> - $array + - array + - $letters + - $key - $letter - $letters + + + - $this + - - (bool) $readable - (bool) $writable - (string) $keyPattern - (string) $namespace - - - - - (int) $mode - - $instanceOf + - AvailableSpaceCapableInterface + - $name + - array - bool - bool - bool - float - int - int - int - int - string + + + + + + + + + + getCapability('lockOnExpire', 0)]]> @@ -453,105 +315,71 @@ getCapability('useRequestTime', false)]]> - getNamespaceIsPrefix - getNamespaceSeparator - getTtlPrecision - setLockOnExpire - setMaxKeyLength - setMinTtl - setNamespaceIsPrefix - setNamespaceSeparator - setStaticTtl - setSupportedDatatypes - setTtlPrecision - setUseRequestTime + + + + + + + + + + + + - $lockOnExpire - $maxKeyLength - $maxTtl - $minTtl - $namespaceIsPrefix - $namespaceSeparator - $staticTtl - $supportedDatatypes - $ttlPrecision - $useRequestTime + + + + + + + + + + - Capabilities + - - (bool) $flag - (bool) $flag - (bool) $flag - (float) $ttlPrecision - (int) $maxKeyLength - (int) $maxTtl - (int) $minTtl - (int) $timeout - (string) $separator - - ClearByPrefixInterface + - bool + - - Event - - $target - $target + + - - Event - - - - - (bool) $flag - - IterableInterface + - getMode - getStorage - setMode + + + - bool + - - - options]]> - - - $options - $options - $options - $options - $options - - - PluginInterface + @@ -559,94 +387,93 @@ serializer]]> - SerializerAdapter + - setExitOnAbort - setOptimizingFactor - setSerializerOptions + + + - - $serializer - - - (bool) $exitOnAbort - (bool) $throwExceptions - (int) $factor - - $baseCapabilities - $baseCapabilities + + getAdapter()]]> - $result - $value + + + + + + + + + + - getAdapter + - $plugin + - $aliases - $factories - $instanceOf + + + - - - $value - - - addItem - replaceItem - touchItem + + + - StorageInterface + + + + + - TaggableInterface + - TotalSpaceCapableInterface + - withConsecutive - withConsecutive - withConsecutive - withConsecutive - withConsecutive + + + + + - getCommonPatternNamesProvider + - $pattern - $pattern - $pattern - $pattern + + + + - getCommonPatternNamesProvider + @@ -656,11 +483,11 @@ - getCommonPatternNamesProvider + - set - set + + @@ -669,62 +496,62 @@ options->getObject()->property]]> - getCommonPatternNamesProvider + - getCommonPatternNamesProvider + - TestCachePattern + - emptyMethod + - $property + - withConsecutive - withConsecutive + + - $keys - $keys + + - testDeleteItemInvalidKeyThrowsException - testGetItemInvalidKeyThrowsException - testHasItemInvalidKeyThrowsException + + + - $item - $key - $key - $key + + + + - get - get - get - get - get - getKey - isHit - isHit - isHit - isHit - isHit - isHit - isHit - set + + + + + + + + + + + + + + @@ -734,124 +561,116 @@ - withConsecutive - withConsecutive - withConsecutive - withConsecutive - withConsecutive + + + + + - testHasProxiesToStorage - testSetMultipleShouldRaisePsrInvalidArgumentExceptionForInvalidKeys - testSetMultipleShouldRemoveItemsFromCacheIfTtlIsBelow1 - testSetMultipleShouldRemoveItemsFromCacheIfTtlIsBelow1AndStorageDoesNotSupportPerItemTtl - testSetShouldAcknowledgeStorageAdapterMaxKeyLengthWithPsrDecorator - testSetShouldRaisePsrInvalidArgumentExceptionForInvalidKeys - testSetShouldRemoveItemFromCacheIfTtlIsBelow1 - testSetShouldRemoveItemFromCacheIfTtlIsBelow1AndStorageDoesNotSupportPerItemTtl + + + + + + + + - array - array + + - - - setCapabilities - - - Generator - Generator + + - withConsecutive + - withConsecutive - withConsecutive + + - withConsecutive - withConsecutive + + - AdapterPluginManagerTypes + - PluginManagerTypes + - $success + - getResult + - - null - - getNamespace - setKeyPattern - setKeyPattern - setKeyPattern - setNamespace - setNamespace - setReadable - setTtl - setTtl - setWritable + + + + + + + + + + - $success + - simpleEventHandlingMethodDefinitions + - getKeyPattern - getTtl - setAdapter - setFromArray - setKeyPattern - setKeyPattern - setNamespace - setReadable - setTtl - setTtl - setWritable + + + + + + + + + + + - $storage + - addPlugin + - AdapterWithStorageAndEventsCapableInterface + - testPluginAliasesResolve - testShareByDefaultAndSharedByDefault + + @@ -860,18 +679,18 @@ adapter->getEventManager()]]> - setMethods + - $cb - $cb + + - $cb[0] - $cb[1] + + - clearExpiredByFactor + @@ -880,19 +699,19 @@ adapter->getEventManager()]]> - $cb - $cb + + - $cb[0] - $cb[1] + + - $exception + - onException - onException + + @@ -901,12 +720,12 @@ adapter->getEventManager()]]> - $cb - $cb + + - $cb[0] - $cb[1] + + @@ -915,84 +734,64 @@ adapter->getEventManager()]]> - setMethods + - $cb - $cb + + - $cb[0] - $cb[1] + + - optimizeByFactor + - $events - $events - $events + + + adapter->getEventManager()]]> - $cb - $cb + + - $cb[0] - $cb[1] + + - $values + - onReadItemPost - onReadItemPost - onReadItemsPost + + + - testShareByDefaultAndSharedByDefault + - - - clearExpired - - - - - internalGetItem - internalRemoveItem - internalSetItem - - - getEventCallbacks - onSetItemPost - onSetItemPre + + + - $handles + - - $options - - $options instanceof Plugin\PluginOptions + - - - optimize - - diff --git a/psalm.xml b/psalm.xml.dist similarity index 100% rename from psalm.xml rename to psalm.xml.dist diff --git a/src/Exception/MissingKeyException.php b/src/Exception/MissingKeyException.php deleted file mode 100644 index 5d5d77f1..00000000 --- a/src/Exception/MissingKeyException.php +++ /dev/null @@ -1,7 +0,0 @@ -options = $options; return $this; } - /** - * @return PatternOptions - */ - public function getOptions() + public function getOptions(): PatternOptions { if (null === $this->options) { $this->setOptions(new PatternOptions()); diff --git a/src/Pattern/CallbackCache.php b/src/Pattern/CallbackCache.php index a7c20c1e..23fa08fe 100644 --- a/src/Pattern/CallbackCache.php +++ b/src/Pattern/CallbackCache.php @@ -3,7 +3,7 @@ namespace Laminas\Cache\Pattern; use Laminas\Cache\Exception; -use Laminas\Stdlib\ErrorHandler; +use Throwable; use function array_key_exists; use function array_values; @@ -15,7 +15,6 @@ use function ob_implicit_flush; use function ob_start; use function serialize; -use function sprintf; use function strtolower; class CallbackCache extends AbstractStorageCapablePattern @@ -25,11 +24,10 @@ class CallbackCache extends AbstractStorageCapablePattern * * @param callable $callback A valid callback * @param array $args Callback arguments - * @return mixed Result * @throws Exception\RuntimeException If invalid cached data. - * @throws \Exception + * @throws Throwable */ - public function call($callback, array $args = []) + public function call(callable $callback, array $args = []): mixed { $options = $this->getOptions(); $storage = $this->getStorage(); @@ -55,11 +53,11 @@ public function call($callback, array $args = []) try { $ret = $callback(...$args); - } catch (\Exception $e) { + } catch (Throwable $throwable) { if ($cacheOutput) { ob_end_flush(); } - throw $e; + throw $throwable; } if ($cacheOutput) { @@ -76,13 +74,12 @@ public function call($callback, array $args = []) /** * function call handler * - * @param string $function Function name to call + * @param callable-string $function Function name to call * @param array $args Function arguments - * @return mixed * @throws Exception\RuntimeException - * @throws \Exception + * @throws Throwable */ - public function __call($function, array $args) + public function __call(string $function, array $args): mixed { return $this->call($function, $args); } @@ -93,11 +90,11 @@ public function __call($function, array $args) * * @param callable $callback A valid callback * @param array $args Callback arguments - * @return string + * @return non-empty-string * @throws Exception\RuntimeException * @throws Exception\InvalidArgumentException */ - public function generateKey($callback, array $args = []) + public function generateKey(callable $callback, array $args = []): string { return $this->generateCallbackKey($callback, $args); } @@ -106,13 +103,13 @@ public function generateKey($callback, array $args = []) * Generate a unique key in base of a key representing the callback part * and a key representing the arguments part. * - * @param callable $callback A valid callback + * @param callable $callback A valid callback * @param array $args Callback arguments + * @return non-empty-string * @throws Exception\RuntimeException If callback not serializable. * @throws Exception\InvalidArgumentException If invalid callback. - * @return string */ - protected function generateCallbackKey($callback, array $args) + protected function generateCallbackKey(callable $callback, array $args): string { if (! is_callable($callback, false, $callbackKey)) { throw new Exception\InvalidArgumentException('Invalid callback'); @@ -121,6 +118,8 @@ protected function generateCallbackKey($callback, array $args) // functions, methods and classnames are case-insensitive $callbackKey = strtolower($callbackKey); + $object = null; + // generate a unique key of object callbacks if (is_object($callback)) { // Closures & __invoke @@ -129,23 +128,17 @@ protected function generateCallbackKey($callback, array $args) // array($object, 'method') $object = $callback[0]; } - if (isset($object)) { - ErrorHandler::start(); + + if (is_object($object)) { try { $serializedObject = serialize($object); - } catch (\Exception $e) { - ErrorHandler::stop(); - throw new Exception\RuntimeException("Can't serialize callback: see previous exception", 0, $e); - } - $error = ErrorHandler::stop(); - - if (! $serializedObject) { + } catch (Throwable $throwable) { throw new Exception\RuntimeException( - sprintf('Cannot serialize callback%s', $error ? ': ' . $error->getMessage() : ''), - 0, - $error + "Can't serialize callback: see previous error", + previous: $throwable, ); } + $callbackKey .= $serializedObject; } @@ -156,28 +149,19 @@ protected function generateCallbackKey($callback, array $args) * Generate a unique key of the argument part. * * @throws Exception\RuntimeException - * @return string */ - protected function generateArgumentsKey(array $args) + protected function generateArgumentsKey(array $args): string { - if (! $args) { + if ($args === []) { return ''; } - ErrorHandler::start(); try { $serializedArgs = serialize(array_values($args)); - } catch (\Exception $e) { - ErrorHandler::stop(); - throw new Exception\RuntimeException("Can't serialize arguments: see previous exception", 0, $e); - } - $error = ErrorHandler::stop(); - - if (! $serializedArgs) { + } catch (Throwable $throwable) { throw new Exception\RuntimeException( - sprintf('Cannot serialize arguments%s', $error ? ': ' . $error->getMessage() : ''), - 0, - $error + "Can't serialize arguments: see previous exception", + previous: $throwable, ); } diff --git a/src/Pattern/CaptureCache.php b/src/Pattern/CaptureCache.php index 6ad3b33c..e673456b 100644 --- a/src/Pattern/CaptureCache.php +++ b/src/Pattern/CaptureCache.php @@ -31,10 +31,10 @@ class CaptureCache extends AbstractPattern /** * Start the cache * - * @param string $pageId Page identifier + * @param string|null $pageId Page identifier * @return void */ - public function start($pageId = null) + public function start(string|null $pageId = null) { if ($pageId === null) { $pageId = $this->detectPageId(); @@ -54,11 +54,9 @@ public function start($pageId = null) /** * Write content to page identity * - * @param string $content - * @param null|string $pageId * @throws Exception\LogicException */ - public function set($content, $pageId = null) + public function set(string $content, string|null $pageId = null): void { $publicDir = $this->getOptions()->getPublicDir(); if ($publicDir === null) { @@ -79,12 +77,10 @@ public function set($content, $pageId = null) /** * Get from cache * - * @param null|string $pageId - * @return string|null * @throws Exception\LogicException * @throws Exception\RuntimeException */ - public function get($pageId = null) + public function get(string|null $pageId = null): string|null { $publicDir = $this->getOptions()->getPublicDir(); if ($publicDir === null) { @@ -108,16 +104,16 @@ public function get($pageId = null) } return $content; } + + return null; } /** * Checks if a cache with given id exists * - * @param null|string $pageId * @throws Exception\LogicException - * @return bool */ - public function has($pageId = null) + public function has(string|null $pageId = null): bool { $publicDir = $this->getOptions()->getPublicDir(); if ($publicDir === null) { @@ -138,12 +134,10 @@ public function has($pageId = null) /** * Remove from cache * - * @param null|string $pageId * @throws Exception\LogicException * @throws Exception\RuntimeException - * @return bool */ - public function remove($pageId = null) + public function remove(string|null $pageId = null): bool { $publicDir = $this->getOptions()->getPublicDir(); if ($publicDir === null) { @@ -174,10 +168,9 @@ public function remove($pageId = null) /** * Clear cached pages matching glob pattern * - * @param string $pattern * @throws Exception\LogicException */ - public function clearByGlob($pattern = '**') + public function clearByGlob(string $pattern = '**'): void { $publicDir = $this->getOptions()->getPublicDir(); if ($publicDir === null) { @@ -199,9 +192,8 @@ public function clearByGlob($pattern = '**') * Determine the page to save from the request * * @throws Exception\RuntimeException - * @return string */ - protected function detectPageId() + protected function detectPageId(): string { if (! isset($_SERVER['REQUEST_URI'])) { throw new Exception\RuntimeException("Can't auto-detect current page identity"); @@ -212,11 +204,8 @@ protected function detectPageId() /** * Get filename for page id - * - * @param string $pageId - * @return string */ - protected function pageId2Filename($pageId) + protected function pageId2Filename(string $pageId): string { if (str_ends_with($pageId, '/')) { return $this->getOptions()->getIndexFilename(); @@ -227,11 +216,8 @@ protected function pageId2Filename($pageId) /** * Get path for page id - * - * @param string $pageId - * @return string */ - protected function pageId2Path($pageId) + protected function pageId2Path(string $pageId): string { if (str_ends_with($pageId, '/')) { $path = rtrim($pageId, '/'); @@ -252,10 +238,9 @@ protected function pageId2Path($pageId) * * @param string $file File complete path * @param string $data Data to write - * @return void * @throws Exception\RuntimeException */ - protected function putFileContent($file, $data) + protected function putFileContent(string $file, string $data): void { $options = $this->getOptions(); $locking = $options->getFileLocking(); @@ -290,11 +275,9 @@ protected function putFileContent($file, $data) /** * Creates directory if not already done. * - * @param string $pathname - * @return void * @throws Exception\RuntimeException */ - protected function createDirectoryStructure($pathname) + protected function createDirectoryStructure(string $pathname): void { // Directory structure already exists if (file_exists($pathname)) { @@ -376,11 +359,8 @@ protected function createDirectoryStructure($pathname) /** * Returns the generated file name. - * - * @param null|string $pageId - * @return string */ - public function getFilename($pageId = null) + public function getFilename(string|null $pageId = null): string { if ($pageId === null) { $pageId = $this->detectPageId(); diff --git a/src/Pattern/ObjectCache.php b/src/Pattern/ObjectCache.php index d0dfa83a..e24c4311 100644 --- a/src/Pattern/ObjectCache.php +++ b/src/Pattern/ObjectCache.php @@ -3,25 +3,37 @@ namespace Laminas\Cache\Pattern; use Laminas\Cache\Exception; +use Laminas\Cache\Storage\StorageInterface; use Stringable; +use Throwable; use function array_shift; use function array_unshift; +use function assert; use function func_get_args; use function in_array; -use function md5; use function method_exists; use function property_exists; +use function sprintf; use function strtolower; -class ObjectCache extends CallbackCache implements Stringable +class ObjectCache extends AbstractStorageCapablePattern implements Stringable { - /** - * @return ObjectCache - */ - public function setOptions(PatternOptions $options) + private CallbackCache $callbackCache; + + public function __construct(StorageInterface $storage, ?PatternOptions $options = null) + { + parent::__construct($storage, $options); + $this->callbackCache = new CallbackCache($storage, $options); + if ($options !== null) { + $this->setOptions($options); + } + } + + public function setOptions(PatternOptions $options): self { parent::setOptions($options); + $this->callbackCache->setOptions($options); if (! $options->getObject()) { throw new Exception\InvalidArgumentException("Missing option 'object'"); @@ -33,17 +45,18 @@ public function setOptions(PatternOptions $options) /** * Call and cache a class method * - * @param string $method Method name to call + * @param non-empty-string $method Method name to call * @param array $args Method arguments - * @return mixed * @throws Exception\RuntimeException - * @throws \Exception + * @throws Throwable */ - public function call($method, array $args = []) + public function call(string $method, array $args = []): mixed { $options = $this->getOptions(); $object = $options->getObject(); - $method = strtolower($method); + assert($object !== null, 'ObjectCache#setOptions verifies that we always have an object set.'); + + $method = strtolower($method); // handle magic methods switch ($method) { @@ -59,22 +72,22 @@ public function call($method, array $args = []) ) { // no caching if property isn't magic // or caching magic properties is disabled - return; + return null; } // remove cached __get and __isset - $removeKeys = null; + $removeKeys = []; if (method_exists($object, '__get')) { $removeKeys[] = $this->generateKey('__get', [$property]); } if (method_exists($object, '__isset')) { $removeKeys[] = $this->generateKey('__isset', [$property]); } - if ($removeKeys) { + if ($removeKeys !== []) { $storage = $this->getStorage(); $storage->removeItems($removeKeys); } - return; + return null; case '__get': $property = array_shift($args); @@ -89,7 +102,7 @@ public function call($method, array $args = []) } array_unshift($args, $property); - return parent::call([$object, '__get'], $args); + return $this->callbackCache->call([$object, '__get'], $args); case '__isset': $property = array_shift($args); @@ -103,7 +116,7 @@ public function call($method, array $args = []) return isset($object->{$property}); } - return parent::call([$object, '__isset'], [$property]); + return $this->callbackCache->call([$object, '__isset'], [$property]); case '__unset': $property = array_shift($args); @@ -116,22 +129,30 @@ public function call($method, array $args = []) ) { // no caching if property isn't magic // or caching magic properties is disabled - return; + return null; } // remove previous cached __get and __isset calls - $removeKeys = null; + $removeKeys = []; if (method_exists($object, '__get')) { $removeKeys[] = $this->generateKey('__get', [$property]); } if (method_exists($object, '__isset')) { $removeKeys[] = $this->generateKey('__isset', [$property]); } - if ($removeKeys) { + if ($removeKeys !== []) { $storage = $this->getStorage(); $storage->removeItems($removeKeys); } - return; + return null; + } + + if (! method_exists($object, $method)) { + throw new Exception\RuntimeException(sprintf( + '%s only accepts methods which are implemented by %s', + $this::class, + $object::class, + )); } $cache = $options->getCacheByDefault(); @@ -145,52 +166,35 @@ public function call($method, array $args = []) return $object->{$method}(...$args); } - return parent::call([$object, $method], $args); + return $this->callbackCache->call([$object, $method], $args); } /** * Generate a unique key in base of a key representing the callback part * and a key representing the arguments part. * - * @param string $method The method - * @param array $args Callback arguments - * @return string + * @param non-empty-string $methodOrProperty The method or the property + * @param array $args Callback arguments + * @return non-empty-string * @throws Exception\RuntimeException */ - public function generateKey($method, array $args = []) + public function generateKey(string $methodOrProperty, array $args = []): string { - return $this->generateCallbackKey( - [$this->getOptions()->getObject(), $method], - $args - ); - } + $object = $this->getOptions()->getObject(); + assert($object !== null, 'ObjectCache#setOptions verifies that we always have an object set.'); - /** - * Generate a unique key in base of a key representing the callback part - * and a key representing the arguments part. - * - * @param callable $callback A valid callback - * @param array $args Callback arguments - * @return string - * @throws Exception\RuntimeException - */ - protected function generateCallbackKey($callback, array $args = []) - { - $callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1])); - $argumentKey = $this->generateArgumentsKey($args); - return $callbackKey . $argumentKey; + return $this->callbackCache->generateKey([$object, $methodOrProperty], $args); } /** * Class method call handler * - * @param string $method Method name to call + * @param non-empty-string $method Method name to call * @param array $args Method arguments - * @return mixed * @throws Exception\RuntimeException - * @throws \Exception + * @throws Throwable */ - public function __call($method, array $args) + public function __call(string $method, array $args): mixed { return $this->call($method, $args); } @@ -205,14 +209,11 @@ public function __call($method, array $args) * * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members * - * @phpcs:disable Squiz.Commenting.FunctionComment.InvalidReturnVoid - * - * @param string $name - * @return void + * @param non-empty-string $name */ - public function __set($name, mixed $value) + public function __set($name, mixed $value): void { - return $this->call('__set', [$name, $value]); + $this->call('__set', [$name, $value]); } /** @@ -224,10 +225,9 @@ public function __set($name, mixed $value) * * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members * - * @param string $name - * @return mixed + * @param non-empty-string $name */ - public function __get($name) + public function __get(string $name): mixed { return $this->call('__get', [$name]); } @@ -241,10 +241,9 @@ public function __get($name) * * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members * - * @param string $name - * @return bool + * @param non-empty-string $name */ - public function __isset($name) + public function __isset(string $name): bool { return $this->call('__isset', [$name]); } @@ -259,15 +258,11 @@ public function __isset($name) * * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members * - * @phpcs:disable Squiz.Commenting.FunctionComment.InvalidReturnVoid - * - * @param string $name - * - * @return void + * @param non-empty-string $name */ - public function __unset($name) + public function __unset(string $name): void { - return $this->call('__unset', [$name]); + $this->call('__unset', [$name]); } /** @@ -284,10 +279,8 @@ public function __toString(): string * Handle invoke calls * * @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke - * - * @return mixed */ - public function __invoke() + public function __invoke(): mixed { return $this->call('__invoke', func_get_args()); } diff --git a/src/Pattern/OutputCache.php b/src/Pattern/OutputCache.php index 9cc2a46b..b3326d9f 100644 --- a/src/Pattern/OutputCache.php +++ b/src/Pattern/OutputCache.php @@ -13,25 +13,17 @@ class OutputCache extends AbstractStorageCapablePattern { /** * The key stack - * - * @var array */ - protected $keyStack = []; + protected array $keyStack = []; /** * if there is a cached item with the given key display it's data and return true * else start buffering output until end() is called or the script ends. * - * @param string $key Key - * @throws Exception\MissingKeyException If key is missing. - * @return bool + * @param non-empty-string $key Key */ - public function start($key) + public function start(string $key): bool { - if (($key = (string) $key) === '') { - throw new Exception\MissingKeyException('Missing key to read/write output from cache'); - } - $success = null; $storage = $this->getStorage(); $data = $storage->getItem($key, $success); @@ -54,7 +46,7 @@ public function start($key) * @throws Exception\RuntimeException If output cache not started or buffering not active. * @return bool TRUE on success, FALSE on failure writing to cache */ - public function end() + public function end(): bool { $key = array_pop($this->keyStack); if ($key === null) { diff --git a/src/Pattern/PatternInterface.php b/src/Pattern/PatternInterface.php index 37e6f323..8328c18e 100644 --- a/src/Pattern/PatternInterface.php +++ b/src/Pattern/PatternInterface.php @@ -6,8 +6,6 @@ interface PatternInterface { /** * Get all pattern options - * - * @return PatternOptions */ - public function getOptions(); + public function getOptions(): PatternOptions; } diff --git a/src/Pattern/PatternOptions.php b/src/Pattern/PatternOptions.php index d4349d11..41e61f94 100644 --- a/src/Pattern/PatternOptions.php +++ b/src/Pattern/PatternOptions.php @@ -4,7 +4,7 @@ use Laminas\Cache\Exception; use Laminas\Stdlib\AbstractOptions; -use Traversable; +use LogicException; use function array_intersect; use function array_map; @@ -30,115 +30,86 @@ class PatternOptions extends AbstractOptions /** * Used by: * - ObjectCache - * - * @var bool */ - protected $cacheByDefault = true; + protected bool $cacheByDefault = true; /** * Used by: * - CallbackCache * - ObjectCache - * - * @var bool */ - protected $cacheOutput = true; + protected bool $cacheOutput = true; /** * Used by: * - CaptureCache - * - * @var false|int */ - protected $umask = false; + protected false|int $umask = false; /** * Used by: * - CaptureCache - * - * @var false|int */ - protected $dirPermission = 0700; + protected false|int $dirPermission = 0700; /** * Used by: * - CaptureCache - * - * @var false|int */ - protected $filePermission = 0600; + protected false|int $filePermission = 0600; /** * Used by: * - CaptureCache - * - * @var bool */ - protected $fileLocking = true; + protected bool $fileLocking = true; /** * Used by: * - CaptureCache - * - * @var string */ - protected $indexFilename = 'index.html'; + protected string $indexFilename = 'index.html'; /** * Used by: * - ObjectCache - * - * @var null|object */ - protected $object; + protected ?object $object = null; /** * Used by: * - ObjectCache - * - * @var bool */ - protected $objectCacheMagicProperties = false; + protected bool $objectCacheMagicProperties = false; /** * Used by: * - ObjectCache - * - * @var array */ - protected $objectCacheMethods = []; + protected array $objectCacheMethods = []; /** * Used by: * - ObjectCache - * - * @var null|string */ - protected $objectKey; + protected ?string $objectKey = null; /** * Used by: * - ObjectCache - * - * @var array */ - protected $objectNonCacheMethods = ['__tostring']; + protected array $objectNonCacheMethods = ['__tostring']; /** * Used by: * - CaptureCache - * - * @var null|string */ - protected $publicDir; + protected ?string $publicDir = null; /** - * Constructor - * - * @param array|Traversable|null $options * @throws Exception\InvalidArgumentException */ - public function __construct($options = null) + public function __construct(iterable|null $options = null) { // disable file/directory permissions by default on windows systems if (stripos(PHP_OS, 'WIN') === 0) { @@ -154,11 +125,8 @@ public function __construct($options = null) * * Used by: * - ObjectCache - * - * @param bool $cacheByDefault - * @return PatternOptions Provides a fluent interface */ - public function setCacheByDefault($cacheByDefault) + public function setCacheByDefault(bool $cacheByDefault): self { $this->cacheByDefault = $cacheByDefault; return $this; @@ -169,10 +137,8 @@ public function setCacheByDefault($cacheByDefault) * * Used by: * - ObjectCache - * - * @return bool */ - public function getCacheByDefault() + public function getCacheByDefault(): bool { return $this->cacheByDefault; } @@ -183,13 +149,10 @@ public function getCacheByDefault() * Used by: * - CallbackCache * - ObjectCache - * - * @param bool $cacheOutput - * @return PatternOptions Provides a fluent interface */ - public function setCacheOutput($cacheOutput) + public function setCacheOutput(bool $cacheOutput): self { - $this->cacheOutput = (bool) $cacheOutput; + $this->cacheOutput = $cacheOutput; return $this; } @@ -199,10 +162,8 @@ public function setCacheOutput($cacheOutput) * Used by: * - CallbackCache * - ObjectCache - * - * @return bool */ - public function getCacheOutput() + public function getCacheOutput(): bool { return $this->cacheOutput; } @@ -210,11 +171,9 @@ public function getCacheOutput() /** * Set directory permission * - * @param false|int|string|float $dirPermission * @throws Exception\InvalidArgumentException - * @return PatternOptions Provides a fluent interface */ - public function setDirPermission($dirPermission) + public function setDirPermission(false|float|int|string $dirPermission): self { if ($dirPermission !== false) { if (is_string($dirPermission)) { @@ -241,10 +200,8 @@ public function setDirPermission($dirPermission) /** * Gets directory permission - * - * @return false|int */ - public function getDirPermission() + public function getDirPermission(): int|false { return $this->dirPermission; } @@ -255,11 +212,9 @@ public function getDirPermission() * Used by: * - CaptureCache * - * @param false|int|string|float $umask * @throws Exception\InvalidArgumentException - * @return PatternOptions Provides a fluent interface */ - public function setUmask($umask) + public function setUmask(false|float|int|string $umask): self { if ($umask !== false) { if (is_string($umask)) { @@ -288,10 +243,8 @@ public function setUmask($umask) * * Used by: * - CaptureCache - * - * @return false|int */ - public function getUmask() + public function getUmask(): int|false { return $this->umask; } @@ -301,13 +254,10 @@ public function getUmask() * * Used by: * - CaptureCache - * - * @param bool $fileLocking - * @return PatternOptions Provides a fluent interface */ - public function setFileLocking($fileLocking) + public function setFileLocking(bool $fileLocking): self { - $this->fileLocking = (bool) $fileLocking; + $this->fileLocking = $fileLocking; return $this; } @@ -316,10 +266,8 @@ public function setFileLocking($fileLocking) * * Used by: * - CaptureCache - * - * @return bool */ - public function getFileLocking() + public function getFileLocking(): bool { return $this->fileLocking; } @@ -327,11 +275,9 @@ public function getFileLocking() /** * Set file permission * - * @param false|int|string|float $filePermission * @throws Exception\InvalidArgumentException - * @return PatternOptions Provides a fluent interface */ - public function setFilePermission($filePermission) + public function setFilePermission(false|float|int|string $filePermission): self { if ($filePermission !== false) { if (is_string($filePermission)) { @@ -364,32 +310,25 @@ public function setFilePermission($filePermission) /** * Gets file permission - * - * @return false|int */ - public function getFilePermission() + public function getFilePermission(): false|int { return $this->filePermission; } /** * Set value for index filename - * - * @param string $indexFilename - * @return PatternOptions Provides a fluent interface */ - public function setIndexFilename($indexFilename) + public function setIndexFilename(string $indexFilename): self { - $this->indexFilename = (string) $indexFilename; + $this->indexFilename = $indexFilename; return $this; } /** * Get value for index filename - * - * @return string */ - public function getIndexFilename() + public function getIndexFilename(): string { return $this->indexFilename; } @@ -398,9 +337,8 @@ public function getIndexFilename() * Set object to cache * * @throws Exception\InvalidArgumentException - * @return PatternOptions Provides a fluent interface */ - public function setObject(mixed $object) + public function setObject(mixed $object): self { if (! is_object($object)) { throw new Exception\InvalidArgumentException( @@ -413,10 +351,8 @@ public function setObject(mixed $object) /** * Get object to cache - * - * @return null|object */ - public function getObject() + public function getObject(): null|object { return $this->object; } @@ -426,13 +362,10 @@ public function getObject() * * Used by: * - ObjectCache - * - * @param bool $objectCacheMagicProperties - * @return PatternOptions Provides a fluent interface */ - public function setObjectCacheMagicProperties($objectCacheMagicProperties) + public function setObjectCacheMagicProperties(bool $objectCacheMagicProperties): self { - $this->objectCacheMagicProperties = (bool) $objectCacheMagicProperties; + $this->objectCacheMagicProperties = $objectCacheMagicProperties; return $this; } @@ -441,10 +374,8 @@ public function setObjectCacheMagicProperties($objectCacheMagicProperties) * * Used by: * - ObjectCache - * - * @return bool */ - public function getObjectCacheMagicProperties() + public function getObjectCacheMagicProperties(): bool { return $this->objectCacheMagicProperties; } @@ -452,10 +383,9 @@ public function getObjectCacheMagicProperties() /** * Set list of object methods for which to cache return values * - * @return PatternOptions Provides a fluent interface * @throws Exception\InvalidArgumentException */ - public function setObjectCacheMethods(array $objectCacheMethods) + public function setObjectCacheMethods(array $objectCacheMethods): self { $this->objectCacheMethods = $this->normalizeObjectMethods($objectCacheMethods); return $this; @@ -466,7 +396,7 @@ public function setObjectCacheMethods(array $objectCacheMethods) * * @return array */ - public function getObjectCacheMethods() + public function getObjectCacheMethods(): array { return $this->objectCacheMethods; } @@ -480,15 +410,10 @@ public function getObjectCacheMethods() * - ObjectCache * * @param null|string $objectKey The object key or NULL to use the objects class name - * @return PatternOptions Provides a fluent interface */ - public function setObjectKey($objectKey) + public function setObjectKey(null|string $objectKey): self { - if ($objectKey !== null) { - $this->objectKey = (string) $objectKey; - } else { - $this->objectKey = null; - } + $this->objectKey = $objectKey; return $this; } @@ -497,24 +422,28 @@ public function setObjectKey($objectKey) * * Used by: * - ObjectCache - * - * @return string */ - public function getObjectKey() + public function getObjectKey(): string { - if ($this->objectKey === null) { - return $this->getObject()::class; + if ($this->objectKey !== null) { + return $this->objectKey; } - return $this->objectKey; + + $object = $this->getObject(); + + if ($object === null) { + throw new LogicException('Missing `object` to detect object key.'); + } + + return $object::class; } /** * Set list of object methods for which NOT to cache return values * - * @return PatternOptions Provides a fluent interface * @throws Exception\InvalidArgumentException */ - public function setObjectNonCacheMethods(array $objectNonCacheMethods) + public function setObjectNonCacheMethods(array $objectNonCacheMethods): self { $this->objectNonCacheMethods = $this->normalizeObjectMethods($objectNonCacheMethods); return $this; @@ -525,7 +454,7 @@ public function setObjectNonCacheMethods(array $objectNonCacheMethods) * * @return array */ - public function getObjectNonCacheMethods() + public function getObjectNonCacheMethods(): array { return $this->objectNonCacheMethods; } @@ -536,14 +465,10 @@ public function getObjectNonCacheMethods() * Used by: * - CaptureCache * - * @param string $publicDir * @throws Exception\InvalidArgumentException - * @return PatternOptions Provides a fluent interface */ - public function setPublicDir($publicDir) + public function setPublicDir(string $publicDir): self { - $publicDir = (string) $publicDir; - if (! is_dir($publicDir)) { throw new Exception\InvalidArgumentException( "Public directory '{$publicDir}' not found or not a directory" @@ -567,10 +492,8 @@ public function setPublicDir($publicDir) * * Used by: * - CaptureCache - * - * @return null|string */ - public function getPublicDir() + public function getPublicDir(): null|string { return $this->publicDir; } @@ -581,7 +504,7 @@ public function getPublicDir() * * @return array */ - protected function recursiveStrtolower(array $array) + protected function recursiveStrtolower(array $array): array { return array_values(array_unique(array_map('strtolower', $array))); } @@ -596,7 +519,7 @@ protected function recursiveStrtolower(array $array) * @return array * @throws Exception\InvalidArgumentException */ - protected function normalizeObjectMethods(array $methods) + protected function normalizeObjectMethods(array $methods): array { $methods = $this->recursiveStrtolower($methods); $intersect = array_intersect(['__set', '__get', '__unset', '__isset'], $methods); diff --git a/src/Psr/CacheItemPool/CacheItemPoolDecorator.php b/src/Psr/CacheItemPool/CacheItemPoolDecorator.php index 91ab2e0b..de48d1ca 100644 --- a/src/Psr/CacheItemPool/CacheItemPoolDecorator.php +++ b/src/Psr/CacheItemPool/CacheItemPoolDecorator.php @@ -13,6 +13,7 @@ use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; use Psr\Clock\ClockInterface; +use Webmozart\Assert\Assert; use function array_diff; use function array_diff_key; @@ -21,12 +22,10 @@ use function array_merge; use function array_unique; use function array_values; -use function assert; use function current; use function date_default_timezone_get; use function gettype; use function in_array; -use function is_array; use function is_string; use function preg_match; use function sprintf; @@ -91,7 +90,7 @@ public function getItem(string $key): CacheItemInterface // ignore } - return new CacheItem($key, $value, $isHit ?? false, $this->clock); + return new CacheItem($key, $value, $isHit, $this->clock); } return clone $this->deferred[$key]; @@ -102,6 +101,11 @@ public function getItem(string $key): CacheItemInterface */ public function getItems(array $keys = []): array { + if ($keys === []) { + return []; + } + + $keys = array_values($keys); $this->validateKeys($keys); $items = []; @@ -113,9 +117,9 @@ public function getItems(array $keys = []): array } } - $keys = array_diff($keys, array_keys($items)); + $keys = array_values(array_diff($keys, array_keys($items))); - if ($keys) { + if ($keys !== []) { try { $cacheItems = $this->storage->getItems($keys); } catch (Exception\InvalidArgumentException $e) { @@ -125,7 +129,6 @@ public function getItems(array $keys = []): array } foreach ($cacheItems as $key => $value) { - assert(is_string($key)); $items[$key] = new CacheItem($key, $value, true, $this->clock); } @@ -197,6 +200,11 @@ public function deleteItem(string $key): bool */ public function deleteItems(array $keys): bool { + if ($keys === []) { + return true; + } + + $keys = array_values($keys); $this->validateKeys($keys); // remove deferred items first @@ -210,11 +218,6 @@ public function deleteItems(array $keys): bool return false; } - // BC compatibility can be removed in 3.0 - if (! is_array($result)) { - return $result !== null; - } - if ($result === []) { return true; } @@ -342,6 +345,7 @@ private function hasDeferredItem(string $key): bool * Throws exception if given key is invalid * * @throws InvalidArgumentException + * @psalm-assert non-empty-string $key */ private function validateKey(mixed $key): void { @@ -352,6 +356,10 @@ private function validateKey(mixed $key): void )); } + if ($key === '') { + throw new InvalidArgumentException('Provided key must not be an empty string.'); + } + if ($this->exceedsMaximumKeyLength($key)) { throw InvalidArgumentException::maximumKeyLengthExceeded($key, $this->maximumKeyLength); } @@ -360,7 +368,8 @@ private function validateKey(mixed $key): void /** * Throws exception if any of given keys is invalid * - * @param array $keys + * @param non-empty-list $keys + * @psalm-assert non-empty-list $keys * @throws InvalidArgumentException */ private function validateKeys(array $keys): void @@ -378,7 +387,9 @@ private function saveMultipleItems(array $items, ?int $itemTtl): array { $keyItemPair = []; foreach ($items as $item) { - $keyItemPair[$item->getKey()] = $item; + $key = $item->getKey(); + Assert::stringNotEmpty($key); + $keyItemPair[$key] = $item; } // delete expired item @@ -396,7 +407,8 @@ private function saveMultipleItems(array $items, ?int $itemTtl): array $keyValuePair = []; foreach ($items as $item) { - $key = $item->getKey(); + $key = $item->getKey(); + Assert::stringNotEmpty($key); $keyValuePair[$key] = $item->get(); } diff --git a/src/Psr/SimpleCache/SimpleCacheDecorator.php b/src/Psr/SimpleCache/SimpleCacheDecorator.php index ba56db36..1f206edb 100644 --- a/src/Psr/SimpleCache/SimpleCacheDecorator.php +++ b/src/Psr/SimpleCache/SimpleCacheDecorator.php @@ -19,6 +19,7 @@ use function array_keys; use function array_map; +use function assert; use function get_debug_type; use function gettype; use function is_array; @@ -77,7 +78,7 @@ public function __construct( */ public function get(string $key, mixed $default = null): mixed { - $this->validateKey($key); + $this->assertValidKey($key); $this->success = null; try { @@ -95,7 +96,7 @@ public function get(string $key, mixed $default = null): mixed */ public function set(string $key, mixed $value, int|DateInterval|null $ttl = null): bool { - $this->validateKey($key); + $this->assertValidKey($key); $ttl = $this->convertTtlToInteger($ttl); // PSR-16 states that 0 or negative TTL values should result in cache @@ -133,10 +134,11 @@ public function set(string $key, mixed $value, int|DateInterval|null $ttl = null */ public function delete(string $key): bool { - $this->validateKey($key); + $this->assertValidKey($key); try { - return null !== $this->storage->removeItem($key); + $this->storage->removeItem($key); + return true; } catch (Throwable) { return false; } @@ -173,6 +175,9 @@ public function getMultiple(iterable $keys, mixed $default = null): array } $keys = $this->convertIterableKeysToList($keys); + if ($keys === []) { + return []; + } try { $results = $this->storage->getItems($keys); @@ -203,8 +208,12 @@ public function setMultiple(iterable $values, int|DateInterval|null $ttl = null) } $values = $this->convertIterableToKeyValueMap($values); - $keys = array_keys($values); - $ttl = $this->convertTtlToInteger($ttl); + if ($values === []) { + return true; + } + + $keys = array_keys($values); + $ttl = $this->convertTtlToInteger($ttl); // PSR-16 states that 0 or negative TTL values should result in cache // invalidation for the items. @@ -251,15 +260,8 @@ public function setMultiple(iterable $values, int|DateInterval|null $ttl = null) */ public function deleteMultiple(iterable $keys): bool { - if (! is_array($keys) && ! is_iterable($keys)) { - throw new SimpleCacheInvalidArgumentException(sprintf( - 'Invalid value provided to %s; must be iterable', - __METHOD__ - )); - } - $keys = $this->convertIterableKeysToList($keys); - if (empty($keys)) { + if ($keys === []) { return true; } @@ -287,7 +289,7 @@ public function deleteMultiple(iterable $keys): bool */ public function has(string $key): bool { - $this->validateKey($key); + $this->assertValidKey($key); try { return $this->storage->hasItem($key); @@ -310,8 +312,11 @@ private static function translateThrowable(Throwable $throwable): PsrCacheExcept /** * @throws SimpleCacheInvalidArgumentException If key is invalid. + * @template T of array-key + * @param T $key + * @psalm-assert (T is string ? non-empty-string : 0) $key */ - private function validateKey(string|int $key): void + private function assertValidKey(string|int $key): void { if ('' === $key) { throw new SimpleCacheInvalidArgumentException( @@ -380,7 +385,7 @@ private function convertTtlToInteger(int|DateInterval|null $ttl): int|null } /** - * @psalm-return list + * @psalm-return list * @throws SimpleCacheInvalidArgumentException For invalid $iterable values. */ private function convertIterableKeysToList(iterable $keys): array @@ -394,7 +399,9 @@ private function convertIterableKeysToList(iterable $keys): array )); } - $this->validateKey($key); + $this->assertValidKey($key); + $key = (string) $key; + assert($key !== ''); $array[] = $key; } @@ -402,7 +409,7 @@ private function convertIterableKeysToList(iterable $keys): array } /** - * @return array + * @return array<0|non-empty-string,mixed> */ private function convertIterableToKeyValueMap(iterable $values): array { @@ -415,11 +422,13 @@ private function convertIterableToKeyValueMap(iterable $values): array )); } - $this->validateKey($key); + $this->assertValidKey($key); $keyValueMap[$key] = $value; } + // phpcs:disable SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable + /** @var array<0|non-empty-string,mixed> $keyValueMap */ return $keyValueMap; } } diff --git a/src/Service/StorageCacheAbstractServiceFactory.php b/src/Service/StorageCacheAbstractServiceFactory.php index a1b8e24a..1369c5f6 100644 --- a/src/Service/StorageCacheAbstractServiceFactory.php +++ b/src/Service/StorageCacheAbstractServiceFactory.php @@ -18,20 +18,19 @@ class StorageCacheAbstractServiceFactory implements AbstractFactoryInterface private const RESERVED_CONFIG_SERVICE_NAME = 'config'; /** @var array|null */ - protected $config; + protected ?array $config = null; /** * Configuration key for cache objects * - * @var string + * @var non-empty-string */ - protected $configKey = self::CACHES_CONFIGURATION_KEY; + protected string $configKey = self::CACHES_CONFIGURATION_KEY; /** * @param string $requestedName - * @return boolean */ - public function canCreate(ContainerInterface $container, $requestedName) + public function canCreate(ContainerInterface $container, $requestedName): bool { if ($requestedName === self::RESERVED_CONFIG_SERVICE_NAME) { return false; @@ -49,9 +48,8 @@ public function canCreate(ContainerInterface $container, $requestedName) * * @param string $requestedName * @param null|array $options - * @return object */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null) + public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null): object { $config = $this->getConfig($container); $factory = $container->get(StorageAdapterFactoryInterface::class); @@ -65,9 +63,9 @@ public function __invoke(ContainerInterface $container, $requestedName, ?array $ /** * Retrieve cache configuration, if any * - * @return array + * @return array */ - protected function getConfig(ContainerInterface $container) + protected function getConfig(ContainerInterface $container): array { if ($this->config !== null) { return $this->config; diff --git a/src/Storage/AbstractMetadataCapableAdapter.php b/src/Storage/AbstractMetadataCapableAdapter.php index 3e68ccca..8770ef36 100644 --- a/src/Storage/AbstractMetadataCapableAdapter.php +++ b/src/Storage/AbstractMetadataCapableAdapter.php @@ -11,13 +11,16 @@ use Exception; use Laminas\Cache\Exception\ExceptionInterface; use Laminas\Cache\Storage\Adapter\AbstractAdapter; +use Laminas\Cache\Storage\Adapter\AdapterOptions; use Webmozart\Assert\Assert; use function is_array; use function is_object; /** + * @template TOptions of AdapterOptions * @template TMetadata of object + * @template-extends AbstractAdapter * @template-implements MetadataCapableInterface */ abstract class AbstractMetadataCapableAdapter extends AbstractAdapter implements MetadataCapableInterface @@ -28,18 +31,18 @@ public function getMetadata(string $key): ?object return null; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, + 'key' => $key, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); - Assert::string($args['key']); - + $key = $args['key']; + $this->assertValidKey($key); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalGetMetadata($args['key']); + : $this->internalGetMetadata($key); $result = $this->triggerPost(__FUNCTION__, $args, $result); if ($result !== null && ! is_object($result)) { @@ -55,7 +58,7 @@ public function getMetadata(string $key): ?object return $result; } catch (Exception $exception) { $result = null; - $result = $this->triggerException(__FUNCTION__, $args, $result, $exception); + $result = $this->triggerThrowable(__FUNCTION__, $args, $result, $exception); Assert::nullOrObject($result); /** @@ -82,19 +85,18 @@ public function getMetadatas(array $keys): array return []; } - $this->normalizeKeys($keys); + $keys = $this->normalizeKeys($keys); $args = new ArrayObject([ - 'keys' => &$keys, + 'keys' => $keys, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); - Assert::isArray($args['keys']); - Assert::allString($args['keys']); + $keys = $this->normalizeKeys($args['keys']); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalGetMetadatas($args['keys']); + : $this->internalGetMetadatas($keys); if (! is_array($result)) { return []; @@ -113,7 +115,7 @@ public function getMetadatas(array $keys): array return $result; } catch (Exception $exception) { $result = []; - $result = $this->triggerException(__FUNCTION__, $args, $result, $exception); + $result = $this->triggerThrowable(__FUNCTION__, $args, $result, $exception); Assert::isArray($result); Assert::allObject($result); diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 88c8e75c..d3b41da2 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -3,6 +3,7 @@ namespace Laminas\Cache\Storage\Adapter; use ArrayObject; +use InvalidArgumentException; use Laminas\Cache\Exception; use Laminas\Cache\Storage\Capabilities; use Laminas\Cache\Storage\Event; @@ -16,67 +17,62 @@ use Laminas\EventManager\ResponseCollection; use SplObjectStorage; use stdClass; -use Traversable; +use Throwable; +use Webmozart\Assert\Assert; use function array_keys; use function array_unique; use function array_values; -use function array_walk; use function func_num_args; +use function is_array; +use function is_string; use function preg_match; use function sprintf; +/** + * @template TOptions of AdapterOptions + */ abstract class AbstractAdapter implements StorageInterface, PluginAwareInterface { /** * The used EventManager if any - * - * @var null|EventManagerInterface */ - protected $events; + protected ?EventManagerInterface $events = null; /** * Event handles of this adapter - * - * @var array */ - protected $eventHandles = []; + protected array $eventHandles = []; /** * The plugin registry * * @var SplObjectStorage|null Registered plugins */ - protected $pluginRegistry; + protected ?SplObjectStorage $pluginRegistry = null; /** * Capabilities of this adapter - * - * @var null|Capabilities */ - protected $capabilities; + protected ?Capabilities $capabilities = null; /** * Marker to change capabilities - * - * @var null|object */ - protected $capabilityMarker; + protected ?object $capabilityMarker = null; /** * options * - * @var mixed + * @var TOptions|null */ - protected $options; + protected ?AdapterOptions $options = null; /** - * Constructor - * - * @param null|array|Traversable|AdapterOptions $options + * @param iterable|TOptions|null $options * @throws Exception\ExceptionInterface */ - public function __construct($options = null) + public function __construct(iterable|AdapterOptions|null $options = null) { if ($options !== null) { $this->setOptions($options); @@ -88,8 +84,6 @@ public function __construct($options = null) * * detach all registered plugins to free * event handles of event manager - * - * @return void */ public function __destruct() { @@ -112,10 +106,9 @@ public function __destruct() * * @see getOptions() * - * @param array|Traversable|AdapterOptions $options - * @return AbstractAdapter Provides a fluent interface + * @param iterable|TOptions $options */ - public function setOptions($options) + public function setOptions(iterable|AdapterOptions $options): self { if ($this->options !== $options) { if (! $options instanceof AdapterOptions) { @@ -132,6 +125,7 @@ public function setOptions($options) $this->getEventManager()->triggerEvent($event); } + return $this; } @@ -140,13 +134,16 @@ public function setOptions($options) * * @see setOptions() * - * @return AdapterOptions + * @return TOptions */ - public function getOptions() + public function getOptions(): AdapterOptions { - if (! $this->options) { + if ($this->options === null) { $this->setOptions(new AdapterOptions()); } + + Assert::notNull($this->options); + return $this->options; } @@ -157,16 +154,13 @@ public function getOptions() * * @see setWritable() * @see setReadable() - * - * @param bool $flag - * @return AbstractAdapter Provides a fluent interface */ - public function setCaching($flag) + public function setCaching(bool $flag): self { - $flag = (bool) $flag; $options = $this->getOptions(); $options->setWritable($flag); $options->setReadable($flag); + return $this; } @@ -177,12 +171,11 @@ public function setCaching($flag) * * @see getWritable() * @see getReadable() - * - * @return bool */ - public function getCaching() + public function getCaching(): bool { $options = $this->getOptions(); + return $options->getWritable() && $options->getReadable(); } @@ -190,36 +183,31 @@ public function getCaching() /** * Get the event manager - * - * @return EventManagerInterface */ - public function getEventManager() + public function getEventManager(): EventManagerInterface { if ($this->events === null) { $this->events = new EventManager(); $this->events->setIdentifiers([self::class, static::class]); } + return $this->events; } /** * Trigger a pre event and return the event response collection * - * @param string $eventName * @return ResponseCollection All handler return values */ - protected function triggerPre($eventName, ArrayObject $args) + protected function triggerPre(string $eventName, ArrayObject $args): ResponseCollection { return $this->getEventManager()->triggerEvent(new Event($eventName . '.pre', $this, $args)); } /** * Triggers the PostEvent and return the result value. - * - * @param string $eventName - * @return mixed */ - protected function triggerPost($eventName, ArrayObject $args, mixed &$result) + protected function triggerPost(string $eventName, ArrayObject $args, mixed $result): mixed { $postEvent = new PostEvent($eventName . '.post', $this, $args, $result); $eventRs = $this->getEventManager()->triggerEvent($postEvent); @@ -229,23 +217,17 @@ protected function triggerPost($eventName, ArrayObject $args, mixed &$result) : $postEvent->getResult(); } - /** - * Trigger an exception event - * - * If the ExceptionEvent has the flag "throwException" enabled throw the - * exception after trigger else return the result. - * - * @param string $eventName - * @throws Exception\ExceptionInterface - * @return mixed - */ - protected function triggerException($eventName, ArrayObject $args, mixed &$result, \Exception $exception) - { - $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception); + protected function triggerThrowable( + string $eventName, + ArrayObject $args, + mixed $result, + Throwable $throwable + ): mixed { + $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $throwable); $eventRs = $this->getEventManager()->triggerEvent($exceptionEvent); if ($exceptionEvent->getThrowException()) { - throw $exceptionEvent->getException(); + throw $exceptionEvent->getThrowable(); } return $eventRs->stopped() @@ -256,16 +238,17 @@ protected function triggerException($eventName, ArrayObject $args, mixed &$resul /** * {@inheritdoc} */ - public function hasPlugin(Plugin\PluginInterface $plugin) + public function hasPlugin(Plugin\PluginInterface $plugin): bool { $registry = $this->getPluginRegistry(); + return $registry->contains($plugin); } /** * {@inheritdoc} */ - public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1) + public function addPlugin(Plugin\PluginInterface $plugin, int $priority = 1): StorageInterface&PluginAwareInterface { $registry = $this->getPluginRegistry(); if ($registry->contains($plugin)) { @@ -284,24 +267,26 @@ public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1) /** * {@inheritdoc} */ - public function removePlugin(Plugin\PluginInterface $plugin) + public function removePlugin(Plugin\PluginInterface $plugin): self { $registry = $this->getPluginRegistry(); if ($registry->contains($plugin)) { $plugin->detach($this->getEventManager()); $registry->detach($plugin); } + return $this; } /** * {@inheritdoc} */ - public function getPluginRegistry() + public function getPluginRegistry(): SplObjectStorage { if (! $this->pluginRegistry instanceof SplObjectStorage) { $this->pluginRegistry = new SplObjectStorage(); } + return $this->pluginRegistry; } @@ -310,109 +295,132 @@ public function getPluginRegistry() /** * Get an item. * - * @param string $key - * @param bool $success - * @param mixed $casToken + * @param-out bool $success * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface * @triggers getItem.pre(PreEvent) * @triggers getItem.post(PostEvent) * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, &$success = null, &$casToken = null) + public function getItem(string $key, ?bool &$success = null, mixed &$casToken = null): mixed { if (! $this->getOptions()->getReadable()) { $success = false; - return; + + return null; } - $this->normalizeKey($key); + $this->assertValidKey($key); $argn = func_num_args(); $args = [ - 'key' => &$key, + 'key' => $key, ]; if ($argn > 1) { - $args['success'] = &$success; + $args['success'] = $success; } if ($argn > 2) { - $args['casToken'] = &$casToken; + $args['casToken'] = $casToken; } $args = new ArrayObject($args); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $key = $args['key']; + $this->assertValidKey($key); if ($eventRs->stopped()) { $result = $eventRs->last(); } elseif ($args->offsetExists('success') && $args->offsetExists('casToken')) { - $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']); + $success = $args['success']; + Assert::nullOrBoolean($success); + $casToken = $args['casToken']; + $result = $this->internalGetItem($key, $success, $casToken); } elseif ($args->offsetExists('success')) { - $result = $this->internalGetItem($args['key'], $args['success']); + $success = $args['success']; + Assert::nullOrBoolean($success); + $result = $this->internalGetItem($key, $success); } else { - $result = $this->internalGetItem($args['key']); + $result = $this->internalGetItem($key); } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { $result = null; $success = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + + $result = $this->triggerThrowable(__FUNCTION__, $args, null, $throwable); } + + return $result; } /** * Internal method to get an item. * - * @param string $normalizedKey - * @param bool $success + * @param non-empty-string $normalizedKey + * @param-out bool $success * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - abstract protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$casToken = null); + abstract protected function internalGetItem( + string $normalizedKey, + ?bool &$success = null, + mixed &$casToken = null + ): mixed; /** * Get multiple items. * - * @param array $keys - * @return array Associative array of keys and values + * @param non-empty-list $keys + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface * @triggers getItems.pre(PreEvent) * @triggers getItems.post(PostEvent) * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys) + public function getItems(array $keys): array { if (! $this->getOptions()->getReadable()) { return []; } - $this->normalizeKeys($keys); + $keys = $this->normalizeKeys($keys); $args = new ArrayObject([ - 'keys' => &$keys, + 'keys' => $keys, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $keys = $args['keys']; + $keys = $this->normalizeKeys($keys); + $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalGetItems($args['keys']); + : $this->internalGetItems($keys); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = []; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, [], $throwable); } + + Assert::isMap($result); + Assert::allStringNotEmpty(array_keys($result)); + + // phpcs:disable SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable + /** @var array $result */ + return $result; } /** * Internal method to get multiple items. * - * @return array Associative array of keys and values + * @param non-empty-list $normalizedKeys + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array &$normalizedKeys) + protected function internalGetItems(array $normalizedKeys): array { $success = null; $result = []; @@ -429,22 +437,20 @@ protected function internalGetItems(array &$normalizedKeys) /** * Test if an item exists. * - * @param string $key - * @return bool * @throws Exception\ExceptionInterface * @triggers hasItem.pre(PreEvent) * @triggers hasItem.post(PostEvent) * @triggers hasItem.exception(ExceptionEvent) */ - public function hasItem($key) + public function hasItem(string $key): bool { if (! $this->getOptions()->getReadable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, + 'key' => $key, ]); try { @@ -454,69 +460,76 @@ public function hasItem($key) ? $eventRs->last() : $this->internalHasItem($args['key']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + + Assert::boolean($result); + return $result; } /** * Internal method to test if an item exists. * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - protected function internalHasItem(&$normalizedKey) + protected function internalHasItem(string $normalizedKey): bool { $success = null; $this->internalGetItem($normalizedKey, $success); + return $success; } /** * Test multiple items. * - * @param array $keys - * @return array Array of found keys + * @param non-empty-list $keys + * @return list Array of found keys * @throws Exception\ExceptionInterface * @triggers hasItems.pre(PreEvent) * @triggers hasItems.post(PostEvent) * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys) + public function hasItems(array $keys): array { if (! $this->getOptions()->getReadable()) { return []; } - $this->normalizeKeys($keys); + $keys = $this->normalizeKeys($keys); $args = new ArrayObject([ - 'keys' => &$keys, + 'keys' => $keys, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); - - $result = $eventRs->stopped() + $keys = $this->normalizeKeys($args['keys']); + $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalHasItems($args['keys']); + : $this->internalHasItems($keys); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = []; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, [], $throwable); } + + Assert::isList($result); + Assert::allStringNotEmpty($result); + + return $result; } /** * Internal method to test multiple items. * - * @return array Array of found keys + * @param non-empty-list $normalizedKeys + * @return list Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array &$normalizedKeys) + protected function internalHasItems(array $normalizedKeys): array { $result = []; foreach ($normalizedKeys as $normalizedKey) { @@ -524,6 +537,7 @@ protected function internalHasItems(array &$normalizedKeys) $result[] = $normalizedKey; } } + return $result; } @@ -532,24 +546,21 @@ protected function internalHasItems(array &$normalizedKeys) /** * Store an item. * - * @param string $key - * @param mixed $value - * @return bool * @throws Exception\ExceptionInterface * @triggers setItem.pre(PreEvent) * @triggers setItem.post(PostEvent) * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value) + public function setItem(string $key, mixed $value): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, - 'value' => &$value, + 'key' => $key, + 'value' => $value, ]); try { @@ -559,64 +570,71 @@ public function setItem($key, $value) ? $eventRs->last() : $this->internalSetItem($args['key'], $args['value']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + + Assert::boolean($result); + return $result; } /** * Internal method to store an item. * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - abstract protected function internalSetItem(&$normalizedKey, mixed &$value); + abstract protected function internalSetItem(string $normalizedKey, mixed $value): bool; /** * Store multiple items. * - * @param array $keyValuePairs - * @return array Array of not stored keys + * @param array $keyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface * @triggers setItems.pre(PreEvent) * @triggers setItems.post(PostEvent) * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs) + public function setItems(array $keyValuePairs): array { if (! $this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } - $this->normalizeKeyValuePairs($keyValuePairs); + $this->assertValidKeyValuePairs($keyValuePairs); $args = new ArrayObject([ - 'keyValuePairs' => &$keyValuePairs, + 'keyValuePairs' => $keyValuePairs, ]); try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); + $eventRs = $this->triggerPre(__FUNCTION__, $args); + $keyValuePairs = $args['keyValuePairs']; + $this->assertValidKeyValuePairs($keyValuePairs); $result = $eventRs->stopped() ? $eventRs->last() : $this->internalSetItems($args['keyValuePairs']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = array_keys($keyValuePairs); - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, array_keys($keyValuePairs), $throwable); } + + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; } /** * Internal method to store multiple items. * - * @return array Array of not stored keys + * @param non-empty-array $normalizedKeyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array &$normalizedKeyValuePairs) + protected function internalSetItems(array $normalizedKeyValuePairs): array { $failedKeys = []; foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { @@ -624,103 +642,112 @@ protected function internalSetItems(array &$normalizedKeyValuePairs) $failedKeys[] = $normalizedKey; } } + return $failedKeys; } /** * Add an item. * - * @param string $key - * @param mixed $value - * @return bool * @throws Exception\ExceptionInterface * @triggers addItem.pre(PreEvent) * @triggers addItem.post(PostEvent) * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value) + public function addItem(string $key, mixed $value): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, - 'value' => &$value, + 'key' => $key, + 'value' => $value, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $key = $args['key']; + $this->assertValidKey($key); + $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalAddItem($args['key'], $args['value']); + : $this->internalAddItem($key, $args['value']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + + Assert::boolean($result); + return $result; } /** * Internal method to add an item. * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - protected function internalAddItem(&$normalizedKey, mixed &$value) + protected function internalAddItem(string $normalizedKey, mixed $value): bool { if ($this->internalHasItem($normalizedKey)) { return false; } + return $this->internalSetItem($normalizedKey, $value); } /** * Add multiple items. * - * @param array $keyValuePairs - * @return array Array of not stored keys + * @param array $keyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface * @triggers addItems.pre(PreEvent) * @triggers addItems.post(PostEvent) * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs) + public function addItems(array $keyValuePairs): array { if (! $this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } - $this->normalizeKeyValuePairs($keyValuePairs); + $this->assertValidKeyValuePairs($keyValuePairs); $args = new ArrayObject([ - 'keyValuePairs' => &$keyValuePairs, + 'keyValuePairs' => $keyValuePairs, ]); try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); + $eventRs = $this->triggerPre(__FUNCTION__, $args); + $keyValuePairs = $args['keyValuePairs']; + $this->assertValidKeyValuePairs($keyValuePairs); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalAddItems($args['keyValuePairs']); + : $this->internalAddItems($keyValuePairs); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = array_keys($keyValuePairs); - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, array_keys($keyValuePairs), $throwable); } + + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; } /** * Internal method to add multiple items. * - * @return array Array of not stored keys + * @param non-empty-array $normalizedKeyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalAddItems(array &$normalizedKeyValuePairs) + protected function internalAddItems(array $normalizedKeyValuePairs): array { $result = []; foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { @@ -728,54 +755,56 @@ protected function internalAddItems(array &$normalizedKeyValuePairs) $result[] = $normalizedKey; } } + return $result; } /** * Replace an existing item. * - * @param string $key - * @param mixed $value - * @return bool * @throws Exception\ExceptionInterface * @triggers replaceItem.pre(PreEvent) * @triggers replaceItem.post(PostEvent) * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value) + public function replaceItem(string $key, mixed $value): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, - 'value' => &$value, + 'key' => $key, + 'value' => $value, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $key = $args['key']; + $this->assertValidKey($key); + $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalReplaceItem($args['key'], $args['value']); + : $this->internalReplaceItem($key, $args['value']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + + Assert::boolean($result); + return $result; } /** * Internal method to replace an existing item. * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(&$normalizedKey, mixed &$value) + protected function internalReplaceItem(string $normalizedKey, mixed $value): bool { if (! $this->internalhasItem($normalizedKey)) { return false; @@ -787,22 +816,22 @@ protected function internalReplaceItem(&$normalizedKey, mixed &$value) /** * Replace multiple existing items. * - * @param array $keyValuePairs - * @return array Array of not stored keys + * @param array $keyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface * @triggers replaceItems.pre(PreEvent) * @triggers replaceItems.post(PostEvent) * @triggers replaceItems.exception(ExceptionEvent) */ - public function replaceItems(array $keyValuePairs) + public function replaceItems(array $keyValuePairs): array { if (! $this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } - $this->normalizeKeyValuePairs($keyValuePairs); + $this->assertValidKeyValuePairs($keyValuePairs); $args = new ArrayObject([ - 'keyValuePairs' => &$keyValuePairs, + 'keyValuePairs' => $keyValuePairs, ]); try { @@ -812,20 +841,24 @@ public function replaceItems(array $keyValuePairs) ? $eventRs->last() : $this->internalReplaceItems($args['keyValuePairs']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = array_keys($keyValuePairs); - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, array_keys($keyValuePairs), $throwable); } + + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; } /** * Internal method to replace multiple existing items. * - * @return array Array of not stored keys + * @param non-empty-array $normalizedKeyValuePairs + * @return list Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalReplaceItems(array &$normalizedKeyValuePairs) + protected function internalReplaceItems(array $normalizedKeyValuePairs): array { $result = []; foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { @@ -833,6 +866,7 @@ protected function internalReplaceItems(array &$normalizedKeyValuePairs) $result[] = $normalizedKey; } } + return $result; } @@ -842,40 +876,38 @@ protected function internalReplaceItems(array &$normalizedKeyValuePairs) * It uses the token received from getItem() to check if the item has * changed before overwriting it. * - * @see getItem() * @see setItem() + * @see getItem() * - * @param mixed $token - * @param string $key - * @param mixed $value - * @return bool * @throws Exception\ExceptionInterface */ - public function checkAndSetItem($token, $key, $value) + public function checkAndSetItem(mixed $token, string $key, mixed $value): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'token' => &$token, - 'key' => &$key, - 'value' => &$value, + 'token' => $token, + 'key' => $key, + 'value' => $value, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); - + $key = $args['key']; + $this->assertValidKey($key); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']); + : $this->internalCheckAndSetItem($args['token'], $key, $args['value']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + Assert::boolean($result); + return $result; } /** @@ -884,11 +916,10 @@ public function checkAndSetItem($token, $key, $value) * @see getItem() * @see setItem() * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - protected function internalCheckAndSetItem(mixed &$token, &$normalizedKey, mixed &$value) + protected function internalCheckAndSetItem(mixed $token, string $normalizedKey, mixed $value): bool { $oldValue = $this->internalGetItem($normalizedKey); if ($oldValue !== $token) { @@ -901,22 +932,20 @@ protected function internalCheckAndSetItem(mixed &$token, &$normalizedKey, mixed /** * Reset lifetime of an item * - * @param string $key - * @return bool * @throws Exception\ExceptionInterface * @triggers touchItem.pre(PreEvent) * @triggers touchItem.post(PostEvent) * @triggers touchItem.exception(ExceptionEvent) */ - public function touchItem($key) + public function touchItem(string $key): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, + 'key' => $key, ]); try { @@ -926,21 +955,22 @@ public function touchItem($key) ? $eventRs->last() : $this->internalTouchItem($args['key']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); } + + Assert::boolean($result); + return $result; } /** * Internal method to reset lifetime of an item * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - protected function internalTouchItem(&$normalizedKey) + protected function internalTouchItem(string $normalizedKey): bool { $success = null; $value = $this->internalGetItem($normalizedKey, $success); @@ -954,22 +984,22 @@ protected function internalTouchItem(&$normalizedKey) /** * Reset lifetime of multiple items. * - * @param array $keys - * @return array Array of not updated keys + * @param non-empty-list $keys + * @return list Array of not updated keys * @throws Exception\ExceptionInterface * @triggers touchItems.pre(PreEvent) * @triggers touchItems.post(PostEvent) * @triggers touchItems.exception(ExceptionEvent) */ - public function touchItems(array $keys) + public function touchItems(array $keys): array { if (! $this->getOptions()->getWritable()) { return $keys; } - $this->normalizeKeys($keys); + $keys = $this->normalizeKeys($keys); $args = new ArrayObject([ - 'keys' => &$keys, + 'keys' => $keys, ]); try { @@ -979,19 +1009,26 @@ public function touchItems(array $keys) ? $eventRs->last() : $this->internalTouchItems($args['keys']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $keys, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, $keys, $throwable); + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; } } /** * Internal method to reset lifetime of multiple items. * - * @return array Array of not updated keys + * @param non-empty-list $normalizedKeys + * @return list Array of not updated keys * @throws Exception\ExceptionInterface */ - protected function internalTouchItems(array &$normalizedKeys) + protected function internalTouchItems(array $normalizedKeys): array { $result = []; foreach ($normalizedKeys as $normalizedKey) { @@ -999,94 +1036,106 @@ protected function internalTouchItems(array &$normalizedKeys) $result[] = $normalizedKey; } } + return $result; } /** * Remove an item. * - * @param string $key - * @return bool * @throws Exception\ExceptionInterface * @triggers removeItem.pre(PreEvent) * @triggers removeItem.post(PostEvent) * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key) + public function removeItem(string $key): bool { if (! $this->getOptions()->getWritable()) { return false; } - $this->normalizeKey($key); + $this->assertValidKey($key); $args = new ArrayObject([ - 'key' => &$key, + 'key' => $key, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $key = $args['key']; + $this->assertValidKey($key); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalRemoveItem($args['key']); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + : $this->internalRemoveItem($key); + + $result = $this->triggerPost(__FUNCTION__, $args, $result); + Assert::boolean($result); + return $result; + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, false, $throwable); + Assert::boolean($result); + return $result; } } /** * Internal method to remove an item. * - * @param string $normalizedKey - * @return bool + * @param non-empty-string $normalizedKey * @throws Exception\ExceptionInterface */ - abstract protected function internalRemoveItem(&$normalizedKey); + abstract protected function internalRemoveItem(string $normalizedKey): bool; /** * Remove multiple items. * - * @param array $keys - * @return array Array of not removed keys + * @param non-empty-list $keys + * @return list Array of not removed keys * @throws Exception\ExceptionInterface * @triggers removeItems.pre(PreEvent) * @triggers removeItems.post(PostEvent) * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys) + public function removeItems(array $keys): array { if (! $this->getOptions()->getWritable()) { return $keys; } - $this->normalizeKeys($keys); + $keys = $this->normalizeKeys($keys); $args = new ArrayObject([ - 'keys' => &$keys, + 'keys' => $keys, ]); try { $eventRs = $this->triggerPre(__FUNCTION__, $args); + $keys = $args['keys']; + $this->normalizeKeys($keys); $result = $eventRs->stopped() ? $eventRs->last() - : $this->internalRemoveItems($args['keys']); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $keys, $e); + : $this->internalRemoveItems($keys); + + $result = $this->triggerPost(__FUNCTION__, $args, $result); + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, $keys, $throwable); + Assert::isList($result); + Assert::allStringNotEmpty($result); + return $result; } } /** * Internal method to remove multiple items. * - * @return array Array of not removed keys + * @param non-empty-list $normalizedKeys + * @return list Array of not removed keys * @throws Exception\ExceptionInterface */ - protected function internalRemoveItems(array &$normalizedKeys) + protected function internalRemoveItems(array $normalizedKeys): array { $result = []; foreach ($normalizedKeys as $normalizedKey) { @@ -1094,6 +1143,7 @@ protected function internalRemoveItems(array &$normalizedKeys) $result[] = $normalizedKey; } } + return $result; } @@ -1102,12 +1152,11 @@ protected function internalRemoveItems(array &$normalizedKeys) /** * Get capabilities of this adapter * - * @return Capabilities * @triggers getCapabilities.pre(PreEvent) * @triggers getCapabilities.post(PostEvent) * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + public function getCapabilities(): Capabilities { $args = new ArrayObject(); @@ -1118,24 +1167,27 @@ public function getCapabilities() ? $eventRs->last() : $this->internalGetCapabilities(); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); + $result = $this->triggerPost(__FUNCTION__, $args, $result); + Assert::isInstanceOf($result, Capabilities::class); + return $result; + } catch (Throwable $throwable) { + $result = $this->triggerThrowable(__FUNCTION__, $args, new Capabilities($this, new stdClass()), $throwable); + Assert::isInstanceOf($result, Capabilities::class); + + return $result; } } /** * Internal method to get capabilities of this adapter - * - * @return Capabilities */ - protected function internalGetCapabilities() + protected function internalGetCapabilities(): Capabilities { if ($this->capabilities === null) { $this->capabilityMarker = new stdClass(); $this->capabilities = new Capabilities($this, $this->capabilityMarker); } + return $this->capabilities; } @@ -1144,56 +1196,92 @@ protected function internalGetCapabilities() /** * Validates and normalizes a key * - * @param string $key - * @return void + * @deprecated Use {@see AbstractAdapter::assertValidKey()} instead. + * * @throws Exception\InvalidArgumentException On an invalid key. + * @psalm-assert non-empty-string $key */ - protected function normalizeKey(&$key) + protected function normalizeKey(string $key): void { - $key = (string) $key; - - if ($key === '') { - throw new Exception\InvalidArgumentException( - "An empty key isn't allowed" - ); - } elseif (($p = $this->getOptions()->getKeyPattern()) && ! preg_match($p, $key)) { - throw new Exception\InvalidArgumentException( - "The key '{$key}' doesn't match against pattern '{$p}'" - ); - } + $this->assertValidKey($key); } /** * Validates and normalizes multiple keys * - * @return void + * @param non-empty-list $keys + * @return non-empty-list $keys * @throws Exception\InvalidArgumentException On an invalid key. */ - protected function normalizeKeys(array &$keys) + protected function normalizeKeys(array $keys): array { - if (! $keys) { - throw new Exception\InvalidArgumentException( - "An empty list of keys isn't allowed" - ); + foreach ($keys as $key) { + $this->assertValidKey($key); } - array_walk($keys, [$this, 'normalizeKey']); - $keys = array_values(array_unique($keys)); + return array_values(array_unique($keys)); } /** * Validates and normalizes an array of key-value pairs * - * @return void + * @deprecated Please use {@see AbstractAdapter::assertValidKeyValuePairs()} instead. + * + * @param array $keyValuePairs + * @psalm-assert array $keyValuePairs * @throws Exception\InvalidArgumentException On an invalid key. */ - protected function normalizeKeyValuePairs(array &$keyValuePairs) + protected function normalizeKeyValuePairs(array $keyValuePairs): void { - $normalizedKeyValuePairs = []; - foreach ($keyValuePairs as $key => $value) { - $this->normalizeKey($key); - $normalizedKeyValuePairs[$key] = $value; + $this->assertValidKeyValuePairs($keyValuePairs); + } + + /** + * @psalm-assert non-empty-string $key + */ + protected function assertValidKey(mixed $key): void + { + if (! is_string($key)) { + throw new Exception\InvalidArgumentException( + "Key has to be string" + ); + } + + if ($key === '') { + throw new Exception\InvalidArgumentException( + "An empty key isn't allowed" + ); + } + + $pattern = $this->getOptions()->getKeyPattern(); + if ($pattern !== '' && ! preg_match($pattern, $key)) { + throw new Exception\InvalidArgumentException( + sprintf( + "The key '%s' doesn't match against pattern '%s'", + $key, + $pattern, + ), + ); + } + } + + /** + * @psalm-assert non-empty-array $keyValuePairs + */ + protected function assertValidKeyValuePairs(mixed $keyValuePairs): void + { + if (! is_array($keyValuePairs)) { + throw new Exception\InvalidArgumentException( + "Key/Value pairs have to be an array" + ); + } + + if ($keyValuePairs === []) { + throw new InvalidArgumentException('Key/Value pairs must not be empty.'); + } + + foreach (array_keys($keyValuePairs) as $key) { + $this->assertValidKey($key); } - $keyValuePairs = $normalizedKeyValuePairs; } } diff --git a/src/Storage/Adapter/AdapterOptions.php b/src/Storage/Adapter/AdapterOptions.php index 2c8cc1be..3869da9b 100644 --- a/src/Storage/Adapter/AdapterOptions.php +++ b/src/Storage/Adapter/AdapterOptions.php @@ -38,57 +38,45 @@ class AdapterOptions extends AbstractOptions * * @var string[] */ - protected $__prioritizedProperties__ = []; + protected array $__prioritizedProperties__ = []; // @codingStandardsIgnoreEnd /** * The adapter using these options - * - * @var null|StorageInterface */ - protected $adapter; + protected ?StorageInterface $adapter = null; /** * Validate key against pattern - * - * @var string */ - protected $keyPattern = ''; + protected string $keyPattern = ''; /** * Namespace option - * - * @var string */ - protected $namespace = 'laminascache'; + protected string $namespace = 'laminascache'; /** * Readable option - * - * @var bool */ - protected $readable = true; + protected bool $readable = true; /** * TTL option * * @var int|float 0 means infinite or maximum of adapter */ - protected $ttl = 0; + protected int|float $ttl = 0; /** * Writable option - * - * @var bool */ - protected $writable = true; + protected bool $writable = true; /** * Adapter using this instance - * - * @return AdapterOptions Provides a fluent interface */ - public function setAdapter(?StorageInterface $adapter = null) + public function setAdapter(?StorageInterface $adapter = null): self { $this->adapter = $adapter; return $this; @@ -97,13 +85,10 @@ public function setAdapter(?StorageInterface $adapter = null) /** * Set key pattern * - * @param string $keyPattern * @throws Exception\InvalidArgumentException - * @return AdapterOptions Provides a fluent interface */ - public function setKeyPattern($keyPattern) + public function setKeyPattern(string $keyPattern): self { - $keyPattern = (string) $keyPattern; if ($this->keyPattern !== $keyPattern) { // validate pattern if ($keyPattern !== '') { @@ -128,23 +113,17 @@ public function setKeyPattern($keyPattern) /** * Get key pattern - * - * @return string */ - public function getKeyPattern() + public function getKeyPattern(): string { return $this->keyPattern; } /** * Set namespace. - * - * @param string $namespace - * @return AdapterOptions Provides a fluent interface */ - public function setNamespace($namespace) + public function setNamespace(string $namespace): self { - $namespace = (string) $namespace; if ($this->namespace !== $namespace) { $this->triggerOptionEvent('namespace', $namespace); $this->namespace = $namespace; @@ -155,23 +134,17 @@ public function setNamespace($namespace) /** * Get namespace - * - * @return string */ - public function getNamespace() + public function getNamespace(): string { return $this->namespace; } /** * Enable/Disable reading data from cache. - * - * @param bool $readable - * @return AdapterOptions Provides a fluent interface */ - public function setReadable($readable) + public function setReadable(bool $readable): self { - $readable = (bool) $readable; if ($this->readable !== $readable) { $this->triggerOptionEvent('readable', $readable); $this->readable = $readable; @@ -181,10 +154,8 @@ public function setReadable($readable) /** * If reading data from cache enabled. - * - * @return bool */ - public function getReadable() + public function getReadable(): bool { return $this->readable; } @@ -192,12 +163,11 @@ public function getReadable() /** * Set time to live. * - * @param numeric $ttl - * @return $this + * @param numeric $ttl */ - public function setTtl($ttl) + public function setTtl(int|float|string $ttl): self { - $this->normalizeTtl($ttl); + $ttl = $this->normalizeTtl($ttl); if ($this->ttl !== $ttl) { $this->triggerOptionEvent('ttl', $ttl); $this->ttl = $ttl; @@ -207,10 +177,8 @@ public function setTtl($ttl) /** * Get time to live. - * - * @return float */ - public function getTtl() + public function getTtl(): float|int { return $this->ttl; } @@ -218,12 +186,10 @@ public function getTtl() /** * Enable/Disable writing data to cache. * - * @param bool $writable * @return $this */ - public function setWritable($writable) + public function setWritable(bool $writable): self { - $writable = (bool) $writable; if ($this->writable !== $writable) { $this->triggerOptionEvent('writable', $writable); $this->writable = $writable; @@ -233,10 +199,8 @@ public function setWritable($writable) /** * If writing data to cache enabled. - * - * @return bool */ - public function getWritable() + public function getWritable(): bool { return $this->writable; } @@ -244,11 +208,8 @@ public function getWritable() /** * Triggers an option event if this options instance has a connection to * an adapter implements EventsCapableInterface. - * - * @param string $optionName - * @return void */ - protected function triggerOptionEvent($optionName, mixed $optionValue) + protected function triggerOptionEvent(string $optionName, mixed $optionValue): void { if ($this->adapter instanceof EventsCapableInterface) { $event = new Event('option', $this->adapter, new ArrayObject([$optionName => $optionValue])); @@ -260,11 +221,10 @@ protected function triggerOptionEvent($optionName, mixed $optionValue) * Validates and normalize a TTL. * * @param numeric $ttl - * @param-out int|float $ttl + * @return non-negative-int|float $ttl * @throws Exception\InvalidArgumentException - * @return void */ - protected function normalizeTtl(&$ttl) + protected function normalizeTtl(int|string|float $ttl): int|float { if (! is_int($ttl)) { $ttl = (float) $ttl; @@ -278,6 +238,8 @@ protected function normalizeTtl(&$ttl) if ($ttl < 0) { throw new Exception\InvalidArgumentException("TTL can't be negative"); } + + return $ttl; } /** @@ -285,7 +247,7 @@ protected function normalizeTtl(&$ttl) * * @return array */ - public function toArray() + public function toArray(): array { $array = []; $transform = static function ($letters): string { @@ -308,11 +270,10 @@ public function toArray() * NOTE: This method was overwritten just to support prioritized properties * {@link https://github.com/zendframework/zf2/issues/6381} * - * @param array|Traversable|AbstractOptions $options + * @param iterable|AbstractOptions $options * @throws Exception\InvalidArgumentException - * @return AbstractOptions Provides fluent interface */ - public function setFromArray($options) + public function setFromArray($options): self { if ($this->__prioritizedProperties__) { if ($options instanceof AbstractOptions) { @@ -344,6 +305,7 @@ public function setFromArray($options) } } - return parent::setFromArray($options); + parent::setFromArray($options); + return $this; } } diff --git a/src/Storage/Adapter/KeyListIterator.php b/src/Storage/Adapter/KeyListIterator.php index 41b35774..4e2fd835 100644 --- a/src/Storage/Adapter/KeyListIterator.php +++ b/src/Storage/Adapter/KeyListIterator.php @@ -13,35 +13,29 @@ * @see ReturnTypeWillChange * * @template-covariant TValue - * @template-implements IteratorInterface + * @template-implements IteratorInterface */ class KeyListIterator implements IteratorInterface, Countable { /** * The iterator mode * - * @var int + * @var IteratorInterface::CURRENT_AS_* */ - protected $mode = IteratorInterface::CURRENT_AS_KEY; + protected int $mode = IteratorInterface::CURRENT_AS_KEY; /** * Number of keys - * - * @var int */ - protected $count; + protected int $count; /** * Current iterator position - * - * @var int */ - protected $position = 0; + protected int $position = 0; /** - * Constructor - * - * @param string[] $keys Keys to iterate over + * @param array $keys Keys to iterate over */ public function __construct( protected StorageInterface $storage, @@ -52,10 +46,8 @@ public function __construct( /** * Get storage instance - * - * @return StorageInterface */ - public function getStorage() + public function getStorage(): StorageInterface { return $this->storage; } @@ -63,9 +55,9 @@ public function getStorage() /** * Get iterator mode * - * @return int Value of IteratorInterface::CURRENT_AS_* + * @return IteratorInterface::CURRENT_AS_* */ - public function getMode() + public function getMode(): int { return $this->mode; } @@ -73,22 +65,18 @@ public function getMode() /** * Set iterator mode * - * @param int $mode - * @return $this + * @param IteratorInterface::CURRENT_AS_* $mode */ - public function setMode($mode) + public function setMode(int $mode): self { - $this->mode = (int) $mode; + $this->mode = $mode; return $this; } /** * Get current key, value or metadata. - * - * @return mixed */ - #[ReturnTypeWillChange] - public function current() + public function current(): mixed { if ($this->mode === IteratorInterface::CURRENT_AS_SELF) { return $this; @@ -106,54 +94,41 @@ public function current() /** * Get current key * - * @return string + * @return non-empty-string */ - #[ReturnTypeWillChange] - public function key() + public function key(): string { return $this->keys[$this->position]; } /** * Checks if current position is valid - * - * @return bool */ - #[ReturnTypeWillChange] - public function valid() + public function valid(): bool { return $this->position < $this->count; } /** * Move forward to next element - * - * @return void */ - #[ReturnTypeWillChange] - public function next() + public function next(): void { $this->position++; } /** * Rewind the Iterator to the first element. - * - * @return void */ - #[ReturnTypeWillChange] - public function rewind() + public function rewind(): void { $this->position = 0; } /** * Count number of items - * - * @return int */ - #[ReturnTypeWillChange] - public function count() + public function count(): int { return $this->count; } diff --git a/src/Storage/AdapterPluginManager.php b/src/Storage/AdapterPluginManager.php index 2299f91a..1ed0a0ce 100644 --- a/src/Storage/AdapterPluginManager.php +++ b/src/Storage/AdapterPluginManager.php @@ -12,7 +12,6 @@ * adapters available. * * @extends AbstractPluginManager - * @final */ final class AdapterPluginManager extends AbstractPluginManager { diff --git a/src/Storage/AvailableSpaceCapableInterface.php b/src/Storage/AvailableSpaceCapableInterface.php index 0094db6c..6592a3a6 100644 --- a/src/Storage/AvailableSpaceCapableInterface.php +++ b/src/Storage/AvailableSpaceCapableInterface.php @@ -6,8 +6,6 @@ interface AvailableSpaceCapableInterface { /** * Get available space in bytes - * - * @return int|float */ - public function getAvailableSpace(); + public function getAvailableSpace(): int; } diff --git a/src/Storage/Capabilities.php b/src/Storage/Capabilities.php index 82844dd6..ce2d1b27 100644 --- a/src/Storage/Capabilities.php +++ b/src/Storage/Capabilities.php @@ -27,70 +27,56 @@ class Capabilities * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|bool */ - protected $lockOnExpire; + protected ?bool $lockOnExpire = null; /** * Max. key length * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|int */ - protected $maxKeyLength; + protected ?int $maxKeyLength = null; /** * Min. TTL (0 means items never expire) * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|int */ - protected $minTtl; + protected ?int $minTtl = null; /** * Max. TTL (0 means infinite) * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|int */ - protected $maxTtl; + protected ?int $maxTtl = null; /** * Namespace is prefix * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|bool */ - protected $namespaceIsPrefix; + protected ?bool $namespaceIsPrefix = null; /** * Namespace separator * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|string */ - protected $namespaceSeparator; + protected ?string $namespaceSeparator = null; /** * Static ttl * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|bool */ - protected $staticTtl; + protected ?bool $staticTtl = null; /** * Supported datatypes @@ -100,31 +86,24 @@ class Capabilities * * @var null|array */ - protected $supportedDatatypes; + protected ?array $supportedDatatypes = null; /** * TTL precision * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|int */ - protected $ttlPrecision; + protected ?int $ttlPrecision = null; /** * Use request time * * If it's NULL the capability isn't set and the getter * returns the base capability or the default value. - * - * @var null|bool */ - protected $useRequestTime; + protected ?bool $useRequestTime = null; - /** - * Constructor - */ public function __construct( protected StorageInterface $storage, /** @@ -141,20 +120,16 @@ public function __construct( /** * Get the storage adapter - * - * @return StorageInterface */ - public function getAdapter() + public function getAdapter(): StorageInterface { return $this->storage; } /** * Get supported datatypes - * - * @return array */ - public function getSupportedDatatypes() + public function getSupportedDatatypes(): array { return $this->getCapability('supportedDatatypes', [ 'NULL' => false, @@ -172,9 +147,8 @@ public function getSupportedDatatypes() * Set supported datatypes * * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface */ - public function setSupportedDatatypes(stdClass $marker, array $datatypes) + public function setSupportedDatatypes(stdClass $marker, array $datatypes): self { $allTypes = [ 'array', @@ -188,7 +162,8 @@ public function setSupportedDatatypes(stdClass $marker, array $datatypes) ]; // check/normalize datatype values - foreach ($datatypes as $type => &$toType) { + $normalized = []; + foreach ($datatypes as $type => $toType) { if (! in_array($type, $allTypes)) { throw new Exception\InvalidArgumentException("Unknown datatype '{$type}'"); } @@ -201,15 +176,17 @@ public function setSupportedDatatypes(stdClass $marker, array $datatypes) } else { $toType = (bool) $toType; } + + $normalized[$type] = $toType; } // add missing datatypes as not supported - $missingTypes = array_diff($allTypes, array_keys($datatypes)); + $missingTypes = array_diff($allTypes, array_keys($normalized)); foreach ($missingTypes as $type) { - $datatypes[$type] = false; + $normalized[$type] = false; } - return $this->setCapability($marker, 'supportedDatatypes', $datatypes); + return $this->setCapability($marker, 'supportedDatatypes', $normalized); } /** @@ -217,7 +194,7 @@ public function setSupportedDatatypes(stdClass $marker, array $datatypes) * * @return int 0 means items never expire */ - public function getMinTtl() + public function getMinTtl(): int { return $this->getCapability('minTtl', 0); } @@ -225,13 +202,10 @@ public function getMinTtl() /** * Set minimum supported time-to-live * - * @param int $minTtl * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface */ - public function setMinTtl(stdClass $marker, $minTtl) + public function setMinTtl(stdClass $marker, int $minTtl): self { - $minTtl = (int) $minTtl; if ($minTtl < 0) { throw new Exception\InvalidArgumentException('$minTtl must be greater or equal 0'); } @@ -243,7 +217,7 @@ public function setMinTtl(stdClass $marker, $minTtl) * * @return int 0 means infinite */ - public function getMaxTtl() + public function getMaxTtl(): int { return $this->getCapability('maxTtl', 0); } @@ -251,13 +225,10 @@ public function getMaxTtl() /** * Set maximum supported time-to-live * - * @param int $maxTtl * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface */ - public function setMaxTtl(stdClass $marker, $maxTtl) + public function setMaxTtl(stdClass $marker, int $maxTtl): self { - $maxTtl = (int) $maxTtl; if ($maxTtl < 0) { throw new Exception\InvalidArgumentException('$maxTtl must be greater or equal 0'); } @@ -267,31 +238,24 @@ public function setMaxTtl(stdClass $marker, $maxTtl) /** * Is the time-to-live handled static (on write) * or dynamic (on read) - * - * @return bool */ - public function getStaticTtl() + public function getStaticTtl(): bool { return $this->getCapability('staticTtl', false); } /** * Set if the time-to-live handled static (on write) or dynamic (on read) - * - * @param bool $flag - * @return Capabilities Fluent interface */ - public function setStaticTtl(stdClass $marker, $flag) + public function setStaticTtl(stdClass $marker, bool $flag): self { - return $this->setCapability($marker, 'staticTtl', (bool) $flag); + return $this->setCapability($marker, 'staticTtl', $flag); } /** * Get time-to-live precision - * - * @return float */ - public function getTtlPrecision() + public function getTtlPrecision(): float { return $this->getCapability('ttlPrecision', 1); } @@ -299,13 +263,10 @@ public function getTtlPrecision() /** * Set time-to-live precision * - * @param float $ttlPrecision * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface */ - public function setTtlPrecision(stdClass $marker, $ttlPrecision) + public function setTtlPrecision(stdClass $marker, float $ttlPrecision): self { - $ttlPrecision = (float) $ttlPrecision; if ($ttlPrecision <= 0) { throw new Exception\InvalidArgumentException('$ttlPrecision must be greater than 0'); } @@ -314,23 +275,18 @@ public function setTtlPrecision(stdClass $marker, $ttlPrecision) /** * Get use request time - * - * @return bool */ - public function getUseRequestTime() + public function getUseRequestTime(): bool { return $this->getCapability('useRequestTime', false); } /** * Set use request time - * - * @param bool $flag - * @return Capabilities Fluent interface */ - public function setUseRequestTime(stdClass $marker, $flag) + public function setUseRequestTime(stdClass $marker, bool $flag): self { - return $this->setCapability($marker, 'useRequestTime', (bool) $flag); + return $this->setCapability($marker, 'useRequestTime', $flag); } /** @@ -340,20 +296,17 @@ public function setUseRequestTime(stdClass $marker, $flag) * >0 = Time in seconds an expired item could be retrieved * -1 = Expired items could be retrieved forever */ - public function getLockOnExpire() + public function getLockOnExpire(): int { return $this->getCapability('lockOnExpire', 0); } /** * Set "lock-on-expire" support in seconds. - * - * @param int $timeout - * @return Capabilities Fluent interface */ - public function setLockOnExpire(stdClass $marker, $timeout) + public function setLockOnExpire(stdClass $marker, int $timeout): self { - return $this->setCapability($marker, 'lockOnExpire', (int) $timeout); + return $this->setCapability($marker, 'lockOnExpire', $timeout); } /** @@ -361,7 +314,7 @@ public function setLockOnExpire(stdClass $marker, $timeout) * * @return int -1 means unknown, 0 means infinite */ - public function getMaxKeyLength() + public function getMaxKeyLength(): int { return $this->getCapability('maxKeyLength', self::UNKNOWN_KEY_LENGTH); } @@ -369,13 +322,10 @@ public function getMaxKeyLength() /** * Set maximum key length * - * @param int $maxKeyLength * @throws Exception\InvalidArgumentException - * @return Capabilities Fluent interface */ - public function setMaxKeyLength(stdClass $marker, $maxKeyLength) + public function setMaxKeyLength(stdClass $marker, int $maxKeyLength): self { - $maxKeyLength = (int) $maxKeyLength; if ($maxKeyLength < -1) { throw new Exception\InvalidArgumentException('$maxKeyLength must be greater or equal than -1'); } @@ -384,53 +334,40 @@ public function setMaxKeyLength(stdClass $marker, $maxKeyLength) /** * Get if namespace support is implemented as prefix - * - * @return bool */ - public function getNamespaceIsPrefix() + public function getNamespaceIsPrefix(): bool { return $this->getCapability('namespaceIsPrefix', true); } /** * Set if namespace support is implemented as prefix - * - * @param bool $flag - * @return Capabilities Fluent interface */ - public function setNamespaceIsPrefix(stdClass $marker, $flag) + public function setNamespaceIsPrefix(stdClass $marker, bool $flag): self { - return $this->setCapability($marker, 'namespaceIsPrefix', (bool) $flag); + return $this->setCapability($marker, 'namespaceIsPrefix', $flag); } /** * Get namespace separator if namespace is implemented as prefix - * - * @return string */ - public function getNamespaceSeparator() + public function getNamespaceSeparator(): string { return $this->getCapability('namespaceSeparator', ''); } /** * Set the namespace separator if namespace is implemented as prefix - * - * @param string $separator - * @return Capabilities Fluent interface */ - public function setNamespaceSeparator(stdClass $marker, $separator) + public function setNamespaceSeparator(stdClass $marker, string $separator): self { - return $this->setCapability($marker, 'namespaceSeparator', (string) $separator); + return $this->setCapability($marker, 'namespaceSeparator', $separator); } /** * Get a capability - * - * @param string $property - * @return mixed */ - protected function getCapability($property, mixed $default = null) + protected function getCapability(string $property, mixed $default = null): mixed { if ($this->$property !== null) { return $this->$property; @@ -444,11 +381,9 @@ protected function getCapability($property, mixed $default = null) /** * Change a capability * - * @param string $property - * @return Capabilities Fluent interface * @throws Exception\InvalidArgumentException */ - protected function setCapability(stdClass $marker, $property, mixed $value) + protected function setCapability(stdClass $marker, string $property, mixed $value): self { if ($this->marker !== $marker) { throw new Exception\InvalidArgumentException('Invalid marker'); diff --git a/src/Storage/ClearByNamespaceInterface.php b/src/Storage/ClearByNamespaceInterface.php index 5f69e6fb..9245d68f 100644 --- a/src/Storage/ClearByNamespaceInterface.php +++ b/src/Storage/ClearByNamespaceInterface.php @@ -6,9 +6,6 @@ interface ClearByNamespaceInterface { /** * Remove items of given namespace - * - * @param string $namespace - * @return bool */ - public function clearByNamespace($namespace); + public function clearByNamespace(string $namespace): bool; } diff --git a/src/Storage/ClearByPrefixInterface.php b/src/Storage/ClearByPrefixInterface.php index 563a836b..6c536294 100644 --- a/src/Storage/ClearByPrefixInterface.php +++ b/src/Storage/ClearByPrefixInterface.php @@ -6,9 +6,6 @@ interface ClearByPrefixInterface { /** * Remove items matching given prefix - * - * @param string $prefix - * @return bool */ - public function clearByPrefix($prefix); + public function clearByPrefix(string $prefix): bool; } diff --git a/src/Storage/ClearExpiredInterface.php b/src/Storage/ClearExpiredInterface.php index 13830bd4..b5fb1e36 100644 --- a/src/Storage/ClearExpiredInterface.php +++ b/src/Storage/ClearExpiredInterface.php @@ -6,8 +6,6 @@ interface ClearExpiredInterface { /** * Remove expired items - * - * @return bool */ - public function clearExpired(); + public function clearExpired(): bool; } diff --git a/src/Storage/Event.php b/src/Storage/Event.php index b9589ee2..e3eddd65 100644 --- a/src/Storage/Event.php +++ b/src/Storage/Event.php @@ -9,13 +9,11 @@ class Event extends BaseEvent { /** - * Constructor - * * Accept a storage adapter and its parameters. * - * @param string $name Event name + * @param non-empty-string $name Event name */ - public function __construct($name, StorageInterface $storage, ArrayObject $params) + public function __construct(string $name, StorageInterface $storage, ArrayObject $params) { parent::__construct($name, $storage, $params); } @@ -23,24 +21,22 @@ public function __construct($name, StorageInterface $storage, ArrayObject $param /** * Set the event target/context * - * @see Laminas\EventManager\Event::setTarget() + * @see \Laminas\EventManager\Event::setTarget() * - * @param StorageInterface $target - * @return Event + * @param StorageInterface $target */ - public function setTarget($target) + public function setTarget($target): void { - return $this->setStorage($target); + parent::setTarget($target); + $this->setStorage($target); } /** * Alias of setTarget * - * @see Laminas\EventManager\Event::setTarget() - * - * @return Event + * @see \Laminas\EventManager\Event::setTarget() */ - public function setStorage(StorageInterface $storage) + public function setStorage(StorageInterface $storage): self { $this->target = $storage; return $this; @@ -48,10 +44,8 @@ public function setStorage(StorageInterface $storage) /** * Alias of getTarget - * - * @return StorageInterface */ - public function getStorage() + public function getStorage(): StorageInterface { return $this->getTarget(); } diff --git a/src/Storage/ExceptionEvent.php b/src/Storage/ExceptionEvent.php index 42361e10..f1f89b22 100644 --- a/src/Storage/ExceptionEvent.php +++ b/src/Storage/ExceptionEvent.php @@ -3,77 +3,66 @@ namespace Laminas\Cache\Storage; use ArrayObject; -use Exception; +use Throwable; class ExceptionEvent extends PostEvent { /** * The exception to be thrown - * - * @var Exception */ - protected $exception; + protected Throwable $throwable; /** * Throw the exception or use the result - * - * @var bool */ - protected $throwException = true; + protected bool $throwException = true; /** - * Constructor - * * Accept a target and its parameters. * - * @param string $name - * @param mixed $result + * @param non-empty-string $name Event name */ - public function __construct($name, StorageInterface $storage, ArrayObject $params, &$result, Exception $exception) - { + public function __construct( + string $name, + StorageInterface $storage, + ArrayObject $params, + mixed $result, + Throwable $throwable, + ) { parent::__construct($name, $storage, $params, $result); - $this->setException($exception); + $this->setThrowable($throwable); } /** * Set the exception to be thrown - * - * @return ExceptionEvent */ - public function setException(Exception $exception) + public function setThrowable(Throwable $throwable): self { - $this->exception = $exception; + $this->throwable = $throwable; return $this; } /** * Get the exception to be thrown - * - * @return Exception */ - public function getException() + public function getThrowable(): Throwable { - return $this->exception; + return $this->throwable; } /** * Throw the exception or use the result - * - * @param bool $flag - * @return ExceptionEvent */ - public function setThrowException($flag) + public function setThrowException(bool $flag): self { - $this->throwException = (bool) $flag; + $this->throwException = $flag; return $this; } /** * Throw the exception or use the result - * - * @return bool */ - public function getThrowException() + public function getThrowException(): bool { return $this->throwException; } diff --git a/src/Storage/FlushableInterface.php b/src/Storage/FlushableInterface.php index 813561e9..5282c0e9 100644 --- a/src/Storage/FlushableInterface.php +++ b/src/Storage/FlushableInterface.php @@ -6,8 +6,6 @@ interface FlushableInterface { /** * Flush the whole storage - * - * @return bool */ - public function flush(); + public function flush(): bool; } diff --git a/src/Storage/IteratorInterface.php b/src/Storage/IteratorInterface.php index 69d11796..230c96b5 100644 --- a/src/Storage/IteratorInterface.php +++ b/src/Storage/IteratorInterface.php @@ -17,23 +17,20 @@ interface IteratorInterface extends Iterator /** * Get storage instance - * - * @return StorageInterface */ - public function getStorage(); + public function getStorage(): StorageInterface; /** * Get iterator mode * - * @return int Value of IteratorInterface::CURRENT_AS_* + * @return IteratorInterface::CURRENT_AS_* */ - public function getMode(); + public function getMode(): int; /** * Set iterator mode * - * @param int $mode Value of IteratorInterface::CURRENT_AS_* - * @return IteratorInterface Fluent interface + * @param IteratorInterface::CURRENT_AS_* $mode */ - public function setMode($mode); + public function setMode(int $mode): self; } diff --git a/src/Storage/MetadataCapableInterface.php b/src/Storage/MetadataCapableInterface.php index 664e1590..fe77a1d6 100644 --- a/src/Storage/MetadataCapableInterface.php +++ b/src/Storage/MetadataCapableInterface.php @@ -22,7 +22,7 @@ public function getMetadata(string $key): ?object; /** * Get multiple metadata * - * @param array $keys + * @param non-empty-list $keys * @return array Associative array of keys and metadata * @throws ExceptionInterface */ diff --git a/src/Storage/OptimizableInterface.php b/src/Storage/OptimizableInterface.php index 8d9b372f..194135a7 100644 --- a/src/Storage/OptimizableInterface.php +++ b/src/Storage/OptimizableInterface.php @@ -6,8 +6,6 @@ interface OptimizableInterface { /** * Optimize the storage - * - * @return bool */ - public function optimize(); + public function optimize(): bool; } diff --git a/src/Storage/Plugin/AbstractPlugin.php b/src/Storage/Plugin/AbstractPlugin.php index 98f36002..22843187 100644 --- a/src/Storage/Plugin/AbstractPlugin.php +++ b/src/Storage/Plugin/AbstractPlugin.php @@ -3,18 +3,16 @@ namespace Laminas\Cache\Storage\Plugin; use Laminas\EventManager\AbstractListenerAggregate; +use Webmozart\Assert\Assert; abstract class AbstractPlugin extends AbstractListenerAggregate implements PluginInterface { - /** @var PluginOptions */ - protected $options; + protected ?PluginOptions $options = null; /** * Set pattern options - * - * @return AbstractPlugin Provides a fluent interface */ - public function setOptions(PluginOptions $options) + public function setOptions(PluginOptions $options): self { $this->options = $options; return $this; @@ -22,14 +20,14 @@ public function setOptions(PluginOptions $options) /** * Get all pattern options - * - * @return PluginOptions */ - public function getOptions() + public function getOptions(): PluginOptions { if (null === $this->options) { $this->setOptions(new PluginOptions()); } + + Assert::notNull($this->options); return $this->options; } } diff --git a/src/Storage/Plugin/ClearExpiredByFactor.php b/src/Storage/Plugin/ClearExpiredByFactor.php index 555cbb01..af6c6d1a 100644 --- a/src/Storage/Plugin/ClearExpiredByFactor.php +++ b/src/Storage/Plugin/ClearExpiredByFactor.php @@ -13,7 +13,7 @@ class ClearExpiredByFactor extends AbstractPlugin /** * {@inheritDoc} */ - public function attach(EventManagerInterface $events, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1): void { $callback = [$this, 'clearExpiredByFactor']; @@ -26,10 +26,9 @@ public function attach(EventManagerInterface $events, $priority = 1) /** * Clear expired items by factor after writing new item(s) * - * @return void * @phpcs:disable Generic.NamingConventions.ConstructorName.OldStyle */ - public function clearExpiredByFactor(PostEvent $event) + public function clearExpiredByFactor(PostEvent $event): void { $storage = $event->getStorage(); if (! $storage instanceof ClearExpiredInterface) { diff --git a/src/Storage/Plugin/ExceptionHandler.php b/src/Storage/Plugin/ExceptionHandler.php index dca0fd5e..c0f0e542 100644 --- a/src/Storage/Plugin/ExceptionHandler.php +++ b/src/Storage/Plugin/ExceptionHandler.php @@ -12,7 +12,7 @@ class ExceptionHandler extends AbstractPlugin /** * {@inheritDoc} */ - public function attach(EventManagerInterface $events, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1): void { $callback = [$this, 'onException']; @@ -50,15 +50,13 @@ public function attach(EventManagerInterface $events, $priority = 1) /** * On exception - * - * @return void */ - public function onException(ExceptionEvent $event) + public function onException(ExceptionEvent $event): void { $options = $this->getOptions(); $callback = $options->getExceptionCallback(); if ($callback !== null) { - call_user_func($callback, $event->getException()); + call_user_func($callback, $event->getThrowable()); } $event->setThrowException($options->getThrowExceptions()); diff --git a/src/Storage/Plugin/IgnoreUserAbort.php b/src/Storage/Plugin/IgnoreUserAbort.php index c66047b2..c126302c 100644 --- a/src/Storage/Plugin/IgnoreUserAbort.php +++ b/src/Storage/Plugin/IgnoreUserAbort.php @@ -13,15 +13,13 @@ class IgnoreUserAbort extends AbstractPlugin { /** * The storage who activated ignore_user_abort. - * - * @var null|StorageInterface */ - protected $activatedTarget; + protected ?StorageInterface $activatedTarget = null; /** * {@inheritDoc} */ - public function attach(EventManagerInterface $events, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1): void { $cbOnBefore = [$this, 'onBefore']; $cbOnAfter = [$this, 'onAfter']; @@ -58,10 +56,8 @@ public function attach(EventManagerInterface $events, $priority = 1) /** * Activate ignore_user_abort if not already done * and save the target who activated it. - * - * @return void */ - public function onBefore(Event $event) + public function onBefore(Event $event): void { if ($this->activatedTarget === null && ! ignore_user_abort(true)) { $this->activatedTarget = $event->getStorage(); @@ -74,10 +70,8 @@ public function onBefore(Event $event) * * If exit_on_abort is enabled and the connection has been aborted * exit the script. - * - * @return void */ - public function onAfter(Event $event) + public function onAfter(Event $event): void { if ($this->activatedTarget === $event->getStorage()) { // exit if connection aborted diff --git a/src/Storage/Plugin/OptimizeByFactor.php b/src/Storage/Plugin/OptimizeByFactor.php index 97598528..6c3a5dc1 100644 --- a/src/Storage/Plugin/OptimizeByFactor.php +++ b/src/Storage/Plugin/OptimizeByFactor.php @@ -13,7 +13,7 @@ class OptimizeByFactor extends AbstractPlugin /** * {@inheritDoc} */ - public function attach(EventManagerInterface $events, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1): void { $callback = [$this, 'optimizeByFactor']; $this->listeners[] = $events->attach('removeItem.post', $callback, $priority); diff --git a/src/Storage/Plugin/PluginInterface.php b/src/Storage/Plugin/PluginInterface.php index 8e9549a4..da441ab1 100644 --- a/src/Storage/Plugin/PluginInterface.php +++ b/src/Storage/Plugin/PluginInterface.php @@ -11,12 +11,10 @@ interface PluginInterface extends ListenerAggregateInterface * * @return PluginInterface */ - public function setOptions(PluginOptions $options); + public function setOptions(PluginOptions $options): self; /** * Get options - * - * @return PluginOptions */ - public function getOptions(); + public function getOptions(): PluginOptions; } diff --git a/src/Storage/Plugin/PluginOptions.php b/src/Storage/Plugin/PluginOptions.php index 008a7950..efbfb90d 100644 --- a/src/Storage/Plugin/PluginOptions.php +++ b/src/Storage/Plugin/PluginOptions.php @@ -6,21 +6,17 @@ use Laminas\Serializer\Adapter\AdapterInterface as SerializerAdapter; use Laminas\Serializer\Serializer as SerializerFactory; use Laminas\Stdlib\AbstractOptions; +use Webmozart\Assert\Assert; -use function get_debug_type; use function is_callable; -use function is_string; -use function sprintf; class PluginOptions extends AbstractOptions { /** * Used by: * - ClearByFactor - * - * @var int */ - protected $clearingFactor = 0; + protected int $clearingFactor = 0; /** * Used by: @@ -33,53 +29,41 @@ class PluginOptions extends AbstractOptions /** * Used by: * - IgnoreUserAbort - * - * @var bool */ - protected $exitOnAbort = true; + protected bool $exitOnAbort = true; /** * Used by: * - OptimizeByFactor - * - * @var int */ - protected $optimizingFactor = 0; + protected int $optimizingFactor = 0; /** * Used by: * - Serializer - * - * @var string|SerializerAdapter + * @phpcs:disable WebimpressCodingStandard.Classes.NoNullValues.Invalid */ - protected $serializer; + protected SerializerAdapter|string|null $serializer = null; /** * Used by: * - Serializer - * - * @var array */ - protected $serializerOptions = []; + protected array $serializerOptions = []; /** * Used by: * - ExceptionHandler - * - * @var bool */ - protected $throwExceptions = true; + protected bool $throwExceptions = true; /** * Set automatic clearing factor * * Used by: * - ClearExpiredByFactor - * - * @param int $clearingFactor - * @return PluginOptions Provides a fluent interface */ - public function setClearingFactor($clearingFactor) + public function setClearingFactor(int $clearingFactor): self { $this->clearingFactor = $this->normalizeFactor($clearingFactor); return $this; @@ -90,10 +74,8 @@ public function setClearingFactor($clearingFactor) * * Used by: * - ClearExpiredByFactor - * - * @return int */ - public function getClearingFactor() + public function getClearingFactor(): int { return $this->clearingFactor; } @@ -104,11 +86,9 @@ public function getClearingFactor() * Used by: * - ExceptionHandler * - * @param null|callable $exceptionCallback * @throws Exception\InvalidArgumentException - * @return PluginOptions Provides a fluent interface */ - public function setExceptionCallback($exceptionCallback) + public function setExceptionCallback(null|callable $exceptionCallback): self { if ($exceptionCallback !== null && ! is_callable($exceptionCallback, true)) { throw new Exception\InvalidArgumentException('Not a valid callback'); @@ -122,32 +102,25 @@ public function setExceptionCallback($exceptionCallback) * * Used by: * - ExceptionHandler - * - * @return null|callable */ - public function getExceptionCallback() + public function getExceptionCallback(): callable|null { return $this->exceptionCallback; } /** * Exit if connection aborted and ignore_user_abort is disabled. - * - * @param bool $exitOnAbort - * @return PluginOptions Provides a fluent interface */ - public function setExitOnAbort($exitOnAbort) + public function setExitOnAbort(bool $exitOnAbort): self { - $this->exitOnAbort = (bool) $exitOnAbort; + $this->exitOnAbort = $exitOnAbort; return $this; } /** * Exit if connection aborted and ignore_user_abort is disabled. - * - * @return bool */ - public function getExitOnAbort() + public function getExitOnAbort(): bool { return $this->exitOnAbort; } @@ -157,11 +130,8 @@ public function getExitOnAbort() * * Used by: * - OptimizeByFactor - * - * @param int $optimizingFactor - * @return PluginOptions Provides a fluent interface */ - public function setOptimizingFactor($optimizingFactor) + public function setOptimizingFactor(int $optimizingFactor): self { $this->optimizingFactor = $this->normalizeFactor($optimizingFactor); return $this; @@ -172,10 +142,8 @@ public function setOptimizingFactor($optimizingFactor) * * Used by: * - OptimizeByFactor - * - * @return int */ - public function getOptimizingFactor() + public function getOptimizingFactor(): int { return $this->optimizingFactor; } @@ -186,23 +154,10 @@ public function getOptimizingFactor() * Used by: * - Serializer * - * @param string|SerializerAdapter $serializer * @throws Exception\InvalidArgumentException - * @return PluginOptions Provides a fluent interface */ - public function setSerializer($serializer) + public function setSerializer(string|SerializerAdapter $serializer): self { - if (! is_string($serializer) && ! $serializer instanceof SerializerAdapter) { - /** - * Until we do lack native type-hint we should check the `$serializer` twice. - */ - throw new Exception\InvalidArgumentException(sprintf( - '%s expects either a string serializer name or Laminas\Serializer\Adapter\AdapterInterface instance; ' - . 'received "%s"', - __METHOD__, - get_debug_type($serializer) - )); - } $this->serializer = $serializer; return $this; } @@ -212,14 +167,12 @@ public function setSerializer($serializer) * * Used by: * - Serializer - * - * @return SerializerAdapter */ - public function getSerializer() + public function getSerializer(): SerializerAdapter { if (! $this->serializer instanceof SerializerAdapter) { // use default serializer - if (! $this->serializer) { + if ($this->serializer === null || $this->serializer === '') { $this->setSerializer(SerializerFactory::getDefaultAdapter()); // instantiate by class name + serializer_options } else { @@ -227,6 +180,7 @@ public function getSerializer() $this->setSerializer(SerializerFactory::factory($this->serializer, $options)); } } + Assert::notNull($this->serializer); return $this->serializer; } @@ -235,10 +189,8 @@ public function getSerializer() * * Used by: * - Serializer - * - * @return PluginOptions Provides a fluent interface */ - public function setSerializerOptions(mixed $serializerOptions) + public function setSerializerOptions(array $serializerOptions): self { $this->serializerOptions = $serializerOptions; return $this; @@ -252,7 +204,7 @@ public function setSerializerOptions(mixed $serializerOptions) * * @return array */ - public function getSerializerOptions() + public function getSerializerOptions(): array { return $this->serializerOptions; } @@ -262,13 +214,10 @@ public function getSerializerOptions() * * Used by: * - ExceptionHandler - * - * @param bool $throwExceptions - * @return PluginOptions Provides a fluent interface */ - public function setThrowExceptions($throwExceptions) + public function setThrowExceptions(bool $throwExceptions): self { - $this->throwExceptions = (bool) $throwExceptions; + $this->throwExceptions = $throwExceptions; return $this; } @@ -277,10 +226,8 @@ public function setThrowExceptions($throwExceptions) * * Used by: * - ExceptionHandler - * - * @return bool */ - public function getThrowExceptions() + public function getThrowExceptions(): bool { return $this->throwExceptions; } @@ -290,13 +237,11 @@ public function getThrowExceptions() * * Cast to int and ensure we have a value greater than zero. * - * @param int $factor - * @return int + * @return non-negative-int * @throws Exception\InvalidArgumentException */ - protected function normalizeFactor($factor) + protected function normalizeFactor(int $factor): int { - $factor = (int) $factor; if ($factor < 0) { throw new Exception\InvalidArgumentException( "Invalid factor '{$factor}': must be greater or equal 0" diff --git a/src/Storage/Plugin/Serializer.php b/src/Storage/Plugin/Serializer.php index f9c077f7..c50bafea 100644 --- a/src/Storage/Plugin/Serializer.php +++ b/src/Storage/Plugin/Serializer.php @@ -12,13 +12,12 @@ class Serializer extends AbstractPlugin { - /** @var array */ - protected $capabilities = []; + protected array $capabilities = []; /** * {@inheritDoc} */ - public function attach(EventManagerInterface $events, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1): void { // The higher the priority the sooner the plugin will be called on pre events // but the later it will be called on post events. @@ -47,10 +46,8 @@ public function attach(EventManagerInterface $events, $priority = 1) /** * On read item post - * - * @return void */ - public function onReadItemPost(PostEvent $event) + public function onReadItemPost(PostEvent $event): void { $result = $event->getResult(); if ($result !== null) { @@ -62,25 +59,21 @@ public function onReadItemPost(PostEvent $event) /** * On read items post - * - * @return void */ - public function onReadItemsPost(PostEvent $event) + public function onReadItemsPost(PostEvent $event): void { $serializer = $this->getOptions()->getSerializer(); $result = $event->getResult(); - foreach ($result as &$value) { - $value = $serializer->unserialize($value); + foreach ($result as $index => $value) { + $result[$index] = $serializer->unserialize($value); } $event->setResult($result); } /** * On write item pre - * - * @return void */ - public function onWriteItemPre(Event $event) + public function onWriteItemPre(Event $event): void { $serializer = $this->getOptions()->getSerializer(); $params = $event->getParams(); @@ -93,24 +86,21 @@ public function onWriteItemPre(Event $event) /** * On write items pre - * - * @return void */ - public function onWriteItemsPre(Event $event) + public function onWriteItemsPre(Event $event): void { $serializer = $this->getOptions()->getSerializer(); $params = $event->getParams(); - foreach ($params['keyValuePairs'] as &$value) { - $value = $serializer->serialize($value); + foreach ($params['keyValuePairs'] as $index => $value) { + $value = $serializer->serialize($value); + $params['keyValuePairs'][$index] = $value; } } /** * On get capabilities - * - * @return void */ - public function onGetCapabilitiesPost(PostEvent $event) + public function onGetCapabilitiesPost(PostEvent $event): void { $baseCapabilities = $event->getResult(); $index = spl_object_hash($baseCapabilities); diff --git a/src/Storage/PluginAwareInterface.php b/src/Storage/PluginAwareInterface.php index 57c76357..58dd466e 100644 --- a/src/Storage/PluginAwareInterface.php +++ b/src/Storage/PluginAwareInterface.php @@ -9,17 +9,14 @@ interface PluginAwareInterface extends PluginCapableInterface /** * Register a plugin * - * @param int $priority - * @return StorageInterface * @throws Exception\LogicException */ - public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1); + public function addPlugin(Plugin\PluginInterface $plugin, int $priority = 1): StorageInterface&PluginAwareInterface; /** * Unregister an already registered plugin * - * @return StorageInterface * @throws Exception\LogicException */ - public function removePlugin(Plugin\PluginInterface $plugin); + public function removePlugin(Plugin\PluginInterface $plugin): StorageInterface&PluginAwareInterface; } diff --git a/src/Storage/PluginCapableInterface.php b/src/Storage/PluginCapableInterface.php index 0f8ada52..2103c008 100644 --- a/src/Storage/PluginCapableInterface.php +++ b/src/Storage/PluginCapableInterface.php @@ -9,15 +9,11 @@ interface PluginCapableInterface extends EventsCapableInterface { /** * Check if a plugin is registered - * - * @return bool */ - public function hasPlugin(Plugin\PluginInterface $plugin); + public function hasPlugin(Plugin\PluginInterface $plugin): bool; /** * Return registry of plugins - * - * @return SplObjectStorage */ - public function getPluginRegistry(); + public function getPluginRegistry(): SplObjectStorage; } diff --git a/src/Storage/PostEvent.php b/src/Storage/PostEvent.php index 725d6060..66224c53 100644 --- a/src/Storage/PostEvent.php +++ b/src/Storage/PostEvent.php @@ -8,20 +8,15 @@ class PostEvent extends Event { /** * The result/return value - * - * @var mixed */ - protected $result; + protected mixed $result; /** - * Constructor - * * Accept a target and its parameters. * - * @param string $name - * @param mixed $result + * @param non-empty-string $name Event name */ - public function __construct($name, StorageInterface $storage, ArrayObject $params, &$result) + public function __construct(string $name, StorageInterface $storage, ArrayObject $params, mixed $result) { parent::__construct($name, $storage, $params); $this->setResult($result); @@ -29,21 +24,17 @@ public function __construct($name, StorageInterface $storage, ArrayObject $param /** * Set the result/return value - * - * @return PostEvent */ - public function setResult(mixed &$value) + public function setResult(mixed $value): self { - $this->result = &$value; + $this->result = $value; return $this; } /** * Get the result/return value - * - * @return mixed */ - public function &getResult() + public function getResult(): mixed { return $this->result; } diff --git a/src/Storage/StorageInterface.php b/src/Storage/StorageInterface.php index eb01bd93..8eb5d7fc 100644 --- a/src/Storage/StorageInterface.php +++ b/src/Storage/StorageInterface.php @@ -3,112 +3,106 @@ namespace Laminas\Cache\Storage; use Laminas\Cache\Exception\ExceptionInterface; -use Traversable; interface StorageInterface { /** * Set options. - * - * @param array|Traversable|Adapter\AdapterOptions $options - * @return StorageInterface Fluent interface */ - public function setOptions($options); + public function setOptions(iterable|Adapter\AdapterOptions $options): self; /** * Get options - * - * @return Adapter\AdapterOptions */ - public function getOptions(); + public function getOptions(): Adapter\AdapterOptions; /* reading */ /** * Get an item. * - * @param string $key - * @param bool $success + * @param non-empty-string $key + * @param-out bool $success * @return mixed Data on success, null on failure * @throws ExceptionInterface */ - public function getItem($key, &$success = null, mixed &$casToken = null); + public function getItem(string $key, bool|null &$success = null, mixed &$casToken = null): mixed; /** * Get multiple items. * - * @return array Associative array of keys and values + * @param non-empty-list $keys + * @return array Associative array of keys and values * @throws ExceptionInterface */ - public function getItems(array $keys); + public function getItems(array $keys): array; /** * Test if an item exists. * - * @param string $key - * @return bool + * @param non-empty-string $key * @throws ExceptionInterface */ - public function hasItem($key); + public function hasItem(string $key): bool; /** * Test multiple items. * - * @return array Array of found keys + * @param non-empty-list $keys + * @return list Array of found keys * @throws ExceptionInterface */ - public function hasItems(array $keys); + public function hasItems(array $keys): array; /* writing */ /** * Store an item. * - * @param string $key - * @return bool + * @param non-empty-string $key * @throws ExceptionInterface */ - public function setItem($key, mixed $value); + public function setItem(string $key, mixed $value): bool; /** * Store multiple items. * - * @return array Array of not stored keys + * @param non-empty-array $keyValuePairs + * @return list Array of not stored keys * @throws ExceptionInterface */ - public function setItems(array $keyValuePairs); + public function setItems(array $keyValuePairs): array; /** * Add an item. * - * @param string $key - * @return bool * @throws ExceptionInterface */ - public function addItem($key, mixed $value); + public function addItem(string $key, mixed $value): bool; /** * Add multiple items. * - * @return array Array of not stored keys + * @param non-empty-array $keyValuePairs + * @return list Array of not stored keys * @throws ExceptionInterface */ - public function addItems(array $keyValuePairs); + public function addItems(array $keyValuePairs): array; /** * Replace an existing item. * - * @param string $key - * @return bool + * @param non-empty-string $key * @throws ExceptionInterface */ - public function replaceItem($key, mixed $value); + public function replaceItem(string $key, mixed $value): bool; /** * Replace multiple existing items. * - * @return array Array of not stored keys + * @param non-empty-array $keyValuePairs + * @return list Array of not stored keys * @throws ExceptionInterface */ - public function replaceItems(array $keyValuePairs); + public function replaceItems(array $keyValuePairs): array; /** * Set an item only if token matches @@ -119,52 +113,50 @@ public function replaceItems(array $keyValuePairs); * @see getItem() * @see setItem() * - * @param string $key - * @return bool + * @param non-empty-string $key + * * @throws ExceptionInterface */ - public function checkAndSetItem(mixed $token, $key, mixed $value); + public function checkAndSetItem(mixed $token, string $key, mixed $value): bool; /** * Reset lifetime of an item * - * @param string $key - * @return bool + * @param non-empty-string $key * @throws ExceptionInterface */ - public function touchItem($key); + public function touchItem(string $key): bool; /** * Reset lifetime of multiple items. * - * @return array Array of not updated keys + * @param non-empty-list $keys + * @return list Array of not updated keys * @throws ExceptionInterface */ - public function touchItems(array $keys); + public function touchItems(array $keys): array; /** * Remove an item. * - * @param string $key - * @return bool + * @param non-empty-string $key * @throws ExceptionInterface */ - public function removeItem($key); + public function removeItem(string $key): bool; /** * Remove multiple items. * - * @return array Array of not removed keys + * @param non-empty-list $keys + * @return list Array of not removed keys * @throws ExceptionInterface */ - public function removeItems(array $keys); + public function removeItems(array $keys): array; /* status */ /** * Capabilities of this storage - * - * @return Capabilities */ - public function getCapabilities(); + public function getCapabilities(): Capabilities; } diff --git a/src/Storage/TaggableInterface.php b/src/Storage/TaggableInterface.php index 0dc9da8c..0947a462 100644 --- a/src/Storage/TaggableInterface.php +++ b/src/Storage/TaggableInterface.php @@ -8,19 +8,16 @@ interface TaggableInterface * Set tags to an item by given key. * An empty array will remove all tags. * - * @param string $key * @param string[] $tags - * @return bool */ - public function setTags($key, array $tags); + public function setTags(string $key, array $tags): bool; /** * Get tags of an item by given key * - * @param string $key - * @return string[]|FALSE + * @return string[]|false */ - public function getTags($key); + public function getTags(string $key): false|array; /** * Remove items matching given tags. @@ -29,8 +26,6 @@ public function getTags($key); * else all given tags must match. * * @param string[] $tags - * @param bool $disjunction - * @return bool */ - public function clearByTags(array $tags, $disjunction = false); + public function clearByTags(array $tags, bool $disjunction = false): bool; } diff --git a/src/Storage/TotalSpaceCapableInterface.php b/src/Storage/TotalSpaceCapableInterface.php index a9acc784..8cb95168 100644 --- a/src/Storage/TotalSpaceCapableInterface.php +++ b/src/Storage/TotalSpaceCapableInterface.php @@ -6,8 +6,6 @@ interface TotalSpaceCapableInterface { /** * Get total space in bytes - * - * @return int|float */ - public function getTotalSpace(); + public function getTotalSpace(): int; } diff --git a/test/Pattern/AbstractCommonPatternTest.php b/test/Pattern/AbstractCommonPatternTest.php index 9ad2a282..856019e8 100644 --- a/test/Pattern/AbstractCommonPatternTest.php +++ b/test/Pattern/AbstractCommonPatternTest.php @@ -14,11 +14,9 @@ */ abstract class AbstractCommonPatternTest extends TestCase { - /** @var PatternInterface */ - protected $pattern; + protected PatternInterface $pattern; - /** @var PatternOptions */ - protected $options; + protected PatternOptions $options; protected function setUp(): void { diff --git a/test/Pattern/AbstractCommonStoragePatternTest.php b/test/Pattern/AbstractCommonStoragePatternTest.php index 586330b0..4ce5fd7c 100644 --- a/test/Pattern/AbstractCommonStoragePatternTest.php +++ b/test/Pattern/AbstractCommonStoragePatternTest.php @@ -18,10 +18,10 @@ abstract class AbstractCommonStoragePatternTest extends AbstractCommonPatternTest { /** @var StorageInterface&MockObject */ - protected $storage; + protected StorageInterface&MockObject $storage; /** @var TPattern */ - protected $pattern; + protected PatternInterface $pattern; protected function setUp(): void { diff --git a/test/Pattern/ObjectCacheTest.php b/test/Pattern/ObjectCacheTest.php index c1e0772c..66424915 100644 --- a/test/Pattern/ObjectCacheTest.php +++ b/test/Pattern/ObjectCacheTest.php @@ -6,7 +6,6 @@ use Laminas\Cache; use Laminas\Cache\Pattern\ObjectCache; -use Laminas\Cache\Pattern\PatternOptions; use Laminas\Cache\Storage\StorageInterface; use LaminasTest\Cache\Pattern\TestAsset\TestObjectCache; @@ -22,9 +21,6 @@ */ class ObjectCacheTest extends AbstractCommonStoragePatternTest { - /** @var PatternOptions */ - protected $options; - protected function setUp(): void { $this->storage = $this->createMock(StorageInterface::class); @@ -127,6 +123,7 @@ public function testEmptyObjectKeys(): void } /** + * @param non-empty-string $method * @param array $args */ protected function executeMethodAndMakeAssertions(string $method, array $args): void diff --git a/test/Pattern/OutputCacheTest.php b/test/Pattern/OutputCacheTest.php index 0c468f91..2194eb01 100644 --- a/test/Pattern/OutputCacheTest.php +++ b/test/Pattern/OutputCacheTest.php @@ -4,7 +4,6 @@ namespace LaminasTest\Cache\Pattern; -use Laminas\Cache\Exception\MissingKeyException; use Laminas\Cache\Pattern\OutputCache; use Laminas\Cache\Storage\StorageInterface; @@ -108,10 +107,4 @@ public function testStartEndCacheHit(): void self::assertSame($output, $data); } - - public function testThrowMissingKeyException(): void - { - $this->expectException(MissingKeyException::class); - $this->pattern->start(''); // empty key - } } diff --git a/test/Psr/CacheItemPool/CacheItemPoolDecoratorTest.php b/test/Psr/CacheItemPool/CacheItemPoolDecoratorTest.php index fb8960e1..4cdb710b 100644 --- a/test/Psr/CacheItemPool/CacheItemPoolDecoratorTest.php +++ b/test/Psr/CacheItemPool/CacheItemPoolDecoratorTest.php @@ -901,18 +901,6 @@ protected function tearDown(): void parent::tearDown(); } - public function testCanHandleRemoveItemsReturningNonArray(): void - { - $this->storage - ->expects(self::once()) - ->method('removeItems') - ->with(['foo']) - ->willReturn(null); - - assert($this->adapter instanceof CacheItemPoolDecorator); - self::assertFalse($this->adapter->deleteItems(['foo'])); - } - /** * @dataProvider deletionVerificationProvider */ diff --git a/test/Psr/SimpleCache/SimpleCacheDecoratorTest.php b/test/Psr/SimpleCache/SimpleCacheDecoratorTest.php index e1158424..05d831f8 100644 --- a/test/Psr/SimpleCache/SimpleCacheDecoratorTest.php +++ b/test/Psr/SimpleCache/SimpleCacheDecoratorTest.php @@ -483,7 +483,7 @@ public function testClearReturnsFalseIfStorageIsNotFlushable(): void $this->options ->expects(self::once()) ->method('getNamespace') - ->willReturn(null); + ->willReturn(''); $storage = $this->createMock(StorageInterface::class); $storage @@ -531,7 +531,7 @@ public function testClearProxiesToStorageFlushIfStorageCanBeClearedByNamespaceWi $this->options ->expects(self::once()) ->method('getNamespace') - ->willReturn(null); + ->willReturn(''); $storage = $this->createMock(FlushableNamespaceStorageInterface::class); diff --git a/test/Psr/SimpleCache/TestAsset/TtlStorage.php b/test/Psr/SimpleCache/TestAsset/TtlStorage.php index ea94e6f3..800695e1 100644 --- a/test/Psr/SimpleCache/TestAsset/TtlStorage.php +++ b/test/Psr/SimpleCache/TestAsset/TtlStorage.php @@ -5,31 +5,28 @@ namespace LaminasTest\Cache\Psr\SimpleCache\TestAsset; use Laminas\Cache\Storage\Adapter; +use Laminas\Cache\Storage\Adapter\AdapterOptions; use Laminas\Cache\Storage\Capabilities; +/** + * @template TOptions of AdapterOptions + * @template-extends Adapter\AbstractAdapter + */ class TtlStorage extends Adapter\AbstractAdapter { private array $data = []; /** @var array */ - public $ttl = []; + public array $ttl = []; - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$casToken = null) + protected function internalGetItem(string $normalizedKey, ?bool &$success = null, mixed &$casToken = null): mixed { $success = isset($this->data[$normalizedKey]); return $success ? $this->data[$normalizedKey] : null; } - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalSetItem(&$normalizedKey, mixed &$value) + protected function internalSetItem(string $normalizedKey, mixed $value): bool { $this->ttl[$normalizedKey] = $this->getOptions()->getTtl(); @@ -37,17 +34,13 @@ protected function internalSetItem(&$normalizedKey, mixed &$value) return true; } - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalRemoveItem(&$normalizedKey) + protected function internalRemoveItem(string $normalizedKey): bool { unset($this->data[$normalizedKey]); return true; } - public function setCapabilities(Capabilities $capabilities) + public function setCapabilities(Capabilities $capabilities): void { $this->capabilities = $capabilities; } diff --git a/test/StaticAnalysis/MetadataCapableAdapter.php b/test/StaticAnalysis/MetadataCapableAdapter.php index 0f222bbd..b1b8a2bf 100644 --- a/test/StaticAnalysis/MetadataCapableAdapter.php +++ b/test/StaticAnalysis/MetadataCapableAdapter.php @@ -5,16 +5,19 @@ namespace LaminasTest\Cache\StaticAnalysis; use Laminas\Cache\Storage\AbstractMetadataCapableAdapter; +use Laminas\Cache\Storage\Adapter\AdapterOptions; /** - * @template-extends AbstractMetadataCapableAdapter + * @uses AdapterOptions + * + * @template-extends AbstractMetadataCapableAdapter */ final class MetadataCapableAdapter extends AbstractMetadataCapableAdapter { /** * {@inheritDoc} */ - protected function internalHasItem(&$normalizedKey) + protected function internalHasItem(string $normalizedKey): bool { return true; } @@ -22,7 +25,7 @@ protected function internalHasItem(&$normalizedKey) /** * {@inheritDoc} */ - protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$casToken = null) + protected function internalGetItem(string $normalizedKey, ?bool &$success = null, mixed &$casToken = null): mixed { return null; } @@ -30,7 +33,7 @@ protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$ca /** * {@inheritDoc} */ - protected function internalSetItem(&$normalizedKey, mixed &$value) + protected function internalSetItem(string $normalizedKey, mixed $value): bool { return false; } @@ -38,7 +41,7 @@ protected function internalSetItem(&$normalizedKey, mixed &$value) /** * {@inheritDoc} */ - protected function internalRemoveItem(&$normalizedKey) + protected function internalRemoveItem(string $normalizedKey): bool { return false; } diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index c03122a7..cf17b05a 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -27,7 +27,6 @@ use function array_keys; use function array_merge; use function array_unique; -use function assert; use function call_user_func_array; use function count; use function current; @@ -112,7 +111,7 @@ public function testSetKeyPattern(): void public function testUnsetKeyPattern(): void { - $this->options->setKeyPattern(null); + $this->options->setKeyPattern(''); self::assertSame('', $this->options->getKeyPattern()); } @@ -209,7 +208,7 @@ public function testInternalTriggerPost(): void self::assertSame($result, $event->getResult()); } - public function testInternalTriggerExceptionThrowRuntimeException(): void + public function testInternalTriggerThrowableThrowsRuntimeException(): void { $storage = $this->getMockForAbstractAdapter(); @@ -223,7 +222,7 @@ public function testInternalTriggerExceptionThrowRuntimeException(): void ]); // call protected method - $method = new ReflectionMethod($storage::class, 'triggerException'); + $method = new ReflectionMethod($storage::class, 'triggerThrowable'); $this->expectException(RuntimeException::class); $this->expectExceptionMessage('test'); @@ -802,13 +801,14 @@ protected function checkPreEventCanChangeArguments(string $method, array $args, $storage = $this->getMockForAbstractAdapter([$internalMethod]); $storage->getEventManager()->attach($eventName, static function (Event $event) use ($expectedArgs): void { $params = $event->getParams(); - /** @psalm-suppress RedundantConditionGivenDocblockType */ - assert($params instanceof ArrayObject); $params->exchangeArray(array_merge($params->getArrayCopy(), $expectedArgs)); }); // set expected arguments of internal method call - $tmp = $storage->expects($this->once())->method($internalMethod); + $tmp = $storage + ->expects($this->once()) + ->method($internalMethod); + $equals = []; foreach ($expectedArgs as $v) { $equals[] = $this->equalTo($v); diff --git a/test/Storage/Adapter/TestAsset/AdapterOptionsWithPrioritizedOptions.php b/test/Storage/Adapter/TestAsset/AdapterOptionsWithPrioritizedOptions.php index 85d618cf..d45c84f7 100644 --- a/test/Storage/Adapter/TestAsset/AdapterOptionsWithPrioritizedOptions.php +++ b/test/Storage/Adapter/TestAsset/AdapterOptionsWithPrioritizedOptions.php @@ -9,7 +9,10 @@ final class AdapterOptionsWithPrioritizedOptions extends AdapterOptions { // @codingStandardsIgnoreStart - protected $__prioritizedProperties__ = [ + /** + * @var string[] + */ + protected array $__prioritizedProperties__ = [ 'key_pattern', 'namespace', ]; diff --git a/test/Storage/TestAsset/ClearExpiredMockAdapter.php b/test/Storage/TestAsset/ClearExpiredMockAdapter.php index 5c40e30b..a4aa8be5 100644 --- a/test/Storage/TestAsset/ClearExpiredMockAdapter.php +++ b/test/Storage/TestAsset/ClearExpiredMockAdapter.php @@ -4,11 +4,17 @@ namespace LaminasTest\Cache\Storage\TestAsset; +use Laminas\Cache\Storage\Adapter\AdapterOptions; use Laminas\Cache\Storage\ClearExpiredInterface; +/** + * @template TOptions of AdapterOptions + * @template-extends MockAdapter + */ class ClearExpiredMockAdapter extends MockAdapter implements ClearExpiredInterface { - public function clearExpired() + public function clearExpired(): bool { + return true; } } diff --git a/test/Storage/TestAsset/MockAdapter.php b/test/Storage/TestAsset/MockAdapter.php index 5f06d2d5..f126fd0f 100644 --- a/test/Storage/TestAsset/MockAdapter.php +++ b/test/Storage/TestAsset/MockAdapter.php @@ -5,30 +5,26 @@ namespace LaminasTest\Cache\Storage\TestAsset; use Laminas\Cache\Storage\Adapter\AbstractAdapter; +use Laminas\Cache\Storage\Adapter\AdapterOptions; +/** + * @template TOptions of AdapterOptions + * @template-extends AbstractAdapter + */ class MockAdapter extends AbstractAdapter { - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalGetItem(&$normalizedKey, &$success = null, mixed &$casToken = null) + protected function internalGetItem(string $normalizedKey, ?bool &$success = null, mixed &$casToken = null): mixed { + return null; } - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalSetItem(&$normalizedKey, mixed &$value) + protected function internalSetItem(string $normalizedKey, mixed $value): bool { + return true; } - /** - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint - * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint - */ - protected function internalRemoveItem(&$normalizedKey) + protected function internalRemoveItem(string $normalizedKey): bool { + return true; } } diff --git a/test/Storage/TestAsset/MockPlugin.php b/test/Storage/TestAsset/MockPlugin.php index a4fdd48c..a99e3bad 100644 --- a/test/Storage/TestAsset/MockPlugin.php +++ b/test/Storage/TestAsset/MockPlugin.php @@ -11,17 +11,14 @@ class MockPlugin extends AbstractPlugin { - /** @var Plugin\PluginOptions */ - protected $options; - /** @var array */ - protected $handles = []; + protected array $handles = []; /** @var array */ - protected $calledEvents = []; + protected array $calledEvents = []; /** @var array */ - protected $eventCallbacks = [ + protected array $eventCallbacks = [ 'setItem.pre' => 'onSetItemPre', 'setItem.post' => 'onSetItemPost', ]; @@ -40,11 +37,6 @@ public function setOptions(Plugin\PluginOptions $options): self return $this; } - public function getOptions(): Plugin\PluginOptions - { - return $this->options; - } - /** * @param int $priority */ diff --git a/test/Storage/TestAsset/OptimizableMockAdapter.php b/test/Storage/TestAsset/OptimizableMockAdapter.php index 7aa1d35c..b03c1b2d 100644 --- a/test/Storage/TestAsset/OptimizableMockAdapter.php +++ b/test/Storage/TestAsset/OptimizableMockAdapter.php @@ -4,11 +4,17 @@ namespace LaminasTest\Cache\Storage\TestAsset; +use Laminas\Cache\Storage\Adapter\AdapterOptions; use Laminas\Cache\Storage\OptimizableInterface; +/** + * @template TOptions of AdapterOptions + * @template-extends MockAdapter + */ class OptimizableMockAdapter extends MockAdapter implements OptimizableInterface { - public function optimize() + public function optimize(): bool { + return true; } }