diff --git a/.laminas-ci/pre-install.sh b/.laminas-ci/pre-install.sh deleted file mode 100755 index b97af799..00000000 --- a/.laminas-ci/pre-install.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# -# @todo The compression adapters that require these non-standard extensions have been deprecated for removal in 3.0 -# This file can be removed along with the adapters. -# - -WORKING_DIRECTORY=$2 -JOB=$3 -PHP_VERSION=$(echo "${JOB}" | jq -r '.php') - -cd "$TMPDIR" || exit 1; - -apt install -y make g++ - -pecl channel-update pecl.php.net - -# Install lzf -pecl install lzf || exit 1 -echo "extension=lzf.so" >> /etc/php/"${PHP_VERSION}"/cli/php.ini - -# Install rar - May 2023 - Rar no longer compiles on 8.1 or 8.2 -#pecl install rar -#echo "extension=rar.so" >> /etc/php/"${PHP_VERSION}"/cli/php.ini - -# Install snappy - May 2023 - Extension no longer compiles -# git clone --recursive --depth=1 https://github.com/kjdev/php-ext-snappy.git -# cd php-ext-snappy || exit 1; -# phpize -# ./configure -# make -# make install -# -# echo "extension=snappy.so" >> /etc/php/"${PHP_VERSION}"/cli/php.ini - -# Debug output -php --ri lzf -echo "" -php --ri rar -echo "" -php --ri snappy -echo "" - -cd "$WORKING_DIRECTORY" || exit 1; diff --git a/composer.json b/composer.json index fea22727..a74586b0 100644 --- a/composer.json +++ b/composer.json @@ -39,9 +39,8 @@ }, "require-dev": { "laminas/laminas-coding-standard": "~2.5.0", - "laminas/laminas-crypt": "^3.11", "laminas/laminas-i18n": "^2.25.0", - "laminas/laminas-uri": "^2.11", + "laminas/laminas-uri": "^2.11.0", "pear/archive_tar": "^1.4.14", "phpunit/phpunit": "^10.5.5", "psalm/plugin-phpunit": "^0.18.4", @@ -53,7 +52,6 @@ "zendframework/zend-filter": "*" }, "suggest": { - "laminas/laminas-crypt": "Laminas\\Crypt component, for encryption filters", "laminas/laminas-i18n": "Laminas\\I18n component for filters depending on i18n functionality", "laminas/laminas-uri": "Laminas\\Uri component, for the UriNormalize filter", "psr/http-factory-implementation": "psr/http-factory-implementation, for creating file upload instances when consuming PSR-7 in file upload filters" diff --git a/composer.lock b/composer.lock index 420d9bb4..999a982c 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": "f0a26528e993851a96af4dfdd476da22", + "content-hash": "4725652ff0b79f76f2859d8244db2db3", "packages": [ { "name": "laminas/laminas-servicemanager", @@ -877,16 +877,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.0.0", + "version": "0.5.1", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "85193c0b0cb5c47894b5eaec906e946f054e7077" + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" }, "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/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", "shasum": "" }, "require": { @@ -894,13 +894,13 @@ }, "require-dev": { "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", "phpstan/phpstan": "^1.9.2", "phpstan/phpstan-deprecation-rules": "^1.0.0", "phpstan/phpstan-phpunit": "^1.2.2", "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "phpunit/phpunit": "^9.5.26 || ^8.5.31", + "theofidry/php-cs-fixer-config": "^1.0", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -926,7 +926,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/0.5.1" }, "funding": [ { @@ -934,7 +934,7 @@ "type": "github" } ], - "time": "2023-09-17T21:38:23+00:00" + "time": "2022-12-24T12:35:10+00:00" }, { "name": "laminas/laminas-coding-standard", @@ -992,70 +992,6 @@ ], "time": "2023-01-05T15:53:40+00:00" }, - { - "name": "laminas/laminas-crypt", - "version": "3.11.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-crypt.git", - "reference": "098fc61a895d1ff5d1c2b861525b4428bf6c3240" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-crypt/zipball/098fc61a895d1ff5d1c2b861525b4428bf6c3240", - "reference": "098fc61a895d1ff5d1c2b861525b4428bf6c3240", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "laminas/laminas-math": "^3.4", - "laminas/laminas-servicemanager": "^3.11.2", - "laminas/laminas-stdlib": "^3.8", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/container": "^1.1" - }, - "conflict": { - "zendframework/zend-crypt": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.4.0", - "phpunit/phpunit": "^9.5.25" - }, - "suggest": { - "ext-openssl": "Required for most features of Laminas\\Crypt" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Crypt\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Strong cryptography tools and password hashing", - "homepage": "https://laminas.dev", - "keywords": [ - "crypt", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-crypt/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-crypt/issues", - "rss": "https://github.com/laminas/laminas-crypt/releases.atom", - "source": "https://github.com/laminas/laminas-crypt" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2023-11-06T23:02:42+00:00" - }, { "name": "laminas/laminas-escaper", "version": "2.13.0", @@ -1120,16 +1056,16 @@ }, { "name": "laminas/laminas-i18n", - "version": "2.25.0", + "version": "2.24.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-i18n.git", - "reference": "4b6df8501bfe96648dadaf8de681cbbaea906e04" + "reference": "4f23433e415b14c4d66a7d7d1983c5890ac9ed2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/4b6df8501bfe96648dadaf8de681cbbaea906e04", - "reference": "4b6df8501bfe96648dadaf8de681cbbaea906e04", + "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/4f23433e415b14c4d66a7d7d1983c5890ac9ed2a", + "reference": "4f23433e415b14c4d66a7d7d1983c5890ac9ed2a", "shasum": "" }, "require": { @@ -1201,74 +1137,7 @@ "type": "community_bridge" } ], - "time": "2023-12-22T15:51:21+00:00" - }, - { - "name": "laminas/laminas-math", - "version": "3.7.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-math.git", - "reference": "3e90445828fd64308de2a600b48c3df051b3b17a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-math/zipball/3e90445828fd64308de2a600b48c3df051b3b17a", - "reference": "3e90445828fd64308de2a600b48c3df051b3b17a", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" - }, - "conflict": { - "zendframework/zend-math": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.4.0", - "phpunit/phpunit": "~9.5.25" - }, - "suggest": { - "ext-bcmath": "If using the bcmath functionality", - "ext-gmp": "If using the gmp functionality" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev", - "dev-develop": "3.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Math\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Create cryptographically secure pseudo-random numbers, and manage big integers", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "math" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-math/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-math/issues", - "rss": "https://github.com/laminas/laminas-math/releases.atom", - "source": "https://github.com/laminas/laminas-math" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2023-10-18T09:53:37+00:00" + "time": "2023-11-06T09:22:50+00:00" }, { "name": "laminas/laminas-uri", @@ -1330,16 +1199,16 @@ }, { "name": "laminas/laminas-validator", - "version": "2.46.0", + "version": "2.42.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-validator.git", - "reference": "98330256f8d8a1357a93f6f7f1a987036aff6329" + "reference": "a5221732b2ff6df59908bbf2eb274ed3688665bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/98330256f8d8a1357a93f6f7f1a987036aff6329", - "reference": "98330256f8d8a1357a93f6f7f1a987036aff6329", + "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/a5221732b2ff6df59908bbf2eb274ed3688665bc", + "reference": "a5221732b2ff6df59908bbf2eb274ed3688665bc", "shasum": "" }, "require": { @@ -1354,15 +1223,15 @@ "require-dev": { "laminas/laminas-coding-standard": "^2.5", "laminas/laminas-db": "^2.18", - "laminas/laminas-filter": "^2.33", - "laminas/laminas-i18n": "^2.24.1", - "laminas/laminas-session": "^2.17", - "laminas/laminas-uri": "^2.11.0", - "phpunit/phpunit": "^10.5.2", + "laminas/laminas-filter": "^2.32", + "laminas/laminas-i18n": "^2.23", + "laminas/laminas-session": "^2.16", + "laminas/laminas-uri": "^2.10.0", + "phpunit/phpunit": "^10.3.3", "psalm/plugin-phpunit": "^0.18.4", - "psr/http-client": "^1.0.3", + "psr/http-client": "^1.0.2", "psr/http-factory": "^1.0.2", - "vimeo/psalm": "^5.17" + "vimeo/psalm": "^5.15" }, "suggest": { "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", @@ -1410,7 +1279,7 @@ "type": "community_bridge" } ], - "time": "2024-01-03T12:43:04+00:00" + "time": "2023-11-06T09:13:00+00:00" }, { "name": "myclabs/deep-copy", @@ -1524,16 +1393,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.18.0", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -1574,9 +1443,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-12-10T21:03:43+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "pear/archive_tar", @@ -1711,22 +1580,21 @@ }, { "name": "pear/pear-core-minimal", - "version": "v1.10.14", + "version": "v1.10.13", "source": { "type": "git", "url": "https://github.com/pear/pear-core-minimal.git", - "reference": "a86fc145edb5caedbf96527214ce3cadc9de4a32" + "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/a86fc145edb5caedbf96527214ce3cadc9de4a32", - "reference": "a86fc145edb5caedbf96527214ce3cadc9de4a32", + "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/aed862e95fd286c53cc546734868dc38ff4b5b1d", + "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d", "shasum": "" }, "require": { "pear/console_getopt": "~1.4", - "pear/pear_exception": "~1.0", - "php": ">=5.4" + "pear/pear_exception": "~1.0" }, "replace": { "rsky/pear-core-min": "self.version" @@ -1756,7 +1624,7 @@ "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", "source": "https://github.com/pear/pear-core-minimal" }, - "time": "2023-11-26T16:15:38+00:00" + "time": "2023-04-19T19:15:47+00:00" }, { "name": "pear/pear_exception", @@ -2139,23 +2007,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.11", + "version": "10.1.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "78c3b7625965c2513ee96569a4dbb62601784145" + "reference": "355324ca4980b8916c18b9db29f3ef484078f26e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145", - "reference": "78c3b7625965c2513ee96569a4dbb62601784145", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e", + "reference": "355324ca4980b8916c18b9db29f3ef484078f26e", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.15", "php": ">=8.1", "phpunit/php-file-iterator": "^4.0", "phpunit/php-text-template": "^3.0", @@ -2205,7 +2073,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7" }, "funding": [ { @@ -2213,7 +2081,7 @@ "type": "github" } ], - "time": "2023-12-21T15:38:30+00:00" + "time": "2023-10-04T15:34:17+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2460,16 +2328,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.5", + "version": "10.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" + "reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cacd8b9dd224efa8eb28beb69004126c7ca1a1a1", + "reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1", "shasum": "" }, "require": { @@ -2509,7 +2377,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "10.4-dev" } }, "autoload": { @@ -2541,7 +2409,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.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.4.2" }, "funding": [ { @@ -2557,7 +2425,7 @@ "type": "tidelift" } ], - "time": "2023-12-27T15:13:52+00:00" + "time": "2023-10-26T07:21:45+00:00" }, { "name": "psalm/plugin-phpunit", @@ -3023,20 +2891,20 @@ }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.10", "php": ">=8.1" }, "require-dev": { @@ -3045,7 +2913,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "3.1-dev" } }, "autoload": { @@ -3069,7 +2937,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" }, "funding": [ { @@ -3077,20 +2945,20 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2023-09-28T11:50:59+00:00" }, { "name": "sebastian/diff", - "version": "5.1.0", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f" + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f", - "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", "shasum": "" }, "require": { @@ -3103,7 +2971,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3136,7 +3004,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0" + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" }, "funding": [ { @@ -3144,7 +3012,7 @@ "type": "github" } ], - "time": "2023-12-22T10:55:06+00:00" + "time": "2023-05-01T07:48:21+00:00" }, { "name": "sebastian/environment", @@ -3352,20 +3220,20 @@ }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.10", "php": ">=8.1" }, "require-dev": { @@ -3398,7 +3266,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" }, "funding": [ { @@ -3406,7 +3274,7 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2023-08-31T09:25:50+00:00" }, { "name": "sebastian/object-enumerator", @@ -3755,16 +3623,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.2.2", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "96be97e664c87613121d073ea39af4c74e57a7f8" + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" }, "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/f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", "shasum": "" }, "require": { @@ -3802,7 +3670,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.0" }, "funding": [ { @@ -3814,20 +3682,20 @@ "type": "github" } ], - "time": "2023-11-14T14:08:51+00:00" + "time": "2023-07-19T18:30:26+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.0", + "version": "3.7.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7" + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5805f7a4e4958dbb5e944ef1e6edae0a303765e7", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", "shasum": "" }, "require": { @@ -3837,7 +3705,7 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ "bin/phpcs", @@ -3856,58 +3724,35 @@ "authors": [ { "name": "Greg Sherwood", - "role": "Former lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "Current lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + "role": "lead" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - } - ], - "time": "2023-12-08T12:32:31+00:00" + "time": "2023-02-22T23:07:41+00:00" }, { "name": "symfony/console", - "version": "v6.4.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { @@ -3915,7 +3760,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "symfony/string": "^5.4|^6.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -3929,16 +3774,12 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -3972,7 +3813,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.2" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -3988,11 +3829,11 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -4039,7 +3880,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.3.0" }, "funding": [ { @@ -4059,16 +3900,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { @@ -4102,7 +3943,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.3.1" }, "funding": [ { @@ -4118,7 +3959,7 @@ "type": "tidelift" } ], - "time": "2023-07-26T17:27:13+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4452,29 +4293,33 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -4484,10 +4329,7 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4514,7 +4356,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -4530,20 +4372,20 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v6.4.2", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", "shasum": "" }, "require": { @@ -4557,11 +4399,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -4600,7 +4442,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.2" + "source": "https://github.com/symfony/string/tree/v6.3.5" }, "funding": [ { @@ -4616,20 +4458,20 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2023-09-18T10:38:32+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -4658,7 +4500,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -4666,20 +4508,20 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "vimeo/psalm", - "version": "5.18.0", + "version": "5.15.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "b113f3ed0259fd6e212d87c3df80eec95a6abf19" + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/b113f3ed0259fd6e212d87c3df80eec95a6abf19", - "reference": "b113f3ed0259fd6e212d87c3df80eec95a6abf19", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", "shasum": "" }, "require": { @@ -4698,14 +4540,14 @@ "ext-tokenizer": "*", "felixfbecker/advanced-json-rpc": "^3.1", "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "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", "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" + "symfony/console": "^4.1.6 || ^5.0 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0" }, "conflict": { "nikic/php-parser": "4.17.0" @@ -4727,7 +4569,7 @@ "psalm/plugin-phpunit": "^0.18", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/process": "^4.4 || ^5.0 || ^6.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -4740,7 +4582,7 @@ "psalm-refactor", "psalter" ], - "type": "project", + "type": "library", "extra": { "branch-alias": { "dev-master": "5.x-dev", @@ -4772,24 +4614,23 @@ "static analysis" ], "support": { - "docs": "https://psalm.dev/docs", "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm" + "source": "https://github.com/vimeo/psalm/tree/5.15.0" }, - "time": "2023-12-16T09:37:35+00:00" + "time": "2023-08-20T23:07:30+00:00" }, { "name": "webimpress/coding-standard", - "version": "1.3.2", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/webimpress/coding-standard.git", - "reference": "710f71ac95d36d931e76b47132b599c39abfab11" + "reference": "b26557e2386711ecb74f22718f4b4bde5ddbc899" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/710f71ac95d36d931e76b47132b599c39abfab11", - "reference": "710f71ac95d36d931e76b47132b599c39abfab11", + "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/b26557e2386711ecb74f22718f4b4bde5ddbc899", + "reference": "b26557e2386711ecb74f22718f4b4bde5ddbc899", "shasum": "" }, "require": { @@ -4797,7 +4638,7 @@ "squizlabs/php_codesniffer": "^3.7.2" }, "require-dev": { - "phpunit/phpunit": "^9.6.15" + "phpunit/phpunit": "^9.6.4" }, "type": "phpcodesniffer-standard", "extra": { @@ -4823,7 +4664,7 @@ ], "support": { "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.3.2" + "source": "https://github.com/webimpress/coding-standard/tree/1.3.1" }, "funding": [ { @@ -4831,7 +4672,7 @@ "type": "github" } ], - "time": "2023-12-18T07:25:41+00:00" + "time": "2023-03-09T15:05:18+00:00" }, { "name": "webmozart/assert", diff --git a/docs/book/v3/file.md b/docs/book/v3/file.md new file mode 100644 index 00000000..5df36d49 --- /dev/null +++ b/docs/book/v3/file.md @@ -0,0 +1,341 @@ +# File Filters + +laminas-filter also comes with a set of classes for filtering file contents, and +performing file operations such as renaming. + +> ## $_FILES +> +> All file filter `filter()` implementations support either a file path string +> *or* a `$_FILES` array as the supplied argument. When a `$_FILES` array is +> passed in, the `tmp_name` is used for the file path. + +## Lowercase + +`Laminas\Filter\File\Lowercase` can be used to convert all file contents to +lowercase. + +### Supported Options + +The following set of options are supported: + +- `encoding`: Set the encoding to use during conversion. + +### Basic Usage + +```php +use Laminas\Filter\File\LowerCase; +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$filter = new LowerCase(); +$filter->filter($files['my-upload']); +``` + +This example converts the contents of an uploaded file to lowercase. After this +process, you can use the [Rename](#rename) or [RenameUpload](#renameupload) +filter to replace this file with your original file, or read directly from file. +But, don't forget, if you upload a file and send your `$_FILES` array to a +filter method, the `LowerCase` filter will only change the temporary file +(`tmp_name` index of array), not the original file. Let's check following +example: + +```php +use Laminas\Filter\File\LowerCase; +use Laminas\Filter\File\Rename; +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$lowercaseFilter = new LowerCase(); +$file = $lowercaseFilter->filter($files['userfile']); +$renameFilter = new Rename([ + 'target' => '/tmp/newfile.txt', + 'randomize' => true, +]); +$filename = $renameFilter->filter($file['tmp_name']); +``` + +With this example, the final, stored file on the server will have the lowercased +content. + +If you want to use a specific encoding when converting file content, you should +specify the encoding when instantiating the `LowerCase` filter, or use the +`setEncoding` method to change it. + +```php +use Laminas\Filter\File\LowerCase; +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$filter = new LowerCase(); +$filter->setEncoding('ISO-8859-1'); +$filter->filter($files['my-upload']); +``` + +The `LowerCase` filter extends from the `StringToLower` filter; read the +[`StringToLower` documentation](/laminas-filter/standard-filters/#stringtolower) +for more information about encoding and its exceptions. + +## Rename + +`Laminas\Filter\File\Rename` can be used to rename a file and/or move a file to a new path. + +### Supported Options + +The following set of options are supported: + +- `target` (string; default: `*`): Target filename or directory; the new name + of the source file. +- `source` (string; default: `*`): Source filename or directory which will be + renamed. Used to match the filtered file with an options set. +- `overwrite` (boolean; default: `false`): Shall existing files be overwritten? + If the file is unable to be moved into the target path, a + `Laminas\Filter\Exception\RuntimeException` will be thrown. +- `randomize` (boolean; default: `false`): Shall target files have a random + postfix attached? The random postfix will generated with `uniqid('_')` after + the file name and before the extension. For example, `file.txt` might be + randomized to `file_4b3403665fea6.txt`. + +An array of option sets is also supported, where a single `Rename` filter +instance can filter several files using different options. The options used for +the filtered file will be matched from the `source` option in the options set. + +### Usage Examples + +Move all filtered files to a different directory: + +```php +// 'target' option is assumed if param is a string +$filter = new \Laminas\Filter\File\Rename('/tmp/'); +echo $filter->filter('./myfile.txt'); +// File has been moved to '/tmp/myfile.txt' +``` + +Rename all filtered files to a new name: + +```php +$filter = new \Laminas\Filter\File\Rename('/tmp/newfile.txt'); +echo $filter->filter('./myfile.txt'); +// File has been renamed to '/tmp/newfile.txt' +``` + +Move to a new path, and randomize file names: + +```php +$filter = new \Laminas\Filter\File\Rename([ + 'target' => '/tmp/newfile.txt', + 'randomize' => true, +]); +echo $filter->filter('./myfile.txt'); +// File has been renamed to '/tmp/newfile_4b3403665fea6.txt' +``` + +Configure different options for several possible source files: + +```php +$filter = new \Laminas\Filter\File\Rename([ + [ + 'source' => 'fileA.txt' + 'target' => '/dest1/newfileA.txt', + 'overwrite' => true, + ], + [ + 'source' => 'fileB.txt' + 'target' => '/dest2/newfileB.txt', + 'randomize' => true, + ], +]); +echo $filter->filter('fileA.txt'); +// File has been renamed to '/dest1/newfileA.txt' +echo $filter->filter('fileB.txt'); +// File has been renamed to '/dest2/newfileB_4b3403665fea6.txt' +``` + +### Public Methods + +The `Rename` filter defines the following public methods in addition to `filter()`: +follows: + +- `getFile() : array`: Returns the files to rename along with their new name and location. +- `setFile(string|array $options) : void`: Sets the file options for renaming. + Removes any previously set file options. +- `addFile(string|array $options) : void`: Adds file options for renaming to + the current list of file options. + +## RenameUpload + +`Laminas\Filter\File\RenameUpload` can be used to rename or move an uploaded file to a new path. + +### Supported Options + +The following set of options are supported: + +- `target` (string; default: `*`): Target directory or full filename path. +- `overwrite` (boolean; default: `false`): Shall existing files be overwritten? + If the file is unable to be moved into the target path, a + `Laminas\Filter\Exception\RuntimeException` will be thrown. +- `randomize` (boolean; default: `false`): Shall target files have a random + postfix attached? The random postfix will generated with `uniqid('_')` after + the file name and before the extension. For example, `file.txt` might be + randomized to `file_4b3403665fea6.txt`. +- `use_upload_name` (boolean; default: `false`): When true, this filter will + use `$_FILES['name']` as the target filename. Otherwise, the default `target` + rules and the `$_FILES['tmp_name']` will be used. +- `use_upload_extension` (boolean; default: `false`): When true, the uploaded + file will maintains its original extension if not specified. For example, if + the uploaded file is `file.txt` and the target is `mynewfile`, the upload + will be renamed to `mynewfile.txt`. +- `stream_factory` (`Psr\Http\Message\StreamFactoryInterface`; default: `null`): + Required when passing a [PSR-7 UploadedFileInterface](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface) + to the filter; used to create a new stream representing the renamed file. + (Since 2.9.0) +- `upload_file_factory` (`Psr\Http\Message\UploadedFileFactoryInterface`; default: + `null`): Required when passing a [PSR-7 UploadedFileInterface](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface) + to the filter; used to create a new uploaded file representation of the + renamed file. (Since 2.9.0) + +> ### Using the upload Name is unsafe +> +> Be **very** careful when using the `use_upload_name` option. For instance, +> extremely bad things could happen if you were to allow uploaded `.php` files +> (or other CGI files) to be moved into the `DocumentRoot`. +> +> It is generally a better idea to supply an internal filename to avoid +> security risks. + +`RenameUpload` does not support an array of options like the`Rename` filter. +When filtering HTML5 file uploads with the `multiple` attribute set, all files +will be filtered with the same option settings. + +### Usage Examples + +Move all filtered files to a different directory: + +```php +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' +// i.e. $files['my-upload']['name'] === 'myfile.txt' + +// 'target' option is assumed if param is a string +$filter = new \Laminas\Filter\File\RenameUpload('./data/uploads/'); +echo $filter->filter($files['my-upload']); +// File has been moved to './data/uploads/php5Wx0aJ' + +// ... or retain the uploaded file name +$filter->setUseUploadName(true); +echo $filter->filter($files['my-upload']); +// File has been moved to './data/uploads/myfile.txt' +``` + +Rename all filtered files to a new name: + +```php +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$filter = new \Laminas\Filter\File\RenameUpload('./data/uploads/newfile.txt'); +echo $filter->filter($files['my-upload']); +// File has been renamed to './data/uploads/newfile.txt' +``` + +Move to a new path and randomize file names: + +```php +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$filter = new \Laminas\Filter\File\RenameUpload([ + 'target' => './data/uploads/newfile.txt', + 'randomize' => true, +]); +echo $filter->filter($files['my-upload']); +// File has been renamed to './data/uploads/newfile_4b3403665fea6.txt' +``` + +Handle a PSR-7 uploaded file: + +```php +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UploadedFileFactoryInterface; +use Psr\Http\Message\UploadedFileInterface; +use Laminas\Filter\File\RenameUpload; + +$filter = new \Laminas\Filter\File\RenameUpload([ + 'target' => './data/uploads/', + 'randomize' => true, + // @var StreamFactoryInterface $streamFactory + 'stream_factory' => $streamFactory, + // @var UploadedFileFactoryInterface $uploadedFileFactory + 'upload_file_factory' => $uploadedFileFactory, +]); + +// @var ServerRequestInterface $request +foreach ($request->getUploadedFiles() as $uploadedFile) { + // @var UploadedFileInterface $uploadedFile + // @var UploadedFileInterface $movedFile + $movedFile = $filter->filter($uploadedFile); + echo $movedFile->getClientFilename(); + // File has been renamed to './data/uploads/newfile_4b3403665fea6.txt' +} +``` + +> ### PSR-7 Support +> +> PSR-7/PSR-17 support has only been available since 2.9.0, and requires a valid +> [psr/http-factory-implementation](https://packagist.org/providers/psr/http-factory-implementation) +> in your application, as it relies on the stream and uploaded file factories in +> order to produce the final `UploadedFileInterface` artifact representing the +> filtered file. +> +> PSR-17 itself requires PHP 7, so your application will need to be running on +> PHP 7 in order to use this feature. +> +> [laminas/laminas-diactoros 2.0](https://docs.laminas.dev/laminas-diactoros/) +> provides a PSR-17 implementation, but requires PHP 7.1. If you are still on +> PHP 7.0, either upgrade, or find a compatible psr/http-factory-implementation. + +## Uppercase + +`Laminas\Filter\File\Uppercase` can be used to convert all file contents to +uppercase. + +### Supported Options + +The following set of options are supported: + +- `encoding`: Set the encoding to use during conversion. + +### Basic Usage + +```php +use Laminas\Filter\File\UpperCase; +use Laminas\Http\PhpEnvironment\Request; + +$request = new Request(); +$files = $request->getFiles(); +// i.e. $files['my-upload']['tmp_name'] === '/tmp/php5Wx0aJ' + +$filter = new UpperCase(); +$filter->filter($files['my-upload']); +``` + +See the documentation on the [`LowerCase`](#lowercase) filter, above, for more +information. diff --git a/docs/book/v3/filter-chains.md b/docs/book/v3/filter-chains.md new file mode 100644 index 00000000..7d9cef8e --- /dev/null +++ b/docs/book/v3/filter-chains.md @@ -0,0 +1,85 @@ +# Filter Chains + +Often, multiple filters should be applied to some value in a particular order. +For example, a login form accepts a username that should be lowercase and +contain only alphabetic characters. + +`Laminas\Filter\FilterChain` provides a simple method by which filters may be +chained together. The following code illustrates how to chain together two +filters for the submitted username and fulfill the above requirements: + +```php +// Create a filter chain and add filters to the chain +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain + ->attach(new Laminas\I18n\Filter\Alpha()) + ->attach(new Laminas\Filter\StringToLower()); + +// Filter the username +$username = $filterChain->filter($_POST['username']); +``` + +Filters are run in the order they are added to the filter chain. In the above +example, the username is first removed of any non-alphabetic characters, and +then any uppercase characters are converted to lowercase. + +Any object that implements `Laminas\Filter\FilterInterface` may be used in a +filter chain. + +## Setting Filter Chain Order + +For each filter added to the `FilterChain`, you can set a priority to define +the chain order. Higher values indicate higher priority (execute first), while +lower and/or negative values indicate lower priority (execute last). The default value is `1000`. + +In the following example, any uppercase characters are converted to lowercase +before any non-alphabetic characters are removed. + +```php +// Create a filter chain and add filters to the chain +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain + ->attach(new Laminas\I18n\Filter\Alpha()) + ->attach(new Laminas\Filter\StringToLower(), 500); +``` + +## Using the Plugin Manager + +A `FilterPluginManager` is attached to every `FilterChain` instance. Every filter +that is used in a `FilterChain` must be known to the `FilterPluginManager`. + +To add a filter to the `FilterChain`, use the `attachByName()` method. The +first parameter is the name of the filter within the `FilterPluginManager`. The +second parameter takes any options for creating the filter instance. The third +parameter is the priority. + +```php +// Create a filter chain and add filters to the chain +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain + ->attachByName('alpha') + ->attachByName('stringtolower', ['encoding' => 'utf-8'], 500); +``` + +The following example shows how to add a custom filter to the `FilterPluginManager` and the +`FilterChain`: + +```php +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain + ->getPluginManager() + ->setInvokableClass('myNewFilter', 'MyCustom\Filter\MyNewFilter'); +$filterChain + ->attachByName('alpha') + ->attachByName('myNewFilter'); +``` + +You can also add your own `FilterPluginManager` implementation: + +```php +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain->setPluginManager(new MyFilterPluginManager()); +$filterChain + ->attach(new Laminas\I18n\Filter\Alpha()) + ->attach(new MyCustom\Filter\MyNewFilter()); +``` diff --git a/docs/book/v3/inflector.md b/docs/book/v3/inflector.md new file mode 100644 index 00000000..320ca2e5 --- /dev/null +++ b/docs/book/v3/inflector.md @@ -0,0 +1,317 @@ +# String Inflection + +`Laminas\Filter\Inflector` is a general purpose tool for rules-based inflection of +strings to a given target. + +As an example, you may find you need to transform MixedCase or camelCasedWords +into a path; for readability, OS policies, or other reasons, you also need to +lower case this; and finally, you want to separate the words using a dash +(`-`). An inflector can do this for you. + +`Laminas\Filter\Inflector` implements `Laminas\Filter\FilterInterface`; you perform +inflection by calling `filter()` on the object instance. + +## Transforming MixedCase and CamelCaseText to another Format + +```php +$inflector = new Laminas\Filter\Inflector('pages/:page.:suffix'); +$inflector->setRules([ + ':page' => ['Word\CamelCaseToDash', 'StringToLower'], + 'suffix' => 'html', +]); + +$string = 'camelCasedWords'; +$filtered = $inflector->filter(['page' => $string]); +// pages/camel-cased-words.html + +$string = 'this_is_not_camel_cased'; +$filtered = $inflector->filter(['page' => $string]); +// pages/this_is_not_camel_cased.html +``` + +## Operation + +An inflector requires a **target** and one or more **rules**. A target is +basically a string that defines placeholders for variables you wish to +substitute. These are specified by prefixing with a `:`: `:script`. + +When calling `filter()`, you then pass in an array of key and value pairs +corresponding to the variables in the target. + +Each variable in the target can have zero or more rules associated with them. +Rules may be either **static** or refer to a laminas-filter class. Static rules +will replace with the text provided. Otherwise, a class matching the rule +provided will be used to inflect the text. Classes are typically specified +using a short name indicating the filter name stripped of any common prefix. + +As an example, you can use any laminas-filter concrete implementations; however, +instead of referring to them as `Laminas\I18n\Filter\Alpha` or +`Laminas\Filter\StringToLower`, you'd specify only `Alpha` or `StringToLower`. + +### Using Custom Filters + +`Laminas\Filter\Inflector` uses `Laminas\Filter\FilterPluginManager` to manage +loading filters to use with inflection. By default, filters registered with +`Laminas\Filter\FilterPluginManager` are available. To access filters with that +prefix but which occur deeper in the hierarchy, such as the various `Word` +filters, simply strip off the `Laminas\Filter` prefix: + +```php +// use Laminas\Filter\Word\CamelCaseToDash as a rule +$inflector->addRules(['script' => 'Word\CamelCaseToDash']); +``` + +To use custom filters, you have two choices: reference them by fully qualified +class name (e.g., `My\Custom\Filter\Mungify`), or manipulate the composed +`FilterPluginManager` instance. + +```php +$filters = $inflector->getPluginManager(); +$filters->addInvokableClass('mungify', 'My\Custom\Filter\Mungify'); +``` + +### Setting the Inflector Target + +The inflector target is a string with some placeholders for variables. +Placeholders take the form of an identifier, a colon (`:`) by default, followed +by a variable name: `:script`, `:path`, etc. The `filter()` method looks for +the identifier followed by the variable name being replaced. + +You can change the identifier using the `setTargetReplacementIdentifier()` +method, or passing it as the fourth argument to the constructor: + +```php +// Via constructor: +$inflector = new Laminas\Filter\Inflector('#foo/#bar.#sfx', array(), null, '#'); + +// Via accessor: +$inflector->setTargetReplacementIdentifier('#'); +``` + +Typically, you will set the target via the constructor. However, you may want +to re-set the target later. `setTarget()` can be used for this purpose: + +```php +$inflector->setTarget('layouts/:script.phtml'); +``` + +Additionally, you may wish to have a class member for your class that you can +use to keep the inflector target updated — without needing to directly update +the target each time (thus saving on method calls). `setTargetReference()` +allows you to do this: + +```php +class Foo +{ + /** + * @var string Inflector target + */ + protected $target = 'foo/:bar/:baz.:suffix'; + + /** + * Constructor + * @return void + */ + public function __construct() + { + $this->inflector = new Laminas\Filter\Inflector(); + $this->inflector->setTargetReference($this->target); + } + + /** + * Set target; updates target in inflector + * + * @param string $target + * @return Foo + */ + public function setTarget($target) + { + $this->target = $target; + return $this; + } +} +``` + +## Inflection Rules + +As mentioned in the introduction, there are two types of rules: static and filter-based. + +> ### Order is important +> +> It is important to note that regardless of the method in which you add rules +> to the inflector, either one-by-one, or all-at-once; the order is very +> important. More specific names, or names that might contain other rule names, +> must be added before least specific names. For example, assuming the two rule +> names `moduleDir` and `module`, the `moduleDir` rule should appear before +> module since `module` is contained within `moduleDir`. If `module` were added +> before `moduleDir`, `module` will match part of `moduleDir` and process it +> leaving `Dir` inside of the target uninflected. + +### Static Rules + +Static rules do simple string substitution; use them when you have a segment in +the target that will typically be static, but which you want to allow the +developer to modify. Use the `setStaticRule()` method to set or modify the +rule: + +```php +$inflector = new Laminas\Filter\Inflector(':script.:suffix'); +$inflector->setStaticRule('suffix', 'phtml'); + +// change it later: +$inflector->setStaticRule('suffix', 'php'); +``` + +Much like the target itself, you can also bind a static rule to a reference, +allowing you to update a single variable instead of require a method call; this +is often useful when your class uses an inflector internally, and you don't +want your users to need to fetch the inflector in order to update it. The +`setStaticRuleReference()` method is used to accomplish this: + +```php +class Foo +{ + /** + * @var string Suffix + */ + private $suffix = 'phtml'; + + /** + * Constructor + * @return void + */ + public function construct() + { + $this->inflector = new Laminas\Filter\Inflector(':script.:suffix'); + $this->inflector->setStaticRuleReference('suffix', $this->suffix); + } + + /** + * Set suffix; updates suffix static rule in inflector + * + * @param string $suffix + * @return Foo + */ + public function setSuffix($suffix) + { + $this->suffix = $suffix; + return $this; + } +} +``` + +### Filter-Based Inflector Rules + +`Laminas\Filter` filters may be used as inflector rules as well. Just like static +rules, these are bound to a target variable; unlike static rules, you may +define multiple filters to use when inflecting. These filters are processed in +order, so be careful to register them in an order that makes sense for the data +you receive. + +Rules may be added using `setFilterRule()` (which overwrites any previous rules +for that variable) or `addFilterRule()` (which appends the new rule to any +existing rule for that variable). Filters are specified in one of the following +ways: + +- **String**. The string may be a filter class name, or a class name segment + minus any prefix set in the inflector's plugin loader (by default, minus the + '`Laminas\Filter`' prefix). +- **Filter object**. Any object instance implementing + `Laminas\Filter\FilterInterface` may be passed as a filter. +- **Array**. An array of one or more strings or filter objects as defined above. + +```php +$inflector = new Laminas\Filter\Inflector(':script.:suffix'); + +// Set rule to use Laminas\Filter\Word\CamelCaseToDash filter +$inflector->setFilterRule('script', 'Word\CamelCaseToDash'); + +// Add rule to lowercase string +$inflector->addFilterRule('script', new Laminas\Filter\StringToLower()); + +// Set rules en-masse +$inflector->setFilterRule('script', [ + 'Word\CamelCaseToDash', + new Laminas\Filter\StringToLower() +]); +``` + +## Setting many Rules at once + +Typically, it's easier to set many rules at once than to configure a single +variable and its inflection rules one at a time. `Laminas\Filter\Inflector`'s +`addRules()` and `setRules()` methods allow this. + +Each method takes an array of variable and rule pairs, where the rule may be +whatever the type of rule accepts (string, filter object, or array). Variable +names accept a special notation to allow setting static rules and filter rules, +according to the following notation: + +- **`:` prefix**: filter rules. +- **No prefix**: static rule. + +As an example: + +```php +// Could also use setRules() with this notation: +$inflector->addRules([ + // Filter rules: + ':controller' => ['Word\CamelCaseToUnderscore','StringToLower'], + ':action' => ['Word\CamelCaseToUnderscore','StringToLower'], + + // Static rule: + 'suffix' => 'phtml', +]); +``` + +## Utility Methods + +`Laminas\Filter\Inflector` has a number of utility methods for retrieving and +setting the plugin loader, manipulating and retrieving rules, and controlling +if and when exceptions are thrown. + +- `setPluginManager()` can be used when you have configured your own + `Laminas\Filter\FilterPluginManager` instance and wish to use it with + `Laminas\Filter\Inflector`; `getPluginManager()` retrieves the currently set + one. +- `setThrowTargetExceptionsOn()` can be used to control whether or not + `filter()` throws an exception when a given replacement identifier passed to + it is not found in the target. By default, no exceptions are thrown. + `isThrowTargetExceptionsOn()` will tell you what the current value is. +- `getRules($spec = null)` can be used to retrieve all registered rules for all + variables, or just the rules for a single variable. +- `getRule($spec, $index)` fetches a single rule for a given variable; this can + be useful for fetching a specific filter rule for a variable that has a + filter chain. `$index` must be passed. +- `clearRules()` will clear all currently registered rules. + +## Using a Traversable or an Array + +You can use a `Traversable` or an array to set rules and other object state in +your inflectors, by passing either type to either the constructor or the +`setOptions()` method. The following settings may be specified: + +- `target` specifies the inflection target. +- `pluginManager` specifies the `Laminas\Filter\FilterPluginManager` instance or + extension to use for obtaining plugins; alternately, you may specify a class + name of a class that extends the `FilterPluginManager`. +- `throwTargetExceptionsOn` should be a boolean indicating whether or not to + throw exceptions when a replacement identifier is still present after + inflection. +- `targetReplacementIdentifier` specifies the character to use when identifying + replacement variables in the target string. +- `rules` specifies an array of inflection rules; it should consist of keys + that specify either values or arrays of values, consistent with `addRules()`. + +As examples: + +```php +// $options implements Traversable: + +// With the constructor: +$inflector = new Laminas\Filter\Inflector($options); + +// Or with setOptions(): +$inflector = new Laminas\Filter\Inflector(); +$inflector->setOptions($options); +``` diff --git a/docs/book/v3/intro.md b/docs/book/v3/intro.md new file mode 100644 index 00000000..ef6e4a3f --- /dev/null +++ b/docs/book/v3/intro.md @@ -0,0 +1,106 @@ +# Introduction + +laminas-filter provides a set of commonly needed data filters. It also provides a +simple filter chaining mechanism by which multiple filters may be applied to a +single datum in a user-defined order. + +## What is a filter? + +In the physical world, a filter is typically used for removing unwanted portions +of input, and the desired portion of the input passes through as filter output +(e.g., coffee). In such scenarios, a filter is an operator that produces a +subset of the input. This type of filtering is useful for web applications: +removing illegal input, trimming unnecessary white space, etc. + +This basic definition of a filter may be extended to include generalized +transformations upon input. A common transformation applied in web applications +is the escaping of HTML entities. For example, if a form field is automatically +populated with untrusted input (e.g., from a web browser), this value should +either be free of HTML entities or contain only escaped HTML entities, in order +to prevent undesired behavior and security vulnerabilities. To meet this +requirement, HTML entities that appear in the input must either be removed or +escaped. Of course, which approach is more appropriate depends on the situation. +A filter that removes the HTML entities operates within the scope of the first +definition of filter - an operator that produces a subset of the input. A filter +that escapes the HTML entities, however, transforms the input (e.g., `&` is +transformed to `&`). Supporting such use cases for web developers is +important, and “to filter”, in the context of using laminas-filter, means to +perform some transformations upon input data. + +## Basic usage of filters + +Having this filter definition established provides the foundation for +`Laminas\Filter\FilterInterface`, which requires a single method named `filter()` +to be implemented by a filter class. + +Following is a basic example of using a filter upon two input data, the +ampersand (`&`) and double quote (`"`) characters: + +```php +$htmlEntities = new Laminas\Filter\HtmlEntities(); + +echo $htmlEntities->filter('&'); // & +echo $htmlEntities->filter('"'); // " +``` + +Also, if a filter inherits from `Laminas\Filter\AbstractFilter` (as do all of the +out-of-the-box filters), you can also use them as invokables: + +```php +$strtolower = new Laminas\Filter\StringToLower; + +echo $strtolower('I LOVE Laminas!'); // i love laminas! +$laminaslove = $strtolower('I LOVE Laminas!'); +``` + +## Double filtering + +When using two filters in succession, you have to keep in mind that it is +often not possible to get the original output by using the opposite filter. Take +the following example: + +```php +$original = 'my_original_content'; + +// Attach a filter +$filter = new Laminas\Filter\Word\UnderscoreToCamelCase(); +$filtered = $filter->filter($original); + +// Use it's opposite +$filter2 = new Laminas\Filter\Word\CamelCaseToUnderscore(); +$filtered = $filter2->filter($filtered) +``` + +The above code example could lead to the impression that you will get the +original output after the second filter has been applied. But thinking logically +this is not the case. After applying the first filter, `my_original_content` will +be changed to `MyOriginalContent`. But after applying the second filter, the result +is `My_Original_Content`. + +As you can see it is not always possible to get the original output by using a +filter which seems to be the opposite. It depends on the filter and also on the +given input. + +## Providing filters via modules + +If you wish to indicate that your laminas-mvc module provides filters, have your +`Module` class implement `Laminas\Filter\FilterProviderInterface`, which defines +the method: + +```php +/** + * @return array + */ +public function getFilterConfig(); +``` + +The method should return an array of configuration following the +[laminas-servicemanager configuration format](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/). + +If you are not using laminas-mvc, but are using a dependency injection container +(e.g., if you are using Mezzio), you can also provide filters using the +top-level `filters` configuration key; the value of that key should be +laminas-servicemanager configuration, as linked above. + +(laminas-mvc users may also provide configuration in the same way, and omit +implementation of the `FilterProviderInterface`.) diff --git a/docs/book/v3/migration/v2-to-v3.md b/docs/book/v3/migration/v2-to-v3.md new file mode 100644 index 00000000..ead2be4a --- /dev/null +++ b/docs/book/v3/migration/v2-to-v3.md @@ -0,0 +1,55 @@ +# Migration from Version 2 to 3 + +laminas-filter version 3 makes a number of changes that may affect your application. +This document details those changes, and provides suggestions on how to update your application to work with version 3. + +## Removed Filters + +The following filters were deprecated in the 2.0.x series of releases and have now been removed: + +### Encryption and Decryption related filters + +These filters had become outdated. 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 + +`Laminas\Filter\StaticFilter` has been removed without replacement. 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 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 Filters + +- `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) + +## Removed Features + +### Final by default + +Nearly all the shipped filters now have the final keyword applied to the class. Individual filters were not designed for inheritance, so if you have filters that do extend from any of the shipped filters, you will likely have to re-consider your design. + +### Removal of supported compression formats + +`Laminas\Filter\Compress` no longer supports the compression formats `Lzf`, `Rar` and `Snappy`. +Support for these formats has been removed so the following classes are no longer available: + +- `Laminas\Filter\Compress\Lzf` +- `Laminas\Filter\Compress\Rar` +- `Laminas\Filter\Compress\Snappy` + +The following compression formats are still available: `Bz2`, `Gz`, `Tar` and `Zip` diff --git a/docs/book/v3/standard-filters.md b/docs/book/v3/standard-filters.md new file mode 100644 index 00000000..665bcf2d --- /dev/null +++ b/docs/book/v3/standard-filters.md @@ -0,0 +1,1490 @@ +# Standard Filters + +laminas-filter comes with a standard set of filters, available for immediate use. + +## AllowList + +This filter will return `null` if the value being filtered is not present the +filter's allowed list of values. If the value is present, it will return that +value. + +For the opposite functionality see the [DenyList](#denylist) filter. + +### Supported Options + +The following options are supported for `Laminas\Filter\AllowList`: + +- `strict`: Uses strict mode for comparisons; passed to `in_array()`'s third argument. +- `list`: An array of allowed values. + +### Basic Usage + +```php +$allowList = new \Laminas\Filter\AllowList([ + 'list' => ['allowed-1', 'allowed-2'] +]); +echo $allowList->filter('allowed-2'); // => 'allowed-2' +echo $allowList->filter('not-allowed'); // => null +``` + +## Alnum + +The `Alnum` filter can be used to return only alphabetic characters and digits +in the unicode "letter" and "number" categories, respectively. All other +characters are suppressed. + +This filter is part of the laminas-i18n package; you will need to include that +package in your application to use it. + +### Supported Options + +The following options are supported for `Alnum`: + +```php +Alnum([ boolean $allowWhiteSpace [, string $locale ]]) +``` + +- `$allowWhiteSpace`: If set to true, then whitespace characters are allowed. + Otherwise they are suppressed. Default is `false` (whitespace is not allowed). + Methods for getting/setting the `allowWhiteSpace` option are also available: + `getAllowWhiteSpace()` and `setAllowWhiteSpace()`. + +- `$locale`: The locale string used in identifying the characters to filter + (locale name, e.g. `en_US`). If unset, it will use the default locale + (`Locale::getDefault()`). Methods for getting/setting the locale are also + available: `getLocale()` and `setLocale()`. + +### Basic Usage + +```php +// Default settings, deny whitespace +$filter = new \Laminas\I18n\Filter\Alnum(); +echo $filter->filter('This is (my) content: 123'); +// Returns 'Thisismycontent123' + +// First param in constructor is $allowWhiteSpace +$filter = new \Laminas\I18n\Filter\Alnum(true); +echo $filter->filter('This is (my) content: 123'); +// Returns 'This is my content 123' +``` + +> ### Supported Languages +> +> `Alnum` works on almost all languages, except: Chinese, Japanese and Korean. +> Within these languages, the english alphabet is used instead of the characters +> from these languages. The language itself is detected using the `Locale` +> class. + +## Alpha + +The `Alpha` filter can be used to return only alphabetic characters in the unicode "letter" +category. All other characters are suppressed. + +This filter is part of the laminas-i18n package; you will need to include that +package in your application to use it. + +### Supported Options + +The following options are supported for `Alpha`: + +```php +Alpha([ boolean $allowWhiteSpace [, string $locale ]]) +``` + +- `$allowWhiteSpace`: If set to true then whitespace characters are allowed. + Otherwise they are suppressed. Default is `false` (whitespace is not allowed). + Methods for getting/setting the allowWhiteSpace option are also available: + `getAllowWhiteSpace()` and `setAllowWhiteSpace()`. + +- `$locale`: The locale string used in identifying the characters to filter + (locale name, e.g. `en_US`). If unset, it will use the default locale + (`Locale::getDefault()`). Methods for getting/setting the locale are also + available: `getLocale()` and `setLocale()`. + +### Basic Usage + +```php +// Default settings, deny whitespace +$filter = new \Laminas\I18n\Filter\Alpha(); +echo $filter->filter('This is (my) content: 123'); +// Returns 'Thisismycontent' + +// Allow whitespace +$filter = new \Laminas\I18n\Filter\Alpha(true); +echo $filter->filter('This is (my) content: 123'); +// Returns 'This is my content ' +``` + +> ### Supported Languages +> +> `Alpha` works on almost all languages, except: Chinese, Japanese and Korean. +> Within these languages, the english alphabet is used instead of the characters +> from these languages. The language itself is detected using the `Locale` +> class. + +## BaseName + +`Laminas\Filter\BaseName` allows you to filter a string which contains the path to +a file, and it will return the base name of this file. + +### Supported Options + +There are no additional options for `Laminas\Filter\BaseName`. + +### Basic Usage + +```php +$filter = new Laminas\Filter\BaseName(); + +print $filter->filter('/vol/tmp/filename'); +``` + +This will return 'filename'. + +```php +$filter = new Laminas\Filter\BaseName(); + +print $filter->filter('/vol/tmp/filename.txt'); +``` + +This will return '`filename.txt`'. + +## Boolean + +This filter changes a given input to be a `BOOLEAN` value. This is often useful when working with +databases or when processing form values. + +### Supported Options + +The following options are supported for `Laminas\Filter\Boolean`: + +- `casting`: When this option is set to `TRUE`, then any given input will be + cast to boolean. This option defaults to `TRUE`. +- `translations`: This option sets the translations which will be used to detect localized input. +- `type`: The `type` option sets the boolean type which should be used. Read + the following for details. + +### Default Behavior + +By default, this filter works by casting the input to a `BOOLEAN` value; in other words, it operates +in a similar fashion to calling `(boolean) $value`. + +```php +$filter = new Laminas\Filter\Boolean(); +$value = ''; +$result = $filter->filter($value); +// returns false +``` + +This means that without providing any configuration, `Laminas\Filter\Boolean` accepts all input types +and returns a `BOOLEAN` just as you would get by type casting to `BOOLEAN`. + +### Changing the Default Behavior + +Sometimes, casting with `(boolean)` will not suffice. `Laminas\Filter\Boolean` +allows you to configure specific types to convert, as well as which to omit. + +The following types can be handled (in this precedence order): + +- `localized`: Converts any string as mapped (case sensitive) in the `translations` option. +- `false`: Converts a string equal to the word "false" (case insensitive) to boolean `FALSE`. +- `null`: Converts a `NULL` value to `FALSE`. +- `array`: Converts an empty `array` to `FALSE`. +- `zero`: Converts a string to `FALSE` if it equates to `'0'` after type juggling. +- `string`: Converts an empty string `''` to `FALSE`. +- `float`: Converts a float `0.0` value to `FALSE`. +- `integer`: Converts an integer `0` value to `FALSE`. +- `boolean`: Returns a boolean value as is. + +There are 2 additional special types: + +- `all`: Converts all above types to `BOOLEAN`. The same as setting all above types. +- `php`: Converts all above types to `BOOLEAN` except `localized` or `false`. The same as setting all above types except `localized` or `false`. + +All other given values will return `TRUE` by default. + +There are several ways to select which of the above types are filtered. You can +give one or multiple types and add them, you can give an array, you can use +constants, or you can give a textual string. See the following examples: + +```php +// converts 0 to false +$filter = new Laminas\Filter\Boolean(Laminas\Filter\Boolean::TYPE_INTEGER); + +// converts 0 and '0' to false +$filter = new Laminas\Filter\Boolean( + Laminas\Filter\Boolean::TYPE_INTEGER + Laminas\Filter\Boolean::TYPE_ZERO_STRING +); + +// converts 0 and '0' to false +$filter = new Laminas\Filter\Boolean([ + 'type' => [ + Laminas\Filter\Boolean::TYPE_INTEGER, + Laminas\Filter\Boolean::TYPE_ZERO_STRING, + ], +]); + +// converts 0 and '0' to false +$filter = new Laminas\Filter\Boolean([ + 'type' => [ + 'integer', + 'zero', + ], +]); +``` + +You can also give an instance of `Laminas\Config\Config` to set the desired types. +To set types after instantiation, use the `setType()` method. + +### Localized Booleans + +As mentioned previously, `Laminas\Filter\Boolean` can also recognise localized "yes" and "no" strings. +This means that you can ask your customer in a form for "yes" or "no" within his native language and +`Laminas\Filter\Boolean` will convert the response to the appropriate boolean value. + +To set the translation and the corresponding value, you can use the `translations` option or the +method `setTranslations`. The translations must be set for any values you wish to map to boolean values. + +```php +$filter = new Laminas\Filter\Boolean([ + 'type' => Laminas\Filter\Boolean::TYPE_LOCALIZED, + 'translations' => [ + 'ja' => true, + 'nein' => false, + 'yes' => true, + 'no' => false, + ], +]); + +// returns false +$result = $filter->filter('nein'); + +// returns true +$result = $filter->filter('yes'); +``` + +### Disable Casting + +Sometimes it is necessary to recognise only `TRUE` or `FALSE` and return all +other values without changes. `Laminas\Filter\Boolean` allows you to do this by +setting the `casting` option to `FALSE`. + +In this case `Laminas\Filter\Boolean` will work as described in the following +table, which shows which values return `TRUE` or `FALSE`. All other given values +are returned without change when `casting` is set to `FALSE` + +Type Constant | Type String | True | False +---- | ---- | ---- | ----- +`Laminas\Filter\Boolean::TYPE_BOOLEAN` | `boolean` | `TRUE` | `FALSE` +`Laminas\Filter\Boolean::TYPE_EMPTY_ARRAY` | `array` | | `[]` +`Laminas\Filter\Boolean::TYPE_FALSE_STRING` | `false` | `'true'` (case insensitive) | `'false'` (case insensitive) +`Laminas\Filter\Boolean::TYPE_FLOAT` | `float` | `1.0` | `0.0` +`Laminas\Filter\Boolean::TYPE_INTEGER` | `integer` | `1` | `0` +`Laminas\Filter\Boolean::TYPE_NULL` | `null` | | `NULL` +`Laminas\Filter\Boolean::TYPE_STRING` | `string` | | `''` +`Laminas\Filter\Boolean::TYPE_ZERO_STRING` | `zero` | `'1'` | `'0'` + +The following example shows the behavior when changing the `casting` option: + +```php +$filter = new Laminas\Filter\Boolean([ + 'type' => Laminas\Filter\Boolean::TYPE_ALL, + 'casting' => false, +]); + +// returns false +$result = $filter->filter(0); + +// returns true +$result = $filter->filter(1); + +// returns the value +$result = $filter->filter(2); +``` + +## Callback + +This filter allows you to use own methods in conjunction with `Laminas\Filter`. You +don't have to create a new filter when you already have a method which does the +job. + +### Supported Options + +The following options are supported for `Laminas\Filter\Callback`: + +- `callback`: This sets the callback which should be used. +- `callback_params`: This property sets the options which are used when the + callback is processed. + +### Basic Usage + +The usage of this filter is quite simple. In this example, we want to create a +filter which reverses a string: + +```php +$filter = new Laminas\Filter\Callback('strrev'); + +print $filter->filter('Hello!'); +// returns "!olleH" +``` + +As you can see it's really simple to use a callback to define custom filters. It +is also possible to use a method, which is defined within a class, by giving an +array as the callback: + +```php +class MyClass +{ + public static function reverse($param); +} + +// The filter definition +$filter = new Laminas\Filter\Callback(array('MyClass', 'reverse')); +print $filter->filter('Hello!'); +``` + +As of PHP 5.5 you can use ::class resolution for given callback class: + +```php +class MyClass +{ + public function __invoke($param); +} + +// The filter definition +$filter = new Laminas\Filter\Callback(MyClass::class); +print $filter->filter('Hello!'); +``` + +To get the actual set callback use `getCallback()` and to set another callback +use `setCallback()`. + +> ### Possible Exceptions +> +> You should note that defining a callback method which can not be called will +> raise an exception. + +### Default Parameters within a Callback + +It is also possible to define default parameters, which are given to the called +method as an array when the filter is executed. This array will be concatenated +with the value which will be filtered. + +```php +$filter = new Laminas\Filter\Callback([ + 'callback' => 'MyMethod', + 'options' => ['key' => 'param1', 'key2' => 'param2'] +]); +$filter->filter(['value' => 'Hello']); +``` + +Calling the above method definition manually would look like this: + +```php +$value = MyMethod('Hello', 'param1', 'param2'); +``` + +## Compress and Decompress + +These two filters are capable of compressing and decompressing strings, files, and directories. + +### Supported Options + +The following options are supported for `Laminas\Filter\Compress` and `Laminas\Filter\Decompress`: + +- `adapter`: The compression adapter which should be used. It defaults to `Gz`. +- `options`: Additional options which are given to the adapter at initiation. + Each adapter supports its own options. + +### Supported Compression Adapters + +The following compression formats are supported by their own adapter: + +- **Bz2** +- **Gz** +- **Tar** +- **Zip** + +Each compression format has different capabilities as described below. All +compression filters may be used in approximately the same ways, and differ +primarily in the options available and the type of compression they offer (both +algorithmically as well as string vs. file vs. directory) + +### Generic Handling + +To create a compression filter, you need to select the compression format you want to use. The +following example takes the **Bz2** adapter. Details for all other adapters are described after +this section. + +The two filters are basically identical, in that they utilize the same backends. +`Laminas\Filter\Compress` should be used when you wish to compress items, and `Laminas\Filter\Decompress` +should be used when you wish to decompress items. + +For instance, if we want to compress a string, we have to initialize `Laminas\Filter\Compress` and +indicate the desired adapter: + +```php +$filter = new Laminas\Filter\Compress('Bz2'); +``` + +To use a different adapter, you simply specify it to the constructor. + +You may also provide an array of options or a `Traversable` object. If you do, +provide minimally the key "adapter", and then either the key "options" or +"adapterOptions", both of which should be an array of options to provide to the +adapter on instantiation. + +```php +$filter = new Laminas\Filter\Compress([ + 'adapter' => 'Bz2', + 'options' => [ + 'blocksize' => 8, + ], +]); +``` + +> ### Default compression Adapter +> +> When no compression adapter is given, then the **Gz** adapter will be used. + +Decompression is essentially the same usage; we simply use the `Decompress` +filter instead: + +```php +$filter = new Laminas\Filter\Decompress('Bz2'); +``` + +To get the compressed string, we have to give the original string. The filtered value is the +compressed version of the original string. + +```php +$filter = new Laminas\Filter\Compress('Bz2'); +$compressed = $filter->filter('Uncompressed string'); +// Returns the compressed string +``` + +Decompression works in reverse, accepting the compressed string, and returning +the original: + +```php +$filter = new Laminas\Filter\Decompress('Bz2'); +$compressed = $filter->filter('Compressed string'); +// Returns the original, uncompressed string +``` + +### Creating an Archive + +Creating an archive file works almost the same as compressing a string. However, in this case we +need an additional parameter which holds the name of the archive we want to create. + +```php +$filter = new Laminas\Filter\Compress([ + 'adapter' => 'Bz2', + 'options' => [ + 'archive' => 'filename.bz2', + ], +]); +$compressed = $filter->filter('Uncompressed string'); +// Returns true on success, and creates the archive file +``` + +In the above example, the uncompressed string is compressed, and is then written +into the given archive file. + +> ### Existing Archives will be overwritten +> +> The content of any existing file will be overwritten when the given filename +> of the archive already exists. + +When you want to compress a file, then you must give the name of the file with its path: + +```php +$filter = new Laminas\Filter\Compress([ + 'adapter' => 'Bz2', + 'options' => [ + 'archive' => 'filename.bz2' + ], +]); +$compressed = $filter->filter('C:\temp\compressme.txt'); +// Returns true on success and creates the archive file +``` + +You may also specify a directory instead of a filename. In this case the whole +directory with all its files and subdirectories will be compressed into the +archive: + +```php +$filter = new Laminas\Filter\Compress([ + 'adapter' => 'Bz2', + 'options' => [ + 'archive' => 'filename.bz2' + ], +]); +$compressed = $filter->filter('C:\temp\somedir'); +// Returns true on success and creates the archive file +``` + +> ### Do not compress large or base Directories +> +> You should never compress large or base directories like a complete partition. +> Compressing a complete partition is a very time consuming task which can lead +> to massive problems on your server when there is not enough space or your +> script takes too much time. + +### Decompressing an Archive + +Decompressing an archive file works almost like compressing it. You must specify either the +`archive` parameter, or give the filename of the archive when you decompress the file. + +```php +$filter = new Laminas\Filter\Decompress('Bz2'); +$decompressed = $filter->filter('filename.bz2'); +// Returns true on success and decompresses the archive file +``` + +Some adapters support decompressing the archive into another subdirectory. In +this case you can set the `target` parameter: + +```php +$filter = new Laminas\Filter\Decompress([ + 'adapter' => 'Zip', + 'options' => [ + 'target' => 'C:\temp', + ] +]); +$decompressed = $filter->filter('filename.zip'); +// Returns true on success, and decompresses the archive file +// into the given target directory +``` + +> ### Directories to extract to must exist +> +> When you want to decompress an archive into a directory, then the target +> directory must exist. + +### Bz2 Adapter + +The Bz2 Adapter can compress and decompress: + +- Strings +- Files +- Directories + +This adapter makes use of PHP's Bz2 extension. + +To customize compression, this adapter supports the following options: + +- `archive`: This parameter sets the archive file which should be used or created. +- `blocksize`: This parameter sets the blocksize to use. It can be from '0' to + '9'. The default value is '4'. + +All options can be set at instantiation or by using a related method; for example, the related +methods for 'blocksize' are `getBlocksize()` and `setBlocksize()`. You can also use the +`setOptions()` method, which accepts an array of all options. + +### Gz Adapter + +The Gz Adapter can compress and decompress: + +- Strings +- Files +- Directories + +This adapter makes use of PHP's Zlib extension. + +To customize the compression this adapter supports the following options: + +- `archive`: This parameter sets the archive file which should be used or created. +- `level`: This compression level to use. It can be from '0' to '9'. The default + value is '9'. +- `mode`: There are two supported modes. `compress` and `deflate`. The default + value is `compress`. + +All options can be set at initiation or by using a related method. For example, the related methods +for `level` are `getLevel()` and `setLevel()`. You can also use the `setOptions()` method which +accepts an array of all options. + +### Tar Adapter + +The Tar Adapter can compress and decompress: + +- Files +- Directories + +> ### Tar does not support Strings +> +> The Tar Adapter can not handle strings. + +This adapter makes use of PEAR's `Archive_Tar` component. + +To customize compression, this adapter supports the following options: + +- `archive`: This parameter sets the archive file which should be used or created. +- `mode`: A mode to use for compression. Supported are either `NULL`, which + means no compression at all; `Gz`, which makes use of PHP's Zlib extension; + and `Bz2`, which makes use of PHP's Bz2 extension. The default value is `NULL`. +- `target`: The target where the decompressed files will be written to. + +All options can be set at instantiation or by using a related method. For +example, the related methods for `target` are `getTarget()` and `setTarget()`. +You can also use the `setOptions()` method which accepts an array of all +options. + +> ### Directory Usage +> +> When compressing directories with Tar, the complete file path is used. This +> means that created Tar files will not only have the subdirectory, but the +> complete path for the compressed file. + +### Zip Adapter + +The Zip Adapter can compress and decompress: + +- Strings +- Files +- Directories + +> ### Zip does not support String Decompression +> +> The Zip Adapter can not handle decompression to a string; decompression will +> always be written to a file. + +This adapter makes use of PHP's `Zip` extension. + +To customize compression, this adapter supports the following options: + +- `archive`: This parameter sets the archive file which should be used or created. +- `target`: The target where the decompressed files will be written to. + +All options can be set at instantiation or by using a related method. For example, the related +methods for `target` are `getTarget()` and `setTarget()`. You can also use the `setOptions()` method +which accepts an array of all options. + +## DenyList + +This filter will return `null` if the value being filtered is present in the filter's list of +values. If the value is not present, it will return that value. + +For the opposite functionality, see the [`AllowList` filter](#allowlist). + +### Supported Options + +The following options are supported for `Laminas\Filter\DenyList`: + +- `strict`: Uses strict mode when comparing; passed to `in_array()`'s third argument. +- `list`: An array of forbidden values. + +### Basic Usage + +```php +$denyList = new \Laminas\Filter\DenyList([ + 'list' => ['forbidden-1', 'forbidden-2'] +]); +echo $denyList->filter('forbidden-1'); // => null +echo $denyList->filter('allowed'); // => 'allowed' +``` + +## Digits + +Returns the string `$value`, removing all but digits. + +### Supported Options + +There are no additional options for `Laminas\Filter\Digits`. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Digits(); + +print $filter->filter('October 2012'); +``` + +This returns "2012". + +```php +$filter = new Laminas\Filter\Digits(); + +print $filter->filter('HTML 5 for Dummies'); +``` + +This returns "5". + +## Dir + +Given a string containing a path to a file, this function will return the name of the directory. + +### Supported Options + +There are no additional options for `Laminas\Filter\Dir`. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Dir(); + +print $filter->filter('/etc/passwd'); +``` + +This returns `/etc`. + +```php +$filter = new Laminas\Filter\Dir(); + +print $filter->filter('C:/Temp/x'); +``` + +This returns `C:/Temp`. + +## HtmlEntities + +Returns the string `$value`, converting characters to their corresponding HTML +entity equivalents when possible. + +### Supported Options + +The following options are supported for `Laminas\Filter\HtmlEntities`: + +- `quotestyle`: Equivalent to the PHP `htmlentities()` native function parameter + `quote_style`. This allows you to define what will be done with 'single' and + "double" quotes. The following constants are accepted: `ENT_COMPAT`, + `ENT_QUOTES`, and `ENT_NOQUOTES`, with the default being `ENT_COMPAT`. +- `charset`: Equivalent to the PHP `htmlentities()` native function parameter + `charset`. This defines the character set to be used in filtering. Unlike the + PHP native function, the default is 'UTF-8'. See the [PHP htmlentities + manual](http://php.net/htmlentities) for a list of supported character sets. + + This option can also be set via the `$options` parameter as a Traversable + object or array. The option key will be accepted as either `charset` or + `encoding`. +- `doublequote`: Equivalent to the PHP `htmlentities()` native function + parameter `double_encode`. If set to `false`, existing HTML entities will not + be encoded. The default is to convert everything (`true`). + + This option must be set via the `$options` parameter or the + `setDoubleEncode()` method. + +### Basic Usage + +```php +$filter = new Laminas\Filter\HtmlEntities(); + +print $filter->filter('<'); +``` + +### Quote Style + +`Laminas\Filter\HtmlEntities` allows changing the quote style used. This can be useful when you want to +leave double, single, or both types of quotes un-filtered. + +```php +$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_QUOTES]); + +$input = "A 'single' and " . '"double"'; +print $filter->filter($input); +``` + +The above example returns `A 'single' and "double"`. Notice +that 'single' as well as "double" quotes are filtered. + +```php +$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_COMPAT]); + +$input = "A 'single' and " . '"double"'; +print $filter->filter($input); +``` + +The above example returns `A 'single' and "double"`. Notice that +"double" quotes are filtered while 'single' quotes are not altered. + +```php +$filter = new Laminas\Filter\HtmlEntities(['quotestyle' => ENT_NOQUOTES]); + +$input = "A 'single' and " . '"double"'; +print $filter->filter($input); +``` + +The above example returns `A 'single' and "double"`. Notice that neither +"double" or 'single' quotes are altered. + +### Helper Methods + +To change or retrieve the `quotestyle` after instantiation, the two methods +`setQuoteStyle()` and `getQuoteStyle()` may be used respectively. +`setQuoteStyle()` accepts one parameter, `$quoteStyle`, which accepts one of the +constants `ENT_COMPAT`, `ENT_QUOTES`, or `ENT_NOQUOTES`. + +```php +$filter = new Laminas\Filter\HtmlEntities(); + +$filter->setQuoteStyle(ENT_QUOTES); +print $filter->getQuoteStyle(ENT_QUOTES); +``` + +To change or retrieve the `charset` after instantiation, the two methods +`setCharSet()` and `getCharSet()` may be used respectively. `setCharSet()` +accepts one parameter, `$charSet`. See the [PHP htmlentities manual +page](http://php.net/htmlentities) for a list of supported character sets. + +```php +$filter = new Laminas\Filter\HtmlEntities(); + +$filter->setQuoteStyle(ENT_QUOTES); +print $filter->getQuoteStyle(ENT_QUOTES); +``` + +To change or retrieve the `doublequote` option after instantiation, the two methods +`setDoubleQuote()` and `getDoubleQuote()` may be used respectively. `setDoubleQuote()` accepts one +boolean parameter, `$doubleQuote`. + +```php +$filter = new Laminas\Filter\HtmlEntities(); + +$filter->setQuoteStyle(ENT_QUOTES); +print $filter->getQuoteStyle(ENT_QUOTES); +``` + +## ToFloat + +- Since 2.9.0 + +`Laminas\Filter\ToFloat` allows you to transform a scalar value into a float. + +### Supported Options + +There are no additional options for `Laminas\Filter\ToFloat`. + +### Basic Usage + +```php +$filter = new Laminas\Filter\ToFloat(); + +print $filter->filter('-4.4'); +``` + +This will return `-4.4` (as a float). + +## ToInt + +`Laminas\Filter\ToInt` allows you to transform a scalar value into an integer. + +### Supported Options + +There are no additional options for `Laminas\Filter\ToInt`. + +### Basic Usage + +```php +$filter = new Laminas\Filter\ToInt(); + +print $filter->filter('-4 is less than 0'); +``` + +This will return '-4'. + +### Migration from 2.0-2.3 to 2.4+ + +Version 2.4 adds support for PHP 7. In PHP 7, `int` is a reserved keyword, which required renaming +the `Int` filter. If you were using the `Int` filter directly previously, you will now receive an +`E_USER_DEPRECATED` notice on instantiation. Please update your code to refer to the `ToInt` class +instead. + +Users pulling their `Int` filter instance from the filter plugin manager receive a `ToInt` instance +instead starting in 2.4.0. + +## ToNull + +This filter will change the given input to be `NULL` if it meets specific +criteria. This is often necessary when you work with databases and want to have +a `NULL` value instead of a boolean or any other type. + +### Supported Options + +The following options are supported for `Laminas\Filter\ToNull`: + +- `type`: The variable type which should be supported. + +### Default Behavior + +Per default this filter works like PHP's `empty()` method; in other words, if +`empty()` returns a boolean `TRUE`, then a `NULL` value will be returned. + +```php +$filter = new Laminas\Filter\ToNull(); +$value = ''; +$result = $filter->filter($value); +// returns null instead of the empty string +``` + +This means that without providing any configuration, `Laminas\Filter\ToNull` will +accept all input types and return `NULL` in the same cases as `empty()`. + +Any other value will be returned as is, without any changes. + +### Changing the Default Behavior + +Sometimes it's not enough to filter based on `empty()`. Therefore +`Laminas\Filter\ToNull` allows you to configure which types will be converted, and +which not. + +The following types can be handled: + +- `boolean`: Converts a boolean `FALSE` value to `NULL`. +- `integer`: Converts an integer `0` value to `NULL`. +- `empty_array`: Converts an empty `array` to `NULL`. +- `float`: Converts an float `0.0` value to `NULL`. +- `string`: Converts an empty string `''` to `NULL`. +- `zero`: Converts a string containing the single character zero (`'0'`) to `NULL`. +- `all`: Converts all above types to `NULL`. (This is the default behavior.) + +There are several ways to select which of the above types are filtered. You can +give one or multiple types and add them, you can give an array, you can use +constants, or you can give a textual string. See the following examples: + +```php +// converts false to null +$filter = new Laminas\Filter\ToNull(Laminas\Filter\ToNull::BOOLEAN); + +// converts false and 0 to null +$filter = new Laminas\Filter\ToNull( + Laminas\Filter\ToNull::BOOLEAN + Laminas\Filter\ToNull::INTEGER +); + +// converts false and 0 to null +$filter = new Laminas\Filter\ToNull([ + Laminas\Filter\ToNull::BOOLEAN, + Laminas\Filter\ToNull::INTEGER +]); + +// converts false and 0 to null +$filter = new Laminas\Filter\ToNull([ + 'boolean', + 'integer', +]); +``` + +You can also give a `Traversable` or an array to set the wished types. To set +types afterwards use `setType()`. + +### Migration from 2.0-2.3 to 2.4+ + +Version 2.4 adds support for PHP 7. In PHP 7, `null` is a reserved keyword, which required renaming +the `Null` filter. If you were using the `Null` filter directly previously, you will now receive an +`E_USER_DEPRECATED` notice on instantiation. Please update your code to refer to the `ToNull` class +instead. + +Users pulling their `Null` filter instance from the filter plugin manager receive a `ToNull` +instance instead starting in 2.4.0. + +## NumberFormat + +The `NumberFormat` filter can be used to return locale-specific number and percentage strings. It +extends the `NumberParse` filter, which acts as wrapper for the `NumberFormatter` class within the +Internationalization extension (Intl). + +This filter is part of the laminas-i18n package; you will need to include that +package in your application to use it. + +### Supported Options + +The following options are supported for `NumberFormat`: + +```php +NumberFormat([ string $locale [, int $style [, int $type ]]]) +``` + +- `$locale`: (Optional) Locale in which the number would be formatted (locale + name, e.g. `en_US`). If unset, it will use the default locale + (`Locale::getDefault()`). Methods for getting/setting the locale are also + available: `getLocale()` and `setLocale()`. + +- `$style`: (Optional) Style of the formatting, one of the + [format style constants](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.unumberformatstyle). + If unset, it will use `NumberFormatter::DEFAULT_STYLE` as the default style. + Methods for getting/setting the format style are also available: `getStyle()` + and `setStyle()`. + +- `$type`: (Optional) The [formatting type](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.types) + to use. If unset, it will use `NumberFormatter::TYPE_DOUBLE` as the default + type. Methods for getting/setting the format type are also available: + `getType()` and `setType()`. + +### Basic Usage + +```php +$filter = new \Laminas\I18n\Filter\NumberFormat('de_DE'); +echo $filter->filter(1234567.8912346); +// Returns '1.234.567,891' + +$filter = new \Laminas\I18n\Filter\NumberFormat('en_US', NumberFormatter::PERCENT); +echo $filter->filter(0.80); +// Returns '80%' + +$filter = new \Laminas\I18n\Filter\NumberFormat('fr_FR', NumberFormatter::SCIENTIFIC); +echo $filter->filter(0.00123456789); +// Returns '1,23456789E-3' +``` + +## NumberParse + +The `NumberParse` filter can be used to parse a number from a string. It acts as +a wrapper for the `NumberFormatter` class within the Internationalization +extension (Intl). + +This filter is part of the laminas-i18n package; you will need to include that +package in your application to use it. + +### Supported Options + +The following options are supported for `NumberParse`: + +```php +NumberParse([ string $locale [, int $style [, int $type ]]]) +``` + +- `$locale`: (Optional) Locale in which the number would be parsed (locale name, + e.g. `en_US`). If unset, it will use the default locale + (`Locale::getDefault()`). Methods for getting/setting the locale are also + available: `getLocale()` and `setLocale()`. + +- `$style`: (Optional) Style of the parsing, one of the + [format style constants](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.unumberformatstyle). + If unset, it will use `NumberFormatter::DEFAULT_STYLE` as the default style. + Methods for getting/setting the parse style are also available: `getStyle()` + and `setStyle()`. + +- `$type`: (Optional) The [parsing type](http://www.php.net/manual/class.numberformatter.php#intl.numberformatter-constants.types) + to use. If unset, it will use `NumberFormatter::TYPE_DOUBLE` as the default + type. Methods for getting/setting the parse type are also available: + `getType()` and `setType()`. + +### Basic Usage + +```php +$filter = new \Laminas\I18n\Filter\NumberParse('de_DE'); +echo $filter->filter('1.234.567,891'); +// Returns 1234567.8912346 + +$filter = new \Laminas\I18n\Filter\NumberParse('en_US', NumberFormatter::PERCENT); +echo $filter->filter('80%'); +// Returns 0.80 + +$filter = new \Laminas\I18n\Filter\NumberParse('fr_FR', NumberFormatter::SCIENTIFIC); +echo $filter->filter('1,23456789E-3'); +// Returns 0.00123456789 +``` + +## PregReplace + +`Laminas\Filter\PregReplace` performs a search using regular expressions and replaces all found +elements. + +### Supported Options + +The following options are supported for `Laminas\Filter\PregReplace`: + +- `pattern`: The pattern to search for. +- `replacement`: The string which to use as a replacement for the matches; this + can optionally contain placeholders for matched groups in the search pattern. + +### Basic Usage + +To use this filter properly, you must give both options listed above. + +The `pattern` option has to be given to set the pattern to search for. It can be +a string for a single pattern, or an array of strings for multiple patterns. + +The `replacement` option indicates the string to replace matches with, and can +contain placeholders for matched groups from the search `pattern`. The value may +be a string replacement, or an array of string replacements. + +```php +$filter = new Laminas\Filter\PregReplace([ + 'pattern' => '/bob/', + 'replacement' => 'john', +]); +$input = 'Hi bob!'; + +$filter->filter($input); +// returns 'Hi john!' +``` + +You can also use `setPattern()` to set the pattern(s), and `setReplacement()` set +the replacement(s). + +```php +$filter = new Laminas\Filter\PregReplace(); +$filter + ->setPattern(array('bob', 'Hi')) + ->setReplacement(array('john', 'Bye')); +$input = 'Hi bob!'; + +$filter->filter($input); +// returns 'Bye john!' +``` + +For more complex usage, read the +[PCRE Pattern chapter of the PHP manual](http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php). + +## RealPath + +This filter will resolve given links and pathnames, and returns the canonicalized +absolute pathnames. + +### Supported Options + +The following options are supported for `Laminas\Filter\RealPath`: + +- `exists`: This option defaults to `TRUE`, which validates that the given path + really exists. + +### Basic Usage + +For any given link or pathname, its absolute path will be returned. References +to `/./`, `/../` and extra `/` sequences in the input path will be stripped. The +resulting path will not have any symbolic links, `/./`, or `/../` sequences. + +`Laminas\Filter\RealPath` will return `FALSE` on failure, e.g. if the file does not exist. On BSD +systems `Laminas\Filter\RealPath` doesn't fail if only the last path component doesn't exist, while +other systems will return `FALSE`. + +```php +$filter = new Laminas\Filter\RealPath(); +$path = '/www/var/path/../../mypath'; +$filtered = $filter->filter($path); + +// returns '/www/mypath' +``` + +### Non-Existing Paths + +Sometimes it is useful to get paths to files that do n0t exist; e.g., when you +want to get the real path for a path you want to create. You can then either +provide a `FALSE` `exists` value at initiation, or use `setExists()` to set it. + +```php +$filter = new Laminas\Filter\RealPath(false); +$path = '/www/var/path/../../non/existing/path'; +$filtered = $filter->filter($path); + +// returns '/www/non/existing/path' +// even when file_exists or realpath would return false +``` + +## StringPrefix + +- Since 2.9.0 + +This filter will add the provided prefix to scalar values. + +### Supported Options + +The following options are supported for `Laminas\Filter\StringPrefix`: + +- `prefix`: The string prefix to add to values. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StringPrefix([ + 'prefix' => 'PHP-', +]); + +echo $filter->filter('MidCentral'); +``` + +The above results in the string `PHP-MidCentral`. + +## StringSuffix + +- Since 2.9.0 + +This filter will add the provided suffix to scalar values. + +### Supported Options + +The following options are supported for `Laminas\Filter\StringSuffix`: + +- `suffix`: The string suffix to append to values. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StringSuffix([ + 'suffix' => '-PHP', +]); + +echo $filter->filter('MidCentral'); +``` + +The above results in the string `MidCentral-PHP`. + +## StringToLower + +This filter converts any input to lowercase. + +### Supported Options + +The following options are supported for `Laminas\Filter\StringToLower`: + +- `encoding`: This option can be used to set an encoding to use. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StringToLower(); + +print $filter->filter('SAMPLE'); +// returns "sample" +``` + +### Handling alternate Encoding + +By default, `StringToLower` will only handle characters from the locale of your +server; characters from other charsets will be ignored. If you have the mbstring +extension, however, you can use the filter with other encodings. Pass the +desired encoding when initiating the `StringToLower` filter, or use the +`setEncoding()` method to change it. + +```php +// using UTF-8 +$filter = new Laminas\Filter\StringToLower('UTF-8'); + +// or give an array which can be useful when using a configuration +$filter = new Laminas\Filter\StringToLower(['encoding' => 'UTF-8']); + +// or do this afterwards +$filter->setEncoding('ISO-8859-1'); +``` + +> ### Setting invalid Encodings +> +> Be aware that you will get an exception when: +> +> - you attempt to set an encoding and the mbstring extension is unavailable; or +> - you attempt to set an encoding unsupported by the mbstring extension. + +## StringToUpper + +This filter converts any input to UPPERCASE. + +### Supported Options + +The following options are supported for `Laminas\Filter\StringToUpper`: + +- `encoding`: This option can be used to set the encoding to use. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StringToUpper(); + +print $filter->filter('Sample'); +// returns "SAMPLE" +``` + +### Different encoded Strings + +Like the `StringToLower` filter, this filter will only handle characters +supported by your server locale, unless you have the mbstring extension enabled. +Using different character sets works the same as with `StringToLower`. + +```php +$filter = new Laminas\Filter\StringToUpper(['encoding' => 'UTF-8']); + +// or do this afterwards +$filter->setEncoding('ISO-8859-1'); +``` + +## StringTrim + +This filter modifies a given string such that certain characters are removed +from the beginning and end. + +### Supported Options + +The following options are supported for `Laminas\Filter\StringTrim`: + +- `charlist`: List of characters to remove from the beginning and end of the + string. If this is not set or is null, the default behavior will be invoked, + which is to remove only whitespace from the beginning and end of the string. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StringTrim(); + +print $filter->filter(' This is (my) content: '); +``` + +The above example returns `This is (my) content:`. Notice that the whitespace +characters have been removed. + +### Specifying alternate Characters + +```php +$filter = new Laminas\Filter\StringTrim(':'); +// or new Laminas\Filter\StringTrim(array('charlist' => ':')); + +print $filter->filter(' This is (my) content:'); +``` + +The above example returns `This is (my) content`. Notice that the whitespace +characters and colon are removed. You can also provide a `Traversable` or an +array with a `charlist` key. To set the desired character list after +instantiation, use the `setCharList()` method. `getCharList()` returns the +current character list. + +## StripNewlines + +This filter modifies a given string and removes all new line characters within +that string. + +### Supported Options + +There are no additional options for `Laminas\Filter\StripNewlines`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\StripNewlines(); + +print $filter->filter(' This is (my)``\n\r``content: '); +``` + +The above example returns `This is (my) content:`. Notice that all newline +characters have been removed. + +## StripTags + +This filter can strip XML and HTML tags from given content. + +> ### Laminas\\Filter\\StripTags is potentially insecure +> +> Be warned that `Laminas\\Filter\\StripTags` should only be used to strip *all* +> available tags. Using `Laminas\\Filter\\StripTags` to make your site secure by +> stripping *some* unwanted tags will lead to unsecure and dangerous code, +> including potential XSS vectors. +> +> For a fully secure solution that allows selected filtering of HTML tags, use +> either Tidy or HtmlPurifier. + +### Supported Options + +The following options are supported for `Laminas\Filter\StripTags`: + +- `allowAttribs`: This option sets the attributes which are accepted. All other + attributes are stripped from the given content. +- `allowTags`: This option sets the tags which are accepted. All other tags will + be stripped from; the given content. + +### Basic Usage + +```php +$filter = new Laminas\Filter\StripTags(); + +print $filter->filter('My content'); +``` + +The result will be the stripped content `My content`. + +When the content contains broken or partial tags, any content following the +opening tag will be completely removed: + +```php +$filter = new Laminas\Filter\StripTags(); + +print $filter->filter('This contains no ending tag'); +``` + +The above will return `This contains`, with the rest being stripped. + +### Allowing defined Tags + +`Laminas\Filter\StripTags` allows stripping all but an allowed set of tags. As an +example, this can be used to strip all markup except for links: + +```php +$filter = new Laminas\Filter\StripTags(['allowTags' => 'a']); + +$input = "A text with
a
link"; +print $filter->filter($input); +``` + +The above will return `A text with a link`; +it strips all tags but the link. By providing an array, you can specify multiple +tags at once. + +> ### Warning +> +> Do not use this feature to secure content. This component does not replace the +> use of a properly configured html filter. + +### Allowing defined Attributes + +You can also strip all but an allowed set of attributes from a tag: + +```php +$filter = new Laminas\Filter\StripTags([ + 'allowTags' => 'img', + 'allowAttribs' => 'src', +]); + +$input = "A text with
a picture"; +print $filter->filter($input); +``` + +The above will return `A text with a picture`; it +strips all tags but ``, and all attributes but `src` from those tags.By +providing an array you can set multiple attributes at once. + +### Allow specific Tags with specific Attributes + +You can also pass the tag allow list as a set of tag/attribute values. Each key +will be an allowed tag, pointing to a list of allowed attributes for that +tag. + +```php +$allowedElements = [ + 'img' => [ + 'src', + 'width' + ], + 'a' => [ + 'href' + ] +]; +$filter = new Laminas\Filter\StripTags($allowedElements); + +$input = "A text with
a picture click " + . "here!"; +print $filter->filter($input); +``` + +The above will return +`A text with a picture click here!` +as the result. + +## UriNormalize + +This filter sets the scheme on a URI if the scheme is missing. + +### Supported Options + +The following options are supported for `Laminas\Filter\UriNormalize`: + +- `defaultScheme`: This option can be used to set the default scheme to use when + parsing scheme-less URIs. +- `enforcedScheme`: Set a URI scheme to enforce on schemeless URIs. + +### Basic Usage + +```php +$filter = new Laminas\Filter\UriNormalize(array( + 'enforcedScheme' => 'https' +)); + +echo $filter->filter('www.example.com'); +``` + +The above results in the string `https://www.example.com`. diff --git a/docs/book/v3/word.md b/docs/book/v3/word.md new file mode 100644 index 00000000..7e1f6540 --- /dev/null +++ b/docs/book/v3/word.md @@ -0,0 +1,315 @@ +# Word Filters + +In addition to the standard set of filters, there are several classes specific +to filtering word strings. + +## CamelCaseToDash + +This filter modifies a given string such that `CamelCaseWords` are converted to `Camel-Case-Words`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\CamelCaseToDash`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\CamelCaseToDash(); + +print $filter->filter('ThisIsMyContent'); +``` + +The above example returns `This-Is-My-Content`. + +## CamelCaseToSeparator + +This filter modifies a given string such that `CamelCaseWords` are converted to `Camel Case Words`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\CamelCaseToSeparator`: + +- `separator`: A separator character. If this is not set, the default separator + is a space. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\CamelCaseToSeparator(':'); +// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => ':')); + +print $filter->filter('ThisIsMyContent'); +``` + +The above example returns `This:Is:My:Content`. + +### Default Behavior + +```php +$filter = new Laminas\Filter\Word\CamelCaseToSeparator(); + +print $filter->filter('ThisIsMyContent'); +``` + +The above example returns `This Is My Content`. + +## CamelCaseToUnderscore + +This filter modifies a given string such that `CamelCaseWords` are converted to +`Camel_Case_Words`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\CamelCaseToUnderscore`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\CamelCaseToUnderscore(); + +print $filter->filter('ThisIsMyContent'); +``` + +The above example returns `This_Is_My_Content`. + +## DashToCamelCase + +This filter modifies a given string such that `words-with-dashes` are converted +to `WordsWithDashes`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\DashToCamelCase`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\DashToCamelCase(); + +print $filter->filter('this-is-my-content'); +``` + +The above example returns `ThisIsMyContent`. + +## DashToSeparator + +This filter modifies a given string such that `words-with-dashes` are converted +to `words with dashes`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\DashToSeparator`: + +- `separator`: A separator character. If this is not set, the default separator + is a space. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\DashToSeparator('+'); +// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => '+')); + +print $filter->filter('this-is-my-content'); +``` + +The above example returns `this+is+my+content`. + +### Default Behavior + +```php +$filter = new Laminas\Filter\Word\DashToSeparator(); + +print $filter->filter('this-is-my-content'); +``` + +The above example returns `this is my content`. + +## DashToUnderscore + +This filter modifies a given string such that `words-with-dashes` are converted +to `words_with_dashes`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\DashToUnderscore`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\DashToUnderscore(); + +print $filter->filter('this-is-my-content'); +``` + +The above example returns `this_is_my_content`. + +## SeparatorToCamelCase + +This filter modifies a given string such that `words with separators` are +converted to `WordsWithSeparators`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\SeparatorToCamelCase`: + +- `separator`: A separator character. If this is not set, the default separator + is a space. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\SeparatorToCamelCase(':'); +// or new Laminas\Filter\Word\SeparatorToCamelCase(array('separator' => ':')); + +print $filter->filter('this:is:my:content'); +``` + +The above example returns `ThisIsMyContent`. + +### Default Behavior + +```php +$filter = new Laminas\Filter\Word\SeparatorToCamelCase(); + +print $filter->filter('this is my content'); +``` + +The above example returns `ThisIsMyContent`. + +## SeparatorToDash + +This filter modifies a given string such that `words with separators` are +converted to `words-with-separators`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\SeparatorToDash`: + +- `separator`: A separator character. If this is not set, the default separator + is a space. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\SeparatorToDash(':'); +// or new Laminas\Filter\Word\SeparatorToDash(array('separator' => ':')); + +print $filter->filter('this:is:my:content'); +``` + +The above example returns `this-is-my-content`. + +### Default Behavior + +```php +$filter = new Laminas\Filter\Word\SeparatorToDash(); + +print $filter->filter('this is my content'); +``` + +The above example returns `this-is-my-content`. + +## SeparatorToSeparator + +This filter modifies a given string such that `words with separators` are +converted to `words-with-separators`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\SeparatorToSeparator`: + +- `searchSeparator`: The search separator character. If this is not set, the + default separator is a space. +- `replaceSeparator`: The replacement separator character. If this is not set, the + default separator is a dash (`-`). + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\SeparatorToSeparator(':', '+'); + +print $filter->filter('this:is:my:content'); +``` + +The above example returns `this+is+my+content`. + +### Default Behaviour + +```php +$filter = new Laminas\Filter\Word\SeparatorToSeparator(); + +print $filter->filter('this is my content'); +``` + +The above example returns `this-is-my-content`. + +## UnderscoreToCamelCase + +This filter modifies a given string such that `words_with_underscores` are +converted to `WordsWithUnderscores`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\UnderscoreToCamelCase`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\UnderscoreToCamelCase(); + +print $filter->filter('this_is_my_content'); +``` + +The above example returns `ThisIsMyContent`. + +## UnderscoreToSeparator + +This filter modifies a given string such that `words_with_underscores` are +converted to `words with underscores`. + +### Supported Options + +The following options are supported for `Laminas\Filter\Word\UnderscoreToSeparator`: + +- `separator`: A separator character. If this is not set, the default separator + is a space. + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\UnderscoreToSeparator('+'); +// or new Laminas\Filter\Word\CamelCaseToSeparator(array('separator' => '+')); + +print $filter->filter('this_is_my_content'); +``` + +The above example returns `this+is+my+content`. + +### Default Behavior + +```php +$filter = new Laminas\Filter\Word\UnderscoreToSeparator(); + +print $filter->filter('this_is_my_content'); +``` + +The above example returns `this is my content`. + +## UnderscoreToDash + +This filter modifies a given string such that `words_with_underscores` are +converted to `words-with-underscores`. + +### Supported Options + +There are no additional options for `Laminas\Filter\Word\UnderscoreToDash`: + +### Basic Usage + +```php +$filter = new Laminas\Filter\Word\UnderscoreToDash(); + +print $filter->filter('this_is_my_content'); +``` + +The above example returns `this-is-my-content`. diff --git a/docs/book/v3/writing-filters.md b/docs/book/v3/writing-filters.md new file mode 100644 index 00000000..48552743 --- /dev/null +++ b/docs/book/v3/writing-filters.md @@ -0,0 +1,41 @@ +# Writing Filters + +`Laminas\Filter` supplies a set of commonly needed filters, but developers will +often need to write custom filters for their particular use cases. You can do +so by writing classes that implement `Laminas\Filter\FilterInterface`, which +defines a single method, `filter()`. + +## Example + +```php +namespace Application\Filter; + +use Laminas\Filter\FilterInterface; + +class MyFilter implements FilterInterface +{ + public function filter($value) + { + // perform some transformation upon $value to arrive on $valueFiltered + + return $valueFiltered; + } +} +``` + +To attach an instance of the filter defined above to a filter chain: + +```php +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain->attach(new Application\Filter\MyFilter()); +``` + +Alternately, add it to the `FilterPluginManager`: + +```php +$filterChain = new Laminas\Filter\FilterChain(); +$filterChain + ->getPluginManager() + ->setInvokableClass('myfilter', Application\Filter\MyFilter::class) +$filterChain->attachByName('myfilter'); +``` diff --git a/mkdocs.yml b/mkdocs.yml index 9fc753eb..4d138a71 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,22 +12,34 @@ nav: - 'String Inflection': v2/inflector.md - 'Static Filter': v2/static-filter.md - 'Writing Filters': v2/writing-filters.md + - v3: + - Introduction: v3/intro.md + - Reference: + - 'Standard Filters': v3/standard-filters.md + - 'Word Filters': v3/word.md + - 'File Filters': v3/file.md + - 'Filter Chains': v3/filter-chains.md + - 'String Inflection': v3/inflector.md + - 'Writing Filters': v3/writing-filters.md + - Migration: + - "Migration from Version 2 to 3": v3/migration/v2-to-v3.md site_name: laminas-filter site_description: "Programmatically filter and normalize data and files." repo_url: 'https://github.com/laminas/laminas-filter' extra: project: Components - current_version: v2 + current_version: v3 versions: - v2 + - v3 plugins: - redirects: redirect_maps: - intro.md: v2/intro.md - standard-filters.md: v2/standard-filters.md - word.md: v2/word.md - file.md: v2/file.md - filter-chains.md: v2/filter-chains.md - inflector.md: v2/inflector.md + intro.md: v3/intro.md + standard-filters.md: v3/standard-filters.md + word.md: v3/word.md + file.md: v3/file.md + filter-chains.md: v3/filter-chains.md + inflector.md: v3/inflector.md static-filter.md: v2/static-filter.md - writing-filters.md: v2/writing-filters.md + writing-filters.md: v3/writing-filters.md diff --git a/psalm-baseline.xml b/psalm-baseline.xml index ad362ba9..0895782c 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,9 +1,6 @@ - + - - filterable - $value @@ -11,15 +8,6 @@ setNullOnAllEmpty setNullOnEmpty - - $expectedInputs - - - - - - - @@ -38,15 +26,6 @@ is_object($options) - - - assert(is_string($encoding)) - is_string($encoding) - - - is_string($encoding) - - setList @@ -56,11 +35,6 @@ (bool) $strict - - - DenyList - - $typeOrOptions @@ -128,28 +102,21 @@ - - - is_string($adapter) - + + $options + - mixed + ($option is null ? array : mixed) - $options + $adapterOptions - - $value - - - new $adapter($options) - - - $options - - - getOptions - + + getOptions($option)]]> + + + is_string($option) ? null : [] + @@ -225,68 +192,6 @@ null !== $content - - - $content - $content - - - $options - - - - - bool - string|null - - - $content - $content - - - options['archive']]]> - options['callback']]]> - options['password']]]> - options['target']]]> - - - (string) $target - - - (string) $archive - (string) $password - - - ! $archive - ! $filelist - $archive - $filelist - - - $filelist - - - - - $compressed - $compressed - - - string - string - - - $compressed - $compressed - - - $content - $content - - - $options - - $result === false @@ -419,37 +324,24 @@ $value - - - + $value - + - - - Encrypt - - - Decrypt - - - is_string($value) - + string - - decrypt - - adapter->decrypt($value)]]> + filter($value)]]> $value + $value - - return $value; - + + $value + @@ -460,350 +352,6 @@ (bool) $strict - - - Encrypt\EncryptionAlgorithmInterface - - - ! is_string($value) - - - new $adapter($options) - - - $adapter - - - $adapter - $adapter - $adapter - $adapter - $adapter - $adapter - adapter]]> - adapter]]> - - - $adapter - $adapter - - - string - string - - - encrypt - new $adapter($options) - new $adapter($options) - toString - - - adapter->encrypt($value)]]> - adapter->toString()]]> - - - $value - - - return $value; - - - __call - getAdapter - getAdapterInstance - - - - - - - - BlockCipher - - - is_array($options) - is_array($options) - compression)]]> - - - encryption)]]> - - - $encryption - encryption]]> - encryption]]> - encryption]]> - - - - - - encryption]]> - $value - - - compression]]> - compression]]> - - - - - - - - - - encryption['key']]]> - encryption['vector']]]> - - - encryption['key']]]> - encryption['key']]]> - encryption['vector']]]> - - - $decrypted - $options - $value - - - array - string - string - string - - - encryption]]> - - - $decrypted - $decrypted - encryption]]> - encryption['key']]]> - encryption['vector']]]> - - - $compression - - - __construct - getCompression - getEncryption - getKey - getVector - - - $compression - - - setCipherAlgorithm - setHashAlgorithm - setKeyIteration - setSalt - - - - - decrypt - encrypt - toString - - - - - compression]]> - compression]]> - - - Openssl - - - is_array($keys) - - - array_values($keys) - - - - - $envKey - - $length - $length - - - - - - $key - $key - $key - $options - - - $fingerprints[$key] - - - $count - $decrypted - $envKey - $i - $i - - - - $length - $option - $option - $option - - - string - - - - $i - - - keys]]> - - - $decrypted - $decrypted - - - __construct - getCompression - getPackage - getPrivateKey - getPublicKey - setEnvelopeKey - setPrivateKey - setPublicKey - - - (bool) $package - - - is_string($key) - - - - - Filter\Decrypt - Filter\Decrypt - parent::filter($content) - - - - - - string|array - string|array - - - filename]]> - filename]]> - filename]]> - $value - $value - - - - - - filename]]> - - $value - - - string|array - - - filename]]> - filename]]> - $uploadData - - - $value - - - return $value; - - - $filename - - - $uploadData - - - getFilename - setFilename - - - $filename - - - filename)]]> - - - - - Filter\Encrypt - parent::filter($content) - - - - - - string|array - - - filename]]> - filename]]> - filename]]> - $value - $value - - - - - - filename]]> - - $value - - - string|array - - - filename]]> - filename]]> - $uploadData - - - $value - - - return $value; - - - $filename - - - $uploadData - - - getFilename - setFilename - - - $filename - - - filename)]]> - - $value @@ -838,6 +386,7 @@ $value + $value $options @@ -982,9 +531,31 @@ + + + + + $value + $value + $value + $value + $value + + string|array + + + $uploadData + $value + $value + $value + + + $value + $value + $uploadData @@ -1004,32 +575,6 @@ - - Blacklist::class - Decrypt::class - Decrypt::class - Decrypt::class - Decrypt::class - Decrypt::class - Encrypt::class - Encrypt::class - Encrypt::class - Encrypt::class - Encrypt::class - File\Decrypt::class - File\Decrypt::class - File\Decrypt::class - File\Decrypt::class - File\Decrypt::class - File\Decrypt::class - File\Encrypt::class - File\Encrypt::class - File\Encrypt::class - File\Encrypt::class - File\Encrypt::class - File\Encrypt::class - Whitelist::class - InvokableFactory::class]]> InvokableFactory::class]]> @@ -1114,7 +659,7 @@ $spec[0] - + @@ -1125,8 +670,8 @@ $processedPart $rule $rules[$spec] - $source[$ruleName] $spec + $value[$ruleName] $sourceName @@ -1142,11 +687,11 @@ $ruleFilter $ruleValue $sourceValue - + $ruleFilter($processedPart) @@ -1163,14 +708,11 @@ rules[$spec][$index]]]> - + - $source + $value - - $source - self @@ -1208,9 +750,6 @@ - - $pattern - @@ -1224,9 +763,6 @@ options['pattern']]]> - options['pattern']]]> - options['pattern']]]> - options['replacement']]]> options['replacement']]]> @@ -1288,8 +824,13 @@ + tagsAllowed[$tagName]]]> + + tagsAllowed[$tagName][$attributeName]]]> + + $attribute $attribute $element @@ -1301,7 +842,6 @@ is_array($options) - is_string($attribute) @@ -1312,9 +852,6 @@ - - $value - $type @@ -1354,15 +891,7 @@ setEnforcedScheme - - - AllowList - - - - is_string($separator) - $separator @@ -1372,10 +901,6 @@ getSeparator - - - - @@ -1473,11 +998,6 @@ returnUnfilteredDataProvider - - - new BlacklistFilter() - - $type @@ -1537,27 +1057,6 @@ null - - - new Lzf() - new Lzf() - - - - - bool - - - - - new SnappyCompression() - new SnappyCompression() - new SnappyCompression() - new SnappyCompression() - new SnappyCompression() - new SnappyCompression() - - $compressed @@ -1592,9 +1091,16 @@ + + $compressed + $input + $compressed + + null + returnUnfilteredDataProvider @@ -1773,19 +1279,6 @@ returnUnfilteredDataProvider - - - $value - $value - - - $filteredValue - - - $value - $value - - @@ -1878,11 +1371,6 @@ true - - $value - $value - $value - $expected $expected diff --git a/src/AbstractDateDropdown.php b/src/AbstractDateDropdown.php index 75093d60..811ef2ca 100644 --- a/src/AbstractDateDropdown.php +++ b/src/AbstractDateDropdown.php @@ -5,6 +5,7 @@ namespace Laminas\Filter; use function array_reduce; +use function assert; use function count; use function is_array; use function is_iterable; @@ -18,34 +19,29 @@ * null_on_all_empty?: bool, * ... * } + * @psalm-type InputArray = array * @template TOptions of Options * @template-extends AbstractFilter + * @template TInput of array */ abstract class AbstractDateDropdown extends AbstractFilter { /** * If true, the filter will return null if any date field is empty - * - * @var bool */ - protected $nullOnEmpty = false; + protected bool $nullOnEmpty = false; /** * If true, the filter will return null if all date fields are empty - * - * @var bool */ - protected $nullOnAllEmpty = false; + protected bool $nullOnAllEmpty = false; /** * Sprintf format string to use for formatting the date, fields will be used in alphabetical order. - * - * @var string */ - protected $format = ''; + protected string $format = ''; - /** @var int */ - protected $expectedInputs; + protected int $expectedInputs = 0; /** * @param mixed $options If array or Traversable, passes value to @@ -59,37 +55,29 @@ public function __construct(mixed $options = null) } /** - * @param bool $nullOnAllEmpty - * @return self + * @return $this */ - public function setNullOnAllEmpty($nullOnAllEmpty) + public function setNullOnAllEmpty(bool $nullOnAllEmpty): self { $this->nullOnAllEmpty = $nullOnAllEmpty; return $this; } - /** - * @return bool - */ - public function isNullOnAllEmpty() + public function isNullOnAllEmpty(): bool { return $this->nullOnAllEmpty; } /** - * @param bool $nullOnEmpty - * @return self + * @return $this */ - public function setNullOnEmpty($nullOnEmpty) + public function setNullOnEmpty(bool $nullOnEmpty): self { $this->nullOnEmpty = $nullOnEmpty; return $this; } - /** - * @return bool - */ - public function isNullOnEmpty() + public function isNullOnEmpty(): bool { return $this->nullOnEmpty; } @@ -98,12 +86,10 @@ public function isNullOnEmpty() * Attempts to filter an array of date/time information to a formatted * string. * - * @param mixed $value input to the filter - * @return mixed|string|null * @throws Exception\RuntimeException If filtering $value is impossible. - * @psalm-return ($value is array ? string|null : mixed) + * @psalm-return ($value is InputArray ? string : mixed|null) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_array($value)) { // nothing to do @@ -113,24 +99,23 @@ public function filter($value) // Convert the date to a specific format if ( $this->isNullOnEmpty() - && array_reduce($value, self::class . '::reduce', false) + && array_reduce($value, [self::class, 'reduce'], false) ) { return null; } if ( $this->isNullOnAllEmpty() - && array_reduce($value, self::class . '::reduce', true) + && array_reduce($value, [self::class, 'reduce'], true) ) { return null; } $this->filterable($value); + assert(is_array($value)); ksort($value); - $value = vsprintf($this->format, $value); - - return $value; + return vsprintf($this->format, $value); } /** @@ -139,7 +124,7 @@ public function filter($value) * @param array $value * @throws Exception\RuntimeException */ - protected function filterable($value) + protected function filterable(array $value): void { if (count($value) !== $this->expectedInputs) { throw new Exception\RuntimeException( @@ -154,12 +139,8 @@ protected function filterable($value) /** * Reduce to a single value - * - * @param string $soFar - * @param string $value - * @return bool */ - public static function reduce($soFar, $value) + private static function reduce(string $soFar, string|null $value): bool { return $soFar || empty($value); } diff --git a/src/AbstractFilter.php b/src/AbstractFilter.php index a053ddb9..6accdef4 100644 --- a/src/AbstractFilter.php +++ b/src/AbstractFilter.php @@ -95,9 +95,8 @@ public function getOptions() * Proxies to {@link filter()} * * @throws Exception\ExceptionInterface If filtering $value is impossible. - * @return mixed */ - public function __invoke(mixed $value) + public function __invoke(mixed $value): mixed { return $this->filter($value); } diff --git a/src/AbstractUnicode.php b/src/AbstractUnicode.php index b9dc9744..11995022 100644 --- a/src/AbstractUnicode.php +++ b/src/AbstractUnicode.php @@ -5,9 +5,7 @@ namespace Laminas\Filter; use function array_map; -use function assert; use function in_array; -use function is_string; use function mb_internal_encoding; use function mb_list_encodings; use function sprintf; @@ -25,12 +23,11 @@ abstract class AbstractUnicode extends AbstractFilter /** * Set the input encoding for the given string * - * @param string|null $encoding - * @return self * @throws Exception\InvalidArgumentException * @throws Exception\ExtensionNotLoadedException + * @return $this */ - public function setEncoding($encoding = null) + public function setEncoding(?string $encoding = null): self { if ($encoding !== null) { $encoding = strtolower($encoding); @@ -49,16 +46,12 @@ public function setEncoding($encoding = null) /** * Returns the set encoding - * - * @return string */ - public function getEncoding() + public function getEncoding(): string { $encoding = $this->options['encoding'] ?? null; - assert($encoding === null || is_string($encoding)); if ($encoding === null) { - $encoding = mb_internal_encoding(); - assert(is_string($encoding)); + $encoding = mb_internal_encoding(); $this->options['encoding'] = $encoding; } diff --git a/src/AllowList.php b/src/AllowList.php index ca348a4a..d9393c15 100644 --- a/src/AllowList.php +++ b/src/AllowList.php @@ -17,9 +17,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class AllowList extends AbstractFilter +final class AllowList extends AbstractFilter { /** @var bool */ protected $strict = false; @@ -58,7 +57,7 @@ public function getStrict() } /** - * Set the list of items to white-list. + * Set the list of items to allow * * @param array|Traversable $list */ @@ -72,7 +71,7 @@ public function setList($list = []): void } /** - * Get the list of items to white-list + * Get the list of items to allow * * @return array */ @@ -84,9 +83,13 @@ public function getList() /** * {@inheritDoc} * - * Will return $value if its present in the white-list. If $value is rejected then it will return null. + * Will return $value if its present in the allow-list. If $value is rejected then it will return null. + * + * @template T + * @param T $value + * @return T|null */ - public function filter($value) + public function filter(mixed $value): mixed { return in_array($value, $this->getList(), $this->getStrict()) ? $value : null; } diff --git a/src/BaseName.php b/src/BaseName.php index 2eedf935..a13da6f5 100644 --- a/src/BaseName.php +++ b/src/BaseName.php @@ -10,9 +10,8 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class BaseName extends AbstractFilter +final class BaseName extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface @@ -21,11 +20,9 @@ class BaseName extends AbstractFilter * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is scalar ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/Blacklist.php b/src/Blacklist.php deleted file mode 100644 index 79d716d7..00000000 --- a/src/Blacklist.php +++ /dev/null @@ -1,12 +0,0 @@ - - * @final */ -class Boolean extends AbstractFilter +final class Boolean extends AbstractFilter { public const TYPE_BOOLEAN = 1; public const TYPE_INTEGER = 2; @@ -207,9 +206,8 @@ public function getTranslations() * Returns a boolean representation of $value * * @param null|array|bool|float|int|string $value - * @return bool|mixed */ - public function filter($value) + public function filter(mixed $value): mixed { $type = $this->getType(); $casting = $this->getCasting(); diff --git a/src/Callback.php b/src/Callback.php index 22e23e23..417a43ee 100644 --- a/src/Callback.php +++ b/src/Callback.php @@ -19,9 +19,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class Callback extends AbstractFilter +final class Callback extends AbstractFilter { /** @var array */ protected $options = [ @@ -101,10 +100,10 @@ public function getCallbackParams() /** * Calls the filter per callback * - * @param mixed $value Options for the set callable + * @param mixed $value Options for the set callable * @return mixed Result from the filter which was called */ - public function filter($value) + public function filter(mixed $value): mixed { $params = (array) $this->options['callback_params']; array_unshift($params, $value); diff --git a/src/Compress.php b/src/Compress.php index 501870e5..1f90ffed 100644 --- a/src/Compress.php +++ b/src/Compress.php @@ -4,6 +4,7 @@ namespace Laminas\Filter; +use Laminas\Filter\Compress\AbstractCompressionAlgorithm; use Laminas\Filter\Compress\CompressionAlgorithmInterface; use Laminas\Stdlib\ArrayUtils; use Traversable; @@ -11,6 +12,7 @@ use function call_user_func_array; use function class_exists; use function get_debug_type; +use function is_a; use function is_array; use function is_string; use function method_exists; @@ -20,31 +22,36 @@ /** * Compresses a given string * - * @psalm-type AdapterType = 'Bz2'|'Gz'|'Lzf'|'Rar'|'Snappy'|'Tar'|'Zip' - * @psalm-type AdapterTypeOrInstance = Compress\CompressionAlgorithmInterface|AdapterType + * @psalm-type AdapterType = 'Bz2'|'Gz'|'Tar'|'Zip'|class-string + * @psalm-type AdapterTypeOrInstance = CompressionAlgorithmInterface|AdapterType * @psalm-type Options = array{ * adapter?: AdapterTypeOrInstance, * options?: array, - * }&array + * adapter_options?: array, + * } * @extends AbstractFilter */ class Compress extends AbstractFilter { + private const DEFAULT_ADAPTER = 'Gz'; + /** * Compression adapter * * @var AdapterTypeOrInstance */ - protected $adapter = 'Gz'; + private string|CompressionAlgorithmInterface $adapter = self::DEFAULT_ADAPTER; /** * Compression adapter constructor options * * @var array */ - protected $adapterOptions = []; + private array $adapterOptions = []; /** + * Given a string or a compression adapter interface, set the adapter. Otherwise, an iterable will set options + * * @param Options|Traversable|null|AdapterTypeOrInstance $options */ public function __construct($options = null) @@ -54,7 +61,7 @@ public function __construct($options = null) $options = ArrayUtils::iteratorToArray($options); } - if (is_string($options) || $options instanceof Compress\CompressionAlgorithmInterface) { + if (is_string($options) || $options instanceof CompressionAlgorithmInterface) { $this->setAdapter($options); return; @@ -68,9 +75,9 @@ public function __construct($options = null) /** * Set filter state * - * @param Options|Traversable $options + * @param Options|iterable $options * @throws Exception\InvalidArgumentException If options is not an array or Traversable. - * @return self + * @return $this */ public function setOptions($options) { @@ -82,64 +89,59 @@ public function setOptions($options) )); } - foreach ($options as $key => $value) { - if ($key === 'options') { - $key = 'adapterOptions'; - } - $method = 'set' . ucfirst($key); - if (method_exists($this, $method)) { - $this->$method($value); - } + $options = $options instanceof Traversable + ? ArrayUtils::iteratorToArray($options) + : $options; + + /** @psalm-var Options $options */ + + $adapter = $options['adapter'] ?? null; + if (is_string($adapter) || $adapter instanceof CompressionAlgorithmInterface) { + $this->setAdapter($adapter); } + + $adapterOptions = $options['options'] ?? []; + $adapterOptions = $options['adapter_options'] ?? $adapterOptions; + + $this->setAdapterOptions($adapterOptions); + return $this; } /** * Returns the current adapter, instantiating it if necessary * - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - * @return CompressionAlgorithmInterface + * @throws Exception\InvalidArgumentException If the adapter type cannot be resolved. */ - public function getAdapter() + public function getAdapter(): CompressionAlgorithmInterface { - if ($this->adapter instanceof Compress\CompressionAlgorithmInterface) { + if ($this->adapter instanceof CompressionAlgorithmInterface) { return $this->adapter; } - $adapter = $this->adapter; - $options = $this->getAdapterOptions(); - if (! class_exists($adapter)) { - $adapter = 'Laminas\\Filter\\Compress\\' . ucfirst($adapter); - if (! class_exists($adapter)) { - throw new Exception\RuntimeException(sprintf( - '%s unable to load adapter; class "%s" not found', - __METHOD__, - $this->adapter - )); - } - } + $adapterClass = class_exists($this->adapter) + ? $this->adapter + : 'Laminas\\Filter\\Compress\\' . ucfirst($this->adapter); - $instance = new $adapter($options); - if (! $instance instanceof Compress\CompressionAlgorithmInterface) { - throw new Exception\InvalidArgumentException(sprintf( - "Compression adapter '%s' does not implement %s", - $adapter, - CompressionAlgorithmInterface::class, - )); + if (! class_exists($adapterClass) || ! is_a($adapterClass, CompressionAlgorithmInterface::class, true)) { + throw new Exception\InvalidArgumentException( + sprintf( + 'Compression adapter "%s" does not implement %s or is not a valid class', + $adapterClass, + CompressionAlgorithmInterface::class, + ), + ); } - $this->adapter = $instance; + $this->adapter = new $adapterClass($this->adapterOptions); return $this->adapter; } /** * Retrieve adapter name - * - * @return string */ - public function getAdapterName() + public function getAdapterName(): string { return $this->getAdapter()->toString(); } @@ -148,21 +150,11 @@ public function getAdapterName() * Sets compression adapter * * @param AdapterTypeOrInstance $adapter Adapter to use - * @return self + * @return $this * @throws Exception\InvalidArgumentException */ - public function setAdapter($adapter) + public function setAdapter(string|CompressionAlgorithmInterface $adapter): self { - if ($adapter instanceof Compress\CompressionAlgorithmInterface) { - $this->adapter = $adapter; - return $this; - } - if (! is_string($adapter)) { - throw new Exception\InvalidArgumentException( - 'Invalid adapter provided; must be string or instance of ' - . CompressionAlgorithmInterface::class - ); - } $this->adapter = $adapter; return $this; @@ -173,7 +165,7 @@ public function setAdapter($adapter) * * @return array */ - public function getAdapterOptions() + public function getAdapterOptions(): array { return $this->adapterOptions; } @@ -182,9 +174,9 @@ public function getAdapterOptions() * Set adapter options * * @param array $options - * @return self + * @return $this */ - public function setAdapterOptions(array $options) + public function setAdapterOptions(array $options): self { $this->adapterOptions = $options; return $this; @@ -193,43 +185,42 @@ public function setAdapterOptions(array $options) /** * Get individual or all options from underlying adapter * - * @param null|string $option - * @return mixed + * @return ($option is null ? array : mixed) */ - public function getOptions($option = null) + public function getOptions(string|null $option = null): mixed { $adapter = $this->getAdapter(); - return $adapter->getOptions($option); + + if ($adapter instanceof AbstractCompressionAlgorithm) { + return $adapter->getOptions($option); + } + + return is_string($option) ? null : []; } /** * Calls adapter methods * - * @param string $method Method to call - * @param string|array $options Options for this method - * @return mixed * @throws Exception\BadMethodCallException */ - public function __call($method, $options) + public function __call(string $method, array $args): mixed { $adapter = $this->getAdapter(); if (! method_exists($adapter, $method)) { throw new Exception\BadMethodCallException("Unknown method '{$method}'"); } - return call_user_func_array([$adapter, $method], $options); + return call_user_func_array([$adapter, $method], $args); } /** - * Defined by Laminas\Filter\FilterInterface - * * Compresses the content $value with the defined settings * - * @param mixed $value Content to compress - * @return string|mixed The compressed content + * @param mixed $value Content to compress + * @return mixed The compressed content * @psalm-return ($value is string ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_string($value)) { return $value; diff --git a/src/Compress/AbstractCompressionAlgorithm.php b/src/Compress/AbstractCompressionAlgorithm.php index 17fc58d2..4846da17 100644 --- a/src/Compress/AbstractCompressionAlgorithm.php +++ b/src/Compress/AbstractCompressionAlgorithm.php @@ -38,10 +38,9 @@ public function __construct($options = null) * Returns one or all set options * * @param string|null $option Option to return - * @return mixed * @psalm-return ($option is null ? TOptions : mixed) */ - public function getOptions($option = null) + public function getOptions(string|null $option = null): mixed { if ($option === null) { return $this->options; diff --git a/src/Compress/Bz2.php b/src/Compress/Bz2.php index e519a4fe..25153dbd 100644 --- a/src/Compress/Bz2.php +++ b/src/Compress/Bz2.php @@ -25,9 +25,8 @@ * archive?: string|null, * } * @extends AbstractCompressionAlgorithm - * @final */ -class Bz2 extends AbstractCompressionAlgorithm +final class Bz2 extends AbstractCompressionAlgorithm { /** * Compression Options diff --git a/src/Compress/Gz.php b/src/Compress/Gz.php index 6b4cb8eb..42d8574a 100644 --- a/src/Compress/Gz.php +++ b/src/Compress/Gz.php @@ -36,9 +36,8 @@ * archive?: string|null, * } * @extends AbstractCompressionAlgorithm - * @final */ -class Gz extends AbstractCompressionAlgorithm +final class Gz extends AbstractCompressionAlgorithm { /** * Compression Options diff --git a/src/Compress/Lzf.php b/src/Compress/Lzf.php deleted file mode 100644 index 7426fa8d..00000000 --- a/src/Compress/Lzf.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ -class Rar extends AbstractCompressionAlgorithm -{ - /** - * Compression Options - * array( - * 'callback' => Callback for compression - * 'archive' => Archive to use - * 'password' => Password to use - * 'target' => Target to write the files to - * ) - * - * @var Options - */ - protected $options = [ - 'callback' => null, - 'archive' => null, - 'password' => null, - 'target' => '.', - ]; - - /** - * @param Options|null $options (Optional) Options to set - * @throws Exception\ExtensionNotLoadedException If rar extension not loaded. - */ - public function __construct($options = null) - { - if (! extension_loaded('rar')) { - throw new Exception\ExtensionNotLoadedException('This filter needs the rar extension'); - } - parent::__construct($options); - } - - /** - * Returns the set callback for compression - * - * @return callable|null - */ - public function getCallback() - { - return $this->options['callback']; - } - - /** - * Sets the callback to use - * - * @param callable $callback - * @return self - * @throws Exception\InvalidArgumentException If invalid callback provided. - */ - public function setCallback($callback) - { - if (! is_callable($callback)) { - throw new Exception\InvalidArgumentException('Invalid callback provided'); - } - - $this->options['callback'] = $callback; - return $this; - } - - /** - * Returns the set archive - * - * @return string|null - */ - public function getArchive() - { - return $this->options['archive']; - } - - /** - * Sets the archive to use for de-/compression - * - * @param string $archive Archive to use - * @return self - */ - public function setArchive($archive) - { - $archive = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $archive); - $this->options['archive'] = (string) $archive; - - return $this; - } - - /** - * Returns the set password - * - * @return string|null - */ - public function getPassword() - { - return $this->options['password']; - } - - /** - * Sets the password to use - * - * @param string $password - * @return self - */ - public function setPassword($password) - { - $this->options['password'] = (string) $password; - return $this; - } - - /** - * Returns the set targetpath - * - * @return string - */ - public function getTarget() - { - return $this->options['target']; - } - - /** - * Sets the targetpath to use - * - * @param string $target - * @return self - * @throws Exception\InvalidArgumentException If specified target directory does not exist. - */ - public function setTarget($target) - { - if (! file_exists(dirname($target))) { - throw new Exception\InvalidArgumentException("The directory '$target' does not exist"); - } - - $target = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, (string) $target); - $this->options['target'] = $target; - return $this; - } - - /** - * Compresses the given content - * - * @param string|array $content - * @return string|null - * @throws Exception\RuntimeException If no callback available, or error during compression. - */ - public function compress($content) - { - $callback = $this->getCallback(); - if ($callback === null) { - throw new Exception\RuntimeException('No compression callback available'); - } - - $options = $this->getOptions(); - unset($options['callback']); - - $result = $callback($options, $content); - if ($result !== true) { - throw new Exception\RuntimeException('Error compressing the RAR Archive'); - } - - return $this->getArchive(); - } - - /** - * Decompresses the given content - * - * @param string $content - * @return bool - * @throws Exception\RuntimeException If archive not found, cannot be opened, - * or error during decompression. - */ - public function decompress($content) - { - if (! file_exists($content)) { - throw new Exception\RuntimeException('RAR Archive not found'); - } - - $archive = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, realpath($content)); - $password = $this->getPassword(); - if ($password !== null) { - $archive = rar_open($archive, $password); - } else { - $archive = rar_open($archive); - } - - if (! $archive) { - throw new Exception\RuntimeException('Error opening the RAR Archive'); - } - - $target = $this->getTarget(); - if (! is_dir($target)) { - $target = dirname($target); - } - - $filelist = rar_list($archive); - if (! $filelist) { - throw new Exception\RuntimeException("Error reading the RAR Archive"); - } - - foreach ($filelist as $file) { - $file->extract($target); - } - - rar_close($archive); - return true; - } - - /** - * Returns the adapter name - * - * @return string - */ - public function toString() - { - return 'Rar'; - } -} diff --git a/src/Compress/Snappy.php b/src/Compress/Snappy.php deleted file mode 100644 index c764d892..00000000 --- a/src/Compress/Snappy.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @final */ -class Tar extends AbstractCompressionAlgorithm +final class Tar extends AbstractCompressionAlgorithm { /** * Compression Options diff --git a/src/Compress/Zip.php b/src/Compress/Zip.php index 79af19f6..43862fcc 100644 --- a/src/Compress/Zip.php +++ b/src/Compress/Zip.php @@ -33,9 +33,8 @@ * target?: string|null, * } * @extends AbstractCompressionAlgorithm - * @final */ -class Zip extends AbstractCompressionAlgorithm +final class Zip extends AbstractCompressionAlgorithm { /** * Compression Options diff --git a/src/DataUnitFormatter.php b/src/DataUnitFormatter.php index 62c657f9..64a9dc73 100644 --- a/src/DataUnitFormatter.php +++ b/src/DataUnitFormatter.php @@ -22,7 +22,6 @@ * prefixes?: list, * } * @extends AbstractFilter - * @final */ final class DataUnitFormatter extends AbstractFilter { @@ -212,11 +211,9 @@ protected function getPrefixAt(mixed $index) * * If the value provided is not numeric, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is numeric ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_numeric($value)) { return $value; diff --git a/src/DateSelect.php b/src/DateSelect.php index 72c39e70..8d565eeb 100644 --- a/src/DateSelect.php +++ b/src/DateSelect.php @@ -10,19 +10,19 @@ * null_on_all_empty?: bool, * ... * } + * @psalm-type InputArray = array{ + * year: numeric, + * month: numeric, + * day: numeric, + * } * @template TOptions of Options - * @template-extends AbstractDateDropdown - * @final + * @template-extends AbstractDateDropdown */ -class DateSelect extends AbstractDateDropdown +final class DateSelect extends AbstractDateDropdown { /** * Year-Month-Day - * - * @var string */ - protected $format = '%3$s-%2$s-%1$s'; - - /** @var int */ - protected $expectedInputs = 3; + protected string $format = '%3$s-%2$s-%1$s'; + protected int $expectedInputs = 3; } diff --git a/src/DateTimeFormatter.php b/src/DateTimeFormatter.php index 2aad025a..0d0b6174 100644 --- a/src/DateTimeFormatter.php +++ b/src/DateTimeFormatter.php @@ -17,9 +17,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class DateTimeFormatter extends AbstractFilter +final class DateTimeFormatter extends AbstractFilter { /** * A valid format string accepted by date() @@ -58,9 +57,8 @@ public function setFormat($format) * * @param DateTime|string|int|mixed $value * @throws Exception\InvalidArgumentException - * @return string|mixed */ - public function filter($value) + public function filter(mixed $value): mixed { try { $result = $this->normalizeDateTime($value); diff --git a/src/DateTimeSelect.php b/src/DateTimeSelect.php index b309cb8c..ac9f0b3b 100644 --- a/src/DateTimeSelect.php +++ b/src/DateTimeSelect.php @@ -14,28 +14,27 @@ * null_on_all_empty?: bool, * ... * } + * @psalm-type InputArray = array{ + * year: numeric, + * month: numeric, + * day: numeric, + * hour: numeric, + * minute: numeric, + * second: numeric + * } * @template TOptions of Options - * @template-extends AbstractDateDropdown - * @final + * @template-extends AbstractDateDropdown */ -class DateTimeSelect extends AbstractDateDropdown +final class DateTimeSelect extends AbstractDateDropdown { /** * Year-Month-Day Hour:Min:Sec - * - * @var string */ - protected $format = '%6$s-%4$s-%1$s %2$s:%3$s:%5$s'; - - /** @var int */ - protected $expectedInputs = 6; + protected string $format = '%6$s-%4$s-%1$s %2$s:%3$s:%5$s'; + protected int $expectedInputs = 6; - /** - * @param mixed $value - * @return array|mixed|null|string - * @throws Exception\RuntimeException - */ - public function filter($value) + /** @inheritDoc */ + public function filter(mixed $value): mixed { if (! is_array($value)) { // nothing to do @@ -53,7 +52,7 @@ public function filter($value) || (isset($value['second']) && empty($value['second'])) ) ) { - return; + return null; } if ( @@ -64,11 +63,11 @@ public function filter($value) && empty($value['day']) && empty($value['hour']) && empty($value['minute']) - && (! isset($value['second']) || empty($value['second'])) + && empty($value['second']) ) ) { // Cannot handle this value - return; + return null; } if (! isset($value['second'])) { @@ -79,8 +78,6 @@ public function filter($value) ksort($value); - $value = vsprintf($this->format, $value); - - return $value; + return vsprintf($this->format, $value); } } diff --git a/src/Decompress.php b/src/Decompress.php index ab3f5511..04aeac9a 100644 --- a/src/Decompress.php +++ b/src/Decompress.php @@ -8,10 +8,8 @@ /** * Decompresses a given string - * - * @final */ -class Decompress extends Compress +final class Decompress extends Compress { /** * Use filter as functor @@ -21,7 +19,7 @@ class Decompress extends Compress * @param mixed $value Content to decompress * @return mixed|string The decompressed content */ - public function __invoke($value) + public function __invoke(mixed $value): mixed { return $this->filter($value); } @@ -34,7 +32,7 @@ public function __invoke($value) * @param mixed $value Content to decompress * @return mixed|string The decompressed content */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_string($value) && $value !== null) { return $value; diff --git a/src/Decrypt.php b/src/Decrypt.php deleted file mode 100644 index 14ddf724..00000000 --- a/src/Decrypt.php +++ /dev/null @@ -1,33 +0,0 @@ -adapter->decrypt($value); - } -} diff --git a/src/DenyList.php b/src/DenyList.php index 6f66850f..3bc99897 100644 --- a/src/DenyList.php +++ b/src/DenyList.php @@ -17,9 +17,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class DenyList extends AbstractFilter +final class DenyList extends AbstractFilter { /** @var bool */ protected $strict = false; @@ -86,7 +85,7 @@ public function getList() * * Will return null if $value is present in the black-list. If $value is NOT present then it will return $value. */ - public function filter($value) + public function filter(mixed $value): mixed { return in_array($value, $this->getList(), $this->getStrict()) ? null : $value; } diff --git a/src/Digits.php b/src/Digits.php index 9414c2de..9671efa9 100644 --- a/src/Digits.php +++ b/src/Digits.php @@ -14,9 +14,8 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class Digits extends AbstractFilter +final class Digits extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface @@ -25,11 +24,9 @@ class Digits extends AbstractFilter * * If the value provided is not integer, float or string, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is int|float|string ? numeric-string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (is_int($value)) { return (string) $value; diff --git a/src/Dir.php b/src/Dir.php index 24862495..a0045ad3 100644 --- a/src/Dir.php +++ b/src/Dir.php @@ -10,20 +10,17 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class Dir extends AbstractFilter +final class Dir extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface * * Returns dirname($value) * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is scalar ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/Encrypt.php b/src/Encrypt.php deleted file mode 100644 index d71aaaa8..00000000 --- a/src/Encrypt.php +++ /dev/null @@ -1,180 +0,0 @@ - - */ -class Encrypt extends AbstractFilter -{ - /** - * Encryption adapter - * - * @param Encrypt\EncryptionAlgorithmInterface - */ - protected $adapter; - - /** - * @param string|array|Traversable $options (Optional) Options to set, if null mcrypt is used - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - $this->setAdapter($options); - } - - /** - * Returns the adapter instance - * - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - * @return Encrypt\EncryptionAlgorithmInterface - */ - public function getAdapterInstance() - { - if ($this->adapter instanceof Encrypt\EncryptionAlgorithmInterface) { - return $this->adapter; - } - - $adapter = $this->adapter; - $options = $this->getOptions(); - if (! class_exists($adapter)) { - $adapter = self::class . '\\' . ucfirst($adapter); - if (! class_exists($adapter)) { - throw new Exception\RuntimeException(sprintf( - '%s unable to load adapter; class "%s" not found', - __METHOD__, - $this->adapter - )); - } - } - - $this->adapter = new $adapter($options); - if (! $this->adapter instanceof Encrypt\EncryptionAlgorithmInterface) { - throw new Exception\InvalidArgumentException(sprintf( - 'Encryption adapter "%s" does not implement %s\\EncryptionAlgorithmInterface', - $adapter, - self::class - )); - } - return $this->adapter; - } - - /** - * Returns the name of the set adapter - * - * @return string - */ - public function getAdapter() - { - return $this->adapter->toString(); - } - - /** - * Sets new encryption options - * - * @param string|array $options (Optional) Encryption options - * @return self - * @throws Exception\DomainException - * @throws Exception\InvalidArgumentException - */ - public function setAdapter($options = null) - { - if (is_string($options)) { - $adapter = $options; - } elseif (isset($options['adapter'])) { - $adapter = $options['adapter']; - unset($options['adapter']); - } else { - $adapter = 'BlockCipher'; - } - - if (! is_array($options)) { - $options = []; - } - - if (class_exists('Laminas\Filter\Encrypt\\' . ucfirst($adapter))) { - $adapter = 'Laminas\Filter\Encrypt\\' . ucfirst($adapter); - } elseif (! class_exists($adapter)) { - throw new Exception\DomainException( - sprintf( - '%s expects a valid registry class name; received "%s", which did not resolve', - __METHOD__, - $adapter - ) - ); - } - - $this->adapter = new $adapter($options); - if (! $this->adapter instanceof Encrypt\EncryptionAlgorithmInterface) { - throw new Exception\InvalidArgumentException( - "Encoding adapter '" . $adapter - . "' does not implement Laminas\\Filter\\Encrypt\\EncryptionAlgorithmInterface" - ); - } - - return $this; - } - - /** - * Calls adapter methods - * - * @param string $method Method to call - * @param string|array $options Options for this method - * @return mixed - * @throws Exception\BadMethodCallException - */ - public function __call($method, $options) - { - $part = substr($method, 0, 3); - if (($part !== 'get' && $part !== 'set') || ! method_exists($this->adapter, $method)) { - throw new Exception\BadMethodCallException("Unknown method '{$method}'"); - } - - return call_user_func_array([$this->adapter, $method], $options); - } - - /** - * Defined by Laminas\Filter\Filter - * - * Encrypts the content $value with the defined settings - * - * @param string $value Content to encrypt - * @return string The encrypted content - */ - public function filter($value) - { - if (! is_string($value) && ! is_numeric($value)) { - return $value; - } - - return $this->adapter->encrypt($value); - } -} diff --git a/src/Encrypt/BlockCipher.php b/src/Encrypt/BlockCipher.php deleted file mode 100644 index 70c0a3a1..00000000 --- a/src/Encrypt/BlockCipher.php +++ /dev/null @@ -1,295 +0,0 @@ - encryption key string - * 'key_iteration' => the number of iterations for the PBKDF2 key generation - * 'algorithm => cipher algorithm to use - * 'hash' => algorithm to use for the authentication - * 'vector' => initialization vector - * ) - */ - protected $encryption = [ - 'key_iteration' => 5000, - 'algorithm' => 'aes', - 'hash' => 'sha256', - ]; - - /** - * BlockCipher - * - * @var BlockCipher - */ - protected $blockCipher; - - /** - * Internal compression - * - * @var array - */ - protected $compression; - - /** - * @param string|array|Traversable $options Encryption Options - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - */ - public function __construct($options) - { - $cipherPluginManager = CryptBlockCipher::getSymmetricPluginManager(); - $cipherType = $cipherPluginManager->has('openssl') ? 'openssl' : 'mcrypt'; - try { - $this->blockCipher = CryptBlockCipher::factory($cipherType, $this->encryption); - } catch (SymmetricException\RuntimeException) { - throw new Exception\RuntimeException(sprintf( - 'The BlockCipher cannot be used without the %s extension', - $cipherType - )); - } - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (is_string($options)) { - $options = ['key' => $options]; - } elseif (! is_array($options)) { - throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); - } - - if (array_key_exists('compression', $options)) { - $this->setCompression($options['compression']); - unset($options['compress']); - } - - $this->setEncryption($options); - } - - /** - * Returns the set encryption options - * - * @return array - */ - public function getEncryption() - { - return $this->encryption; - } - - /** - * Sets new encryption options - * - * @param string|array $options Encryption options - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setEncryption($options) - { - if (is_string($options)) { - $this->blockCipher->setKey($options); - $this->encryption['key'] = $options; - return $this; - } - - if (! is_array($options)) { - throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); - } - - $options += $this->encryption; - - if (isset($options['key'])) { - $this->blockCipher->setKey($options['key']); - } - - if (isset($options['algorithm'])) { - try { - $this->blockCipher->setCipherAlgorithm($options['algorithm']); - } catch (CryptException\InvalidArgumentException) { - throw new Exception\InvalidArgumentException( - "The algorithm '{$options['algorithm']}' is not supported" - ); - } - } - - if (isset($options['hash'])) { - try { - $this->blockCipher->setHashAlgorithm($options['hash']); - } catch (CryptException\InvalidArgumentException) { - throw new Exception\InvalidArgumentException("The algorithm '{$options['hash']}' is not supported"); - } - } - - if (isset($options['vector'])) { - $this->setVector($options['vector']); - } - - if (isset($options['key_iteration'])) { - $this->blockCipher->setKeyIteration($options['key_iteration']); - } - - $this->encryption = $options; - - return $this; - } - - /** - * Returns the initialization vector - * - * @return string - */ - public function getVector() - { - return $this->encryption['vector']; - } - - /** - * Set the inizialization vector - * - * @param string $vector - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setVector($vector) - { - try { - $this->blockCipher->setSalt($vector); - } catch (CryptException\InvalidArgumentException $e) { - throw new Exception\InvalidArgumentException($e->getMessage()); - } - $this->encryption['vector'] = $vector; - return $this; - } - - /** - * Set the encryption key - * - * @param string $key - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setKey($key) - { - try { - $this->blockCipher->setKey($key); - } catch (CryptException\InvalidArgumentException $e) { - throw new Exception\InvalidArgumentException($e->getMessage()); - } - $this->encryption['key'] = $key; - return $this; - } - - /** - * Get the encryption key - * - * @return string - */ - public function getKey() - { - return $this->encryption['key']; - } - - /** - * Returns the compression - * - * @return array - */ - public function getCompression() - { - return $this->compression; - } - - /** - * Sets an internal compression for values to encrypt - * - * @param string|array $compression - * @return $this - */ - public function setCompression($compression) - { - if (is_string($this->compression)) { - $compression = ['adapter' => $compression]; - } - - $this->compression = $compression; - return $this; - } - - /** - * Defined by Laminas\Filter\FilterInterface - * - * Encrypts $value with the defined settings - * - * @param string $value The content to encrypt - * @throws Exception\InvalidArgumentException - * @return string The encrypted content - */ - public function encrypt($value) - { - // compress prior to encryption - if (! empty($this->compression)) { - $compress = new Compress($this->compression); - $value = $compress($value); - } - - try { - $encrypted = $this->blockCipher->encrypt($value); - } catch (CryptException\InvalidArgumentException $e) { - throw new Exception\InvalidArgumentException($e->getMessage()); - } - return $encrypted; - } - - /** - * Defined by Laminas\Filter\FilterInterface - * - * Decrypts $value with the defined settings - * - * @param string $value Content to decrypt - * @return string The decrypted content - */ - public function decrypt($value) - { - $decrypted = $this->blockCipher->decrypt($value); - - // decompress after decryption - if (! empty($this->compression)) { - $decompress = new Decompress($this->compression); - $decrypted = $decompress($decrypted); - } - - return $decrypted; - } - - /** - * Returns the adapter name - * - * @return string - */ - public function toString() - { - return 'BlockCipher'; - } -} diff --git a/src/Encrypt/EncryptionAlgorithmInterface.php b/src/Encrypt/EncryptionAlgorithmInterface.php deleted file mode 100644 index a3e46a55..00000000 --- a/src/Encrypt/EncryptionAlgorithmInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -= 3. Use of this adapter should be avoided - * - * @psalm-type Options = array{ - * public?: string, - * private?: string, - * envelope?: string, - * passphrase?: string, - * package?: bool, - * compression?: string|array{adapter: string}, - * } - * @psalm-type CompressionOptions = array{ - * adapter: string, - * }&array - * @final - */ -class Openssl implements EncryptionAlgorithmInterface -{ - /** - * Definitions for encryption - * - * @internal - * - * @var array{ - * public: string[], - * private: string[], - * envelope: string[], - * } - */ - protected $keys = [ - 'public' => [], - 'private' => [], - 'envelope' => [], - ]; - - /** - * Internal passphrase - * - * @internal - * - * @var string|null - */ - protected $passphrase; - - /** - * Internal compression - * - * @internal - * - * @var CompressionOptions|null - */ - protected $compression; - - /** - * Internal create package - * - * @internal - * - * @var bool - */ - protected $package = false; - - /** - * Available options - * 'public' => public key - * 'private' => private key - * 'envelope' => envelope key - * 'passphrase' => passphrase - * 'compression' => compress value with this compression adapter - * 'package' => pack envelope keys into encrypted string, simplifies decryption - * - * @param string|Options|Traversable $options Options for this adapter - * @throws Exception\ExtensionNotLoadedException - */ - public function __construct($options = []) - { - if (! extension_loaded('openssl')) { - throw new Exception\ExtensionNotLoadedException('This filter needs the openssl extension'); - } - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if (! is_array($options)) { - $options = ['public' => $options]; - } - - if (array_key_exists('passphrase', $options)) { - $this->setPassphrase($options['passphrase']); - unset($options['passphrase']); - } - - if (array_key_exists('compression', $options)) { - $this->setCompression($options['compression']); - unset($options['compression']); - } - - if (array_key_exists('package', $options)) { - $this->setPackage($options['package']); - unset($options['package']); - } - - $this->_setKeys($options); - } - - /** - * Sets the encryption keys - * - * @internal - * - * @param array $keys Key with type association - * @return $this - * @throws Exception\InvalidArgumentException - */ - protected function _setKeys($keys) // phpcs:ignore - { - if (! is_array($keys)) { - throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); - } - - foreach ($keys as $type => $key) { - if (is_string($key) && is_file($key) && is_readable($key)) { - $cert = file_get_contents($key); - } else { - $cert = $key; - $key = count($this->keys[$type]); - } - - switch ($type) { - case 'public': - $test = openssl_pkey_get_public($cert); - if ($test === false) { - throw new Exception\InvalidArgumentException("Public key '{$cert}' not valid"); - } - - $this->keys['public'][$key] = $cert; - break; - case 'private': - if (null !== $this->getPassphrase()) { - $test = openssl_pkey_get_private($cert, $this->getPassphrase()); - } else { - $test = openssl_pkey_get_private($cert); - } - if ($test === false) { - throw new Exception\InvalidArgumentException("Private key '{$cert}' not valid"); - } - - $this->keys['private'][$key] = $cert; - break; - case 'envelope': - $this->keys['envelope'][$key] = $cert; - break; - default: - break; - } - } - - return $this; - } - - /** - * Returns all public keys - * - * @return string[] - */ - public function getPublicKey() - { - return $this->keys['public']; - } - - /** - * Sets public keys - * - * @param string|array $key Public keys - * @return self - */ - public function setPublicKey($key) - { - if (is_array($key)) { - foreach ($key as $type => $option) { - if ($type !== 'public') { - $key['public'] = $option; - unset($key[$type]); - } - } - } else { - $key = ['public' => $key]; - } - - return $this->_setKeys($key); - } - - /** - * Returns all private keys - * - * @return string[] - */ - public function getPrivateKey() - { - return $this->keys['private']; - } - - /** - * Sets private keys - * - * @param string|array $key Private key - * @param string|null $passphrase - * @return self - */ - public function setPrivateKey($key, $passphrase = null) - { - if (is_array($key)) { - foreach ($key as $type => $option) { - if ($type !== 'private') { - $key['private'] = $option; - unset($key[$type]); - } - } - } else { - $key = ['private' => $key]; - } - - if ($passphrase !== null) { - $this->setPassphrase($passphrase); - } - - return $this->_setKeys($key); - } - - /** - * Returns all envelope keys - * - * @return string[] - */ - public function getEnvelopeKey() - { - return $this->keys['envelope']; - } - - /** - * Sets envelope keys - * - * @param string|array $key Envelope keys - * @return self - */ - public function setEnvelopeKey($key) - { - if (is_array($key)) { - foreach ($key as $type => $option) { - if ($type !== 'envelope') { - $key['envelope'] = $option; - unset($key[$type]); - } - } - } else { - $key = ['envelope' => $key]; - } - - return $this->_setKeys($key); - } - - /** - * Returns the passphrase - * - * @return string|null - */ - public function getPassphrase() - { - return $this->passphrase; - } - - /** - * Sets a new passphrase - * - * @param string $passphrase - * @return self - */ - public function setPassphrase($passphrase) - { - $this->passphrase = $passphrase; - return $this; - } - - /** - * Returns the compression - * - * @return CompressionOptions|null - */ - public function getCompression() - { - return $this->compression; - } - - /** - * Sets an internal compression for values to encrypt - * - * @param string|CompressionOptions $compression - * @return self - */ - public function setCompression($compression) - { - if (is_string($compression)) { - $compression = ['adapter' => $compression]; - } - - $this->compression = $compression; - return $this; - } - - /** - * Returns if header should be packaged - * - * @return bool - */ - public function getPackage() - { - return $this->package; - } - - /** - * Sets if the envelope keys should be included in the encrypted value - * - * @param bool $package - * @return self - */ - public function setPackage($package) - { - $this->package = (bool) $package; - return $this; - } - - /** - * Encrypts $value with the defined settings - * Note that you also need the "encrypted" keys to be able to decrypt - * - * @param string $value Content to encrypt - * @return string The encrypted content - * @throws Exception\RuntimeException - */ - public function encrypt($value) - { - if (! $this->keys['public']) { - throw new Exception\RuntimeException('Openssl can not encrypt without public keys'); - } - - $encryptedkeys = []; - $keys = []; - $fingerprints = []; - $count = -1; - foreach ($this->keys['public'] as $key => $cert) { - $keys[$key] = openssl_pkey_get_public($cert); - assert($keys[$key] instanceof OpenSSLAsymmetricKey); - if ($this->package) { - $details = openssl_pkey_get_details($keys[$key]); - if ($details === false) { - $details = ['key' => 'Laminas']; - } - - ++$count; - $fingerprints[$count] = md5($details['key']); - } - } - - // compress prior to encryption - if (! empty($this->compression)) { - $compress = new Compress($this->compression); - $value = $compress->filter($value); - } - - $bytesSealed = openssl_seal($value, $encrypted, $encryptedkeys, array_values($keys), 'RC4'); - - if ($bytesSealed === false) { - throw new Exception\RuntimeException('Openssl was not able to encrypt your content with the given options'); - } - - $this->keys['envelope'] = $encryptedkeys; - - // Pack data and envelope keys into single string - if ($this->package) { - $header = pack('n', count($this->keys['envelope'])); - foreach ($this->keys['envelope'] as $key => $envKey) { - $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey; - } - - $encrypted = $header . $encrypted; - } - - return $encrypted; - } - - /** - * Defined by Laminas\Filter\FilterInterface - * - * Decrypts $value with the defined settings - * - * @param string $value Content to decrypt - * @return string The decrypted content - * @throws Exception\RuntimeException - */ - public function decrypt($value) - { - $decrypted = ''; - $envelope = current($this->getEnvelopeKey()); - - if (count($this->keys['private']) !== 1) { - throw new Exception\RuntimeException('Please give a private key for decryption with Openssl'); - } - - if (! $this->package && empty($envelope)) { - throw new Exception\RuntimeException('Please give an envelope key for decryption with Openssl'); - } - - foreach ($this->keys['private'] as $cert) { - if (null !== $this->getPassphrase()) { - $keys = openssl_pkey_get_private($cert, $this->getPassphrase()); - } else { - $keys = openssl_pkey_get_private($cert); - } - } - - if ($this->package) { - $details = openssl_pkey_get_details($keys); - if ($details !== false) { - $fingerprint = md5($details['key']); - } else { - $fingerprint = md5("Laminas"); - } - - $count = unpack('ncount', $value); - $count = $count['count']; - $length = 2; - for ($i = $count; $i > 0; --$i) { - $header = unpack('H32print/nsize', substr($value, $length, 18)); - $length += 18; - if ($header['print'] === $fingerprint) { - $envelope = substr($value, $length, $header['size']); - } - - $length += $header['size']; - } - - // remainder of string is the value to decrypt - $value = substr($value, $length); - } - - $crypt = openssl_open($value, $decrypted, $envelope, $keys, 'RC4'); - - if ($crypt === false) { - throw new Exception\RuntimeException('Openssl was not able to decrypt you content with the given options'); - } - - // decompress after decryption - if (! empty($this->compression)) { - $decompress = new Decompress($this->compression); - $decrypted = $decompress($decrypted); - } - - return $decrypted; - } - - /** - * Returns the adapter name - * - * @return string - */ - public function toString() - { - return 'Openssl'; - } -} diff --git a/src/File/Decrypt.php b/src/File/Decrypt.php deleted file mode 100644 index 9cef96b1..00000000 --- a/src/File/Decrypt.php +++ /dev/null @@ -1,112 +0,0 @@ -filename; - } - - /** - * Sets the new filename where the content will be stored - * - * @param string $filename (Optional) New filename to set - * @return self - */ - public function setFilename($filename = null) - { - $this->filename = $filename; - return $this; - } - - /** - * Defined by Laminas\Filter\FilterInterface - * - * Decrypts the file $value with the defined settings - * - * @param string|array $value Full path of file to change or $_FILES data array - * @return string|array The filename which has been set - * @throws Exception\InvalidArgumentException - * @throws Exception\RuntimeException - */ - public function filter($value) - { - if (! is_scalar($value) && ! is_array($value)) { - return $value; - } - - // An uploaded file? Retrieve the 'tmp_name' - $isFileUpload = false; - if (is_array($value)) { - if (! isset($value['tmp_name'])) { - return $value; - } - - $isFileUpload = true; - $uploadData = $value; - $value = $value['tmp_name']; - } - - if (! file_exists($value)) { - throw new Exception\InvalidArgumentException("File '$value' not found"); - } - - if (! isset($this->filename)) { - $this->filename = $value; - } - - if (file_exists($this->filename) && ! is_writable($this->filename)) { - throw new Exception\RuntimeException("File '{$this->filename}' is not writable"); - } - - $content = file_get_contents($value); - if (! $content) { - throw new Exception\RuntimeException("Problem while reading file '$value'"); - } - - $decrypted = parent::filter($content); - $result = file_put_contents($this->filename, $decrypted); - - if (! $result) { - throw new Exception\RuntimeException("Problem while writing file '{$this->filename}'"); - } - - if ($isFileUpload) { - $uploadData['tmp_name'] = $this->filename; - return $uploadData; - } - return $this->filename; - } -} diff --git a/src/File/Encrypt.php b/src/File/Encrypt.php deleted file mode 100644 index c01cb4ce..00000000 --- a/src/File/Encrypt.php +++ /dev/null @@ -1,112 +0,0 @@ -filename; - } - - /** - * Sets the new filename where the content will be stored - * - * @param string $filename (Optional) New filename to set - * @return self - */ - public function setFilename($filename = null) - { - $this->filename = $filename; - return $this; - } - - /** - * Defined by Laminas\Filter\Filter - * - * Encrypts the file $value with the defined settings - * - * @param string|array $value Full path of file to change or $_FILES data array - * @return string|array The filename which has been set, or false when there were errors - * @throws Exception\InvalidArgumentException - * @throws Exception\RuntimeException - */ - public function filter($value) - { - if (! is_scalar($value) && ! is_array($value)) { - return $value; - } - - // An uploaded file? Retrieve the 'tmp_name' - $isFileUpload = false; - if (is_array($value)) { - if (! isset($value['tmp_name'])) { - return $value; - } - - $isFileUpload = true; - $uploadData = $value; - $value = $value['tmp_name']; - } - - if (! file_exists($value)) { - throw new Exception\InvalidArgumentException("File '$value' not found"); - } - - if (! isset($this->filename)) { - $this->filename = $value; - } - - if (file_exists($this->filename) && ! is_writable($this->filename)) { - throw new Exception\RuntimeException("File '{$this->filename}' is not writable"); - } - - $content = file_get_contents($value); - if (! $content) { - throw new Exception\RuntimeException("Problem while reading file '$value'"); - } - - $encrypted = parent::filter($content); - $result = file_put_contents($this->filename, $encrypted); - - if (! $result) { - throw new Exception\RuntimeException("Problem while writing file '{$this->filename}'"); - } - - if ($isFileUpload) { - $uploadData['tmp_name'] = $this->filename; - return $uploadData; - } - return $this->filename; - } -} diff --git a/src/File/LowerCase.php b/src/File/LowerCase.php index 615733e3..c348d948 100644 --- a/src/File/LowerCase.php +++ b/src/File/LowerCase.php @@ -16,20 +16,19 @@ use function is_string; use function is_writable; -/** @final */ -class LowerCase extends StringToLower +final class LowerCase extends StringToLower { /** * Defined by Laminas\Filter\Filter * * Does a lowercase on the content of the given file * - * @param mixed $value Full path of file to change or $_FILES data array - * @return string|mixed The given $value + * @param mixed $value Full path of file to change or $_FILES data array + * @return mixed The given $value * @throws Exception\InvalidArgumentException * @throws Exception\RuntimeException */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value) && ! is_array($value)) { return $value; diff --git a/src/File/Rename.php b/src/File/Rename.php index 5aaea12f..7aee66b6 100644 --- a/src/File/Rename.php +++ b/src/File/Rename.php @@ -33,9 +33,8 @@ * } * @template TOptions of Options * @template-extends Filter\AbstractFilter - * @final */ -class Rename extends Filter\AbstractFilter +final class Rename extends Filter\AbstractFilter { /** * Internal array of array(source, target, overwrite) @@ -177,11 +176,11 @@ public function getNewName($value, $source = false) * Renames the file $value to the new name set before * Returns the file $value, removing all but digit characters * - * @param mixed $value Full path of file to change or $_FILES data array - * @throws Exception\RuntimeException + * @param mixed $value Full path of file to change or $_FILES data array * @return mixed|string|array The new filename which has been set + * @throws Exception\RuntimeException */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value) && ! is_array($value)) { return $value; diff --git a/src/File/RenameUpload.php b/src/File/RenameUpload.php index 8b7f1e08..94327df0 100644 --- a/src/File/RenameUpload.php +++ b/src/File/RenameUpload.php @@ -229,7 +229,7 @@ public function getRandomize() * - UploadedFileInterface for UploadedFileInterface $value * @throws Exception\RuntimeException */ - public function filter($value) + public function filter(mixed $value): mixed { // PSR-7 uploaded file if ($value instanceof UploadedFileInterface) { diff --git a/src/File/UpperCase.php b/src/File/UpperCase.php index 76372026..d7ad3e23 100644 --- a/src/File/UpperCase.php +++ b/src/File/UpperCase.php @@ -15,8 +15,7 @@ use function is_string; use function is_writable; -/** @final */ -class UpperCase extends StringToUpper +final class UpperCase extends StringToUpper { /** * Defined by Laminas\Filter\FilterInterface @@ -28,7 +27,7 @@ class UpperCase extends StringToUpper * @throws Exception\RuntimeException * @throws Exception\InvalidArgumentException */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value) && ! is_array($value)) { return $value; diff --git a/src/FilterChain.php b/src/FilterChain.php index 18a84811..0320feda 100644 --- a/src/FilterChain.php +++ b/src/FilterChain.php @@ -20,7 +20,6 @@ use function strtolower; /** - * @final * @psalm-type FilterChainConfiguration = array{ * filters?: list, @@ -35,7 +34,7 @@ * @extends AbstractFilter * @implements IteratorAggregate */ -class FilterChain extends AbstractFilter implements Countable, IteratorAggregate +final class FilterChain extends AbstractFilter implements Countable, IteratorAggregate { /** * Default priority at which filters are added @@ -233,11 +232,9 @@ public function getFilters() * * Filters are run in the order in which they were added to the chain (FIFO) * - * @param mixed $value - * @return mixed * @psalm-suppress MixedAssignment values are always mixed */ - public function filter($value) + public function filter(mixed $value): mixed { $valueFiltered = $value; foreach ($this as $filter) { diff --git a/src/FilterInterface.php b/src/FilterInterface.php index 6e75bff8..7d6bc9a5 100644 --- a/src/FilterInterface.php +++ b/src/FilterInterface.php @@ -9,9 +9,9 @@ interface FilterInterface /** * Returns the result of filtering $value * - * @param mixed $value * @throws Exception\RuntimeException If filtering $value is impossible. - * @return mixed */ - public function filter($value); + public function filter(mixed $value): mixed; + + public function __invoke(mixed $value): mixed; } diff --git a/src/FilterPluginManager.php b/src/FilterPluginManager.php index 53bf403e..86b29074 100644 --- a/src/FilterPluginManager.php +++ b/src/FilterPluginManager.php @@ -24,10 +24,9 @@ * FilterInterface. Additionally, it registers a number of default filters * available, as well as aliases for them. * - * @final * @extends AbstractPluginManager */ -class FilterPluginManager extends AbstractPluginManager +final class FilterPluginManager extends AbstractPluginManager { protected $aliases = [ // @codingStandardsIgnoreStart @@ -55,8 +54,6 @@ class FilterPluginManager extends AbstractPluginManager 'AllowList' => AllowList::class, 'basename' => BaseName::class, 'Basename' => BaseName::class, - 'blacklist' => DenyList::class, - 'Blacklist' => DenyList::class, 'boolean' => Boolean::class, 'Boolean' => Boolean::class, 'callback' => Callback::class, @@ -81,8 +78,6 @@ class FilterPluginManager extends AbstractPluginManager 'DateTimeSelect' => DateTimeSelect::class, 'decompress' => Decompress::class, 'Decompress' => Decompress::class, - 'decrypt' => Decrypt::class, - 'Decrypt' => Decrypt::class, 'denylist' => DenyList::class, 'denyList' => DenyList::class, 'DenyList' => DenyList::class, @@ -90,14 +85,6 @@ class FilterPluginManager extends AbstractPluginManager 'Digits' => Digits::class, 'dir' => Dir::class, 'Dir' => Dir::class, - 'encrypt' => Encrypt::class, - 'Encrypt' => Encrypt::class, - 'filedecrypt' => File\Decrypt::class, - 'fileDecrypt' => File\Decrypt::class, - 'FileDecrypt' => File\Decrypt::class, - 'fileencrypt' => File\Encrypt::class, - 'fileEncrypt' => File\Encrypt::class, - 'FileEncrypt' => File\Encrypt::class, 'filelowercase' => File\LowerCase::class, 'fileLowercase' => File\LowerCase::class, 'FileLowercase' => File\LowerCase::class, @@ -164,8 +151,6 @@ class FilterPluginManager extends AbstractPluginManager 'urinormalize' => UriNormalize::class, 'uriNormalize' => UriNormalize::class, 'UriNormalize' => UriNormalize::class, - 'whitelist' => AllowList::class, - 'Whitelist' => AllowList::class, 'wordcamelcasetodash' => Word\CamelCaseToDash::class, 'wordCamelCaseToDash' => Word\CamelCaseToDash::class, 'WordCamelCaseToDash' => Word\CamelCaseToDash::class, @@ -212,7 +197,6 @@ class FilterPluginManager extends AbstractPluginManager 'Zend\I18n\Filter\NumberFormat' => NumberFormat::class, 'Zend\I18n\Filter\NumberParse' => NumberParse::class, 'Zend\Filter\BaseName' => BaseName::class, - 'Zend\Filter\Blacklist' => DenyList::class, 'Zend\Filter\Boolean' => Boolean::class, 'Zend\Filter\Callback' => Callback::class, 'Zend\Filter\Compress' => Compress::class, @@ -221,12 +205,8 @@ class FilterPluginManager extends AbstractPluginManager 'Zend\Filter\DateTimeFormatter' => DateTimeFormatter::class, 'Zend\Filter\DateTimeSelect' => DateTimeSelect::class, 'Zend\Filter\Decompress' => Decompress::class, - 'Zend\Filter\Decrypt' => Decrypt::class, 'Zend\Filter\Digits' => Digits::class, 'Zend\Filter\Dir' => Dir::class, - 'Zend\Filter\Encrypt' => Encrypt::class, - 'Zend\Filter\File\Decrypt' => File\Decrypt::class, - 'Zend\Filter\File\Encrypt' => File\Encrypt::class, 'Zend\Filter\File\LowerCase' => File\LowerCase::class, 'Zend\Filter\File\Rename' => File\Rename::class, 'Zend\Filter\File\RenameUpload' => File\RenameUpload::class, @@ -248,7 +228,6 @@ class FilterPluginManager extends AbstractPluginManager 'Zend\Filter\StripNewlines' => StripNewlines::class, 'Zend\Filter\StripTags' => StripTags::class, 'Zend\Filter\UriNormalize' => UriNormalize::class, - 'Zend\Filter\Whitelist' => AllowList::class, 'Zend\Filter\Word\CamelCaseToDash' => Word\CamelCaseToDash::class, 'Zend\Filter\Word\CamelCaseToSeparator' => Word\CamelCaseToSeparator::class, 'Zend\Filter\Word\CamelCaseToUnderscore' => Word\CamelCaseToUnderscore::class, @@ -272,7 +251,6 @@ class FilterPluginManager extends AbstractPluginManager 'zendi18nfilternumberformat' => NumberFormat::class, 'zendi18nfilternumberparse' => NumberParse::class, 'zendfilterbasename' => BaseName::class, - 'zendfilterblacklist' => DenyList::class, 'zendfilterboolean' => Boolean::class, 'zendfiltercallback' => Callback::class, 'zendfiltercompress' => Compress::class, @@ -281,12 +259,8 @@ class FilterPluginManager extends AbstractPluginManager 'zendfilterdatetimeformatter' => DateTimeFormatter::class, 'zendfilterdatetimeselect' => DateTimeSelect::class, 'zendfilterdecompress' => Decompress::class, - 'zendfilterdecrypt' => Decrypt::class, 'zendfilterdigits' => Digits::class, 'zendfilterdir' => Dir::class, - 'zendfilterencrypt' => Encrypt::class, - 'zendfilterfiledecrypt' => File\Decrypt::class, - 'zendfilterfileencrypt' => File\Encrypt::class, 'zendfilterfilelowercase' => File\LowerCase::class, 'zendfilterfilerename' => File\Rename::class, 'zendfilterfilerenameupload' => File\RenameUpload::class, @@ -305,7 +279,6 @@ class FilterPluginManager extends AbstractPluginManager 'zendfilterstriptags' => StripTags::class, 'zendfilteruppercasewords' => UpperCaseWords::class, 'zendfilterurinormalize' => UriNormalize::class, - 'zendfilterwhitelist' => AllowList::class, 'zendfilterwordcamelcasetodash' => Word\CamelCaseToDash::class, 'zendfilterwordcamelcasetoseparator' => Word\CamelCaseToSeparator::class, 'zendfilterwordcamelcasetounderscore' => Word\CamelCaseToUnderscore::class, @@ -337,7 +310,6 @@ class FilterPluginManager extends AbstractPluginManager // Standard filters AllowList::class => InvokableFactory::class, BaseName::class => InvokableFactory::class, - Blacklist::class => InvokableFactory::class, Boolean::class => InvokableFactory::class, Callback::class => InvokableFactory::class, Compress::class => InvokableFactory::class, @@ -346,13 +318,9 @@ class FilterPluginManager extends AbstractPluginManager DateTimeFormatter::class => InvokableFactory::class, DateTimeSelect::class => InvokableFactory::class, Decompress::class => InvokableFactory::class, - Decrypt::class => InvokableFactory::class, DenyList::class => InvokableFactory::class, Digits::class => InvokableFactory::class, Dir::class => InvokableFactory::class, - Encrypt::class => InvokableFactory::class, - File\Decrypt::class => InvokableFactory::class, - File\Encrypt::class => InvokableFactory::class, File\LowerCase::class => InvokableFactory::class, File\Rename::class => InvokableFactory::class, File\RenameUpload::class => InvokableFactory::class, @@ -376,7 +344,6 @@ class FilterPluginManager extends AbstractPluginManager ToInt::class => InvokableFactory::class, ToNull::class => InvokableFactory::class, UriNormalize::class => InvokableFactory::class, - Whitelist::class => InvokableFactory::class, Word\CamelCaseToDash::class => InvokableFactory::class, Word\CamelCaseToSeparator::class => InvokableFactory::class, Word\CamelCaseToUnderscore::class => InvokableFactory::class, @@ -400,7 +367,6 @@ class FilterPluginManager extends AbstractPluginManager 'laminasi18nfilternumberformat' => InvokableFactory::class, 'laminasi18nfilternumberparse' => InvokableFactory::class, 'laminasfilterbasename' => InvokableFactory::class, - 'laminasfilterblacklist' => InvokableFactory::class, 'laminasfilterboolean' => InvokableFactory::class, 'laminasfiltercallback' => InvokableFactory::class, 'laminasfiltercompress' => InvokableFactory::class, @@ -409,12 +375,8 @@ class FilterPluginManager extends AbstractPluginManager 'laminasfilterdatetimeformatter' => InvokableFactory::class, 'laminasfilterdatetimeselect' => InvokableFactory::class, 'laminasfilterdecompress' => InvokableFactory::class, - 'laminasfilterdecrypt' => InvokableFactory::class, 'laminasfilterdigits' => InvokableFactory::class, 'laminasfilterdir' => InvokableFactory::class, - 'laminasfilterencrypt' => InvokableFactory::class, - 'laminasfilterfiledecrypt' => InvokableFactory::class, - 'laminasfilterfileencrypt' => InvokableFactory::class, 'laminasfilterfilelowercase' => InvokableFactory::class, 'laminasfilterfilerename' => InvokableFactory::class, 'laminasfilterfilerenameupload' => InvokableFactory::class, @@ -433,7 +395,6 @@ class FilterPluginManager extends AbstractPluginManager 'laminasfilterstriptags' => InvokableFactory::class, 'laminasfilteruppercasewords' => InvokableFactory::class, 'laminasfilterurinormalize' => InvokableFactory::class, - 'laminasfilterwhitelist' => InvokableFactory::class, 'laminasfilterwordcamelcasetodash' => InvokableFactory::class, 'laminasfilterwordcamelcasetoseparator' => InvokableFactory::class, 'laminasfilterwordcamelcasetounderscore' => InvokableFactory::class, diff --git a/src/HtmlEntities.php b/src/HtmlEntities.php index 8a2584d0..cef0c80d 100644 --- a/src/HtmlEntities.php +++ b/src/HtmlEntities.php @@ -26,9 +26,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class HtmlEntities extends AbstractFilter +final class HtmlEntities extends AbstractFilter { /** * Corresponds to the second htmlentities() argument @@ -190,12 +189,10 @@ public function setDoubleQuote($doubleQuote) * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @throws Exception\DomainException On encoding mismatches. * @psalm-return ($value is scalar ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/Inflector.php b/src/Inflector.php index ea626cd1..3fd5d9c8 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -35,9 +35,8 @@ * pluginManager?: FilterPluginManager, * } * @extends AbstractFilter - * @final */ -class Inflector extends AbstractFilter +final class Inflector extends AbstractFilter { /** @var FilterPluginManager */ protected $pluginManager; @@ -407,31 +406,30 @@ public function setStaticRuleReference($name, mixed &$reference) /** * Inflect * - * @param string|array $source + * @param string|array $value * @throws Exception\RuntimeException - * @return string */ - public function filter($source) + public function filter(mixed $value): mixed { // clean source - foreach ((array) $source as $sourceName => $sourceValue) { - $source[ltrim($sourceName, ':')] = $sourceValue; + foreach ((array) $value as $sourceName => $sourceValue) { + $value[ltrim($sourceName, ':')] = $sourceValue; } $pregQuotedTargetReplacementIdentifier = preg_quote($this->targetReplacementIdentifier, '#'); $processedParts = []; foreach ($this->rules as $ruleName => $ruleValue) { - if (isset($source[$ruleName])) { + if (isset($value[$ruleName])) { if (is_string($ruleValue)) { // overriding the set rule $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace( '\\', '\\\\', - $source[$ruleName] + $value[$ruleName] ); } elseif (is_array($ruleValue)) { - $processedPart = $source[$ruleName]; + $processedPart = $value[$ruleName]; foreach ($ruleValue as $ruleFilter) { $processedPart = $ruleFilter($processedPart); } diff --git a/src/MonthSelect.php b/src/MonthSelect.php index 2722f28f..d90ca512 100644 --- a/src/MonthSelect.php +++ b/src/MonthSelect.php @@ -10,19 +10,18 @@ * null_on_all_empty?: bool, * ... * } + * @psalm-type InputArray = array{ + * year: numeric, + * month: numeric, + * } * @template TOptions of Options - * @template-extends AbstractDateDropdown - * @final + * @template-extends AbstractDateDropdown */ -class MonthSelect extends AbstractDateDropdown +final class MonthSelect extends AbstractDateDropdown { /** * Year-Month - * - * @var string */ - protected $format = '%2$s-%1$s'; - - /** @var int */ - protected $expectedInputs = 2; + protected string $format = '%2$s-%1$s'; + protected int $expectedInputs = 2; } diff --git a/src/PregReplace.php b/src/PregReplace.php index bb793778..faabc3ca 100644 --- a/src/PregReplace.php +++ b/src/PregReplace.php @@ -19,13 +19,12 @@ /** * @psalm-type Options = array{ - * pattern?: string|list|null, + * pattern?: non-empty-string|list|null, * replacement?: string|list, * } * @extends AbstractFilter - * @final */ -class PregReplace extends AbstractFilter +final class PregReplace extends AbstractFilter { /** @var Options */ protected $options = [ @@ -65,7 +64,7 @@ public function __construct($options = null) * * @see preg_replace() * - * @param string|list $pattern - same as the first argument of preg_replace + * @param non-empty-string|list $pattern - same as the first argument of preg_replace * @return self * @throws Exception\InvalidArgumentException */ @@ -96,7 +95,7 @@ public function setPattern($pattern) /** * Get currently set match pattern * - * @return string|list|null + * @return non-empty-string|list|null */ public function getPattern() { @@ -138,11 +137,9 @@ public function getReplacement() /** * Perform regexp replacement as filter * - * @param mixed $value - * @return mixed * @throws Exception\RuntimeException */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, @@ -156,17 +153,16 @@ public function filter($value) */ private function filterNormalizedValue($value) { - if ($this->options['pattern'] === null) { + $pattern = $this->options['pattern'] ?? null; + if ($pattern === null) { throw new Exception\RuntimeException(sprintf( 'Filter %s does not have a valid pattern set', static::class )); } - /** @var string|string[] $pattern */ - $pattern = $this->options['pattern']; /** @var string|string[] $replacement */ - $replacement = $this->options['replacement']; + $replacement = $this->options['replacement'] ?? ''; return preg_replace($pattern, $replacement, $value); } diff --git a/src/RealPath.php b/src/RealPath.php index 593c7bab..17526379 100644 --- a/src/RealPath.php +++ b/src/RealPath.php @@ -29,9 +29,8 @@ * } * @template TOptions of Options * @extends AbstractFilter - * @final */ -class RealPath extends AbstractFilter +final class RealPath extends AbstractFilter { /** @var TOptions $options */ protected $options = [ @@ -83,11 +82,9 @@ public function getExists() * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is string ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_string($value)) { return $value; diff --git a/src/StaticFilter.php b/src/StaticFilter.php deleted file mode 100644 index 03952d20..00000000 --- a/src/StaticFilter.php +++ /dev/null @@ -1,69 +0,0 @@ -get($classBaseName, $args); - - return $filter instanceof FilterInterface - ? $filter->filter($value) - : $filter($value); - } -} diff --git a/src/StringPrefix.php b/src/StringPrefix.php index 0eaf8b91..b76116dd 100644 --- a/src/StringPrefix.php +++ b/src/StringPrefix.php @@ -14,9 +14,8 @@ * prefix?: null|string, * } * @extends AbstractFilter - * @final */ -class StringPrefix extends AbstractFilter +final class StringPrefix extends AbstractFilter { /** @var Options */ protected $options = [ @@ -75,7 +74,7 @@ public function getPrefix() /** * {@inheritdoc} */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/StringSuffix.php b/src/StringSuffix.php index d9ffaad5..c602ea39 100644 --- a/src/StringSuffix.php +++ b/src/StringSuffix.php @@ -14,9 +14,8 @@ * suffix?: null|string, * } * @extends AbstractFilter - * @final */ -class StringSuffix extends AbstractFilter +final class StringSuffix extends AbstractFilter { /** @var Options */ protected $options = [ @@ -76,7 +75,7 @@ public function getSuffix() /** * {@inheritdoc} */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/StringToLower.php b/src/StringToLower.php index 449b2e59..cf9981be 100644 --- a/src/StringToLower.php +++ b/src/StringToLower.php @@ -34,11 +34,9 @@ public function __construct($encodingOrOptions = null) * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is string ? string : $value) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/StringToUpper.php b/src/StringToUpper.php index 15f18731..9c7a2a84 100644 --- a/src/StringToUpper.php +++ b/src/StringToUpper.php @@ -34,11 +34,9 @@ public function __construct($encodingOrOptions = null) * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is scalar ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/StringTrim.php b/src/StringTrim.php index 917a155f..a6252d1f 100644 --- a/src/StringTrim.php +++ b/src/StringTrim.php @@ -16,9 +16,8 @@ * charlist?: string|null, * } * @extends AbstractFilter - * @final */ -class StringTrim extends AbstractFilter +final class StringTrim extends AbstractFilter { /** @var Options */ protected $options = [ @@ -73,11 +72,9 @@ public function getCharList() * * Returns the string $value with characters stripped from the beginning and end * - * @param mixed $value - * @return string|mixed * @psalm-return ($value is string ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_string($value)) { return $value; diff --git a/src/StripNewlines.php b/src/StripNewlines.php index 7feb4eac..0add04c0 100644 --- a/src/StripNewlines.php +++ b/src/StripNewlines.php @@ -11,19 +11,15 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class StripNewlines extends AbstractFilter +final class StripNewlines extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface * * Returns $value without newline control characters - * - * @param mixed $value - * @return mixed */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, diff --git a/src/StripTags.php b/src/StripTags.php index 7222014b..b26af1d1 100644 --- a/src/StripTags.php +++ b/src/StripTags.php @@ -31,9 +31,8 @@ * ... * } * @extends AbstractFilter - * @final */ -class StripTags extends AbstractFilter +final class StripTags extends AbstractFilter { /** * Unique ID prefix used for allowing comments @@ -190,10 +189,9 @@ public function setAttributesAllowed($attributesAllowed) * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return string|mixed + * @psalm-return ($value is scalar ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/ToFloat.php b/src/ToFloat.php index f7613e5d..a46013d4 100644 --- a/src/ToFloat.php +++ b/src/ToFloat.php @@ -9,9 +9,8 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class ToFloat extends AbstractFilter +final class ToFloat extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface @@ -20,11 +19,9 @@ class ToFloat extends AbstractFilter * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return float|mixed * @psalm-return ($value is scalar ? float : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/ToInt.php b/src/ToInt.php index be86fd13..467f7b79 100644 --- a/src/ToInt.php +++ b/src/ToInt.php @@ -9,9 +9,8 @@ /** * @psalm-type Options = array{} * @extends AbstractFilter - * @final */ -class ToInt extends AbstractFilter +final class ToInt extends AbstractFilter { /** * Defined by Laminas\Filter\FilterInterface @@ -20,11 +19,9 @@ class ToInt extends AbstractFilter * * If the value provided is non-scalar, the value will remain unfiltered * - * @param mixed $value - * @return int|mixed * @psalm-return ($value is scalar ? int : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/ToNull.php b/src/ToNull.php index a2dbaeae..2af0bd39 100644 --- a/src/ToNull.php +++ b/src/ToNull.php @@ -21,9 +21,8 @@ * type?: int-mask-of, * } * @extends AbstractFilter - * @final */ -class ToNull extends AbstractFilter +final class ToNull extends AbstractFilter { public const TYPE_BOOLEAN = 1; public const TYPE_INTEGER = 2; @@ -129,11 +128,8 @@ public function getType() * * Returns null representation of $value, if value is empty and matches * types that should be considered null. - * - * @param null|array|bool|float|int|string $value - * @return null|mixed */ - public function filter($value) + public function filter(mixed $value): mixed { $type = $this->getType(); diff --git a/src/UpperCaseWords.php b/src/UpperCaseWords.php index 90dd6d61..36d7b978 100644 --- a/src/UpperCaseWords.php +++ b/src/UpperCaseWords.php @@ -44,10 +44,10 @@ public function __construct($encodingOrOptions = null) * If the value provided is not a string, the value will remain unfiltered * * @param string|mixed $value - * @return string|mixed + * @return mixed * @psalm-return ($value is string ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_string($value)) { return $value; diff --git a/src/UriNormalize.php b/src/UriNormalize.php index 547afe68..769e0058 100644 --- a/src/UriNormalize.php +++ b/src/UriNormalize.php @@ -23,9 +23,8 @@ * } * @template TOptions of Options * @template-extends AbstractFilter - * @final */ -class UriNormalize extends AbstractFilter +final class UriNormalize extends AbstractFilter { /** * The default scheme to use when parsing scheme-less URIs @@ -90,11 +89,8 @@ public function setEnforcedScheme($enforcedScheme) /** * Filter the URL by normalizing it and applying a default scheme if set - * - * @param mixed $value - * @return mixed|string */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value)) { return $value; diff --git a/src/Whitelist.php b/src/Whitelist.php deleted file mode 100644 index 977f5dff..00000000 --- a/src/Whitelist.php +++ /dev/null @@ -1,12 +0,0 @@ -setSeparator($separator['separator']); return; @@ -37,28 +34,14 @@ public function __construct($separator = ' ') $this->setSeparator($separator); } - /** - * Sets a new separator - * - * @param string $separator Separator - * @return self - * @throws Exception\InvalidArgumentException - */ - public function setSeparator($separator) + /** @return $this */ + public function setSeparator(string $separator): self { - if (! is_string($separator)) { - throw new Exception\InvalidArgumentException('"' . $separator . '" is not a valid separator.'); - } $this->separator = $separator; return $this; } - /** - * Returns the actual set separator - * - * @return string - */ - public function getSeparator() + public function getSeparator(): string { return $this->separator; } diff --git a/src/Word/CamelCaseToDash.php b/src/Word/CamelCaseToDash.php index 7c4a37f2..8fb00db5 100644 --- a/src/Word/CamelCaseToDash.php +++ b/src/Word/CamelCaseToDash.php @@ -11,9 +11,8 @@ * } * @template TOptions of Options * @extends CamelCaseToSeparator - * @final */ -class CamelCaseToDash extends CamelCaseToSeparator +final class CamelCaseToDash extends CamelCaseToSeparator { public function __construct() { diff --git a/src/Word/CamelCaseToSeparator.php b/src/Word/CamelCaseToSeparator.php index cdc0d5fa..4b885cf7 100644 --- a/src/Word/CamelCaseToSeparator.php +++ b/src/Word/CamelCaseToSeparator.php @@ -19,11 +19,7 @@ */ class CamelCaseToSeparator extends AbstractSeparator { - /** - * @param mixed $value - * @return mixed - */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, @@ -35,7 +31,7 @@ public function filter($value) * @param string|string[] $value * @return string|string[] */ - private function filterNormalizedValue($value) + private function filterNormalizedValue(string|array $value): string|array { if (StringUtils::hasPcreUnicodeSupport()) { $pattern = ['#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#']; diff --git a/src/Word/CamelCaseToUnderscore.php b/src/Word/CamelCaseToUnderscore.php index c26339d8..b37876e9 100644 --- a/src/Word/CamelCaseToUnderscore.php +++ b/src/Word/CamelCaseToUnderscore.php @@ -11,9 +11,8 @@ * } * @template TOptions of Options * @extends CamelCaseToSeparator - * @final */ -class CamelCaseToUnderscore extends CamelCaseToSeparator +final class CamelCaseToUnderscore extends CamelCaseToSeparator { public function __construct() { diff --git a/src/Word/DashToCamelCase.php b/src/Word/DashToCamelCase.php index e566d6b7..38eff9db 100644 --- a/src/Word/DashToCamelCase.php +++ b/src/Word/DashToCamelCase.php @@ -11,9 +11,8 @@ * } * @template TOptions of Options * @extends SeparatorToCamelCase - * @final */ -class DashToCamelCase extends SeparatorToCamelCase +final class DashToCamelCase extends SeparatorToCamelCase { public function __construct() { diff --git a/src/Word/DashToSeparator.php b/src/Word/DashToSeparator.php index 76dc898c..fbb023d8 100644 --- a/src/Word/DashToSeparator.php +++ b/src/Word/DashToSeparator.php @@ -15,15 +15,10 @@ * } * @template TOptions of Options * @extends AbstractSeparator - * @final */ -class DashToSeparator extends AbstractSeparator +final class DashToSeparator extends AbstractSeparator { - /** - * @param mixed $value - * @return mixed - */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, diff --git a/src/Word/DashToUnderscore.php b/src/Word/DashToUnderscore.php index 08f6a065..71ada928 100644 --- a/src/Word/DashToUnderscore.php +++ b/src/Word/DashToUnderscore.php @@ -12,9 +12,8 @@ * } * @template TOptions of Options * @template-extends SeparatorToSeparator - * @final */ -class DashToUnderscore extends SeparatorToSeparator +final class DashToUnderscore extends SeparatorToSeparator { public function __construct() { diff --git a/src/Word/SeparatorToCamelCase.php b/src/Word/SeparatorToCamelCase.php index d97f5aca..c4b732d3 100644 --- a/src/Word/SeparatorToCamelCase.php +++ b/src/Word/SeparatorToCamelCase.php @@ -22,11 +22,7 @@ */ class SeparatorToCamelCase extends AbstractSeparator { - /** - * @param mixed $value - * @return mixed - */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, diff --git a/src/Word/SeparatorToDash.php b/src/Word/SeparatorToDash.php index af150094..7c7ea43d 100644 --- a/src/Word/SeparatorToDash.php +++ b/src/Word/SeparatorToDash.php @@ -12,9 +12,8 @@ * } * @template TOptions of Options * @template-extends SeparatorToSeparator - * @final */ -class SeparatorToDash extends SeparatorToSeparator +final class SeparatorToDash extends SeparatorToSeparator { /** * @param string $searchSeparator Separator to search for change diff --git a/src/Word/SeparatorToSeparator.php b/src/Word/SeparatorToSeparator.php index 83fbfcf3..9a63aa7c 100644 --- a/src/Word/SeparatorToSeparator.php +++ b/src/Word/SeparatorToSeparator.php @@ -86,11 +86,9 @@ public function getReplacementSeparator() * * Returns the string $value, replacing the searched separators with the defined ones * - * @param string|mixed $value - * @return mixed * @psalm-return ($value is string ? string : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { return self::applyFilterOnlyToStringableValuesAndStringableArrayValues( $value, diff --git a/src/Word/Service/SeparatorToSeparatorFactory.php b/src/Word/Service/SeparatorToSeparatorFactory.php index 416701c5..937a94f2 100644 --- a/src/Word/Service/SeparatorToSeparatorFactory.php +++ b/src/Word/Service/SeparatorToSeparatorFactory.php @@ -16,8 +16,7 @@ use function iterator_to_array; use function sprintf; -/** @final */ -class SeparatorToSeparatorFactory implements FactoryInterface +final class SeparatorToSeparatorFactory implements FactoryInterface { /** * Options to pass to the constructor (when used in v2), if any. diff --git a/src/Word/UnderscoreToDash.php b/src/Word/UnderscoreToDash.php index 456ac873..ef805dbf 100644 --- a/src/Word/UnderscoreToDash.php +++ b/src/Word/UnderscoreToDash.php @@ -12,9 +12,8 @@ * } * @template TOptions of Options * @template-extends SeparatorToSeparator - * @final */ -class UnderscoreToDash extends SeparatorToSeparator +final class UnderscoreToDash extends SeparatorToSeparator { public function __construct() { diff --git a/src/Word/UnderscoreToStudlyCase.php b/src/Word/UnderscoreToStudlyCase.php index 461d1be2..8dd81653 100755 --- a/src/Word/UnderscoreToStudlyCase.php +++ b/src/Word/UnderscoreToStudlyCase.php @@ -20,18 +20,15 @@ * } * @template TOptions of Options * @template-extends UnderscoreToCamelCase - * @final */ -class UnderscoreToStudlyCase extends UnderscoreToCamelCase +final class UnderscoreToStudlyCase extends UnderscoreToCamelCase { /** * Defined by Laminas\Filter\Filter * - * @param mixed $value - * @return string|array * @psalm-return ($value is scalar ? string : $value is array ? array : mixed) */ - public function filter($value) + public function filter(mixed $value): mixed { if (! is_scalar($value) && ! is_array($value)) { return $value; diff --git a/test/AbstractUnicodeTest.php b/test/AbstractUnicodeTest.php index 7e9f549b..bfd862b6 100644 --- a/test/AbstractUnicodeTest.php +++ b/test/AbstractUnicodeTest.php @@ -23,8 +23,7 @@ protected function setUp(): void parent::setUp(); $this->filter = new class extends AbstractUnicode { - /** @param mixed $value */ - public function filter($value): string + public function filter(mixed $value): mixed { assert(is_string($value)); return strtolower($value); diff --git a/test/BlacklistTest.php b/test/BlacklistTest.php deleted file mode 100644 index 681c272d..00000000 --- a/test/BlacklistTest.php +++ /dev/null @@ -1,28 +0,0 @@ -get('blacklist'); - - self::assertInstanceOf(DenyList::class, $filter); - } -} diff --git a/test/Compress/LzfTest.php b/test/Compress/LzfTest.php deleted file mode 100644 index 7d6fc919..00000000 --- a/test/Compress/LzfTest.php +++ /dev/null @@ -1,44 +0,0 @@ -compress($text); - self::assertNotEquals($text, $compressed); - - $decompressed = $filter->decompress($compressed); - self::assertSame($text, $decompressed); - } - - /** - * testing toString - */ - public function testLzfToString(): void - { - $filter = new Lzf(); - self::assertSame('Lzf', $filter->toString()); - } -} diff --git a/test/Compress/RarTest.php b/test/Compress/RarTest.php deleted file mode 100644 index 10492602..00000000 --- a/test/Compress/RarTest.php +++ /dev/null @@ -1,290 +0,0 @@ -tmp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('laminasilter'); - mkdir($this->tmp); - - $files = [ - $this->tmp . '/zipextracted.txt', - $this->tmp . '/_compress/Compress/First/Second/zipextracted.txt', - $this->tmp . '/_compress/Compress/First/Second', - $this->tmp . '/_compress/Compress/First/zipextracted.txt', - $this->tmp . '/_compress/Compress/First', - $this->tmp . '/_compress/Compress/zipextracted.txt', - $this->tmp . '/_compress/Compress', - $this->tmp . '/_compress/zipextracted.txt', - $this->tmp . '/_compress', - ]; - - foreach ($files as $file) { - if (file_exists($file)) { - if (is_dir($file)) { - rmdir($file); - } else { - unlink($file); - } - } - } - } - - public function tearDown(): void - { - $files = [ - $this->tmp . '/zipextracted.txt', - $this->tmp . '/_compress/Compress/First/Second/zipextracted.txt', - $this->tmp . '/_compress/Compress/First/Second', - $this->tmp . '/_compress/Compress/First/zipextracted.txt', - $this->tmp . '/_compress/Compress/First', - $this->tmp . '/_compress/Compress/zipextracted.txt', - $this->tmp . '/_compress/Compress', - $this->tmp . '/_compress/zipextracted.txt', - $this->tmp . '/_compress', - ]; - - foreach ($files as $file) { - if (file_exists($file)) { - if (is_dir($file)) { - rmdir($file); - } else { - unlink($file); - } - } - } - } - - /** - * Basic usage - */ - public function testBasicUsage(): void - { - $filter = new RarCompression( - [ - 'archive' => dirname(__DIR__) . '/_files/compressed.rar', - 'target' => $this->tmp . '/zipextracted.txt', - 'callback' => [self::class, 'rarCompress'], - ] - ); - - $content = $filter->compress('compress me'); - self::assertSame( - dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'compressed.rar', - $content - ); - - $content = $filter->decompress($content); - self::assertTrue($content); - $content = file_get_contents($this->tmp . '/zipextracted.txt'); - self::assertSame('compress me', $content); - } - - /** - * Setting Options - */ - public function testRarGetSetOptions(): void - { - $filter = new RarCompression(); - self::assertEquals( - [ - 'archive' => null, - 'callback' => null, - 'password' => null, - 'target' => '.', - ], - $filter->getOptions() - ); - - self::assertSame(null, $filter->getOptions('archive')); - - self::assertNull($filter->getOptions('nooption')); - $filter->setOptions(['nooption' => 'foo']); - self::assertNull($filter->getOptions('nooption')); - - $filter->setOptions(['archive' => 'temp.txt']); - self::assertSame('temp.txt', $filter->getOptions('archive')); - } - - /** - * Setting Archive - */ - public function testRarGetSetArchive(): void - { - $filter = new RarCompression(); - self::assertSame(null, $filter->getArchive()); - $filter->setArchive('Testfile.txt'); - self::assertSame('Testfile.txt', $filter->getArchive()); - self::assertSame('Testfile.txt', $filter->getOptions('archive')); - } - - /** - * Setting Password - */ - public function testRarGetSetPassword(): void - { - $filter = new RarCompression(); - self::assertSame(null, $filter->getPassword()); - $filter->setPassword('test'); - self::assertSame('test', $filter->getPassword()); - self::assertSame('test', $filter->getOptions('password')); - $filter->setOptions(['password' => 'test2']); - self::assertSame('test2', $filter->getPassword()); - self::assertSame('test2', $filter->getOptions('password')); - } - - /** - * Setting Target - */ - public function testRarGetSetTarget(): void - { - $filter = new RarCompression(); - self::assertSame('.', $filter->getTarget()); - $filter->setTarget('Testfile.txt'); - self::assertSame('Testfile.txt', $filter->getTarget()); - self::assertSame('Testfile.txt', $filter->getOptions('target')); - - $this->expectException(Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('does not exist'); - $filter->setTarget('/unknown/path/to/file.txt'); - } - - /** - * Setting Callback - */ - public function testSettingCallback(): void - { - $filter = new RarCompression(); - - $callback = [self::class, 'rarCompress']; - $filter->setCallback($callback); - self::assertSame($callback, $filter->getCallback()); - } - - public function testSettingCallbackThrowsExceptionOnMissingCallback(): void - { - $filter = new RarCompression(); - - $this->expectException(Exception\RuntimeException::class); - $this->expectExceptionMessage('No compression callback available'); - $filter->compress('test.txt'); - } - - public function testSettingCallbackThrowsExceptionOnInvalidCallback(): void - { - $filter = new RarCompression(); - - $this->expectException(Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid callback provided'); - /** @psalm-suppress UndefinedFunction */ - $filter->setCallback('invalidCallback'); - } - - /** - * Compress to Archive - */ - public function testRarCompressFile(): void - { - $filter = new RarCompression( - [ - 'archive' => dirname(__DIR__) . '/_files/compressed.rar', - 'target' => $this->tmp . '/zipextracted.txt', - 'callback' => [self::class, 'rarCompress'], - ] - ); - file_put_contents($this->tmp . '/zipextracted.txt', 'compress me'); - - $content = $filter->compress($this->tmp . '/zipextracted.txt'); - self::assertSame( - dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'compressed.rar', - $content - ); - - $content = $filter->decompress($content); - self::assertTrue($content); - $content = file_get_contents($this->tmp . '/zipextracted.txt'); - self::assertSame('compress me', $content); - } - - /** - * Compress directory to Filename - */ - public function testRarCompressDirectory(): void - { - $filter = new RarCompression( - [ - 'archive' => dirname(__DIR__) . '/_files/compressed.rar', - 'target' => $this->tmp . '/_compress', - 'callback' => [self::class, 'rarCompress'], - ] - ); - $content = $filter->compress(dirname(__DIR__) . '/_files/Compress'); - self::assertSame( - dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'compressed.rar', - $content - ); - - mkdir($this->tmp . '/_compress'); - $content = $filter->decompress($content); - self::assertTrue($content); - - $base = $this->tmp - . DIRECTORY_SEPARATOR - . '_compress' - . DIRECTORY_SEPARATOR - . 'Compress' - . DIRECTORY_SEPARATOR; - self::assertFileExists($base); - self::assertFileExists($base . 'zipextracted.txt'); - self::assertFileExists($base . 'First' . DIRECTORY_SEPARATOR . 'zipextracted.txt'); - self::assertFileExists( - $base . 'First' . DIRECTORY_SEPARATOR . 'Second' . DIRECTORY_SEPARATOR . 'zipextracted.txt' - ); - } - - /** - * testing toString - */ - public function testRarToString(): void - { - $filter = new RarCompression(); - self::assertSame('Rar', $filter->toString()); - } - - /** - * Test callback for compression - */ - public static function rarCompress(): bool - { - return true; - } -} diff --git a/test/Compress/SnappyTest.php b/test/Compress/SnappyTest.php deleted file mode 100644 index 2cd4db09..00000000 --- a/test/Compress/SnappyTest.php +++ /dev/null @@ -1,110 +0,0 @@ -compress('compress me'); - self::assertNotEquals('compress me', $content); - - $content = $filter->decompress($content); - self::assertSame('compress me', $content); - } - - public function testANonStringWillYieldATypeErrorDuringCompression(): void - { - set_error_handler(function ($num, $message): never { - throw new TypeError($message); - }); - - try { - /** @psalm-suppress InvalidArgument, InvalidCast */ - (new SnappyCompression())->compress([]); - self::fail('An exception was expected'); - } catch (TypeError $e) { - self::assertStringContainsString('snappy_compress : expects parameter to be string', $e->getMessage()); - } finally { - restore_error_handler(); - } - } - - public function testNonScalarInputCausesAnException(): void - { - $filter = new SnappyCompression(); - /** @psalm-suppress UnusedClosureParam */ - set_error_handler(static fn (int $num, string $msg): bool => true, E_WARNING); - try { - /** @psalm-suppress InvalidArgument, InvalidCast */ - $filter->compress([]); - self::fail('No exception was thrown'); - } catch (Exception\RuntimeException $e) { - self::assertStringContainsString('Error while compressing', $e->getMessage()); - } finally { - restore_error_handler(); - } - } - - /** - * Snappy should handle empty input data correctly. - */ - public function testEmptyString(): void - { - $filter = new SnappyCompression(); - - $content = $filter->compress(''); - $content = $filter->decompress($content); - self::assertSame('', $content, 'Snappy failed to decompress empty string.'); - } - - /** - * Snappy should throw an exception when decompressing invalid data. - */ - public function testInvalidData(): void - { - $filter = new SnappyCompression(); - - $this->expectException(Exception\RuntimeException::class); - $this->expectExceptionMessage('Error while decompressing.'); - - /** @psalm-suppress UnusedClosureParam */ - set_error_handler(static fn (int $num, string $msg): bool => true, E_WARNING); - $filter->decompress('123'); - restore_error_handler(); - } - - /** - * testing toString - */ - public function testSnappyToString(): void - { - $filter = new SnappyCompression(); - self::assertSame('Snappy', $filter->toString()); - } -} diff --git a/test/FilterPluginManagerCompatibilityTest.php b/test/FilterPluginManagerCompatibilityTest.php index ec4ceef2..262b1897 100644 --- a/test/FilterPluginManagerCompatibilityTest.php +++ b/test/FilterPluginManagerCompatibilityTest.php @@ -13,39 +13,12 @@ use PHPUnit\Framework\TestCase; use ReflectionProperty; -use function in_array; use function strpos; class FilterPluginManagerCompatibilityTest extends TestCase { use CommonPluginManagerTrait; - /** - * The following aliases are skipped because they are deprecated crypto related filters. - * - * These deprecated filters rely on `laminas-crypt` which is not fully compatible with PHP 8.2 and OpenSSL 3+ - */ - private const SKIPPED_ALIASES = [ - 'decrypt', - 'encrypt', - 'Decrypt', - 'Encrypt', - 'filedecrypt', - 'fileencrypt', - 'fileDecrypt', - 'fileEncrypt', - 'FileDecrypt', - 'FileEncrypt', - 'Zend\Filter\Decrypt', - 'Zend\Filter\Encrypt', - 'Zend\Filter\File\Decrypt', - 'Zend\Filter\File\Encrypt', - 'zendfilterdecrypt', - 'zendfilterencrypt', - 'zendfilterfiledecrypt', - 'zendfilterfileencrypt', - ]; - protected static function getPluginManager(): FilterPluginManager { return new FilterPluginManager(new ServiceManager()); @@ -82,10 +55,6 @@ public static function aliasProvider(): Generator continue; } - if (in_array($alias, self::SKIPPED_ALIASES, true)) { - continue; - } - yield $alias => [$alias, $target]; } } diff --git a/test/StaticFilterTest.php b/test/StaticFilterTest.php deleted file mode 100644 index 8b0b580f..00000000 --- a/test/StaticFilterTest.php +++ /dev/null @@ -1,125 +0,0 @@ - ENT_COMPAT]); - self::assertSame('"O\'Reilly"', $filteredValue); - - // Test HtmlEntities with a different ctor argument, - // and make sure it gives the correct response - // so we know it passed the arg to the ctor. - $filteredValue = StaticFilter::execute('"O\'Reilly"', HtmlEntities::class, ['quotestyle' => ENT_QUOTES]); - self::assertSame('"O'Reilly"', $filteredValue); - } - - /** - * Ensures that if we specify a validator class basename that doesn't - * exist in the namespace, get() throws an exception. - * - * Refactored to conform with Laminas-2724. - */ - #[Group('Laminas-2724')] - public function testStaticFactoryClassNotFound(): void - { - $this->expectException(Exception\ExceptionInterface::class); - StaticFilter::execute('1234', 'UnknownFilter'); - } - - public function testUsesDifferentConfigurationOnEachRequest(): void - { - $first = StaticFilter::execute('foo', Callback::class, [ - 'callback' => static fn($value): string => 'FOO', - ]); - $second = StaticFilter::execute('foo', Callback::class, [ - 'callback' => static fn($value): string => 'BAR', - ]); - self::assertNotSame($first, $second); - self::assertSame('FOO', $first); - self::assertSame('BAR', $second); - } - - public function testThatCallablesRegisteredWithThePluginManagerCanBeExecuted(): void - { - $plugins = new FilterPluginManager(new ServiceManager()); - $plugins->setService('doStuff', static fn(string $value): string => strtoupper($value)); - - StaticFilter::setPluginManager($plugins); - - self::assertEquals( - 'FOO', - StaticFilter::execute('foo', 'doStuff') - ); - } -} diff --git a/test/TestAsset/LowerCase.php b/test/TestAsset/LowerCase.php index 8f3b65a6..80bf6f6a 100644 --- a/test/TestAsset/LowerCase.php +++ b/test/TestAsset/LowerCase.php @@ -11,7 +11,7 @@ /** @template-extends AbstractFilter */ class LowerCase extends AbstractFilter { - public function filter($value) + public function filter(mixed $value): mixed { return strtolower($value); } diff --git a/test/TestAsset/StripUpperCase.php b/test/TestAsset/StripUpperCase.php index a10f763f..ef7ccbae 100644 --- a/test/TestAsset/StripUpperCase.php +++ b/test/TestAsset/StripUpperCase.php @@ -11,7 +11,7 @@ /** @template-extends AbstractFilter */ class StripUpperCase extends AbstractFilter { - public function filter($value) + public function filter(mixed $value): mixed { return preg_replace('/[A-Z]/', '', $value); } diff --git a/test/WhitelistTest.php b/test/WhitelistTest.php deleted file mode 100644 index 5557d7ea..00000000 --- a/test/WhitelistTest.php +++ /dev/null @@ -1,21 +0,0 @@ -get('whitelist'); - - self::assertInstanceOf(AllowList::class, $filter); - } -}