diff --git a/.laminas-ci.json b/.laminas-ci.json index 623a8eca..df25c514 100644 --- a/.laminas-ci.json +++ b/.laminas-ci.json @@ -1,5 +1,6 @@ { - "ignore_php_platform_requirements": { - "8.3": true - } + "ignore_php_platform_requirements": { + "8.3": false + }, + "backwardCompatibilityCheck": true } diff --git a/composer.json b/composer.json index 571b84ce..060f82fe 100644 --- a/composer.json +++ b/composer.json @@ -39,11 +39,11 @@ }, "require-dev": { "laminas/laminas-coding-standard": "~2.5.0", - "pear/archive_tar": "^1.4.14", - "phpunit/phpunit": "^10.5.11", + "pear/archive_tar": "^1.5.0", + "phpunit/phpunit": "^10.5.20", "psalm/plugin-phpunit": "^0.19.0", - "psr/http-factory": "^1.0.2", - "vimeo/psalm": "^5.22.2" + "psr/http-factory": "^1.1.0", + "vimeo/psalm": "^5.24.0" }, "conflict": { "laminas/laminas-validator": "<2.10.1", diff --git a/composer.lock b/composer.lock index 14f056fb..166f7ca6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "494a41a79c1b61ce078ae5eb5e230184", + "content-hash": "948e8e0f3c009716155def9307d2353d", "packages": [ { "name": "brick/varexporter", @@ -403,16 +403,16 @@ }, { "name": "amphp/byte-stream", - "version": "v1.8.1", + "version": "v1.8.2", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", "shasum": "" }, "require": { @@ -428,11 +428,6 @@ "psalm/phar": "^3.11.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { "files": [ "lib/functions.php" @@ -456,7 +451,7 @@ } ], "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", + "homepage": "https://amphp.org/byte-stream", "keywords": [ "amp", "amphp", @@ -466,9 +461,8 @@ "stream" ], "support": { - "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" }, "funding": [ { @@ -476,7 +470,7 @@ "type": "github" } ], - "time": "2021-03-30T17:13:30+00:00" + "time": "2024-04-13T18:00:56+00:00" }, { "name": "composer/package-versions-deprecated", @@ -553,16 +547,16 @@ }, { "name": "composer/pcre", - "version": "3.1.3", + "version": "3.1.4", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8" + "reference": "04229f163664973f68f38f6f73d917799168ef24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8", - "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8", + "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", + "reference": "04229f163664973f68f38f6f73d917799168ef24", "shasum": "" }, "require": { @@ -604,7 +598,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.3" + "source": "https://github.com/composer/pcre/tree/3.1.4" }, "funding": [ { @@ -620,7 +614,7 @@ "type": "tidelift" } ], - "time": "2024-03-19T10:26:25+00:00" + "time": "2024-05-27T13:40:54+00:00" }, { "name": "composer/semver", @@ -705,16 +699,16 @@ }, { "name": "composer/xdebug-handler", - "version": "3.0.4", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255" + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255", - "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { @@ -751,7 +745,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.4" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { @@ -767,7 +761,7 @@ "type": "tidelift" } ], - "time": "2024-03-26T18:29:49+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", @@ -1101,16 +1095,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -1118,11 +1112,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -1148,7 +1143,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -1156,7 +1151,7 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "netresearch/jsonmapper", @@ -2088,16 +2083,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.16", + "version": "10.5.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd" + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", - "reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/547d314dc24ec1e177720d45c6263fb226cc2ae3", + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3", "shasum": "" }, "require": { @@ -2169,7 +2164,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.20" }, "funding": [ { @@ -2185,7 +2180,7 @@ "type": "tidelift" } ], - "time": "2024-03-28T10:08:10+00:00" + "time": "2024-04-24T06:32:35+00:00" }, { "name": "psalm/plugin-phpunit", @@ -2249,20 +2244,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -2286,7 +2281,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -2298,9 +2293,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -3384,16 +3379,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.2.3", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab" + "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/c95fd4db94ec199f798d4b5b4a81757bd20d88ab", - "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f56b220fe2db1ade4c88098d83413ebdfc3bf876", + "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876", "shasum": "" }, "require": { @@ -3406,6 +3401,11 @@ "spatie/pest-plugin-snapshots": "^1.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { "Spatie\\ArrayToXml\\": "src" @@ -3431,7 +3431,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.3" + "source": "https://github.com/spatie/array-to-xml/tree/3.3.0" }, "funding": [ { @@ -3443,20 +3443,20 @@ "type": "github" } ], - "time": "2024-02-07T10:39:02+00:00" + "time": "2024-05-01T10:20:27+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.1", + "version": "3.10.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909" + "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/267a4405fff1d9c847134db3a3c92f1ab7f77909", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", + "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", "shasum": "" }, "require": { @@ -3523,20 +3523,20 @@ "type": "open_collective" } ], - "time": "2024-03-31T21:03:09+00:00" + "time": "2024-05-22T21:24:41+00:00" }, { "name": "symfony/console", - "version": "v6.4.6", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f" + "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a2708a5da5c87d1d0d52937bdeac625df659e11f", - "reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f", + "url": "https://api.github.com/repos/symfony/console/zipball/be5854cee0e8c7b110f00d695d11debdfa1a2a91", + "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91", "shasum": "" }, "require": { @@ -3601,7 +3601,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.6" + "source": "https://github.com/symfony/console/tree/v6.4.8" }, "funding": [ { @@ -3617,20 +3617,20 @@ "type": "tidelift" } ], - "time": "2024-03-29T19:07:53+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -3639,7 +3639,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3668,7 +3668,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -3684,20 +3684,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.6", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3" + "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/9919b5509ada52cc7f66f9a35c86a4a29955c9d3", - "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d37529150e7081c51b3c5d5718c55a04a9503f3", + "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3", "shasum": "" }, "require": { @@ -3705,6 +3705,9 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -3731,7 +3734,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.6" + "source": "https://github.com/symfony/filesystem/tree/v6.4.8" }, "funding": [ { @@ -3747,7 +3750,7 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:36:20+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4069,21 +4072,22 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.2", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -4091,7 +4095,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -4131,7 +4135,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -4147,20 +4151,20 @@ "type": "tidelift" } ], - "time": "2023-12-19T21:51:00+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/string", - "version": "v6.4.4", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" + "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "url": "https://api.github.com/repos/symfony/string/zipball/a147c0f826c4a1f3afb763ab8e009e37c877a44d", + "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d", "shasum": "" }, "require": { @@ -4217,7 +4221,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.4" + "source": "https://github.com/symfony/string/tree/v6.4.8" }, "funding": [ { @@ -4233,7 +4237,7 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:16:41+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "theseer/tokenizer", @@ -4287,16 +4291,16 @@ }, { "name": "vimeo/psalm", - "version": "5.23.1", + "version": "5.24.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "8471a896ccea3526b26d082f4461eeea467f10a4" + "reference": "462c80e31c34e58cc4f750c656be3927e80e550e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/8471a896ccea3526b26d082f4461eeea467f10a4", - "reference": "8471a896ccea3526b26d082f4461eeea467f10a4", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/462c80e31c34e58cc4f750c656be3927e80e550e", + "reference": "462c80e31c34e58cc4f750c656be3927e80e550e", "shasum": "" }, "require": { @@ -4393,7 +4397,7 @@ "issues": "https://github.com/vimeo/psalm/issues", "source": "https://github.com/vimeo/psalm" }, - "time": "2024-03-11T20:33:46+00:00" + "time": "2024-05-01T19:32:08+00:00" }, { "name": "webimpress/coding-standard", diff --git a/docs/book/v2/installation.md b/docs/book/v2/installation.md new file mode 100644 index 00000000..be1198c9 --- /dev/null +++ b/docs/book/v2/installation.md @@ -0,0 +1,5 @@ +# This Is Only a Placeholder + +The content of this page can be found under: + +https://github.com/laminas/documentation-theme/blob/master/theme/pages/installation.html diff --git a/docs/book/v2/intro.md b/docs/book/v2/intro.md index 611cdaee..f10ac0ba 100644 --- a/docs/book/v2/intro.md +++ b/docs/book/v2/intro.md @@ -55,6 +55,9 @@ $laminaslove = $strtolower('I LOVE Laminas!'); ## Using the StaticFilter +CAUTION: **Deprecated** +This filter is deprecated since version 2.15.0 and [will be removed](migration/preparing-for-v3.md#static-filter-removal) in version 3.0. + If it is inconvenient to load a given filter class and create an instance of the filter, you can use `StaticFilter` with its `execute()` method as an alternative invocation style. The first argument of this method is a data input value, that diff --git a/docs/book/v2/migration/preparing-for-v3.md b/docs/book/v2/migration/preparing-for-v3.md new file mode 100644 index 00000000..d36e406b --- /dev/null +++ b/docs/book/v2/migration/preparing-for-v3.md @@ -0,0 +1,55 @@ +# Preparing for Version 3 + +Version 3 will introduce a number of backwards incompatible changes. This document is intended to help you prepare for these changes. + +## Removed Features + +### Inheritance Changes + +Most filters will be closed to inheritance in v3 by employing the `final` keyword. +To prepare for this change, search for classes in your codebase that extend from any of the concrete filters and either re-implement them completely, or consider refactoring them to use composition instead of inheritance. + +If you have extended an existing filter for a use-case that is not handled by this library, also consider sending a patch if you think that the library could benefit from your changes. + +### Compression Filter Adapter Removal + +The Lzf, Snappy and Rar compression adapters will be removed in version 3.0. +If you are currently using any of these compression formats with laminas-filter, you will need to either use an alternative format such as Zip, Tar, Gz or Bz2, or, write a custom adapter to support your desired compression format. + +### Encryption & Decryption Filter Removal + +These filters have become outdated and will be removed in version 3.0 of this library. We recommend that you make use of a maintained encryption library and [write your own filters](../writing-filters.md) if you need to encrypt or decrypt content using the `FilterInterface` contract. + +- `Laminas\Filter\File\Decrypt` +- `Laminas\Filter\File\Encrypt` +- `Laminas\Filter\Decrypt` +- `Laminas\Filter\Encrypt` + +### Static Filter Removal + +`Laminas\Filter\StaticFilter` will be removed without replacement in v3. Most filters are "new-able" so similar behaviour can be accomplished with: + +```php +$filtered = (new \Laminas\Filter\HtmlEntities())('Nuts & Bolts'); +``` + +For filters requiring more complex construction, we encourage you to make use of dependency injection and compose the filter itself, or via the `FilterPluginManager`, for example: + +```php +$pluginManager = $container->get(\Laminas\Filter\FilterPluginManager::class); +$filter = $pluginManager->get(\Laminas\Filter\HtmlEntities::class); +$filtered = $filter->filter('A String'); +``` + +### Whitelist & Blacklist Filter Removal + +The deprecated filters `Whitelist` & `Blacklist` will be removed in v3 for their more favourably named counterparts `AllowList` and `DenyList` + +- `Laminas\Filter\Whitelist` has been replaced by [`Laminas\Filter\AllowList`](../standard-filters.md#allowlist) +- `Laminas\Filter\Blacklist` has been replaced by [`Laminas\Filter\DenyList`](../standard-filters.md#denylist) + +### UriNormalize Filter Removal + +The [UriNormalize](../standard-filters.md#urinormalize) filter will be removed in version 3, primarily because its functionality is provided by `laminas-uri` which is no longer maintained. + +There is not a direct replacement, but, if you were using the filter to normalize URL schemes, this functionality has been preserved in a new filter [ForceUriScheme](../standard-filters.md#forceurischeme). diff --git a/docs/book/v2/standard-filters.md b/docs/book/v2/standard-filters.md index ec5ae81d..09cbce30 100644 --- a/docs/book/v2/standard-filters.md +++ b/docs/book/v2/standard-filters.md @@ -1181,6 +1181,25 @@ $decrypted = $filter->filter('encoded_text_normally_unreadable'); print $decrypted; ``` +## ForceUriScheme + +This filter will ensure that, given a string that looks like a URI with a host-name and scheme, the scheme will be forced to `https` by default, or any other arbitrary scheme provided as an option. + +Any value that cannot be identified as an URI to begin with, will be returned un-filtered. Furthermore, URI parsing is rudimentary so for reliable results, you should ensure that the input is a valid URI prior to filtering. + +### Supported Options + +The only supported option is `scheme` which defaults to `https` + +### Example Usage + +```php +$filter = new Laminas\Filter\ForceUriScheme(['scheme' => 'ftp']); + +$filter->filter('https://example.com/path'); // 'ftp://example.com/path' +$filter->filter('example.com'); // 'example.com' - Unfiltered because it lacks a scheme +``` + ## HtmlEntities Returns the string `$value`, converting characters to their corresponding HTML @@ -1912,6 +1931,9 @@ as the result. ## UriNormalize +CAUTION: **Deprecated** +This filter is deprecated since version 2.36.0 and will be removed in version 3.0. The ability to force the scheme has been moved to the [ForceUriScheme filter](#forceurischeme). + This filter sets the scheme on a URI if the scheme is missing. ### Supported Options diff --git a/docs/book/v2/static-filter.md b/docs/book/v2/static-filter.md index 126c139e..5eae7260 100644 --- a/docs/book/v2/static-filter.md +++ b/docs/book/v2/static-filter.md @@ -1,5 +1,8 @@ # Static Filter +CAUTION: **Deprecated** +This filter is deprecated since version 2.15.0 and [will be removed](migration/preparing-for-v3.md#static-filter-removal) in version 3.0. + If it is inconvenient to load a given filter class and create an instance of the filter, you can use `StaticFilter` with it's method `execute()` as an alternative invocation style. The first argument of this method is a data input diff --git a/mkdocs.yml b/mkdocs.yml index 4d138a71..be132bee 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,7 @@ nav: - Home: index.md - v2: - Introduction: v2/intro.md + - Installation: v2/installation.md - Reference: - 'Standard Filters': v2/standard-filters.md - 'Word Filters': v2/word.md @@ -12,6 +13,8 @@ nav: - 'String Inflection': v2/inflector.md - 'Static Filter': v2/static-filter.md - 'Writing Filters': v2/writing-filters.md + - Migration: + - 'Preparing for v3': v2/migration/preparing-for-v3.md - v3: - Introduction: v3/intro.md - Reference: @@ -28,6 +31,9 @@ site_description: "Programmatically filter and normalize data and files." repo_url: 'https://github.com/laminas/laminas-filter' extra: project: Components + installation: + config_provider_class: 'Laminas\Filter\ConfigProvider' + module_class: 'Laminas\Filter\Module' current_version: v3 versions: - v2 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5e0205e4..f767b4e4 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + @@ -1027,6 +1027,12 @@ + + + + + + diff --git a/src/FilterChain.php b/src/FilterChain.php index 2a12972c..d908fb7e 100644 --- a/src/FilterChain.php +++ b/src/FilterChain.php @@ -28,7 +28,7 @@ * priority?: int, * }>, * callbacks?: list * } @@ -86,7 +86,7 @@ public function setOptions($options) foreach ($value as $spec) { $callback = $spec['callback'] ?? false; $priority = $spec['priority'] ?? static::DEFAULT_PRIORITY; - if (is_callable($callback)) { + if (is_callable($callback) || $callback instanceof FilterInterface) { $this->attach($callback, $priority); } } diff --git a/src/FilterPluginManager.php b/src/FilterPluginManager.php index 15aa6e04..a2310ee8 100644 --- a/src/FilterPluginManager.php +++ b/src/FilterPluginManager.php @@ -45,6 +45,7 @@ final class FilterPluginManager extends AbstractPluginManager File\Rename::class => InvokableFactory::class, File\RenameUpload::class => InvokableFactory::class, File\UpperCase::class => InvokableFactory::class, + ForceUriScheme::class => InvokableFactory::class, HtmlEntities::class => InvokableFactory::class, Inflector::class => InvokableFactory::class, ToFloat::class => InvokableFactory::class, diff --git a/src/ForceUriScheme.php b/src/ForceUriScheme.php new file mode 100644 index 00000000..01140131 --- /dev/null +++ b/src/ForceUriScheme.php @@ -0,0 +1,77 @@ + self::DEFAULT_SCHEME]) + { + if (! preg_match('/^[a-z0-9]+$/i', $options['scheme'])) { + throw new InvalidArgumentException(sprintf( + 'The `scheme` option should be a string consisting only of letters and numbers. Please omit the :// ' + . ' Received "%s"', + $options['scheme'], + )); + } + + $this->scheme = $options['scheme']; + } + + public function __invoke(mixed $value): mixed + { + return $this->filter($value); + } + + public function filter(mixed $value): mixed + { + if (! is_string($value) || $value === '') { + return $value; + } + + $url = parse_url($value); + + if (! isset($url['host']) || $url['host'] === '') { + return $value; + } + + if (! isset($url['scheme']) || $url['scheme'] === '') { + return sprintf( + '%s://%s', + $this->scheme, + ltrim($value, ':/'), + ); + } + + $search = sprintf( + '/^(%s)(.+)/', + preg_quote($url['scheme'], '/'), + ); + $replace = sprintf( + '%s$2', + $this->scheme, + ); + + return preg_replace($search, $replace, $value); + } +} diff --git a/src/StripTags.php b/src/StripTags.php index b26af1d1..7e938016 100644 --- a/src/StripTags.php +++ b/src/StripTags.php @@ -286,7 +286,7 @@ protected function _filterTag($tag) // phpcs:ignore // Iterate over each matched attribute foreach ($matches[1] as $index => $attributeName) { $attributeName = strtolower($attributeName); - $attributeDelimiter = empty($matches[2][$index]) ? $matches[4][$index] : $matches[2][$index]; + $attributeDelimiter = $matches[2][$index] === '' ? $matches[4][$index] : $matches[2][$index]; $attributeValue = $matches[3][$index] === '' ? $matches[5][$index] : $matches[3][$index]; // If the attribute is not allowed, then remove it entirely diff --git a/test/FilterChainTest.php b/test/FilterChainTest.php index 649d1e34..5c496d3f 100644 --- a/test/FilterChainTest.php +++ b/test/FilterChainTest.php @@ -10,6 +10,7 @@ use Laminas\Filter\StringToLower; use Laminas\Filter\StringTrim; use Laminas\Filter\StripTags; +use LaminasTest\Filter\TestAsset\StrRepeatFilterInterface; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; @@ -77,7 +78,7 @@ public function testAllowsConfiguringFilters(): void $chain = new FilterChain(); $chain->setOptions($config); $value = ' abc '; - $valueExpected = 'ABC '; + $valueExpected = 'ABC ABC '; self::assertSame($valueExpected, $chain->filter($value)); } @@ -86,7 +87,7 @@ public function testAllowsConfiguringFiltersViaConstructor(): void $config = $this->getChainConfig(); $chain = new FilterChain($config); $value = ' abc '; - $valueExpected = 'ABC'; + $valueExpected = 'ABCABC'; self::assertSame($valueExpected, $chain->filter($value)); } @@ -96,7 +97,7 @@ public function testConfigurationAllowsTraversableObjects(): void $config = new ArrayIterator($config); $chain = new FilterChain($config); $value = ' abc '; - $valueExpected = 'ABC'; + $valueExpected = 'ABCABC'; self::assertSame($valueExpected, $chain->filter($value)); } @@ -117,6 +118,7 @@ private function getChainConfig(): array return [ 'callbacks' => [ ['callback' => [self::class, 'staticUcaseFilter']], + ['callback' => new StrRepeatFilterInterface()], [ 'priority' => 10000, 'callback' => static fn(string $value): string => trim($value), diff --git a/test/ForceUriSchemeTest.php b/test/ForceUriSchemeTest.php new file mode 100644 index 00000000..140aa1d2 --- /dev/null +++ b/test/ForceUriSchemeTest.php @@ -0,0 +1,96 @@ + */ + public static function filterDataProvider(): array + { + return [ + ['https', 'www.example.com/foo', 'www.example.com/foo'], + ['https', 'www.example.com', 'www.example.com'], + ['https', 'example.com', 'example.com'], + ['https', 'http://www.example.com', 'https://www.example.com'], + ['ftp', 'https://www.example.com', 'ftp://www.example.com'], + ['foobar5', 'https://www.example.com', 'foobar5://www.example.com'], + ['https', '//www.example.com', 'https://www.example.com'], + ['https', 'http://http.example.com', 'https://http.example.com'], + ['https', '42', '42'], + ['https', 42, 42], + ['https', false, false], + ['https', null, null], + ['https', (object) [], (object) []], + ]; + } + + /** + * @param non-empty-string $scheme + */ + #[DataProvider('filterDataProvider')] + public function testBasicFiltering(string $scheme, mixed $input, mixed $expect): void + { + $filter = new ForceUriScheme(['scheme' => $scheme]); + self::assertEquals($expect, $filter->filter($input)); + } + + /** + * @param non-empty-string $scheme + */ + #[DataProvider('filterDataProvider')] + public function testFilterCanBeInvoked(string $scheme, mixed $input, mixed $expect): void + { + $filter = new ForceUriScheme(['scheme' => $scheme]); + self::assertEquals($expect, $filter->__invoke($input)); + } + + /** @return list */ + public static function badSchemeProvider(): array + { + return [ + [''], + ['foo://'], + ['mailto:'], + ['...'], + ]; + } + + #[DataProvider('badSchemeProvider')] + public function testInvalidScheme(string $scheme): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The `scheme` option should be a string consisting only of letters and numbers'); + + /** @psalm-suppress ArgumentTypeCoercion */ + new ForceUriScheme(['scheme' => $scheme]); + } + + public function testThatThePluginManagerWillReturnAnInstance(): void + { + $manager = new FilterPluginManager($this->createMock(ContainerInterface::class)); + $filter = $manager->get(ForceUriScheme::class); + self::assertInstanceOf(ForceUriScheme::class, $filter); + + self::assertSame('https://example.com', $filter->filter('ftp://example.com')); + } + + public function testThatThePluginManagerCanBuildWithOptions(): void + { + $manager = new FilterPluginManager($this->createMock(ContainerInterface::class)); + $filter = $manager->build(ForceUriScheme::class, ['scheme' => 'muppets']); + self::assertInstanceOf(ForceUriScheme::class, $filter); + + self::assertSame('muppets://example.com', $filter->filter('ftp://example.com')); + } +} diff --git a/test/TestAsset/StrRepeatFilterInterface.php b/test/TestAsset/StrRepeatFilterInterface.php new file mode 100644 index 00000000..7b53694b --- /dev/null +++ b/test/TestAsset/StrRepeatFilterInterface.php @@ -0,0 +1,22 @@ +filter($value); + } +}