diff --git a/.gitignore b/.gitignore index d2e65b1f..a0699cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /test/TestAsset/.cache/ /vendor/ .phpunit.result.cache +.phpcs.cache diff --git a/composer.json b/composer.json index 739b0128..eccff7ec 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,9 @@ "sort-packages": true, "platform": { "php": "7.3.99" + }, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true } }, "extra": { @@ -41,12 +44,12 @@ "ext-gd": "*", "ext-libxml": "*", "http-interop/http-factory-tests": "^0.9.0", - "laminas/laminas-coding-standard": "~1.0.0", - "php-http/psr7-integration-tests": "^1.1", + "laminas/laminas-coding-standard": "~2.3.0", + "php-http/psr7-integration-tests": "^1.1.1", "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.1", + "phpunit/phpunit": "^9.5", "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.3" + "vimeo/psalm": "^4.24.0" }, "provide": { "psr/http-factory-implementation": "1.0", diff --git a/composer.lock b/composer.lock index c23b900a..47cde60e 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": "b18fbd2edf66315a12f5bdba7eeda7a0", + "content-hash": "ab56f78e3052c428dda4d5d8e0cdb17b", "packages": [ { "name": "psr/http-factory", @@ -573,6 +573,81 @@ ], "time": "2022-02-25T21:32:43+00:00" }, + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.7.2", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, + "time": "2022-02-04T12:51:07+00:00" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "v0.1.1", @@ -832,31 +907,36 @@ }, { "name": "laminas/laminas-coding-standard", - "version": "1.0.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "08880ce2fbfe62d471cd3cb766a91da630b32539" + "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/08880ce2fbfe62d471cd3cb766a91da630b32539", - "reference": "08880ce2fbfe62d471cd3cb766a91da630b32539", + "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/bcf6e07fe4690240be7beb6d884d0b0fafa6a251", + "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251", "shasum": "" }, "require": { - "laminas/laminas-zendframework-bridge": "^1.0", - "squizlabs/php_codesniffer": "^2.7" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "php": "^7.3 || ^8.0", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.6", + "webimpress/coding-standard": "^1.2" }, - "replace": { - "zendframework/zend-coding-standard": "self.version" + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "LaminasCodingStandard\\": "src/LaminasCodingStandard/" + } }, - "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "description": "Laminas coding standard", + "description": "Laminas Coding Standard", "homepage": "https://laminas.dev", "keywords": [ "Coding Standard", @@ -870,69 +950,13 @@ "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", "source": "https://github.com/laminas/laminas-coding-standard" }, - "time": "2019-12-31T16:28:26+00:00" - }, - { - "name": "laminas/laminas-zendframework-bridge", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-zendframework-bridge.git", - "reference": "88bf037259869891afce6504cacc4f8a07b24d0f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/88bf037259869891afce6504cacc4f8a07b24d0f", - "reference": "88bf037259869891afce6504cacc4f8a07b24d0f", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "psalm/plugin-phpunit": "^0.15.1", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.6" - }, - "type": "library", - "extra": { - "laminas": { - "module": "Laminas\\ZendFrameworkBridge" - } - }, - "autoload": { - "files": [ - "src/autoload.php" - ], - "psr-4": { - "Laminas\\ZendFrameworkBridge\\": "src//" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Alias legacy ZF class names to Laminas Project equivalents.", - "keywords": [ - "ZendFramework", - "autoloading", - "laminas", - "zf" - ], - "support": { - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", - "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", - "source": "https://github.com/laminas/laminas-zendframework-bridge" - }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", "type": "community_bridge" } ], - "time": "2021-12-21T14:34:37+00:00" + "time": "2021-05-29T15:53:59+00:00" }, { "name": "myclabs/deep-copy", @@ -1602,6 +1626,51 @@ }, "time": "2020-07-09T08:33:42+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.6.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "135607f9ccc297d6923d49c2bcf309f509413215" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/135607f9ccc297d6923d49c2bcf309f509413215", + "reference": "135607f9ccc297d6923d49c2bcf309f509413215", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.6.4" + }, + "time": "2022-06-26T13:09:08+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.15", @@ -3144,66 +3213,100 @@ ], "time": "2020-09-28T06:39:44+00:00" }, + { + "name": "slevomat/coding-standard", + "version": "7.2.1", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90", + "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": "^1.5.1", + "squizlabs/php_codesniffer": "^3.6.2" + }, + "require-dev": { + "phing/phing": "2.17.3", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.4.10|1.7.1", + "phpstan/phpstan-deprecation-rules": "1.0.0", + "phpstan/phpstan-phpunit": "1.0.0|1.1.1", + "phpstan/phpstan-strict-rules": "1.2.3", + "phpunit/phpunit": "7.5.20|8.5.21|9.5.20" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2022-05-25T10:58:12+00:00" + }, { "name": "squizlabs/php_codesniffer", - "version": "2.9.2", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745" + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -3215,7 +3318,7 @@ } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", "standards" @@ -3225,20 +3328,20 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2018-11-07T22:31:41+00:00" + "time": "2022-06-18T07:21:10+00:00" }, { "name": "symfony/console", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb" + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb", + "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", "shasum": "" }, "require": { @@ -3308,7 +3411,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.9" + "source": "https://github.com/symfony/console/tree/v5.4.10" }, "funding": [ { @@ -3324,11 +3427,11 @@ "type": "tidelift" } ], - "time": "2022-05-18T06:17:34+00:00" + "time": "2022-06-26T13:00:04+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -3375,7 +3478,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ { @@ -3887,16 +3990,16 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { @@ -3950,7 +4053,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -3966,20 +4069,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99" + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", + "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", "shasum": "" }, "require": { @@ -4036,7 +4139,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.9" + "source": "https://github.com/symfony/string/tree/v5.4.10" }, "funding": [ { @@ -4052,7 +4155,7 @@ "type": "tidelift" } ], - "time": "2022-04-19T10:40:37+00:00" + "time": "2022-06-26T15:57:47+00:00" }, { "name": "theseer/tokenizer", @@ -4106,16 +4209,16 @@ }, { "name": "vimeo/psalm", - "version": "4.23.0", + "version": "4.24.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "f1fe6ff483bf325c803df9f510d09a03fd796f88" + "reference": "06dd975cb55d36af80f242561738f16c5f58264f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/f1fe6ff483bf325c803df9f510d09a03fd796f88", - "reference": "f1fe6ff483bf325c803df9f510d09a03fd796f88", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/06dd975cb55d36af80f242561738f16c5f58264f", + "reference": "06dd975cb55d36af80f242561738f16c5f58264f", "shasum": "" }, "require": { @@ -4207,9 +4310,64 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.23.0" + "source": "https://github.com/vimeo/psalm/tree/4.24.0" + }, + "time": "2022-06-26T11:47:54+00:00" + }, + { + "name": "webimpress/coding-standard", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/webimpress/coding-standard.git", + "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", + "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", + "shasum": "" + }, + "require": { + "php": "^7.3 || ^8.0", + "squizlabs/php_codesniffer": "^3.6.2" }, - "time": "2022-04-28T17:35:49+00:00" + "require-dev": { + "phpunit/phpunit": "^9.5.13" + }, + "type": "phpcodesniffer-standard", + "extra": { + "dev-master": "1.2.x-dev", + "dev-develop": "1.3.x-dev" + }, + "autoload": { + "psr-4": { + "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "Webimpress Coding Standard", + "keywords": [ + "Coding Standard", + "PSR-2", + "phpcs", + "psr-12", + "webimpress" + ], + "support": { + "issues": "https://github.com/webimpress/coding-standard/issues", + "source": "https://github.com/webimpress/coding-standard/tree/1.2.4" + }, + "funding": [ + { + "url": "https://github.com/michalbundyra", + "type": "github" + } + ], + "time": "2022-02-15T19:52:12+00:00" }, { "name": "webmozart/assert", diff --git a/phpcs.xml b/phpcs.xml index 1a80a862..6ce2a0b0 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,8 +1,24 @@ - - + + + + + + + + + + src test + + + + + 0 + diff --git a/psalm-baseline.xml b/psalm-baseline.xml index ce464c80..6b595c35 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + null|callable @@ -14,25 +14,10 @@ $previous->getCode() - - - $code - - - $code - - - - - $code - - - $code - - - + ! is_string($name) + ! is_string($stream) && ! is_resource($stream) is_string($version) @@ -44,9 +29,6 @@ $headerNames - - $stream - $header $header @@ -288,19 +270,6 @@ - - - ?int - - - $stats['size'] - - - $resource - - - $resource - $resource $this->resource @@ -310,9 +279,6 @@ $stream - - is_resource($resource) - @@ -363,9 +329,18 @@ + + laminas_createUploadedFile(...func_get_args()) + + + UploadedFile + func_get_args() + + UploadedFile + @@ -411,9 +386,18 @@ + + laminas_marshalUriFromSapi(...func_get_args()) + + + Uri + func_get_args() + + Uri + @@ -439,12 +423,11 @@ $headers[$header] $host - + $host $iisUrlRewritten $origPathInfo $unencodedUrl - $value array @@ -502,9 +485,6 @@ - - $cookieHeader - func_get_args() @@ -513,41 +493,10 @@ function () { - - $callback - $expected - - - $callback - $ret $ret - - array - - - - - $assertion - $expected - $value - $value - $value - - - assertValues - getFilterValues - testAssertValidRaisesExceptionForInvalidValue - testFiltersValuesPerRfc7230 - testValidatesValuesPerRfc7230 - validateValues - - - $value - $value - @@ -555,403 +504,41 @@ - - $value - $value + $value $version - - [ $value ] - [ $value ] - - - - - $message - $test - - - assertStreamContents - getFileContents - testCanReadStreamIteratively - testCastingToStringReturnsFullContentsRegardlesOfPriorReads - testGetContentsReturnCacheWhenReachedEof - testGetContentsReturnsRemainingContentsOfStream - testMultipleCastsToStringReturnSameContentsEvenIfReadsOccur - testStreamIsNeverWritable - - - $contents - $message - - - $content - $contents - assertSame - - testCanReadContentFromNotSeekableResource - testClose - testDetach - testGetContents - testGetContentsRaisesExceptionWhenPointerIsBehindOffset - testGetMetadata - testGetSize - testIsReadable - testIsSeekable - testIsWritable - testRead - testReadRaisesExceptionWhenPointerIsBehindOffset - testRewind - testSeek - testTell - testToString - testWrite - testWriteRaisesExceptionWhenPointerIsBehindOffset - - - - - testDeserializeFromArray - testMissingBodyParamInSerializedRequestThrowsException - testSerializeToArray - function () use ($payload) { - - $exceptionMessage - $expectations - $expectations - $line - $line - $line - $message - $requestTarget - $requestTarget - $text - - - $exceptionMessage - $message - $text - $payload[$i++] - - $expect - $expect + $i - $method - $method - - array - array - array - array - array - - + $i - $line - $line - $line 'UNLOCK' => ['UNLOCK'] - - ['TOTALLY INVALID'] - - - $body - $contains - $expected - $headers - $hostKey - $method - $method - $method - $request - $requestTarget - $uri - $value - - - customRequestMethods - headersWithInjectionVectors - hostHeaderKeys - invalidHeaderTypes - invalidMethod - invalidRequestBody - invalidRequestMethod - invalidRequestUri - requestsWithUri - testAllowsCustomRequestMethodsThatFollowSpec - testCanProvideARequestTarget - testConstructorCanAcceptAllMessageParts - testConstructorRaisesExceptionForHeadersWithCRLFVectors - testConstructorRaisesExceptionForInvalidBody - testConstructorRaisesExceptionForInvalidHeaders - testConstructorRaisesExceptionForInvalidMethod - testConstructorRaisesExceptionForInvalidStream - testConstructorRaisesExceptionForInvalidUri - testDefaultStreamIsWritable - testGetHeadersContainsHostHeaderIfUriWithHostIsDeleted - testGetHeadersContainsHostHeaderIfUriWithHostIsPresent - testGetHeadersContainsNoHostHeaderIfNoUriPresent - testGetHeadersContainsNoHostHeaderIfUriDoesNotContainHost - testGetHostHeaderLineReturnsEmptyStringIfNoUriPresent - testGetHostHeaderLineReturnsEmptyStringIfUriDoesNotContainHost - testGetHostHeaderLineReturnsUriHostWhenPresent - testGetHostHeaderReturnsEmptyArrayIfNoUriPresent - testGetHostHeaderReturnsEmptyArrayIfUriDoesNotContainHost - testGetHostHeaderReturnsUriHostWhenHostHeaderDeleted - testGetHostHeaderReturnsUriHostWhenPresent - testHostHeaderNotSetFromUriOnCreationIfHostHeaderSpecified - testHostHeaderSetFromUriOnCreationIfNoHostHeaderSpecified - testHostHeaderUpdatesToUriHostAndPortWhenPreserveHostDisabledAndNonStandardPort - testMethodIsGetByDefault - testMethodMutatorReturnsCloneWithChangedMethod - testNotPassingPreserveHostFlagWhenUpdatingUriWithoutHostDoesNotUpdateHostHeader - testPassingPreserveHostFlagWhenUpdatingUriDoesNotUpdateHostHeader - testRequestTargetCannotContainWhitespace - testRequestTargetDoesNotCacheBetweenInstances - testRequestTargetIsSlashWhenNoUriPresent - testRequestTargetIsSlashWhenUriHasNoPathOrQuery - testReturnsRequestTargetWhenUriIsPresent - testReturnsUnpopulatedUriByDefault - testSettingNewUriResetsRequestTarget - testWithInvalidMethod - testWithUriAndNoPreserveHostWillOverwriteHostHeaderRegardlessOfOriginalCase - testWithUriReturnsNewInstanceWithNewUri - validRequestTargets - - - $body - $contains - $headers - $hostKey - $hostKey - $method - $method - $method - $requestTarget - $uri - - - getRequestTarget - - - - - createResponse - createSerializedResponse - testDeserializeFromArray - testMissingBodyParamInSerializedRequestThrowsException - testSerializeToArray - - - $response - $response - $serializedRequest - $serializedResponse - - - $serializedRequest['body'] - - - $response - $response - $serializedRequest - $serializedResponse - - - - - testConstructor - testHeaderConstructor - - - - - $body - - - invalidHtmlContent - testAllowsStreamsForResponseBody - testConstructorAcceptsHtmlString - testConstructorAllowsPassingHeaders - testConstructorAllowsPassingStatus - testConstructorRewindsBodyStream - testRaisesExceptionforNonStringNonStreamBodyContent - - - $body - - - - - $value - $value - - - scalarValuesForJSON - testCanProvideAlternateContentTypeViaHeadersPassedToConstructor - testCanProvideStatusCodeToConstructor - testConstructorAcceptsDataAndCreatesJsonEncodedMessageBody - testConstructorRewindsBodyStream - testEncodingOptionsGetter - testJsonErrorHandlingOfBadEmbeddedData - testJsonErrorHandlingOfResources - testModifyingThePayloadDoesntMutateResponseInstance - testPayloadGetter - testScalarValuePassedToConstructorJsonEncodesDirectly - testUsesSaneDefaultJsonEncodingFlags - testWithEncodingOptions - testWithPayload - valuesToJsonEncode - - - - - $uri - - - invalidUris - testConstructorAcceptsStringUriAndProduces302ResponseWithLocationHeader - testConstructorAcceptsUriInstanceAndProduces302ResponseWithLocationHeader - testConstructorAllowsSpecifyingAlternateStatusCode - testConstructorAllowsSpecifyingHeaders - testConstructorRaisesExceptionOnInvalidUri - - - $uri - - - - - $exceptionMessage - $message - $text - - - headersWithContinuationLines - messagesWithInvalidHeaders - testCanDeserializeBasicResponse - testCanDeserializeResponseWithHeaderContinuations - testCanDeserializeResponseWithMultipleHeadersOfSameName - testCanDeserializeResponseWithoutBody - testCanDeserializeResponseWithoutHeadersButContainingBody - testCanDeserializeResponseWithoutHeadersOrBody - testDeserializationRaisesExceptionForInvalidStatusLine - testDeserializationRaisesExceptionForMalformedHeaders - testDeserializeCorrectlyCastsStatusCodeToInteger - testFromStreamThrowsExceptionWhenStreamIsNotReadable - testFromStreamThrowsExceptionWhenStreamIsNotSeekable - testOmitsReasonPhraseFromStatusLineIfEmpty - testSerializesBasicResponse - testSerializesMultipleHeadersCorrectly - testSerializesResponseWithoutBodyCorrectly - - - $exceptionMessage - $message - $text - - - - - $body - - - invalidContent - testAllowsStreamsForResponseBody - testConstructorAcceptsBodyAsString - testConstructorAllowsPassingHeaders - testConstructorAllowsPassingStatus - testConstructorRewindsBodyStream - testRaisesExceptionforNonStringNonStreamBodyContent - - - $body - - - $body - - - invalidContent - testAllowsStreamsForResponseBody - testConstructorAcceptsBodyAsString - testConstructorAllowsPassingHeaders - testConstructorAllowsPassingStatus - testConstructorRewindsBodyStream + testRaisesExceptionforNonStringNonStreamBodyContent - - $body - - - [ 'TOTALLY INVALID' ] - - - $body - $code - $code - $code - $contains - $headers - $invalidReasonPhrase - $reasonPhrase - $value - - - headersWithInjectionVectors - ianaCodesReasonPhrasesProvider - invalidHeaderTypes - invalidReasonPhrases - invalidResponseBody - invalidStatusCodes - testCanSetCustomReasonPhrase - testCannotSetInvalidStatusCode - testConstructorCanAcceptAllMessageParts - testConstructorRaisesExceptionForHeadersWithCRLFVectors - testConstructorRaisesExceptionForInvalidBody - testConstructorRaisesExceptionForInvalidHeaders - testConstructorRaisesExceptionForInvalidStream - testCreateWithValidStatusCodes - testReasonPhraseCanBeEmpty - testReasonPhraseDefaultsAgainstIana - testReasonPhraseDefaultsToStandards - testStatusCodeIs200ByDefault - testStatusCodeMutatorReturnsCloneWithChanges - testWithStatusRaisesAnExceptionForNonStringReasonPhrases - validStatusCodes - - - $body - $code - $code - $code - $contains - $headers - $invalidReasonPhrase - $responseCode @@ -966,105 +553,11 @@ $normalizedFiles['fooFiles'] - - $expected - $protocol - - - cookieHeaderValues - marshalProtocolVersionProvider - testCanCreateServerRequestViaFromGlobalsMethod - testCookieHeaderVariations - testCreateFromGlobalsShouldNotPreserveKeysWhenCreatedWithAnEmptyValue - testCreateFromGlobalsShouldPreserveKeysWhenCreatedWithAZeroValue - testFromGlobalsUsesCookieHeaderInsteadOfCookieSuperGlobal - testFromGlobalsUsesCookieSuperGlobalWhenCookieHeaderIsNotSet - testMarshalHostAndPortReturnsEmptyValuesIfNoHostHeaderAndNoServerName - testMarshalHostAndPortReturnsServerAddrForHostIfPresentAndHostIsIpv6Address - testMarshalHostAndPortReturnsServerNameForHostIfServerAddrPresentButHostIsNotIpv6Address - testMarshalHostAndPortReturnsServerNameForHostWhenPresent - testMarshalHostAndPortReturnsServerPortForPortWhenPresentWithServerName - testMarshalHostAndPortUsesHostHeaderWhenPresent - testMarshalHostAndPortWillDetectPortInHostHeaderWhenPresent - testMarshalHostAndPortWillDetectPortInIpv6StyleHost - testMarshalInvalidHeadersStrippedFromServerArray - testMarshalProtocolReturnsDefaultValueIfHeaderIsNotPresent - testMarshalProtocolVersionReturnsHttpVersions - testMarshalProtocolVersionRisesExceptionIfVersionIsNotRecognized - testMarshalRequestUriFallsBackToRoot - testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUrlButNoXRewriteUrlPresent - testMarshalRequestUriStripsSchemeHostAndPortInformationWhenPresent - testMarshalRequestUriUsesIISUnencodedUrlValueIfPresentAndUrlWasRewritten - testMarshalRequestUriUsesOrigPathInfoIfPresent - testMarshalUriDetectsHttpsSchemeFromServerValue - testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue - testMarshalUriInjectsFragmentFromServer - testMarshalUriInjectsQueryStringFromServer - testMarshalUriStripsQueryStringFromRequestUri - testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff - testMarshalsExpectedHeadersFromServerArray - testMarshalsVariablesPrefixedByApacheFromServerArray - testNormalizeFilesReturnsOnlyActualFilesWhenOriginalFilesContainsNestedAssociativeArrays - testNormalizeServerReturnsArrayUnalteredIfApacheHeadersDoNotContainAuthorization - testNormalizeServerUsesLowerCaseAuthorizationHeaderFromApacheWhenPresent - testNormalizeServerUsesMixedCaseAuthorizationHeaderFromApacheWhenPresent - testReturnsServerValueUnchangedIfHttpAuthorizationHeaderIsPresent - testServerRequestFactoryHasAWritableEmptyBody - - - $data - - - $data - $param - - - array - iterable - $parsedBody - - $methodReturned - $parameterMethod - $request - - - provideMethods - testAllowsRemovingAttributeWithNullValue - testAllowsRemovingNonExistentAttribute - testAttributeMutatorReturnsCloneWithChanges - testAttributesAreEmptyByDefault - testCookieParamsAreAnEmptyArrayAtInitialization - testCookiesAreEmptyByDefault - testCookiesMutatorReturnsCloneWithChanges - testNestedUploadedFiles - testParsedBodyIsEmptyByDefault - testParsedBodyIsNullAtInitialization - testParsedBodyMutatorReturnsCloneWithChanges - testQueryParamsAreAnEmptyArrayAtInitialization - testQueryParamsAreEmptyByDefault - testQueryParamsMutatorReturnsCloneWithChanges - testRemovingAttributeReturnsCloneWithoutAttribute - testServerParamsAreEmptyByDefault - testSingleAttributesWhenEmptyByDefault - testTryToAddInvalidUploadedFiles - testUploadedFilesAreEmptyByDefault - testUsesProvidedConstructorArguments - - - $parameterMethod - - - $new - - - getAttribute - withoutAttribute - @@ -1073,95 +566,10 @@ [' THIS WILL NOT WORK '] - - $fileShouldExist - $fileShouldExist - $flag - $flag - $mode - $mode - $resource - - - $tmpnam - - - findNonExistentTempName - getResourceFor67 - invalidResources - provideDataForIsReadable - provideDataForIsWritable - testAttachWithInvalidStringResourceRaisesException - testAttachWithNonStringNonResourceRaisesException - testAttachWithResourceAttachesResource - testAttachWithStringRepresentingResourceCreatesAndAttachesResource - testCanInstantiateWithGDResource - testCanInstantiateWithStreamIdentifier - testCanInstantiteWithStreamResource - testCanReadContentFromNotSeekableResource - testCloseClosesResource - testCloseDoesNothingAfterDetach - testCloseUnsetsResource - testDetachReturnsResource - testEofReportsFalseWhenNotAtEndOfStream - testEofReportsTrueWhenAtEndOfStream - testEofReportsTrueWhenStreamIsDetached - testGetContentsRisesExceptionIfStreamIsNotReadable - testGetContentsShouldGetFullStreamContents - testGetContentsShouldReturnStreamContentsFromCurrentPointer - testGetMetadataReturnsAllMetadataWhenNoKeyPresent - testGetMetadataReturnsDataForSpecifiedKey - testGetMetadataReturnsNullIfNoDataExistsForKey - testGetSizeReturnsStreamSize - testIsReadableReturnsCorrectFlagForMode - testIsReadableReturnsFalseIfStreamIsNotReadable - testIsReadableReturnsFalseWhenStreamIsDetached - testIsSeekableReturnsFalseForDetachedStreams - testIsSeekableReturnsTrueForReadableStreams - testIsWritableReturnsCorrectFlagForMode - testIsWritableReturnsFalseIfStreamIsNotWritable - testIsWritableReturnsFalseWhenStreamIsDetached - testIsWritableReturnsTrueForWritableMemoryStream - testPassingInvalidStreamResourceToConstructorRaisesException - testRaisesExceptionOnAttachForNonStreamResources - testRaisesExceptionOnConstructionForNonStreamResources - testReadRaisesExceptionWhenStreamIsDetached - testReadReturnsEmptyStringWhenAtEndOfFile - testRewindResetsToStartOfStream - testSeekAdvancesToGivenOffsetOfStream - testSeekRaisesExceptionWhenStreamIsDetached - testSizeReportsNullForPhpInputStreams - testSizeReportsNullWhenNoResourcePresent - testStringSerializationReturnsEmptyStringWhenStreamIsNotReadable - testTellRaisesExceptionIfResourceIsDetached - testTellReportsCurrentPositionInResource - testToStringRetrievesFullContentsOfStream - testWriteRaisesExceptionWhenStreamIsDetached - testWriteRaisesExceptionWhenStreamIsNotWritable - - - $mode - $mode - $resource - $resource - $resource - $this->tmpnam - $this->tmpnam - $this->tmpnam - $this->tmpnam - - - $resource - $resource + $test - - - push - reset - - $path @@ -1169,145 +577,17 @@ - - '3001' + 1 - - $credential - $expected - $expected - $expected - $expected - $method - $method - $path - $port - $port - $port - $query - $query - $query - $result - $result - $scheme - $scheme - $scheme - $url - $url - $url - $user - $value - $value - - - authorityInfo - invalidPaths - invalidPorts - invalidQueryStrings - invalidSchemes - invalidStringComponentValues - mutations - queryStringsForEncoding - standardSchemePortCombinations - testAuthorityIsPrefixedByDoubleSlashIfPresent - testAuthorityOmitsPortForStandardSchemePortCombinations - testCanEmitOriginFormUrl - testCanSerializeToString - testConstructWithUnsupportedSchemeRaisesAnException - testConstructorRaisesExceptionForSeriouslyMalformedURI - testConstructorSetsAllProperties - testESchemeStripsOffDelimiter - testEmptyPathOnOriginFormRemainsAnEmptyPath - testEncodeFragmentPrefixIfPresent - testFragmentIsNotDoubleEncoded - testFragmentIsProperlyEncoded - testHostIsLowercase - testHostIsLowercaseWhenIsSetViwWithHost - testMutatingSchemeStripsOffDelimiter - testMutatingWithUnsupportedSchemeRaisesAnException - testMutationResetsUriStringPropertyInClone - testPassingInvalidValueToWithMethodRaisesException - testPathDoesNotBecomeDoubleEncoded - testPathIsNotPrefixedWithSlashIfSetWithoutOne - testPathIsProperlyEncoded - testPathNotSlashPrefixedIsEmittedWithSlashDelimiterWhenUriIsCastToString - testProperlyTrimsLeadingSlashesToPreventXSS - testQueryIsNotDoubleEncoded - testQueryIsProperlyEncoded - testReservedCharsInPathUnencoded - testRetrievingAuthorityReturnsExpectedValues - testSettingEmptyPathOnAbsoluteUriReturnsAnEmptyPath - testStringRepresentationOfAbsoluteUriWithNoPathSetsAnEmptyPath - testStringRepresentationOfOriginFormWithNoPathRetainsEmptyPath - testStripsQueryPrefixIfPresent - testUriDistinguishZeroFromEmptyString - testUriDoesNotAppendColonToHostIfPortIsEmpty - testUtf8Path - testUtf8Query - testUtf8Uri - testWithFragmentReturnsNewInstanceWithProvidedFragment - testWithFragmentReturnsSameInstanceWithProvidedFragmentSameAsBefore - testWithHostReturnsNewInstanceWithProvidedHost - testWithHostReturnsSameInstanceWithProvidedHostIsSameAsBefore - testWithPathRaisesExceptionForInvalidPaths - testWithPathReturnsNewInstanceWithProvidedPath - testWithPathReturnsSameInstanceWithProvidedPathSameAsBefore - testWithPortRaisesExceptionForInvalidPorts - testWithPortReturnsNewInstanceWithProvidedPort - testWithPortReturnsSameInstanceWithProvidedPortIsSameAsBefore - testWithQueryRaisesExceptionForInvalidQueryStrings - testWithQueryReturnsNewInstanceWithProvidedQuery - testWithSchemeReturnsNewInstanceWithNewScheme - testWithSchemeReturnsSameInstanceWithSameScheme - testWithUserInfoEncodesUsernameAndPassword - testWithUserInfoReturnsNewInstanceWithProvidedUser - testWithUserInfoReturnsNewInstanceWithProvidedUserAndPassword - testWithUserInfoReturnsSameInstanceIfUserAndPasswordAreSameAsBefore - testWithUserInfoThrowExceptionIfPasswordIsNotString - userInfoProvider - utf8PathsDataProvider - utf8QueryStringsDataProvider - validPorts - - - $credential - $expected - $path - $port - $port - $port - $query - $query - $scheme - $scheme + $test - $url - $url - $url - $user $test - - $port - $scheme - - - - - array - array - - - testCreatesUploadedFileFromFlatFileSpecification - testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFiles - testTraversesNestedFileSpecificationContainingNumericIndicesToExtractUploadedFiles - testTraversesNestedFileSpecificationToExtractUploadedFile - $normalised['my-form']['details']['avatars'] $normalised['slide-shows'][0]['slides'] diff --git a/src/AbstractSerializer.php b/src/AbstractSerializer.php index 1ede2889..3b290f05 100644 --- a/src/AbstractSerializer.php +++ b/src/AbstractSerializer.php @@ -31,10 +31,10 @@ abstract class AbstractSerializer * Retrieves a line from the stream; a line is defined as a sequence of * characters ending in a CRLF sequence. * - * @throws Exception\DeserializationException if the sequence contains a CR + * @throws Exception\DeserializationException If the sequence contains a CR * or LF in isolation, or ends in a CR. */ - protected static function getLine(StreamInterface $stream) : string + protected static function getLine(StreamInterface $stream): string { $line = ''; $crFound = false; @@ -84,7 +84,7 @@ protected static function getLine(StreamInterface $stream) : string * * @throws Exception\DeserializationException For invalid headers. */ - protected static function splitStream(StreamInterface $stream) : array + protected static function splitStream(StreamInterface $stream): array { $headers = []; $currentHeader = false; @@ -108,7 +108,7 @@ protected static function splitStream(StreamInterface $stream) : array } // Append continuation to last header value found - $value = array_pop($headers[$currentHeader]); + $value = array_pop($headers[$currentHeader]); $headers[$currentHeader][] = $value . ' ' . trim($line, "\t "); } @@ -121,7 +121,7 @@ protected static function splitStream(StreamInterface $stream) : array * * @psalm-param array $headers */ - protected static function serializeHeaders(array $headers) : string + protected static function serializeHeaders(array $headers): string { $lines = []; foreach ($headers as $header => $values) { @@ -139,7 +139,7 @@ protected static function serializeHeaders(array $headers) : string * * @param string $header */ - protected static function filterHeader($header) : string + protected static function filterHeader($header): string { $filtered = str_replace('-', ' ', $header); $filtered = ucwords($filtered); diff --git a/src/CallbackStream.php b/src/CallbackStream.php index f908fd00..4027e665 100644 --- a/src/CallbackStream.php +++ b/src/CallbackStream.php @@ -15,13 +15,10 @@ */ class CallbackStream implements StreamInterface { - /** - * @var callable|null - */ + /** @var callable|null */ protected $callback; /** - * @param callable $callback * @throws Exception\InvalidArgumentException */ public function __construct(callable $callback) @@ -32,7 +29,7 @@ public function __construct(callable $callback) /** * {@inheritdoc} */ - public function __toString() : string + public function __toString(): string { return $this->getContents(); } @@ -40,18 +37,19 @@ public function __toString() : string /** * {@inheritdoc} */ - public function close() : void + public function close(): void { $this->callback = null; } /** * {@inheritdoc} + * * @return null|callable */ - public function detach() : ?callable + public function detach(): ?callable { - $callback = $this->callback; + $callback = $this->callback; $this->callback = null; return $callback; } @@ -59,7 +57,7 @@ public function detach() : ?callable /** * Attach a new callback to the instance. */ - public function attach(callable $callback) : void + public function attach(callable $callback): void { $this->callback = $callback; } @@ -67,7 +65,7 @@ public function attach(callable $callback) : void /** * {@inheritdoc} */ - public function getSize() : ?int + public function getSize(): ?int { return null; } @@ -75,7 +73,7 @@ public function getSize() : ?int /** * {@inheritdoc} */ - public function tell() : int + public function tell(): int { throw Exception\UntellableStreamException::forCallbackStream(); } @@ -83,7 +81,7 @@ public function tell() : int /** * {@inheritdoc} */ - public function eof() : bool + public function eof(): bool { return empty($this->callback); } @@ -91,13 +89,14 @@ public function eof() : bool /** * {@inheritdoc} */ - public function isSeekable() : bool + public function isSeekable(): bool { return false; } /** * {@inheritdoc} + * * @param int $offset * @param int $whence * @return void @@ -110,7 +109,7 @@ public function seek($offset, $whence = SEEK_SET) /** * {@inheritdoc} */ - public function rewind() : void + public function rewind(): void { throw Exception\UnrewindableStreamException::forCallbackStream(); } @@ -118,7 +117,7 @@ public function rewind() : void /** * {@inheritdoc} */ - public function isWritable() : bool + public function isWritable(): bool { return false; } @@ -126,7 +125,7 @@ public function isWritable() : bool /** * {@inheritdoc} */ - public function write($string) : void + public function write($string): void { throw Exception\UnwritableStreamException::forCallbackStream(); } @@ -134,7 +133,7 @@ public function write($string) : void /** * {@inheritdoc} */ - public function isReadable() : bool + public function isReadable(): bool { return false; } @@ -142,7 +141,7 @@ public function isReadable() : bool /** * {@inheritdoc} */ - public function read($length) : string + public function read($length): string { throw Exception\UnreadableStreamException::forCallbackStream(); } @@ -150,7 +149,7 @@ public function read($length) : string /** * {@inheritdoc} */ - public function getContents() : string + public function getContents(): string { $callback = $this->detach(); $contents = $callback ? $callback() : ''; @@ -163,9 +162,9 @@ public function getContents() : string public function getMetadata($key = null) { $metadata = [ - 'eof' => $this->eof(), + 'eof' => $this->eof(), 'stream_type' => 'callback', - 'seekable' => false + 'seekable' => false, ]; if (null === $key) { diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 78afa047..ae4e96f4 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -4,17 +4,17 @@ namespace Laminas\Diactoros; -use Psr\Http\Message\ServerRequestFactoryInterface; use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\UploadedFileFactoryInterface; use Psr\Http\Message\UriFactoryInterface; class ConfigProvider { - public const CONFIG_KEY = 'laminas-diactoros'; - public const X_FORWARDED = 'x-forwarded-request-filter'; + public const CONFIG_KEY = 'laminas-diactoros'; + public const X_FORWARDED = 'x-forwarded-request-filter'; public const X_FORWARDED_TRUSTED_PROXIES = 'trusted-proxies'; public const X_FORWARDED_TRUSTED_HEADERS = 'trusted-headers'; @@ -23,10 +23,10 @@ class ConfigProvider * * @return array */ - public function __invoke() : array + public function __invoke(): array { return [ - 'dependencies' => $this->getDependencies(), + 'dependencies' => $this->getDependencies(), self::CONFIG_KEY => $this->getComponentConfig(), ]; } @@ -35,7 +35,7 @@ public function __invoke() : array * Returns the container dependencies. * Maps factory interfaces to factories. */ - public function getDependencies() : array + public function getDependencies(): array { // @codingStandardsIgnoreStart return [ diff --git a/src/Exception/DeserializationException.php b/src/Exception/DeserializationException.php index 61f5c7c6..424e3471 100644 --- a/src/Exception/DeserializationException.php +++ b/src/Exception/DeserializationException.php @@ -9,37 +9,37 @@ class DeserializationException extends UnexpectedValueException implements ExceptionInterface { - public static function forInvalidHeader() : self + public static function forInvalidHeader(): self { throw new self('Invalid header detected'); } - public static function forInvalidHeaderContinuation() : self + public static function forInvalidHeaderContinuation(): self { throw new self('Invalid header continuation'); } - public static function forRequestFromArray(Throwable $previous) : self + public static function forRequestFromArray(Throwable $previous): self { return new self('Cannot deserialize request', $previous->getCode(), $previous); } - public static function forResponseFromArray(Throwable $previous) : self + public static function forResponseFromArray(Throwable $previous): self { return new self('Cannot deserialize response', $previous->getCode(), $previous); } - public static function forUnexpectedCarriageReturn() : self + public static function forUnexpectedCarriageReturn(): self { throw new self('Unexpected carriage return detected'); } - public static function forUnexpectedEndOfHeaders() : self + public static function forUnexpectedEndOfHeaders(): self { throw new self('Unexpected end of headers'); } - public static function forUnexpectedLineFeed() : self + public static function forUnexpectedLineFeed(): self { throw new self('Unexpected line feed detected'); } diff --git a/src/Exception/InvalidForwardedHeaderNameException.php b/src/Exception/InvalidForwardedHeaderNameException.php index 1c446439..219bc3ef 100644 --- a/src/Exception/InvalidForwardedHeaderNameException.php +++ b/src/Exception/InvalidForwardedHeaderNameException.php @@ -6,6 +6,12 @@ use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders; +use function get_class; +use function gettype; +use function is_object; +use function is_string; +use function sprintf; + class InvalidForwardedHeaderNameException extends RuntimeException implements ExceptionInterface { /** @param mixed $name */ diff --git a/src/Exception/InvalidProxyAddressException.php b/src/Exception/InvalidProxyAddressException.php index 3c8a68d2..56cbdeb6 100644 --- a/src/Exception/InvalidProxyAddressException.php +++ b/src/Exception/InvalidProxyAddressException.php @@ -4,6 +4,11 @@ namespace Laminas\Diactoros\Exception; +use function get_class; +use function gettype; +use function is_object; +use function sprintf; + class InvalidProxyAddressException extends RuntimeException implements ExceptionInterface { /** @param mixed $proxy */ diff --git a/src/Exception/InvalidStreamPointerPositionException.php b/src/Exception/InvalidStreamPointerPositionException.php index 6c54d0f5..acaa7e7f 100644 --- a/src/Exception/InvalidStreamPointerPositionException.php +++ b/src/Exception/InvalidStreamPointerPositionException.php @@ -9,10 +9,11 @@ class InvalidStreamPointerPositionException extends RuntimeException implements ExceptionInterface { + /** @param int $code */ public function __construct( string $message = 'Invalid pointer position', $code = 0, - Throwable $previous = null + ?Throwable $previous = null ) { parent::__construct($message, $code, $previous); } diff --git a/src/Exception/SerializationException.php b/src/Exception/SerializationException.php index 7e831a3c..fc2b6f09 100644 --- a/src/Exception/SerializationException.php +++ b/src/Exception/SerializationException.php @@ -8,12 +8,12 @@ class SerializationException extends UnexpectedValueException implements ExceptionInterface { - public static function forInvalidRequestLine() : self + public static function forInvalidRequestLine(): self { return new self('Invalid request line detected'); } - public static function forInvalidStatusLine() : self + public static function forInvalidStatusLine(): self { return new self('No status line detected'); } diff --git a/src/Exception/UnreadableStreamException.php b/src/Exception/UnreadableStreamException.php index daca6650..212ac7e1 100644 --- a/src/Exception/UnreadableStreamException.php +++ b/src/Exception/UnreadableStreamException.php @@ -8,22 +8,22 @@ class UnreadableStreamException extends RuntimeException implements ExceptionInterface { - public static function dueToConfiguration() : self + public static function dueToConfiguration(): self { return new self('Stream is not readable'); } - public static function dueToMissingResource() : self + public static function dueToMissingResource(): self { return new self('No resource available; cannot read'); } - public static function dueToPhpError() : self + public static function dueToPhpError(): self { return new self('Error reading stream'); } - public static function forCallbackStream() : self + public static function forCallbackStream(): self { return new self('Callback streams cannot read'); } diff --git a/src/Exception/UnrecognizedProtocolVersionException.php b/src/Exception/UnrecognizedProtocolVersionException.php index 76d6f2b2..475fdcb4 100644 --- a/src/Exception/UnrecognizedProtocolVersionException.php +++ b/src/Exception/UnrecognizedProtocolVersionException.php @@ -10,7 +10,7 @@ class UnrecognizedProtocolVersionException extends UnexpectedValueException implements ExceptionInterface { - public static function forVersion(string $version) : self + public static function forVersion(string $version): self { return new self(sprintf('Unrecognized protocol version (%s)', $version)); } diff --git a/src/Exception/UnrewindableStreamException.php b/src/Exception/UnrewindableStreamException.php index a3330080..0d1d5aeb 100644 --- a/src/Exception/UnrewindableStreamException.php +++ b/src/Exception/UnrewindableStreamException.php @@ -8,7 +8,7 @@ class UnrewindableStreamException extends RuntimeException implements ExceptionInterface { - public static function forCallbackStream() : self + public static function forCallbackStream(): self { return new self('Callback streams cannot rewind position'); } diff --git a/src/Exception/UnseekableStreamException.php b/src/Exception/UnseekableStreamException.php index 46c2af6d..0bb7cebc 100644 --- a/src/Exception/UnseekableStreamException.php +++ b/src/Exception/UnseekableStreamException.php @@ -8,22 +8,22 @@ class UnseekableStreamException extends RuntimeException implements ExceptionInterface { - public static function dueToConfiguration() : self + public static function dueToConfiguration(): self { return new self('Stream is not seekable'); } - public static function dueToMissingResource() : self + public static function dueToMissingResource(): self { return new self('No resource available; cannot seek position'); } - public static function dueToPhpError() : self + public static function dueToPhpError(): self { return new self('Error seeking within stream'); } - public static function forCallbackStream() : self + public static function forCallbackStream(): self { return new self('Callback streams cannot seek position'); } diff --git a/src/Exception/UntellableStreamException.php b/src/Exception/UntellableStreamException.php index ec1e9239..c66fd25a 100644 --- a/src/Exception/UntellableStreamException.php +++ b/src/Exception/UntellableStreamException.php @@ -8,17 +8,17 @@ class UntellableStreamException extends RuntimeException implements ExceptionInterface { - public static function dueToMissingResource() : self + public static function dueToMissingResource(): self { return new self('No resource available; cannot tell position'); } - public static function dueToPhpError() : self + public static function dueToPhpError(): self { return new self('Error occurred during tell operation'); } - public static function forCallbackStream() : self + public static function forCallbackStream(): self { return new self('Callback streams cannot tell position'); } diff --git a/src/Exception/UnwritableStreamException.php b/src/Exception/UnwritableStreamException.php index 30fbfdf3..13b7e376 100644 --- a/src/Exception/UnwritableStreamException.php +++ b/src/Exception/UnwritableStreamException.php @@ -8,22 +8,22 @@ class UnwritableStreamException extends RuntimeException implements ExceptionInterface { - public static function dueToConfiguration() : self + public static function dueToConfiguration(): self { return new self('Stream is not writable'); } - public static function dueToMissingResource() : self + public static function dueToMissingResource(): self { return new self('No resource available; cannot write'); } - public static function dueToPhpError() : self + public static function dueToPhpError(): self { return new self('Error writing to stream'); } - public static function forCallbackStream() : self + public static function forCallbackStream(): self { return new self('Callback streams cannot write'); } diff --git a/src/Exception/UploadedFileAlreadyMovedException.php b/src/Exception/UploadedFileAlreadyMovedException.php index 8571597a..9025c1cb 100644 --- a/src/Exception/UploadedFileAlreadyMovedException.php +++ b/src/Exception/UploadedFileAlreadyMovedException.php @@ -9,10 +9,11 @@ class UploadedFileAlreadyMovedException extends RuntimeException implements ExceptionInterface { + /** @param int $code */ public function __construct( string $message = 'Cannot retrieve stream after it has already moved', $code = 0, - Throwable $previous = null + ?Throwable $previous = null ) { parent::__construct($message, $code, $previous); } diff --git a/src/Exception/UploadedFileErrorException.php b/src/Exception/UploadedFileErrorException.php index a12e95ab..7c416132 100644 --- a/src/Exception/UploadedFileErrorException.php +++ b/src/Exception/UploadedFileErrorException.php @@ -10,12 +10,12 @@ class UploadedFileErrorException extends RuntimeException implements ExceptionInterface { - public static function forUnmovableFile() : self + public static function forUnmovableFile(): self { return new self('Error occurred while moving uploaded file'); } - public static function dueToStreamUploadError(string $error) : self + public static function dueToStreamUploadError(string $error): self { return new self(sprintf( 'Cannot retrieve stream due to upload error: %s', @@ -23,12 +23,12 @@ public static function dueToStreamUploadError(string $error) : self )); } - public static function dueToUnwritablePath() : self + public static function dueToUnwritablePath(): self { return new self('Unable to write to designated path'); } - public static function dueToUnwritableTarget(string $targetDirectory) : self + public static function dueToUnwritableTarget(string $targetDirectory): self { return new self(sprintf( 'The target directory `%s` does not exist or is not writable', diff --git a/src/HeaderSecurity.php b/src/HeaderSecurity.php index 2fedc61f..69a25254 100644 --- a/src/HeaderSecurity.php +++ b/src/HeaderSecurity.php @@ -17,17 +17,12 @@ /** * Provide security tools around HTTP headers to prevent common injection vectors. - * - * Code is largely lifted from the Laminas\Http\Header\HeaderValue implementation in - * Laminas, released with the copyright and license below. - * - * @copyright Copyright (c) 2005-2015 Laminas (https://www.zend.com) - * @license https://getlaminas.org/license/new-bsd New BSD License */ final class HeaderSecurity { /** * Private constructor; non-instantiable. + * * @codeCoverageIgnore */ private function __construct() @@ -48,7 +43,7 @@ private function __construct() * * @see http://en.wikipedia.org/wiki/HTTP_response_splitting */ - public static function filter(string $value) : string + public static function filter(string $value): string { $length = strlen($value); $string = ''; @@ -61,7 +56,7 @@ public static function filter(string $value) : string $ws = ord($value[$i + 2]); if ($lf === 10 && in_array($ws, [9, 32], true)) { $string .= $value[$i] . $value[$i + 1]; - $i += 1; + $i += 1; } continue; @@ -72,7 +67,8 @@ public static function filter(string $value) : string // 32-126, 128-254 === visible // 127 === DEL // 255 === null byte - if (($ascii < 32 && $ascii !== 9) + if ( + ($ascii < 32 && $ascii !== 9) || $ascii === 127 || $ascii > 254 ) { @@ -92,12 +88,13 @@ public static function filter(string $value) : string * tabs are allowed in values; header continuations MUST consist of * a single CRLF sequence followed by a space or horizontal tab. * - * @param string|int|float $value * @see http://en.wikipedia.org/wiki/HTTP_response_splitting + * + * @param string|int|float $value */ - public static function isValid($value) : bool + public static function isValid($value): bool { - $value = (string) $value; + $value = (string) $value; // Look for: // \n not preceded by \r, OR @@ -125,14 +122,14 @@ public static function isValid($value) : bool * Assert a header value is valid. * * @param mixed $value Value to be tested. This method asserts it is a string or number. - * @throws Exception\InvalidArgumentException for invalid values + * @throws Exception\InvalidArgumentException For invalid values. */ - public static function assertValid($value) : void + public static function assertValid($value): void { if (! is_string($value) && ! is_numeric($value)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid header value type; must be a string or numeric; received %s', - (is_object($value) ? get_class($value) : gettype($value)) + is_object($value) ? get_class($value) : gettype($value) )); } if (! self::isValid($value)) { @@ -147,15 +144,16 @@ public static function assertValid($value) : void * Assert whether or not a header name is valid. * * @see http://tools.ietf.org/html/rfc7230#section-3.2 + * * @param mixed $name * @throws Exception\InvalidArgumentException */ - public static function assertValidName($name) : void + public static function assertValidName($name): void { if (! is_string($name)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid header name type; expected string; received %s', - (is_object($name) ? get_class($name) : gettype($name)) + is_object($name) ? get_class($name) : gettype($name) )); } if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/', $name)) { diff --git a/src/MessageTrait.php b/src/MessageTrait.php index b80599bc..dac56ea8 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -9,6 +9,7 @@ use function array_map; use function array_merge; +use function array_values; use function get_class; use function gettype; use function implode; @@ -33,7 +34,6 @@ trait MessageTrait * List of all registered headers, as key => array of values. * * @var array - * * @psalm-var array> */ protected $headers = []; @@ -42,19 +42,14 @@ trait MessageTrait * Map of normalized header name to original name used to register header. * * @var array - * * @psalm-var array */ protected $headerNames = []; - /** - * @var string - */ + /** @var string */ private $protocol = '1.1'; - /** - * @var StreamInterface - */ + /** @var StreamInterface */ private $stream; /** @@ -64,7 +59,7 @@ trait MessageTrait * * @return string HTTP protocol version. */ - public function getProtocolVersion() : string + public function getProtocolVersion(): string { return $this->protocol; } @@ -82,10 +77,10 @@ public function getProtocolVersion() : string * @param string $version HTTP protocol version * @return static */ - public function withProtocolVersion($version) : MessageInterface + public function withProtocolVersion($version): MessageInterface { $this->validateProtocolVersion($version); - $new = clone $this; + $new = clone $this; $new->protocol = $version; return $new; } @@ -110,10 +105,9 @@ public function withProtocolVersion($version) : MessageInterface * * @return array Returns an associative array of the message's headers. Each * key MUST be a header name, and each value MUST be an array of strings. - * * @psalm-return array> */ - public function getHeaders() : array + public function getHeaders(): array { return $this->headers; } @@ -126,7 +120,7 @@ public function getHeaders() : array * name using a case-insensitive string comparison. Returns false if * no matching header name is found in the message. */ - public function hasHeader($header) : bool + public function hasHeader($header): bool { return isset($this->headerNames[strtolower($header)]); } @@ -145,7 +139,7 @@ public function hasHeader($header) : bool * header. If the header does not appear in the message, this method MUST * return an empty array. */ - public function getHeader($header) : array + public function getHeader($header): array { if (! $this->hasHeader($header)) { return []; @@ -175,7 +169,7 @@ public function getHeader($header) : array * concatenated together using a comma. If the header does not appear in * the message, this method MUST return an empty string. */ - public function getHeaderLine($name) : string + public function getHeaderLine($name): string { $value = $this->getHeader($name); if (empty($value)) { @@ -199,9 +193,9 @@ public function getHeaderLine($name) : string * @param string $name Case-insensitive header field name. * @param string|string[] $value Header value(s). * @return static - * @throws Exception\InvalidArgumentException for invalid header names or values. + * @throws Exception\InvalidArgumentException For invalid header names or values. */ - public function withHeader($name, $value) : MessageInterface + public function withHeader($name, $value): MessageInterface { $this->assertHeader($name); @@ -235,9 +229,9 @@ public function withHeader($name, $value) : MessageInterface * @param string $name Case-insensitive header field name to add. * @param string|string[] $value Header value(s). * @return static - * @throws Exception\InvalidArgumentException for invalid header names or values. + * @throws Exception\InvalidArgumentException For invalid header names or values. */ - public function withAddedHeader($name, $value) : MessageInterface + public function withAddedHeader($name, $value): MessageInterface { $this->assertHeader($name); @@ -247,8 +241,8 @@ public function withAddedHeader($name, $value) : MessageInterface $header = $this->headerNames[strtolower($name)]; - $new = clone $this; - $value = $this->filterHeaderValue($value); + $new = clone $this; + $value = $this->filterHeaderValue($value); $new->headers[$header] = array_merge($this->headers[$header], $value); return $new; } @@ -265,7 +259,7 @@ public function withAddedHeader($name, $value) : MessageInterface * @param string $name Case-insensitive header field name to remove. * @return static */ - public function withoutHeader($name) : MessageInterface + public function withoutHeader($name): MessageInterface { if (! is_string($name) || $name === '' || ! $this->hasHeader($name)) { return clone $this; @@ -284,7 +278,7 @@ public function withoutHeader($name) : MessageInterface * * @return StreamInterface Returns the body as a stream. */ - public function getBody() : StreamInterface + public function getBody(): StreamInterface { return $this->stream; } @@ -302,14 +296,17 @@ public function getBody() : StreamInterface * @return static * @throws Exception\InvalidArgumentException When the body is not valid. */ - public function withBody(StreamInterface $body) : MessageInterface + public function withBody(StreamInterface $body): MessageInterface { - $new = clone $this; + $new = clone $this; $new->stream = $body; return $new; } - private function getStream($stream, string $modeIfNotInstance) : StreamInterface + /** + * @param StreamInterface|string|resource $stream + */ + private function getStream($stream, string $modeIfNotInstance): StreamInterface { if ($stream instanceof StreamInterface) { return $stream; @@ -333,7 +330,7 @@ private function getStream($stream, string $modeIfNotInstance) : StreamInterface * * @param array $originalHeaders Headers to filter. */ - private function setHeaders(array $originalHeaders) : void + private function setHeaders(array $originalHeaders): void { $headerNames = $headers = []; @@ -343,20 +340,20 @@ private function setHeaders(array $originalHeaders) : void $this->assertHeader($header); $headerNames[strtolower($header)] = $header; - $headers[$header] = $value; + $headers[$header] = $value; } $this->headerNames = $headerNames; - $this->headers = $headers; + $this->headers = $headers; } /** * Validate the HTTP protocol version * * @param string $version - * @throws Exception\InvalidArgumentException on invalid HTTP protocol version + * @throws Exception\InvalidArgumentException On invalid HTTP protocol version. */ - private function validateProtocolVersion($version) : void + private function validateProtocolVersion($version): void { if (empty($version)) { throw new Exception\InvalidArgumentException( @@ -366,7 +363,7 @@ private function validateProtocolVersion($version) : void if (! is_string($version)) { throw new Exception\InvalidArgumentException(sprintf( 'Unsupported HTTP protocol version; must be a string, received %s', - (is_object($version) ? get_class($version) : gettype($version)) + is_object($version) ? get_class($version) : gettype($version) )); } @@ -384,7 +381,7 @@ private function validateProtocolVersion($version) : void * @param mixed $values * @return string[] */ - private function filterHeaderValue($values) : array + private function filterHeaderValue($values): array { if (! is_array($values)) { $values = [$values]; @@ -400,7 +397,7 @@ private function filterHeaderValue($values) : array return array_map(function ($value) { HeaderSecurity::assertValid($value); - $value = (string)$value; + $value = (string) $value; // Normalize line folding to a single space (RFC 7230#3.2.4). $value = str_replace(["\r\n\t", "\r\n "], ' ', $value); @@ -414,10 +411,9 @@ private function filterHeaderValue($values) : array * Ensure header name and values are valid. * * @param string $name - * * @throws Exception\InvalidArgumentException */ - private function assertHeader($name) : void + private function assertHeader($name): void { HeaderSecurity::assertValidName($name); } diff --git a/src/PhpInputStream.php b/src/PhpInputStream.php index 876f91f4..47a94b9e 100644 --- a/src/PhpInputStream.php +++ b/src/PhpInputStream.php @@ -11,14 +11,10 @@ */ class PhpInputStream extends Stream { - /** - * @var string - */ + /** @var string */ private $cache = ''; - /** - * @var bool - */ + /** @var bool */ private $reachedEof = false; /** @@ -32,7 +28,7 @@ public function __construct($stream = 'php://input') /** * {@inheritdoc} */ - public function __toString() : string + public function __toString(): string { if ($this->reachedEof) { return $this->cache; @@ -45,7 +41,7 @@ public function __toString() : string /** * {@inheritdoc} */ - public function isWritable() : bool + public function isWritable(): bool { return false; } @@ -53,7 +49,7 @@ public function isWritable() : bool /** * {@inheritdoc} */ - public function read($length) : string + public function read($length): string { $content = parent::read($length); if (! $this->reachedEof) { @@ -70,7 +66,7 @@ public function read($length) : string /** * {@inheritdoc} */ - public function getContents($maxLength = -1) : string + public function getContents($maxLength = -1): string { if ($this->reachedEof) { return $this->cache; diff --git a/src/RelativeStream.php b/src/RelativeStream.php index 993a266d..3f91e285 100644 --- a/src/RelativeStream.php +++ b/src/RelativeStream.php @@ -9,40 +9,29 @@ use const SEEK_SET; /** - * Class RelativeStream - * * Wrapper for default Stream class, representing subpart (starting from given offset) of initial stream. * It can be used to avoid copying full stream, conserving memory. - * @example see Laminas\Diactoros\AbstractSerializer::splitStream() + * + * @see AbstractSerializer::splitStream() */ final class RelativeStream implements StreamInterface { - /** - * @var StreamInterface - */ + /** @var StreamInterface */ private $decoratedStream; - /** - * @var int - */ + /** @var int */ private $offset; - /** - * Class constructor - * - * @param StreamInterface $decoratedStream - * @param int $offset - */ public function __construct(StreamInterface $decoratedStream, ?int $offset) { $this->decoratedStream = $decoratedStream; - $this->offset = (int) $offset; + $this->offset = (int) $offset; } /** * {@inheritdoc} */ - public function __toString() : string + public function __toString(): string { if ($this->isSeekable()) { $this->seek(0); @@ -53,7 +42,7 @@ public function __toString() : string /** * {@inheritdoc} */ - public function close() : void + public function close(): void { $this->decoratedStream->close(); } @@ -69,7 +58,7 @@ public function detach() /** * {@inheritdoc} */ - public function getSize() : int + public function getSize(): int { return $this->decoratedStream->getSize() - $this->offset; } @@ -77,7 +66,7 @@ public function getSize() : int /** * {@inheritdoc} */ - public function tell() : int + public function tell(): int { return $this->decoratedStream->tell() - $this->offset; } @@ -85,7 +74,7 @@ public function tell() : int /** * {@inheritdoc} */ - public function eof() : bool + public function eof(): bool { return $this->decoratedStream->eof(); } @@ -93,7 +82,7 @@ public function eof() : bool /** * {@inheritdoc} */ - public function isSeekable() : bool + public function isSeekable(): bool { return $this->decoratedStream->isSeekable(); } @@ -101,9 +90,9 @@ public function isSeekable() : bool /** * {@inheritdoc} */ - public function seek($offset, $whence = SEEK_SET) : void + public function seek($offset, $whence = SEEK_SET): void { - if ($whence == SEEK_SET) { + if ($whence === SEEK_SET) { $this->decoratedStream->seek($offset + $this->offset, $whence); return; } @@ -113,7 +102,7 @@ public function seek($offset, $whence = SEEK_SET) : void /** * {@inheritdoc} */ - public function rewind() : void + public function rewind(): void { $this->seek(0); } @@ -121,7 +110,7 @@ public function rewind() : void /** * {@inheritdoc} */ - public function isWritable() : bool + public function isWritable(): bool { return $this->decoratedStream->isWritable(); } @@ -129,7 +118,7 @@ public function isWritable() : bool /** * {@inheritdoc} */ - public function write($string) : int + public function write($string): int { if ($this->tell() < 0) { throw new Exception\InvalidStreamPointerPositionException(); @@ -140,7 +129,7 @@ public function write($string) : int /** * {@inheritdoc} */ - public function isReadable() : bool + public function isReadable(): bool { return $this->decoratedStream->isReadable(); } @@ -148,7 +137,7 @@ public function isReadable() : bool /** * {@inheritdoc} */ - public function read($length) : string + public function read($length): string { if ($this->tell() < 0) { throw new Exception\InvalidStreamPointerPositionException(); @@ -159,7 +148,7 @@ public function read($length) : string /** * {@inheritdoc} */ - public function getContents() : string + public function getContents(): string { if ($this->tell() < 0) { throw new Exception\InvalidStreamPointerPositionException(); diff --git a/src/Request.php b/src/Request.php index 1805cdf7..504581c2 100644 --- a/src/Request.php +++ b/src/Request.php @@ -26,9 +26,9 @@ class Request implements RequestInterface * @param null|string $method HTTP method for the request, if any. * @param string|resource|StreamInterface $body Message body, if any. * @param array $headers Headers for the message, if any. - * @throws Exception\InvalidArgumentException for any invalid value. + * @throws Exception\InvalidArgumentException For any invalid value. */ - public function __construct($uri = null, string $method = null, $body = 'php://temp', array $headers = []) + public function __construct($uri = null, ?string $method = null, $body = 'php://temp', array $headers = []) { $this->initialize($uri, $method, $body, $headers); } @@ -36,10 +36,11 @@ public function __construct($uri = null, string $method = null, $body = 'php://t /** * {@inheritdoc} */ - public function getHeaders() : array + public function getHeaders(): array { $headers = $this->headers; - if (! $this->hasHeader('host') + if ( + ! $this->hasHeader('host') && $this->uri->getHost() ) { $headers['Host'] = [$this->getHostFromUri()]; @@ -51,10 +52,11 @@ public function getHeaders() : array /** * {@inheritdoc} */ - public function getHeader($name) : array + public function getHeader($name): array { if (empty($name) || ! $this->hasHeader($name)) { - if (strtolower($name) === 'host' + if ( + strtolower($name) === 'host' && $this->uri->getHost() ) { return [$this->getHostFromUri()]; diff --git a/src/Request/ArraySerializer.php b/src/Request/ArraySerializer.php index 92cfff34..884b7c2b 100644 --- a/src/Request/ArraySerializer.php +++ b/src/Request/ArraySerializer.php @@ -24,7 +24,7 @@ final class ArraySerializer /** * Serialize a request message to an array. */ - public static function toArray(RequestInterface $request) : array + public static function toArray(RequestInterface $request): array { return [ 'method' => $request->getMethod(), @@ -39,14 +39,14 @@ public static function toArray(RequestInterface $request) : array /** * Deserialize a request array to a request instance. * - * @throws Exception\DeserializationException when cannot deserialize response + * @throws Exception\DeserializationException When the response cannot be deserialized. */ - public static function fromArray(array $serializedRequest) : Request + public static function fromArray(array $serializedRequest): Request { try { - $uri = self::getValueFromKey($serializedRequest, 'uri'); - $method = self::getValueFromKey($serializedRequest, 'method'); - $body = new Stream('php://memory', 'wb+'); + $uri = self::getValueFromKey($serializedRequest, 'uri'); + $method = self::getValueFromKey($serializedRequest, 'method'); + $body = new Stream('php://memory', 'wb+'); $body->write(self::getValueFromKey($serializedRequest, 'body')); $headers = self::getValueFromKey($serializedRequest, 'headers'); $requestTarget = self::getValueFromKey($serializedRequest, 'request_target'); @@ -64,7 +64,7 @@ public static function fromArray(array $serializedRequest) : Request * @return mixed * @throws Exception\DeserializationException */ - private static function getValueFromKey(array $data, string $key, string $message = null) + private static function getValueFromKey(array $data, string $key, ?string $message = null) { if (isset($data[$key])) { return $data[$key]; diff --git a/src/Request/Serializer.php b/src/Request/Serializer.php index 3033be23..b6faf114 100644 --- a/src/Request/Serializer.php +++ b/src/Request/Serializer.php @@ -29,9 +29,9 @@ final class Serializer extends AbstractSerializer * * Internally, casts the message to a stream and invokes fromStream(). * - * @throws Exception\SerializationException when errors occur parsing the message. + * @throws Exception\SerializationException When errors occur parsing the message. */ - public static function fromString(string $message) : Request + public static function fromString(string $message): Request { $stream = new Stream('php://temp', 'wb+'); $stream->write($message); @@ -41,11 +41,10 @@ public static function fromString(string $message) : Request /** * Deserialize a request stream to a request instance. * - * @throws Exception\InvalidArgumentException if the message stream is not - * readable or seekable. - * @throws Exception\SerializationException if an invalid request line is detected. + * @throws Exception\InvalidArgumentException If the message stream is not readable or seekable. + * @throws Exception\SerializationException If an invalid request line is detected. */ - public static function fromStream(StreamInterface $stream) : Request + public static function fromStream(StreamInterface $stream): Request { if (! $stream->isReadable() || ! $stream->isSeekable()) { throw new Exception\InvalidArgumentException('Message stream must be both readable and seekable'); @@ -54,7 +53,7 @@ public static function fromStream(StreamInterface $stream) : Request $stream->rewind(); [$method, $requestTarget, $version] = self::getRequestLine($stream); - $uri = self::createUriFromRequestTarget($requestTarget); + $uri = self::createUriFromRequestTarget($requestTarget); [$headers, $body] = self::splitStream($stream); @@ -66,12 +65,12 @@ public static function fromStream(StreamInterface $stream) : Request /** * Serialize a request message to a string. */ - public static function toString(RequestInterface $request) : string + public static function toString(RequestInterface $request): string { $httpMethod = $request->getMethod(); - $headers = self::serializeHeaders($request->getHeaders()); - $body = (string) $request->getBody(); - $format = '%s %s HTTP/%s%s%s'; + $headers = self::serializeHeaders($request->getHeaders()); + $body = (string) $request->getBody(); + $format = '%s %s HTTP/%s%s%s'; if (! empty($headers)) { $headers = "\r\n" . $headers; @@ -99,15 +98,17 @@ public static function toString(RequestInterface $request) : string * * @throws Exception\SerializationException */ - private static function getRequestLine(StreamInterface $stream) : array + private static function getRequestLine(StreamInterface $stream): array { $requestLine = self::getLine($stream); - if (! preg_match( - '#^(?P[!\#$%&\'*+.^_`|~a-zA-Z0-9-]+) (?P[^\s]+) HTTP/(?P[1-9]\d*\.\d+)$#', - $requestLine, - $matches - )) { + if ( + ! preg_match( + '#^(?P[!\#$%&\'*+.^_`|~a-zA-Z0-9-]+) (?P[^\s]+) HTTP/(?P[1-9]\d*\.\d+)$#', + $requestLine, + $matches + ) + ) { throw Exception\SerializationException::forInvalidRequestLine(); } @@ -121,7 +122,7 @@ private static function getRequestLine(StreamInterface $stream) : array * instance is returned; otherwise, the value is used to create and return * a new Uri instance. */ - private static function createUriFromRequestTarget(string $requestTarget) : Uri + private static function createUriFromRequestTarget(string $requestTarget): Uri { if (preg_match('#^https?://#', $requestTarget)) { return new Uri($requestTarget); diff --git a/src/RequestFactory.php b/src/RequestFactory.php index 9a6d9a64..9632d277 100644 --- a/src/RequestFactory.php +++ b/src/RequestFactory.php @@ -12,7 +12,7 @@ class RequestFactory implements RequestFactoryInterface /** * {@inheritDoc} */ - public function createRequest(string $method, $uri) : RequestInterface + public function createRequest(string $method, $uri): RequestInterface { return new Request($uri, $method); } diff --git a/src/RequestTrait.php b/src/RequestTrait.php index d22617f6..dd4fe6f5 100644 --- a/src/RequestTrait.php +++ b/src/RequestTrait.php @@ -31,9 +31,7 @@ trait RequestTrait { use MessageTrait; - /** - * @var string - */ + /** @var string */ private $method = 'GET'; /** @@ -43,9 +41,7 @@ trait RequestTrait */ private $requestTarget; - /** - * @var UriInterface - */ + /** @var UriInterface */ private $uri; /** @@ -57,14 +53,14 @@ trait RequestTrait * @param null|string $method HTTP method for the request, if any. * @param string|resource|StreamInterface $body Message body, if any. * @param array $headers Headers for the message, if any. - * @throws Exception\InvalidArgumentException for any invalid value. + * @throws Exception\InvalidArgumentException For any invalid value. */ private function initialize( $uri = null, - string $method = null, + ?string $method = null, $body = 'php://memory', array $headers = [] - ) : void { + ): void { if ($method !== null) { $this->setMethod($method); } @@ -78,7 +74,7 @@ private function initialize( // Host header is provided if (! $this->hasHeader('Host') && $this->uri->getHost()) { $this->headerNames['host'] = 'Host'; - $this->headers['Host'] = [$this->getHostFromUri()]; + $this->headers['Host'] = [$this->getHostFromUri()]; } } @@ -97,7 +93,7 @@ private function initialize( * @param null|string|UriInterface $uri * @throws Exception\InvalidArgumentException */ - private function createUri($uri) : UriInterface + private function createUri($uri): UriInterface { if ($uri instanceof UriInterface) { return $uri; @@ -127,7 +123,7 @@ private function createUri($uri) : UriInterface * If no URI is available, and no request-target has been specifically * provided, this method MUST return the string "/". */ - public function getRequestTarget() : string + public function getRequestTarget(): string { if (null !== $this->requestTarget) { return $this->requestTarget; @@ -159,10 +155,11 @@ public function getRequestTarget() : string * * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various * request-target forms allowed in request messages) + * * @param string $requestTarget - * @throws Exception\InvalidArgumentException if the request target is invalid. + * @throws Exception\InvalidArgumentException If the request target is invalid. */ - public function withRequestTarget($requestTarget) : RequestInterface + public function withRequestTarget($requestTarget): RequestInterface { if (preg_match('#\s#', $requestTarget)) { throw new Exception\InvalidArgumentException( @@ -170,7 +167,7 @@ public function withRequestTarget($requestTarget) : RequestInterface ); } - $new = clone $this; + $new = clone $this; $new->requestTarget = $requestTarget; return $new; } @@ -180,7 +177,7 @@ public function withRequestTarget($requestTarget) : RequestInterface * * @return string Returns the request method. */ - public function getMethod() : string + public function getMethod(): string { return $this->method; } @@ -197,9 +194,9 @@ public function getMethod() : string * changed request method. * * @param string $method Case-insensitive method. - * @throws Exception\InvalidArgumentException for invalid HTTP methods. + * @throws Exception\InvalidArgumentException For invalid HTTP methods. */ - public function withMethod($method) : RequestInterface + public function withMethod($method): RequestInterface { $new = clone $this; $new->setMethod($method); @@ -212,10 +209,11 @@ public function withMethod($method) : RequestInterface * This method MUST return a UriInterface instance. * * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * * @return UriInterface Returns a UriInterface instance * representing the URI of the request, if any. */ - public function getUri() : UriInterface + public function getUri(): UriInterface { return $this->uri; } @@ -241,12 +239,13 @@ public function getUri() : UriInterface * new UriInterface instance. * * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * * @param UriInterface $uri New request URI to use. * @param bool $preserveHost Preserve the original state of the Host header. */ - public function withUri(UriInterface $uri, $preserveHost = false) : RequestInterface + public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface { - $new = clone $this; + $new = clone $this; $new->uri = $uri; if ($preserveHost && $this->hasHeader('Host')) { @@ -282,9 +281,9 @@ public function withUri(UriInterface $uri, $preserveHost = false) : RequestInter * Set and validate the HTTP method * * @param string $method - * @throws Exception\InvalidArgumentException on invalid HTTP method. + * @throws Exception\InvalidArgumentException On invalid HTTP method. */ - private function setMethod($method) : void + private function setMethod($method): void { if (! is_string($method)) { throw new Exception\InvalidArgumentException(sprintf( @@ -305,7 +304,7 @@ private function setMethod($method) : void /** * Retrieve the host from the URI instance */ - private function getHostFromUri() : string + private function getHostFromUri(): string { $host = $this->uri->getHost(); $host .= $this->uri->getPort() ? ':' . $this->uri->getPort() : ''; diff --git a/src/Response.php b/src/Response.php index e7235824..ef01e020 100644 --- a/src/Response.php +++ b/src/Response.php @@ -7,10 +7,13 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; +use function get_class; use function gettype; use function is_float; use function is_numeric; +use function is_object; use function is_scalar; +use function is_string; use function sprintf; /** @@ -31,7 +34,6 @@ class Response implements ResponseInterface * Map of standard HTTP status code/reason phrases * * @var array - * * @psalm-var array */ private $phrases = [ @@ -108,21 +110,17 @@ class Response implements ResponseInterface 599 => 'Network Connect Timeout Error', ]; - /** - * @var string - */ + /** @var string */ private $reasonPhrase; - /** - * @var int - */ + /** @var int */ private $statusCode; /** * @param string|resource|StreamInterface $body Stream identifier and/or actual stream resource * @param int $status Status code for the response, if any. * @param array $headers Headers for the response, if any. - * @throws Exception\InvalidArgumentException on any invalid element. + * @throws Exception\InvalidArgumentException On any invalid element. */ public function __construct($body = 'php://memory', int $status = 200, array $headers = []) { @@ -134,7 +132,7 @@ public function __construct($body = 'php://memory', int $status = 200, array $he /** * {@inheritdoc} */ - public function getStatusCode() : int + public function getStatusCode(): int { return $this->statusCode; } @@ -142,7 +140,7 @@ public function getStatusCode() : int /** * {@inheritdoc} */ - public function getReasonPhrase() : string + public function getReasonPhrase(): string { return $this->reasonPhrase; } @@ -150,7 +148,7 @@ public function getReasonPhrase() : string /** * {@inheritdoc} */ - public function withStatus($code, $reasonPhrase = '') : Response + public function withStatus($code, $reasonPhrase = ''): Response { $new = clone $this; $new->setStatusCode($code, $reasonPhrase); @@ -162,11 +160,12 @@ public function withStatus($code, $reasonPhrase = '') : Response * * @param int $code * @param string $reasonPhrase - * @throws Exception\InvalidArgumentException on an invalid status code. + * @throws Exception\InvalidArgumentException On an invalid status code. */ - private function setStatusCode($code, $reasonPhrase = '') : void + private function setStatusCode($code, $reasonPhrase = ''): void { - if (! is_numeric($code) + if ( + ! is_numeric($code) || is_float($code) || $code < static::MIN_STATUS_CODE_VALUE || $code > static::MAX_STATUS_CODE_VALUE @@ -191,6 +190,6 @@ private function setStatusCode($code, $reasonPhrase = '') : void } $this->reasonPhrase = $reasonPhrase; - $this->statusCode = (int) $code; + $this->statusCode = (int) $code; } } diff --git a/src/Response/ArraySerializer.php b/src/Response/ArraySerializer.php index 462458dc..6667d017 100644 --- a/src/Response/ArraySerializer.php +++ b/src/Response/ArraySerializer.php @@ -24,7 +24,7 @@ final class ArraySerializer /** * Serialize a response message to an array. */ - public static function toArray(ResponseInterface $response) : array + public static function toArray(ResponseInterface $response): array { return [ 'status_code' => $response->getStatusCode(), @@ -38,9 +38,9 @@ public static function toArray(ResponseInterface $response) : array /** * Deserialize a response array to a response instance. * - * @throws Exception\DeserializationException when cannot deserialize response + * @throws Exception\DeserializationException When cannot deserialize response. */ - public static function fromArray(array $serializedResponse) : Response + public static function fromArray(array $serializedResponse): Response { try { $body = new Stream('php://memory', 'wb+'); @@ -61,12 +61,10 @@ public static function fromArray(array $serializedResponse) : Response /** * @param array $data - * @param string $key - * @param string $message * @return mixed * @throws Exception\DeserializationException */ - private static function getValueFromKey(array $data, string $key, string $message = null) + private static function getValueFromKey(array $data, string $key, ?string $message = null) { if (isset($data[$key])) { return $data[$key]; diff --git a/src/Response/EmptyResponse.php b/src/Response/EmptyResponse.php index 7f082ba3..82140e81 100644 --- a/src/Response/EmptyResponse.php +++ b/src/Response/EmptyResponse.php @@ -28,9 +28,8 @@ public function __construct(int $status = 204, array $headers = []) * Create an empty response with the given headers. * * @param array $headers Headers for the response. - * @return EmptyResponse */ - public static function withHeaders(array $headers) : EmptyResponse + public static function withHeaders(array $headers): EmptyResponse { return new static(204, $headers); } diff --git a/src/Response/HtmlResponse.php b/src/Response/HtmlResponse.php index e7527a3a..298b87c3 100644 --- a/src/Response/HtmlResponse.php +++ b/src/Response/HtmlResponse.php @@ -35,7 +35,7 @@ class HtmlResponse extends Response * @param string|StreamInterface $html HTML or stream for the message body. * @param int $status Integer status code for the response; 200 by default. * @param array $headers Array of headers to use at initialization. - * @throws Exception\InvalidArgumentException if $html is neither a string or stream. + * @throws Exception\InvalidArgumentException If $html is neither a string or stream. */ public function __construct($html, int $status = 200, array $headers = []) { @@ -50,9 +50,9 @@ public function __construct($html, int $status = 200, array $headers = []) * Create the message body. * * @param string|StreamInterface $html - * @throws Exception\InvalidArgumentException if $html is neither a string or stream. + * @throws Exception\InvalidArgumentException If $html is neither a string or stream. */ - private function createBody($html) : StreamInterface + private function createBody($html): StreamInterface { if ($html instanceof StreamInterface) { return $html; @@ -61,8 +61,8 @@ private function createBody($html) : StreamInterface if (! is_string($html)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid content (%s) provided to %s', - (is_object($html) ? get_class($html) : gettype($html)), - __CLASS__ + is_object($html) ? get_class($html) : gettype($html), + self::class )); } diff --git a/src/Response/InjectContentTypeTrait.php b/src/Response/InjectContentTypeTrait.php index 0a955866..c6de0b4c 100644 --- a/src/Response/InjectContentTypeTrait.php +++ b/src/Response/InjectContentTypeTrait.php @@ -15,10 +15,10 @@ trait InjectContentTypeTrait * * @return array Headers with injected Content-Type */ - private function injectContentType(string $contentType, array $headers) : array + private function injectContentType(string $contentType, array $headers): array { $hasContentType = array_reduce(array_keys($headers), function ($carry, $item) { - return $carry ?: (strtolower($item) === 'content-type'); + return $carry ?: strtolower($item) === 'content-type'; }, false); if (! $hasContentType) { diff --git a/src/Response/JsonResponse.php b/src/Response/JsonResponse.php index 84baa959..91c79e5c 100644 --- a/src/Response/JsonResponse.php +++ b/src/Response/JsonResponse.php @@ -44,14 +44,10 @@ class JsonResponse extends Response | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES; - /** - * @var mixed - */ + /** @var mixed */ private $payload; - /** - * @var int - */ + /** @var int */ private $encodingOptions; /** @@ -70,7 +66,7 @@ class JsonResponse extends Response * @param int $status Integer status code for the response; 200 by default. * @param array $headers Array of headers to use at initialization. * @param int $encodingOptions JSON encoding options to use. - * @throws Exception\InvalidArgumentException if unable to encode the $data to JSON. + * @throws Exception\InvalidArgumentException If unable to encode the $data to JSON. */ public function __construct( $data, @@ -100,26 +96,26 @@ public function getPayload() /** * @param mixed $data */ - public function withPayload($data) : JsonResponse + public function withPayload($data): JsonResponse { $new = clone $this; $new->setPayload($data); return $this->updateBodyFor($new); } - public function getEncodingOptions() : int + public function getEncodingOptions(): int { return $this->encodingOptions; } - public function withEncodingOptions(int $encodingOptions) : JsonResponse + public function withEncodingOptions(int $encodingOptions): JsonResponse { - $new = clone $this; + $new = clone $this; $new->encodingOptions = $encodingOptions; return $this->updateBodyFor($new); } - private function createBodyFromJson(string $json) : Stream + private function createBodyFromJson(string $json): Stream { $body = new Stream('php://temp', 'wb+'); $body->write($json); @@ -132,9 +128,9 @@ private function createBodyFromJson(string $json) : Stream * Encode the provided data to JSON. * * @param mixed $data - * @throws Exception\InvalidArgumentException if unable to encode the $data to JSON. + * @throws Exception\InvalidArgumentException If unable to encode the $data to JSON. */ - private function jsonEncode($data, int $encodingOptions) : string + private function jsonEncode($data, int $encodingOptions): string { if (is_resource($data)) { throw new Exception\InvalidArgumentException('Cannot JSON encode resources'); @@ -148,7 +144,7 @@ private function jsonEncode($data, int $encodingOptions) : string if (JSON_ERROR_NONE !== json_last_error()) { throw new Exception\InvalidArgumentException(sprintf( 'Unable to encode data to JSON in %s: %s', - __CLASS__, + self::class, json_last_error_msg() )); } @@ -159,7 +155,7 @@ private function jsonEncode($data, int $encodingOptions) : string /** * @param mixed $data */ - private function setPayload($data) : void + private function setPayload($data): void { if (is_object($data)) { $data = clone $data; @@ -174,7 +170,7 @@ private function setPayload($data) : void * @param self $toUpdate Instance to update. * @return JsonResponse Returns a new instance with an updated body. */ - private function updateBodyFor(JsonResponse $toUpdate) : JsonResponse + private function updateBodyFor(JsonResponse $toUpdate): JsonResponse { $json = $this->jsonEncode($toUpdate->payload, $toUpdate->encodingOptions); $body = $this->createBodyFromJson($json); diff --git a/src/Response/RedirectResponse.php b/src/Response/RedirectResponse.php index 9aa784f4..e2ec04e2 100644 --- a/src/Response/RedirectResponse.php +++ b/src/Response/RedirectResponse.php @@ -36,7 +36,7 @@ public function __construct($uri, int $status = 302, array $headers = []) if (! is_string($uri) && ! $uri instanceof UriInterface) { throw new Exception\InvalidArgumentException(sprintf( 'Uri provided to %s MUST be a string or Psr\Http\Message\UriInterface instance; received "%s"', - __CLASS__, + self::class, is_object($uri) ? get_class($uri) : gettype($uri) )); } diff --git a/src/Response/Serializer.php b/src/Response/Serializer.php index ed56c180..01cceef0 100644 --- a/src/Response/Serializer.php +++ b/src/Response/Serializer.php @@ -19,9 +19,9 @@ final class Serializer extends AbstractSerializer /** * Deserialize a response string to a response instance. * - * @throws Exception\SerializationException when errors occur parsing the message. + * @throws Exception\SerializationException When errors occur parsing the message. */ - public static function fromString(string $message) : Response + public static function fromString(string $message): Response { $stream = new Stream('php://temp', 'wb+'); $stream->write($message); @@ -31,10 +31,10 @@ public static function fromString(string $message) : Response /** * Parse a response from a stream. * - * @throws Exception\InvalidArgumentException when the stream is not readable. - * @throws Exception\SerializationException when errors occur parsing the message. + * @throws Exception\InvalidArgumentException When the stream is not readable. + * @throws Exception\SerializationException When errors occur parsing the message. */ - public static function fromStream(StreamInterface $stream) : Response + public static function fromStream(StreamInterface $stream): Response { if (! $stream->isReadable() || ! $stream->isSeekable()) { throw new Exception\InvalidArgumentException('Message stream must be both readable and seekable'); @@ -53,7 +53,7 @@ public static function fromStream(StreamInterface $stream) : Response /** * Create a string representation of a response. */ - public static function toString(ResponseInterface $response) : string + public static function toString(ResponseInterface $response): string { $reasonPhrase = $response->getReasonPhrase(); $headers = self::serializeHeaders($response->getHeaders()); @@ -70,7 +70,7 @@ public static function toString(ResponseInterface $response) : string $format, $response->getProtocolVersion(), $response->getStatusCode(), - ($reasonPhrase ? ' ' . $reasonPhrase : ''), + $reasonPhrase ? ' ' . $reasonPhrase : '', $headers, $body ); @@ -80,17 +80,19 @@ public static function toString(ResponseInterface $response) : string * Retrieve the status line for the message. * * @return array Array with three elements: 0 => version, 1 => status, 2 => reason - * @throws Exception\SerializationException if line is malformed + * @throws Exception\SerializationException If line is malformed. */ - private static function getStatusLine(StreamInterface $stream) : array + private static function getStatusLine(StreamInterface $stream): array { $line = self::getLine($stream); - if (! preg_match( - '#^HTTP/(?P[1-9]\d*\.\d) (?P[1-5]\d{2})(\s+(?P.+))?$#', - $line, - $matches - )) { + if ( + ! preg_match( + '#^HTTP/(?P[1-9]\d*\.\d) (?P[1-5]\d{2})(\s+(?P.+))?$#', + $line, + $matches + ) + ) { throw Exception\SerializationException::forInvalidStatusLine(); } diff --git a/src/Response/TextResponse.php b/src/Response/TextResponse.php index c2120a4c..65ee3e08 100644 --- a/src/Response/TextResponse.php +++ b/src/Response/TextResponse.php @@ -35,7 +35,7 @@ class TextResponse extends Response * @param string|StreamInterface $text String or stream for the message body. * @param int $status Integer status code for the response; 200 by default. * @param array $headers Array of headers to use at initialization. - * @throws Exception\InvalidArgumentException if $text is neither a string or stream. + * @throws Exception\InvalidArgumentException If $text is neither a string or stream. */ public function __construct($text, int $status = 200, array $headers = []) { @@ -50,9 +50,9 @@ public function __construct($text, int $status = 200, array $headers = []) * Create the message body. * * @param string|StreamInterface $text - * @throws Exception\InvalidArgumentException if $text is neither a string or stream. + * @throws Exception\InvalidArgumentException If $text is neither a string or stream. */ - private function createBody($text) : StreamInterface + private function createBody($text): StreamInterface { if ($text instanceof StreamInterface) { return $text; @@ -61,8 +61,8 @@ private function createBody($text) : StreamInterface if (! is_string($text)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid content (%s) provided to %s', - (is_object($text) ? get_class($text) : gettype($text)), - __CLASS__ + is_object($text) ? get_class($text) : gettype($text), + self::class )); } diff --git a/src/Response/XmlResponse.php b/src/Response/XmlResponse.php index 0c445598..f0cb0bac 100644 --- a/src/Response/XmlResponse.php +++ b/src/Response/XmlResponse.php @@ -34,7 +34,7 @@ class XmlResponse extends Response * @param string|StreamInterface $xml String or stream for the message body. * @param int $status Integer status code for the response; 200 by default. * @param array $headers Array of headers to use at initialization. - * @throws Exception\InvalidArgumentException if $text is neither a string or stream. + * @throws Exception\InvalidArgumentException If $text is neither a string or stream. */ public function __construct( $xml, @@ -52,9 +52,9 @@ public function __construct( * Create the message body. * * @param string|StreamInterface $xml - * @throws Exception\InvalidArgumentException if $xml is neither a string or stream. + * @throws Exception\InvalidArgumentException If $xml is neither a string or stream. */ - private function createBody($xml) : StreamInterface + private function createBody($xml): StreamInterface { if ($xml instanceof StreamInterface) { return $xml; @@ -63,8 +63,8 @@ private function createBody($xml) : StreamInterface if (! is_string($xml)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid content (%s) provided to %s', - (is_object($xml) ? get_class($xml) : gettype($xml)), - __CLASS__ + is_object($xml) ? get_class($xml) : gettype($xml), + self::class )); } diff --git a/src/ResponseFactory.php b/src/ResponseFactory.php index 2c0060f7..b605d2db 100644 --- a/src/ResponseFactory.php +++ b/src/ResponseFactory.php @@ -12,7 +12,7 @@ class ResponseFactory implements ResponseFactoryInterface /** * {@inheritDoc} */ - public function createResponse(int $code = 200, string $reasonPhrase = '') : ResponseInterface + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface { return (new Response()) ->withStatus($code, $reasonPhrase); diff --git a/src/ServerRequest.php b/src/ServerRequest.php index 313fc055..7e67f000 100644 --- a/src/ServerRequest.php +++ b/src/ServerRequest.php @@ -10,7 +10,10 @@ use Psr\Http\Message\UriInterface; use function array_key_exists; +use function gettype; use function is_array; +use function is_object; +use function sprintf; /** * Server-side HTTP request @@ -30,34 +33,22 @@ class ServerRequest implements ServerRequestInterface { use RequestTrait; - /** - * @var array - */ + /** @var array */ private $attributes = []; - /** - * @var array - */ + /** @var array */ private $cookieParams = []; - /** - * @var null|array|object - */ + /** @var null|array|object */ private $parsedBody; - /** - * @var array - */ + /** @var array */ private $queryParams = []; - /** - * @var array - */ + /** @var array */ private $serverParams; - /** - * @var array - */ + /** @var array */ private $uploadedFiles; /** @@ -71,13 +62,13 @@ class ServerRequest implements ServerRequestInterface * @param array $queryParams Query params for the message, if any. * @param null|array|object $parsedBody The deserialized body parameters, if any. * @param string $protocol HTTP protocol version. - * @throws Exception\InvalidArgumentException for any invalid value. + * @throws Exception\InvalidArgumentException For any invalid value. */ public function __construct( array $serverParams = [], array $uploadedFiles = [], $uri = null, - string $method = null, + ?string $method = null, $body = 'php://input', array $headers = [], array $cookies = [], @@ -103,7 +94,7 @@ public function __construct( /** * {@inheritdoc} */ - public function getServerParams() : array + public function getServerParams(): array { return $this->serverParams; } @@ -111,7 +102,7 @@ public function getServerParams() : array /** * {@inheritdoc} */ - public function getUploadedFiles() : array + public function getUploadedFiles(): array { return $this->uploadedFiles; } @@ -119,10 +110,10 @@ public function getUploadedFiles() : array /** * {@inheritdoc} */ - public function withUploadedFiles(array $uploadedFiles) : ServerRequest + public function withUploadedFiles(array $uploadedFiles): ServerRequest { $this->validateUploadedFiles($uploadedFiles); - $new = clone $this; + $new = clone $this; $new->uploadedFiles = $uploadedFiles; return $new; } @@ -130,7 +121,7 @@ public function withUploadedFiles(array $uploadedFiles) : ServerRequest /** * {@inheritdoc} */ - public function getCookieParams() : array + public function getCookieParams(): array { return $this->cookieParams; } @@ -138,9 +129,9 @@ public function getCookieParams() : array /** * {@inheritdoc} */ - public function withCookieParams(array $cookies) : ServerRequest + public function withCookieParams(array $cookies): ServerRequest { - $new = clone $this; + $new = clone $this; $new->cookieParams = $cookies; return $new; } @@ -148,7 +139,7 @@ public function withCookieParams(array $cookies) : ServerRequest /** * {@inheritdoc} */ - public function getQueryParams() : array + public function getQueryParams(): array { return $this->queryParams; } @@ -156,9 +147,9 @@ public function getQueryParams() : array /** * {@inheritdoc} */ - public function withQueryParams(array $query) : ServerRequest + public function withQueryParams(array $query): ServerRequest { - $new = clone $this; + $new = clone $this; $new->queryParams = $query; return $new; } @@ -174,7 +165,7 @@ public function getParsedBody() /** * {@inheritdoc} */ - public function withParsedBody($data) : ServerRequest + public function withParsedBody($data): ServerRequest { if (! is_array($data) && ! is_object($data) && null !== $data) { throw new Exception\InvalidArgumentException(sprintf( @@ -184,7 +175,7 @@ public function withParsedBody($data) : ServerRequest )); } - $new = clone $this; + $new = clone $this; $new->parsedBody = $data; return $new; } @@ -192,7 +183,7 @@ public function withParsedBody($data) : ServerRequest /** * {@inheritdoc} */ - public function getAttributes() : array + public function getAttributes(): array { return $this->attributes; } @@ -212,9 +203,9 @@ public function getAttribute($attribute, $default = null) /** * {@inheritdoc} */ - public function withAttribute($attribute, $value) : ServerRequest + public function withAttribute($attribute, $value): ServerRequest { - $new = clone $this; + $new = clone $this; $new->attributes[$attribute] = $value; return $new; } @@ -222,7 +213,7 @@ public function withAttribute($attribute, $value) : ServerRequest /** * {@inheritdoc} */ - public function withoutAttribute($name) : ServerRequest + public function withoutAttribute($name): ServerRequest { $new = clone $this; unset($new->attributes[$name]); @@ -232,9 +223,9 @@ public function withoutAttribute($name) : ServerRequest /** * Recursively validate the structure in an uploaded files array. * - * @throws Exception\InvalidArgumentException if any leaf is not an UploadedFileInterface instance. + * @throws Exception\InvalidArgumentException If any leaf is not an UploadedFileInterface instance. */ - private function validateUploadedFiles(array $uploadedFiles) : void + private function validateUploadedFiles(array $uploadedFiles): void { foreach ($uploadedFiles as $file) { if (is_array($file)) { diff --git a/src/ServerRequestFactory.php b/src/ServerRequestFactory.php index 506970d9..4d74bf3c 100644 --- a/src/ServerRequestFactory.php +++ b/src/ServerRequestFactory.php @@ -9,16 +9,29 @@ use Psr\Http\Message\ServerRequestFactoryInterface; use Psr\Http\Message\ServerRequestInterface; +use function array_change_key_case; use function array_key_exists; +use function explode; +use function gettype; +use function implode; +use function is_array; +use function is_bool; use function is_callable; +use function is_string; +use function ltrim; +use function preg_match; +use function preg_replace; +use function sprintf; +use function strlen; +use function strpos; +use function strrpos; +use function strtolower; +use function substr; + +use const CASE_LOWER; /** * Class for marshaling a request object from the current PHP environment. - * - * Logic largely refactored from the Laminas Laminas\Http\PhpEnvironment\Request class. - * - * @copyright Copyright (c) 2005-2015 Laminas (https://www.zend.com) - * @license https://getlaminas.org/license/new-bsd New BSD License */ class ServerRequestFactory implements ServerRequestFactoryInterface { @@ -39,6 +52,7 @@ class ServerRequestFactory implements ServerRequestFactoryInterface * order to marshal the request URI and headers. * * @see fromServer() + * * @param array $server $_SERVER superglobal * @param array $query $_GET superglobal * @param array $body $_POST superglobal @@ -49,19 +63,18 @@ class ServerRequestFactory implements ServerRequestFactoryInterface * returned by this method. When not present, a default instance of * FilterUsingXForwardedHeaders is created, using the `trustReservedSubnets()` * constructor. - * @return ServerRequest */ public static function fromGlobals( - array $server = null, - array $query = null, - array $body = null, - array $cookies = null, - array $files = null, + ?array $server = null, + ?array $query = null, + ?array $body = null, + ?array $cookies = null, + ?array $files = null, ?FilterServerRequestInterface $requestFilter = null - ) : ServerRequest { + ): ServerRequest { $requestFilter = $requestFilter ?: FilterUsingXForwardedHeaders::trustReservedSubnets(); - $server = normalizeServer( + $server = normalizeServer( $server ?: $_SERVER, is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null ); @@ -89,7 +102,7 @@ public static function fromGlobals( /** * {@inheritDoc} */ - public function createServerRequest(string $method, $uri, array $serverParams = []) : ServerRequestInterface + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface { $uploadedFiles = []; @@ -108,12 +121,12 @@ public function createServerRequest(string $method, $uri, array $serverParams = * @param array> $headers * @param array $server SAPI parameters */ - private static function marshalUriFromSapi(array $server, array $headers) : Uri + private static function marshalUriFromSapi(array $server, array $headers): Uri { $uri = new Uri(''); // URI scheme - $https = false; + $https = false; if (array_key_exists('HTTPS', $server)) { $https = self::marshalHttpsValue($server['HTTPS']); } elseif (array_key_exists('https', $server)) { @@ -162,7 +175,7 @@ private static function marshalUriFromSapi(array $server, array $headers) : Uri * @return array{string, int|null} Array of two items, host and port, * in that order (can be passed to a list() operation). */ - private static function marshalHostAndPort(array $server, array $headers) : array + private static function marshalHostAndPort(array $server, array $headers): array { static $defaults = ['', null]; @@ -174,7 +187,7 @@ private static function marshalHostAndPort(array $server, array $headers) : arra // - A comma indicates that multiple host headers have been sent which is not legal // and might be used in an attack where a load balancer sees a different host header // than Diactoros. - if (! \preg_match('/[\\t ,]/', $host)) { + if (! preg_match('/[\\t ,]/', $host)) { return self::marshalHostAndPortFromHeader($host); } } @@ -186,7 +199,8 @@ private static function marshalHostAndPort(array $server, array $headers) : arra $host = (string) $server['SERVER_NAME']; $port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null; - if (! isset($server['SERVER_ADDR']) + if ( + ! isset($server['SERVER_ADDR']) || ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host) ) { return [$host, $port]; @@ -201,7 +215,7 @@ private static function marshalHostAndPort(array $server, array $headers) : arra * @return array{string, int|null} Array of two items, host and port, * in that order (can be passed to a list() operation). */ - private static function marshalIpv6HostAndPort(array $server, ?int $port) : array + private static function marshalIpv6HostAndPort(array $server, ?int $port): array { $host = '[' . (string) $server['SERVER_ADDR'] . ']'; $port = $port ?: 80; @@ -229,7 +243,7 @@ private static function marshalIpv6HostAndPort(array $server, ?int $port) : arra * - REQUEST_URI * - ORIG_PATH_INFO */ - private static function marshalRequestPath(array $server) : string + private static function marshalRequestPath(array $server): string { // IIS7 with URL Rewrite: make sure we get the unencoded url // (double slash problem). @@ -256,7 +270,7 @@ private static function marshalRequestPath(array $server) : string /** * @param mixed $https */ - private static function marshalHttpsValue($https) : bool + private static function marshalHttpsValue($https): bool { if (is_bool($https)) { return $https; diff --git a/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php b/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php index 00b9707b..4ae9c17f 100644 --- a/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php +++ b/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php @@ -8,6 +8,17 @@ use Laminas\Diactoros\Exception\InvalidProxyAddressException; use Psr\Http\Message\ServerRequestInterface; +use function explode; +use function filter_var; +use function in_array; +use function is_string; +use function strpos; +use function strtolower; + +use const FILTER_FLAG_IPV4; +use const FILTER_FLAG_IPV6; +use const FILTER_VALIDATE_IP; + /** * Modify the URI to reflect the X-Forwarded-* headers. * @@ -30,9 +41,7 @@ final class FilterUsingXForwardedHeaders implements FilterServerRequestInterface self::HEADER_PROTO, ]; - /** - * @var list - */ + /** @var list */ private $trustedHeaders; /** @var list */ @@ -84,7 +93,7 @@ public function __invoke(ServerRequestInterface $request): ServerRequestInterfac break; case self::HEADER_PROTO: $scheme = strtolower($header) === 'https' ? 'https' : 'http'; - $uri = $uri->withScheme($scheme); + $uri = $uri->withScheme($scheme); break; } } @@ -229,7 +238,7 @@ private static function validateProxyCIDR($cidr): bool $mask = null; if (false !== strpos($cidr, '/')) { [$address, $mask] = explode('/', $cidr, 2); - $mask = (int) $mask; + $mask = (int) $mask; } if (false !== strpos($address, ':')) { diff --git a/src/ServerRequestFilter/IPRange.php b/src/ServerRequestFilter/IPRange.php index 871dde84..a306ffd8 100644 --- a/src/ServerRequestFilter/IPRange.php +++ b/src/ServerRequestFilter/IPRange.php @@ -4,6 +4,18 @@ namespace Laminas\Diactoros\ServerRequestFilter; +use function explode; +use function inet_pton; +use function intval; +use function ip2long; +use function pack; +use function sprintf; +use function str_pad; +use function str_repeat; +use function strpos; +use function substr_compare; +use function unpack; + /** @internal */ final class IPRange { @@ -32,7 +44,7 @@ public static function matchesIPv4(string $ip, string $cidr): bool if (false !== strpos($cidr, '/')) { [$subnet, $mask] = explode('/', $cidr, 2); - $mask = (int) $mask; + $mask = (int) $mask; } if ($mask < 0 || $mask > 32) { @@ -62,7 +74,7 @@ public static function matchesIPv6(string $ip, string $cidr): bool if (false !== strpos($cidr, '/')) { [$subnet, $mask] = explode('/', $cidr, 2); - $mask = (int) $mask; + $mask = (int) $mask; } if ($mask < 0 || $mask > 128) { @@ -72,7 +84,7 @@ public static function matchesIPv6(string $ip, string $cidr): bool $ip = inet_pton($ip); $subnet = inet_pton($subnet); - if (false == $ip || false == $subnet) { + if (false === $ip || false === $subnet) { // Invalid data return false; } diff --git a/src/Stream.php b/src/Stream.php index 063e96c7..29c1931b 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -4,8 +4,10 @@ namespace Laminas\Diactoros; +use GdImage; use Psr\Http\Message\StreamInterface; use RuntimeException; +use Throwable; use function array_key_exists; use function fclose; @@ -17,16 +19,16 @@ use function ftell; use function fwrite; use function get_resource_type; +use function in_array; use function is_int; use function is_resource; use function is_string; -use function restore_error_handler; -use function set_error_handler; +use function sprintf; use function stream_get_contents; use function stream_get_meta_data; use function strstr; -use const E_WARNING; +use const PHP_VERSION_ID; use const SEEK_SET; /** @@ -39,14 +41,10 @@ class Stream implements StreamInterface */ private const ALLOWED_STREAM_RESOURCE_TYPES = ['gd', 'stream']; - /** - * @var resource|null - */ + /** @var resource|null */ protected $resource; - /** - * @var string|resource - */ + /** @var string|resource */ protected $stream; /** @@ -62,7 +60,7 @@ public function __construct($stream, string $mode = 'r') /** * {@inheritdoc} */ - public function __toString() : string + public function __toString(): string { if (! $this->isReadable()) { return ''; @@ -82,7 +80,7 @@ public function __toString() : string /** * {@inheritdoc} */ - public function close() : void + public function close(): void { if (! $this->resource) { return; @@ -97,7 +95,7 @@ public function close() : void */ public function detach() { - $resource = $this->resource; + $resource = $this->resource; $this->resource = null; return $resource; } @@ -106,12 +104,10 @@ public function detach() * Attach a new stream/resource to the instance. * * @param string|resource $resource - * @param string $mode - * @throws Exception\InvalidArgumentException for stream identifier that cannot be - * cast to a resource - * @throws Exception\InvalidArgumentException for non-resource stream + * @throws Exception\InvalidArgumentException For stream identifier that cannot be cast to a resource. + * @throws Exception\InvalidArgumentException For non-resource stream. */ - public function attach($resource, string $mode = 'r') : void + public function attach($resource, string $mode = 'r'): void { $this->setStream($resource, $mode); } @@ -119,7 +115,7 @@ public function attach($resource, string $mode = 'r') : void /** * {@inheritdoc} */ - public function getSize() : ?int + public function getSize(): ?int { if (null === $this->resource) { return null; @@ -136,7 +132,7 @@ public function getSize() : ?int /** * {@inheritdoc} */ - public function tell() : int + public function tell(): int { if (! $this->resource) { throw Exception\UntellableStreamException::dueToMissingResource(); @@ -153,7 +149,7 @@ public function tell() : int /** * {@inheritdoc} */ - public function eof() : bool + public function eof(): bool { if (! $this->resource) { return true; @@ -165,7 +161,7 @@ public function eof() : bool /** * {@inheritdoc} */ - public function isSeekable() : bool + public function isSeekable(): bool { if (! $this->resource) { return false; @@ -178,7 +174,7 @@ public function isSeekable() : bool /** * {@inheritdoc} */ - public function seek($offset, $whence = SEEK_SET) : void + public function seek($offset, $whence = SEEK_SET): void { if (! $this->resource) { throw Exception\UnseekableStreamException::dueToMissingResource(); @@ -198,7 +194,7 @@ public function seek($offset, $whence = SEEK_SET) : void /** * {@inheritdoc} */ - public function rewind() : void + public function rewind(): void { $this->seek(0); } @@ -206,7 +202,7 @@ public function rewind() : void /** * {@inheritdoc} */ - public function isWritable() : bool + public function isWritable(): bool { if (! $this->resource) { return false; @@ -215,19 +211,17 @@ public function isWritable() : bool $meta = stream_get_meta_data($this->resource); $mode = $meta['mode']; - return ( - strstr($mode, 'x') + return strstr($mode, 'x') || strstr($mode, 'w') || strstr($mode, 'c') || strstr($mode, 'a') - || strstr($mode, '+') - ); + || strstr($mode, '+'); } /** * {@inheritdoc} */ - public function write($string) : int + public function write($string): int { if (! $this->resource) { throw Exception\UnwritableStreamException::dueToMissingResource(); @@ -249,7 +243,7 @@ public function write($string) : int /** * {@inheritdoc} */ - public function isReadable() : bool + public function isReadable(): bool { if (! $this->resource) { return false; @@ -258,13 +252,13 @@ public function isReadable() : bool $meta = stream_get_meta_data($this->resource); $mode = $meta['mode']; - return (strstr($mode, 'r') || strstr($mode, '+')); + return strstr($mode, 'r') || strstr($mode, '+'); } /** * {@inheritdoc} */ - public function read($length) : string + public function read($length): string { if (! $this->resource) { throw Exception\UnreadableStreamException::dueToMissingResource(); @@ -286,7 +280,7 @@ public function read($length) : string /** * {@inheritdoc} */ - public function getContents() : string + public function getContents(): string { if (! $this->isReadable()) { throw Exception\UnreadableStreamException::dueToConfiguration(); @@ -321,27 +315,22 @@ public function getMetadata($key = null) * * @param string|resource $stream String stream target or stream resource. * @param string $mode Resource mode for stream target. - * @throws Exception\InvalidArgumentException for invalid streams or resources. + * @throws Exception\InvalidArgumentException For invalid streams or resources. */ - private function setStream($stream, string $mode = 'r') : void + private function setStream($stream, string $mode = 'r'): void { - $error = null; $resource = $stream; if (is_string($stream)) { - set_error_handler(function ($e) use (&$error) { - if ($e !== E_WARNING) { - return; - } - - $error = $e; - }); - $resource = fopen($stream, $mode); - restore_error_handler(); - } - - if ($error) { - throw new Exception\RuntimeException('Invalid stream reference provided'); + try { + $resource = fopen($stream, $mode); + } catch (Throwable $error) { + throw new Exception\RuntimeException( + sprintf('Invalid stream reference provided: %s', $error->getMessage()), + 0, + $error + ); + } } if (! $this->isValidStreamResourceType($resource)) { @@ -360,7 +349,8 @@ private function setStream($stream, string $mode = 'r') : void /** * Determine if a resource is one of the resource types allowed to instantiate a Stream * - * @param resource $resource Stream resource. + * @param mixed $resource Stream resource. + * @psalm-assert-if-true resource $resource */ private function isValidStreamResourceType($resource): bool { @@ -368,7 +358,7 @@ private function isValidStreamResourceType($resource): bool return in_array(get_resource_type($resource), self::ALLOWED_STREAM_RESOURCE_TYPES, true); } - if (PHP_VERSION_ID >= 80000 && $resource instanceof \GdImage) { + if (PHP_VERSION_ID >= 80000 && $resource instanceof GdImage) { return true; } diff --git a/src/StreamFactory.php b/src/StreamFactory.php index 9105ff2e..54596dba 100644 --- a/src/StreamFactory.php +++ b/src/StreamFactory.php @@ -9,8 +9,6 @@ use function fopen; use function fwrite; -use function get_resource_type; -use function is_resource; use function rewind; class StreamFactory implements StreamFactoryInterface @@ -18,7 +16,7 @@ class StreamFactory implements StreamFactoryInterface /** * {@inheritDoc} */ - public function createStream(string $content = '') : StreamInterface + public function createStream(string $content = ''): StreamInterface { $resource = fopen('php://temp', 'r+'); fwrite($resource, $content); @@ -30,7 +28,7 @@ public function createStream(string $content = '') : StreamInterface /** * {@inheritDoc} */ - public function createStreamFromFile(string $file, string $mode = 'r') : StreamInterface + public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface { return new Stream($file, $mode); } @@ -38,7 +36,7 @@ public function createStreamFromFile(string $file, string $mode = 'r') : StreamI /** * {@inheritDoc} */ - public function createStreamFromResource($resource) : StreamInterface + public function createStreamFromResource($resource): StreamInterface { return new Stream($resource); } diff --git a/src/UploadedFile.php b/src/UploadedFile.php index e918697f..93e8bf27 100644 --- a/src/UploadedFile.php +++ b/src/UploadedFile.php @@ -9,16 +9,16 @@ use function dirname; use function fclose; +use function file_exists; use function fopen; use function fwrite; use function is_dir; -use function is_int; use function is_resource; use function is_string; use function is_writable; use function move_uploaded_file; -use function sprintf; use function strpos; +use function unlink; use const PHP_SAPI; use const UPLOAD_ERR_CANT_WRITE; @@ -44,55 +44,37 @@ class UploadedFile implements UploadedFileInterface UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the file upload.', ]; - /** - * @var string|null - */ + /** @var string|null */ private $clientFilename; - /** - * @var string|null - */ + /** @var string|null */ private $clientMediaType; - /** - * @var int - */ + /** @var int */ private $error; - /** - * @var null|string - */ + /** @var null|string */ private $file; - /** - * @var bool - */ + /** @var bool */ private $moved = false; - /** - * @var int - */ + /** @var int */ private $size; - /** - * @var null|StreamInterface - */ + /** @var null|StreamInterface */ private $stream; /** * @param string|resource|StreamInterface $streamOrFile - * @param int $size - * @param int $errorStatus - * @param string|null $clientFilename - * @param string|null $clientMediaType * @throws Exception\InvalidArgumentException */ public function __construct( $streamOrFile, int $size, int $errorStatus, - string $clientFilename = null, - string $clientMediaType = null + ?string $clientFilename = null, + ?string $clientMediaType = null ) { if ($errorStatus === UPLOAD_ERR_OK) { if (is_string($streamOrFile)) { @@ -119,16 +101,16 @@ public function __construct( } $this->error = $errorStatus; - $this->clientFilename = $clientFilename; + $this->clientFilename = $clientFilename; $this->clientMediaType = $clientMediaType; } /** * {@inheritdoc} - * @throws Exception\UploadedFileAlreadyMovedException if the upload was - * not successful. + * + * @throws Exception\UploadedFileAlreadyMovedException If the upload was not successful. */ - public function getStream() : StreamInterface + public function getStream(): StreamInterface { if ($this->error !== UPLOAD_ERR_OK) { throw Exception\UploadedFileErrorException::dueToStreamUploadError( @@ -153,13 +135,14 @@ public function getStream() : StreamInterface * * @see http://php.net/is_uploaded_file * @see http://php.net/move_uploaded_file + * * @param string $targetPath Path to which to move the uploaded file. - * @throws Exception\UploadedFileErrorException if the upload was not successful. - * @throws Exception\InvalidArgumentException if the $path specified is invalid. - * @throws Exception\UploadedFileErrorException on any error during the + * @throws Exception\UploadedFileErrorException If the upload was not successful. + * @throws Exception\InvalidArgumentException If the $path specified is invalid. + * @throws Exception\UploadedFileErrorException On any error during the * move operation, or on the second or subsequent call to the method. */ - public function moveTo($targetPath) : void + public function moveTo($targetPath): void { if ($this->moved) { throw new Exception\UploadedFileAlreadyMovedException('Cannot move file; already moved!'); @@ -184,7 +167,7 @@ public function moveTo($targetPath) : void $sapi = PHP_SAPI; switch (true) { - case (empty($sapi) || 0 === strpos($sapi, 'cli') || 0 === strpos($sapi, 'phpdbg') || ! $this->file): + case empty($sapi) || 0 === strpos($sapi, 'cli') || 0 === strpos($sapi, 'phpdbg') || ! $this->file: // Non-SAPI environment, or no filename present $this->writeFile($targetPath); @@ -211,7 +194,7 @@ public function moveTo($targetPath) : void * * @return int|null The file size in bytes or null if unknown. */ - public function getSize() : ?int + public function getSize(): ?int { return $this->size; } @@ -220,9 +203,10 @@ public function getSize() : ?int * {@inheritdoc} * * @see http://php.net/manual/en/features.file-upload.errors.php + * * @return int One of PHP's UPLOAD_ERR_XXX constants. */ - public function getError() : int + public function getError(): int { return $this->error; } @@ -233,7 +217,7 @@ public function getError() : int * @return string|null The filename sent by the client or null if none * was provided. */ - public function getClientFilename() : ?string + public function getClientFilename(): ?string { return $this->clientFilename; } @@ -241,17 +225,15 @@ public function getClientFilename() : ?string /** * {@inheritdoc} */ - public function getClientMediaType() : ?string + public function getClientMediaType(): ?string { return $this->clientMediaType; } /** * Write internal stream to given path - * - * @param string $path */ - private function writeFile(string $path) : void + private function writeFile(string $path): void { $handle = fopen($path, 'wb+'); if (false === $handle) { diff --git a/src/UploadedFileFactory.php b/src/UploadedFileFactory.php index 073c3ee3..1fa5fa34 100644 --- a/src/UploadedFileFactory.php +++ b/src/UploadedFileFactory.php @@ -17,11 +17,11 @@ class UploadedFileFactory implements UploadedFileFactoryInterface */ public function createUploadedFile( StreamInterface $stream, - int $size = null, + ?int $size = null, int $error = UPLOAD_ERR_OK, - string $clientFilename = null, - string $clientMediaType = null - ) : UploadedFileInterface { + ?string $clientFilename = null, + ?string $clientMediaType = null + ): UploadedFileInterface { if ($size === null) { $size = $stream->getSize(); } diff --git a/src/Uri.php b/src/Uri.php index cf173d95..feb43309 100644 --- a/src/Uri.php +++ b/src/Uri.php @@ -11,6 +11,7 @@ use function get_class; use function gettype; use function implode; +use function is_float; use function is_numeric; use function is_object; use function is_string; @@ -52,51 +53,36 @@ class Uri implements UriInterface */ public const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~\pL'; - /** - * @var int[] Array indexed by valid scheme names to their corresponding ports. - */ + /** @var int[] Array indexed by valid scheme names to their corresponding ports. */ protected $allowedSchemes = [ 'http' => 80, 'https' => 443, ]; - /** - * @var string - */ + /** @var string */ private $scheme = ''; - /** - * @var string - */ + /** @var string */ private $userInfo = ''; - /** - * @var string - */ + /** @var string */ private $host = ''; - /** - * @var int|null - */ + /** @var int|null */ private $port; - /** - * @var string - */ + /** @var string */ private $path = ''; - /** - * @var string - */ + /** @var string */ private $query = ''; - /** - * @var string - */ + /** @var string */ private $fragment = ''; /** * generated uri string cache + * * @var string|null */ private $uriString; @@ -124,7 +110,7 @@ public function __clone() /** * {@inheritdoc} */ - public function __toString() : string + public function __toString(): string { if (null !== $this->uriString) { return $this->uriString; @@ -144,7 +130,7 @@ public function __toString() : string /** * {@inheritdoc} */ - public function getScheme() : string + public function getScheme(): string { return $this->scheme; } @@ -152,7 +138,7 @@ public function getScheme() : string /** * {@inheritdoc} */ - public function getAuthority() : string + public function getAuthority(): string { if ('' === $this->host) { return ''; @@ -177,7 +163,7 @@ public function getAuthority() : string * * {@inheritdoc} */ - public function getUserInfo() : string + public function getUserInfo(): string { return $this->userInfo; } @@ -185,7 +171,7 @@ public function getUserInfo() : string /** * {@inheritdoc} */ - public function getHost() : string + public function getHost(): string { return $this->host; } @@ -193,7 +179,7 @@ public function getHost() : string /** * {@inheritdoc} */ - public function getPort() : ?int + public function getPort(): ?int { return $this->isNonStandardPort($this->scheme, $this->host, $this->port) ? $this->port @@ -203,7 +189,7 @@ public function getPort() : ?int /** * {@inheritdoc} */ - public function getPath() : string + public function getPath(): string { return $this->path; } @@ -211,7 +197,7 @@ public function getPath() : string /** * {@inheritdoc} */ - public function getQuery() : string + public function getQuery(): string { return $this->query; } @@ -219,7 +205,7 @@ public function getQuery() : string /** * {@inheritdoc} */ - public function getFragment() : string + public function getFragment(): string { return $this->fragment; } @@ -227,7 +213,7 @@ public function getFragment() : string /** * {@inheritdoc} */ - public function withScheme($scheme) : UriInterface + public function withScheme($scheme): UriInterface { if (! is_string($scheme)) { throw new Exception\InvalidArgumentException(sprintf( @@ -244,7 +230,7 @@ public function withScheme($scheme) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->scheme = $scheme; return $new; @@ -258,7 +244,7 @@ public function withScheme($scheme) : UriInterface * * {@inheritdoc} */ - public function withUserInfo($user, $password = null) : UriInterface + public function withUserInfo($user, $password = null): UriInterface { if (! is_string($user)) { throw new Exception\InvalidArgumentException(sprintf( @@ -285,7 +271,7 @@ public function withUserInfo($user, $password = null) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->userInfo = $info; return $new; @@ -294,7 +280,7 @@ public function withUserInfo($user, $password = null) : UriInterface /** * {@inheritdoc} */ - public function withHost($host) : UriInterface + public function withHost($host): UriInterface { if (! is_string($host)) { throw new Exception\InvalidArgumentException(sprintf( @@ -309,7 +295,7 @@ public function withHost($host) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->host = strtolower($host); return $new; @@ -318,7 +304,7 @@ public function withHost($host) : UriInterface /** * {@inheritdoc} */ - public function withPort($port) : UriInterface + public function withPort($port): UriInterface { if ($port !== null) { if (! is_numeric($port) || is_float($port)) { @@ -343,7 +329,7 @@ public function withPort($port) : UriInterface )); } - $new = clone $this; + $new = clone $this; $new->port = $port; return $new; @@ -352,7 +338,7 @@ public function withPort($port) : UriInterface /** * {@inheritdoc} */ - public function withPath($path) : UriInterface + public function withPath($path): UriInterface { if (! is_string($path)) { throw new Exception\InvalidArgumentException( @@ -379,7 +365,7 @@ public function withPath($path) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->path = $path; return $new; @@ -388,7 +374,7 @@ public function withPath($path) : UriInterface /** * {@inheritdoc} */ - public function withQuery($query) : UriInterface + public function withQuery($query): UriInterface { if (! is_string($query)) { throw new Exception\InvalidArgumentException( @@ -409,7 +395,7 @@ public function withQuery($query) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->query = $query; return $new; @@ -418,7 +404,7 @@ public function withQuery($query) : UriInterface /** * {@inheritdoc} */ - public function withFragment($fragment) : UriInterface + public function withFragment($fragment): UriInterface { if (! is_string($fragment)) { throw new Exception\InvalidArgumentException(sprintf( @@ -435,7 +421,7 @@ public function withFragment($fragment) : UriInterface return $this; } - $new = clone $this; + $new = clone $this; $new->fragment = $fragment; return $new; @@ -444,7 +430,7 @@ public function withFragment($fragment) : UriInterface /** * Parse a URI into its parts, and set the properties */ - private function parseUri(string $uri) : void + private function parseUri(string $uri): void { $parts = parse_url($uri); @@ -454,13 +440,13 @@ private function parseUri(string $uri) : void ); } - $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; - $this->userInfo = isset($parts['user']) ? $this->filterUserInfoPart($parts['user']) : ''; - $this->host = isset($parts['host']) ? strtolower($parts['host']) : ''; - $this->port = $parts['port'] ?? null; - $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; - $this->query = isset($parts['query']) ? $this->filterQuery($parts['query']) : ''; - $this->fragment = isset($parts['fragment']) ? $this->filterFragment($parts['fragment']) : ''; + $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; + $this->userInfo = isset($parts['user']) ? $this->filterUserInfoPart($parts['user']) : ''; + $this->host = isset($parts['host']) ? strtolower($parts['host']) : ''; + $this->port = $parts['port'] ?? null; + $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; + $this->query = isset($parts['query']) ? $this->filterQuery($parts['query']) : ''; + $this->fragment = isset($parts['fragment']) ? $this->filterFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { $this->userInfo .= ':' . $parts['pass']; @@ -476,7 +462,7 @@ private static function createUriString( string $path, string $query, string $fragment - ) : string { + ): string { $uri = ''; if ('' !== $scheme) { @@ -493,7 +479,6 @@ private static function createUriString( $uri .= $path; - if ('' !== $query) { $uri .= sprintf('?%s', $query); } @@ -508,7 +493,7 @@ private static function createUriString( /** * Is a given port non-standard for the current scheme? */ - private function isNonStandardPort(string $scheme, string $host, ?int $port) : bool + private function isNonStandardPort(string $scheme, string $host, ?int $port): bool { if ('' === $scheme) { return '' === $host || null !== $port; @@ -527,7 +512,7 @@ private function isNonStandardPort(string $scheme, string $host, ?int $port) : b * @param string $scheme Scheme name. * @return string Filtered scheme. */ - private function filterScheme(string $scheme) : string + private function filterScheme(string $scheme): string { $scheme = strtolower($scheme); $scheme = preg_replace('#:(//)?$#', '', $scheme); @@ -549,11 +534,8 @@ private function filterScheme(string $scheme) : string /** * Filters a part of user info in a URI to ensure it is properly encoded. - * - * @param string $part - * @return string */ - private function filterUserInfoPart(string $part) : string + private function filterUserInfoPart(string $part): string { $part = $this->filterInvalidUtf8($part); @@ -569,7 +551,7 @@ private function filterUserInfoPart(string $part) : string /** * Filters the path of a URI to ensure it is properly encoded. */ - private function filterPath(string $path) : string + private function filterPath(string $path): string { $path = $this->filterInvalidUtf8($path); @@ -596,7 +578,7 @@ private function filterPath(string $path) : string /** * Encode invalid UTF-8 characters in given string. All other characters are unchanged. */ - private function filterInvalidUtf8(string $string) : string + private function filterInvalidUtf8(string $string): string { // check if given string contains only valid UTF-8 characters if (preg_match('//u', $string)) { @@ -618,7 +600,7 @@ private function filterInvalidUtf8(string $string) : string * * Ensures that the values in the query string are properly urlencoded. */ - private function filterQuery(string $query) : string + private function filterQuery(string $query): string { if ('' !== $query && strpos($query, '?') === 0) { $query = substr($query, 1); @@ -644,10 +626,9 @@ private function filterQuery(string $query) : string /** * Split a query value into a key/value tuple. * - * @param string $value * @return array A value with exactly two elements, key and value */ - private function splitQueryValue(string $value) : array + private function splitQueryValue(string $value): array { $data = explode('=', $value, 2); if (! isset($data[1])) { @@ -659,7 +640,7 @@ private function splitQueryValue(string $value) : array /** * Filter a fragment value to ensure it is properly encoded. */ - private function filterFragment(string $fragment) : string + private function filterFragment(string $fragment): string { if ('' !== $fragment && strpos($fragment, '#') === 0) { $fragment = '%23' . substr($fragment, 1); @@ -671,7 +652,7 @@ private function filterFragment(string $fragment) : string /** * Filter a query string key or value, or a fragment. */ - private function filterQueryOrFragment(string $value) : string + private function filterQueryOrFragment(string $value): string { $value = $this->filterInvalidUtf8($value); @@ -685,7 +666,7 @@ private function filterQueryOrFragment(string $value) : string /** * URL encode a character returned by a regex. */ - private function urlEncodeChar(array $matches) : string + private function urlEncodeChar(array $matches): string { return rawurlencode($matches[0]); } diff --git a/src/UriFactory.php b/src/UriFactory.php index ed53827b..f460e37d 100644 --- a/src/UriFactory.php +++ b/src/UriFactory.php @@ -12,7 +12,7 @@ class UriFactory implements UriFactoryInterface /** * {@inheritDoc} */ - public function createUri(string $uri = '') : UriInterface + public function createUri(string $uri = ''): UriInterface { return new Uri($uri); } diff --git a/src/functions/create_uploaded_file.legacy.php b/src/functions/create_uploaded_file.legacy.php index 3ccd4458..110101e6 100644 --- a/src/functions/create_uploaded_file.legacy.php +++ b/src/functions/create_uploaded_file.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\createUploadedFile as laminas_createUploadedFile; /** * @deprecated Use Laminas\Diactoros\createUploadedFile instead */ -function createUploadedFile(array $spec) : UploadedFile +function createUploadedFile(array $spec): UploadedFile { return laminas_createUploadedFile(...func_get_args()); } diff --git a/src/functions/create_uploaded_file.php b/src/functions/create_uploaded_file.php index 9ec4c1c4..22c37e9e 100644 --- a/src/functions/create_uploaded_file.php +++ b/src/functions/create_uploaded_file.php @@ -4,16 +4,19 @@ namespace Laminas\Diactoros; +use function sprintf; + /** * Create an uploaded file instance from an array of values. * * @param array $spec A single $_FILES entry. - * @throws Exception\InvalidArgumentException if one or more of the tmp_name, + * @throws Exception\InvalidArgumentException If one or more of the tmp_name, * size, or error keys are missing from $spec. */ -function createUploadedFile(array $spec) : UploadedFile +function createUploadedFile(array $spec): UploadedFile { - if (! isset($spec['tmp_name']) + if ( + ! isset($spec['tmp_name']) || ! isset($spec['size']) || ! isset($spec['error']) ) { diff --git a/src/functions/marshal_headers_from_sapi.legacy.php b/src/functions/marshal_headers_from_sapi.legacy.php index c1fd2f35..372ad292 100644 --- a/src/functions/marshal_headers_from_sapi.legacy.php +++ b/src/functions/marshal_headers_from_sapi.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\marshalHeadersFromSapi as laminas_marshalHeadersFromSapi; /** * @deprecated Use Laminas\Diactoros\marshalHeadersFromSapi instead */ -function marshalHeadersFromSapi(array $server) : array +function marshalHeadersFromSapi(array $server): array { return laminas_marshalHeadersFromSapi(...func_get_args()); } diff --git a/src/functions/marshal_headers_from_sapi.php b/src/functions/marshal_headers_from_sapi.php index 2bca072b..a00e7c11 100644 --- a/src/functions/marshal_headers_from_sapi.php +++ b/src/functions/marshal_headers_from_sapi.php @@ -15,10 +15,10 @@ * @param array $server Values obtained from the SAPI (generally `$_SERVER`). * @return array Header/value pairs */ -function marshalHeadersFromSapi(array $server) : array +function marshalHeadersFromSapi(array $server): array { $contentHeaderLookup = isset($server['LAMINAS_DIACTOROS_STRICT_CONTENT_HEADER_LOOKUP']) - ? static function (string $key) : bool { + ? static function (string $key): bool { static $contentHeaders = [ 'CONTENT_TYPE' => true, 'CONTENT_LENGTH' => true, @@ -53,13 +53,13 @@ function marshalHeadersFromSapi(array $server) : array } if (strpos($key, 'HTTP_') === 0) { - $name = strtr(strtolower(substr($key, 5)), '_', '-'); + $name = strtr(strtolower(substr($key, 5)), '_', '-'); $headers[$name] = $value; continue; } if ($contentHeaderLookup($key)) { - $name = strtr(strtolower($key), '_', '-'); + $name = strtr(strtolower($key), '_', '-'); $headers[$name] = $value; continue; } diff --git a/src/functions/marshal_method_from_sapi.legacy.php b/src/functions/marshal_method_from_sapi.legacy.php index 7db5e0e8..2eb83d97 100644 --- a/src/functions/marshal_method_from_sapi.legacy.php +++ b/src/functions/marshal_method_from_sapi.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\marshalMethodFromSapi as laminas_marshalMethodFromSapi; /** * @deprecated Use Laminas\Diactoros\marshalMethodFromSapi instead */ -function marshalMethodFromSapi(array $server) : string +function marshalMethodFromSapi(array $server): string { return laminas_marshalMethodFromSapi(...func_get_args()); } diff --git a/src/functions/marshal_method_from_sapi.php b/src/functions/marshal_method_from_sapi.php index 03f286e8..8feeb316 100644 --- a/src/functions/marshal_method_from_sapi.php +++ b/src/functions/marshal_method_from_sapi.php @@ -7,7 +7,7 @@ /** * Retrieve the request method from the SAPI parameters. */ -function marshalMethodFromSapi(array $server) : string +function marshalMethodFromSapi(array $server): string { return $server['REQUEST_METHOD'] ?? 'GET'; } diff --git a/src/functions/marshal_protocol_version_from_sapi.legacy.php b/src/functions/marshal_protocol_version_from_sapi.legacy.php index 9c262d57..2c69d6db 100644 --- a/src/functions/marshal_protocol_version_from_sapi.legacy.php +++ b/src/functions/marshal_protocol_version_from_sapi.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\marshalProtocolVersionFromSapi as laminas_marshalProtocolVersionFromSapi; /** * @deprecated Use Laminas\Diactoros\marshalProtocolVersionFromSapi instead */ -function marshalProtocolVersionFromSapi(array $server) : string +function marshalProtocolVersionFromSapi(array $server): string { return laminas_marshalProtocolVersionFromSapi(...func_get_args()); } diff --git a/src/functions/marshal_protocol_version_from_sapi.php b/src/functions/marshal_protocol_version_from_sapi.php index e64089da..a5eefee8 100644 --- a/src/functions/marshal_protocol_version_from_sapi.php +++ b/src/functions/marshal_protocol_version_from_sapi.php @@ -9,10 +9,10 @@ /** * Return HTTP protocol version (X.Y) as discovered within a `$_SERVER` array. * - * @throws Exception\UnrecognizedProtocolVersionException if the + * @throws Exception\UnrecognizedProtocolVersionException If the * $server['SERVER_PROTOCOL'] value is malformed. */ -function marshalProtocolVersionFromSapi(array $server) : string +function marshalProtocolVersionFromSapi(array $server): string { if (! isset($server['SERVER_PROTOCOL'])) { return '1.1'; diff --git a/src/functions/marshal_uri_from_sapi.legacy.php b/src/functions/marshal_uri_from_sapi.legacy.php index f121f23f..660ddd4e 100644 --- a/src/functions/marshal_uri_from_sapi.legacy.php +++ b/src/functions/marshal_uri_from_sapi.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\marshalUriFromSapi as laminas_marshalUriFromSapi; /** * @deprecated Use Laminas\Diactoros\marshalUriFromSapi instead */ -function marshalUriFromSapi(array $server, array $headers) : Uri +function marshalUriFromSapi(array $server, array $headers): Uri { return laminas_marshalUriFromSapi(...func_get_args()); } diff --git a/src/functions/marshal_uri_from_sapi.php b/src/functions/marshal_uri_from_sapi.php index 0092aeff..abdcfe8a 100644 --- a/src/functions/marshal_uri_from_sapi.php +++ b/src/functions/marshal_uri_from_sapi.php @@ -7,25 +7,33 @@ use function array_change_key_case; use function array_key_exists; use function explode; +use function gettype; use function implode; use function is_array; +use function is_bool; +use function is_string; use function ltrim; use function preg_match; use function preg_replace; +use function sprintf; use function strlen; use function strpos; +use function strrpos; use function strtolower; use function substr; +use const CASE_LOWER; + /** * Marshal a Uri instance based on the values presnt in the $_SERVER array and headers. * - * @param array $server SAPI parameters - * @param array $headers HTTP request headers * @deprecated This function is deprecated as of 2.11.1, and will be removed in * 3.0.0. As of 2.11.1, it is no longer used internally. + * + * @param array $server SAPI parameters + * @param array $headers HTTP request headers */ -function marshalUriFromSapi(array $server, array $headers) : Uri +function marshalUriFromSapi(array $server, array $headers): Uri { /** * Retrieve a header value from an array of headers using a case-insensitive lookup. @@ -38,8 +46,7 @@ function marshalUriFromSapi(array $server, array $headers) : Uri $header = strtolower($name); $headers = array_change_key_case($headers, CASE_LOWER); if (array_key_exists($header, $headers)) { - $value = is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header]; - return $value; + return is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header]; } return $default; @@ -51,7 +58,7 @@ function marshalUriFromSapi(array $server, array $headers) : Uri * @return array Array of two items, host and port, in that order (can be * passed to a list() operation). */ - $marshalHostAndPort = function (array $headers, array $server) use ($getHeaderFromArray) : array { + $marshalHostAndPort = function (array $headers, array $server) use ($getHeaderFromArray): array { /** * @param string|array $host * @return array Array of two items, host and port, in that order (can be @@ -77,7 +84,7 @@ function marshalUriFromSapi(array $server, array $headers) : Uri * @return array Array of two items, host and port, in that order (can be * passed to a list() operation). */ - $marshalIpv6HostAndPort = function (array $server, ?int $port) : array { + $marshalIpv6HostAndPort = function (array $server, ?int $port): array { $host = '[' . $server['SERVER_ADDR'] . ']'; $port = $port ?: 80; if ($port . ']' === substr($host, strrpos($host, ':') + 1)) { @@ -107,7 +114,8 @@ function marshalUriFromSapi(array $server, array $headers) : Uri $host = $server['SERVER_NAME']; $port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null; - if (! isset($server['SERVER_ADDR']) + if ( + ! isset($server['SERVER_ADDR']) || ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host) ) { return [$host, $port]; @@ -130,7 +138,7 @@ function marshalUriFromSapi(array $server, array $headers) : Uri * * From Laminas\Http\PhpEnvironment\Request class */ - $marshalRequestPath = function (array $server) : string { + $marshalRequestPath = function (array $server): string { // IIS7 with URL Rewrite: make sure we get the unencoded url // (double slash problem). $iisUrlRewritten = $server['IIS_WasUrlRewritten'] ?? null; @@ -156,8 +164,8 @@ function marshalUriFromSapi(array $server, array $headers) : Uri $uri = new Uri(''); // URI scheme - $scheme = 'http'; - $marshalHttpsValue = function ($https) : bool { + $scheme = 'http'; + $marshalHttpsValue = function ($https): bool { if (is_bool($https)) { return $https; } @@ -179,7 +187,8 @@ function marshalUriFromSapi(array $server, array $headers) : Uri $https = false; } - if ($https + if ( + $https || strtolower($getHeaderFromArray('x-forwarded-proto', $headers, '')) === 'https' ) { $scheme = 'https'; diff --git a/src/functions/normalize_server.legacy.php b/src/functions/normalize_server.legacy.php index a4287f20..b355c4d8 100644 --- a/src/functions/normalize_server.legacy.php +++ b/src/functions/normalize_server.legacy.php @@ -4,12 +4,13 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\normalizeServer as laminas_normalizeServer; /** * @deprecated Use Laminas\Diactoros\normalizeServer instead */ -function normalizeServer(array $server, callable $apacheRequestHeaderCallback = null) : array +function normalizeServer(array $server, ?callable $apacheRequestHeaderCallback = null): array { return laminas_normalizeServer(...func_get_args()); } diff --git a/src/functions/normalize_server.php b/src/functions/normalize_server.php index b673d9d1..c9efb388 100644 --- a/src/functions/normalize_server.php +++ b/src/functions/normalize_server.php @@ -18,7 +18,7 @@ * `apache_request_headers` under the Apache mod_php. * @return array Either $server verbatim, or with an added HTTP_AUTHORIZATION header. */ -function normalizeServer(array $server, callable $apacheRequestHeaderCallback = null) : array +function normalizeServer(array $server, ?callable $apacheRequestHeaderCallback = null): array { if (null === $apacheRequestHeaderCallback && is_callable('apache_request_headers')) { $apacheRequestHeaderCallback = 'apache_request_headers'; @@ -26,7 +26,8 @@ function normalizeServer(array $server, callable $apacheRequestHeaderCallback = // If the HTTP_AUTHORIZATION value is already set, or the callback is not // callable, we return verbatim - if (isset($server['HTTP_AUTHORIZATION']) + if ( + isset($server['HTTP_AUTHORIZATION']) || ! is_callable($apacheRequestHeaderCallback) ) { return $server; diff --git a/src/functions/normalize_uploaded_files.legacy.php b/src/functions/normalize_uploaded_files.legacy.php index 69d1244d..b21323fa 100644 --- a/src/functions/normalize_uploaded_files.legacy.php +++ b/src/functions/normalize_uploaded_files.legacy.php @@ -4,14 +4,13 @@ namespace Zend\Diactoros; -use Psr\Http\Message\UploadedFileInterface; - +use function func_get_args; use function Laminas\Diactoros\normalizeUploadedFiles as laminas_normalizeUploadedFiles; /** * @deprecated Use Laminas\Diactoros\normalizeUploadedFiles instead */ -function normalizeUploadedFiles(array $files) : array +function normalizeUploadedFiles(array $files): array { return laminas_normalizeUploadedFiles(...func_get_args()); } diff --git a/src/functions/normalize_uploaded_files.php b/src/functions/normalize_uploaded_files.php index 406ea235..ef32ec2e 100644 --- a/src/functions/normalize_uploaded_files.php +++ b/src/functions/normalize_uploaded_files.php @@ -7,6 +7,7 @@ use Psr\Http\Message\UploadedFileInterface; use function is_array; +use function sprintf; /** * Normalize uploaded files @@ -15,9 +16,9 @@ * arrays are normalized. * * @return UploadedFileInterface[] - * @throws Exception\InvalidArgumentException for unrecognized values + * @throws Exception\InvalidArgumentException For unrecognized values. */ -function normalizeUploadedFiles(array $files) : array +function normalizeUploadedFiles(array $files): array { /** * Traverse a nested tree of uploaded file specifications. @@ -33,9 +34,9 @@ function normalizeUploadedFiles(array $files) : array array $tmpNameTree, array $sizeTree, array $errorTree, - array $nameTree = null, - array $typeTree = null - ) use (&$recursiveNormalize) : array { + ?array $nameTree = null, + ?array $typeTree = null + ) use (&$recursiveNormalize): array { $normalized = []; foreach ($tmpNameTree as $key => $value) { if (is_array($value)) { @@ -51,10 +52,10 @@ function normalizeUploadedFiles(array $files) : array } $normalized[$key] = createUploadedFile([ 'tmp_name' => $tmpNameTree[$key], - 'size' => $sizeTree[$key], - 'error' => $errorTree[$key], - 'name' => $nameTree[$key] ?? null, - 'type' => $typeTree[$key] ?? null, + 'size' => $sizeTree[$key], + 'error' => $errorTree[$key], + 'name' => $nameTree[$key] ?? null, + 'type' => $typeTree[$key] ?? null, ]); } return $normalized; @@ -74,8 +75,9 @@ function normalizeUploadedFiles(array $files) : array * @param array $files * @return UploadedFile[] */ - $normalizeUploadedFileSpecification = function (array $files = []) use (&$recursiveNormalize) : array { - if (! isset($files['tmp_name']) || ! is_array($files['tmp_name']) + $normalizeUploadedFileSpecification = function (array $files = []) use (&$recursiveNormalize): array { + if ( + ! isset($files['tmp_name']) || ! is_array($files['tmp_name']) || ! isset($files['size']) || ! is_array($files['size']) || ! isset($files['error']) || ! is_array($files['error']) ) { diff --git a/src/functions/parse_cookie_header.legacy.php b/src/functions/parse_cookie_header.legacy.php index 1297d36a..e0e0f6c1 100644 --- a/src/functions/parse_cookie_header.legacy.php +++ b/src/functions/parse_cookie_header.legacy.php @@ -4,12 +4,15 @@ namespace Zend\Diactoros; +use function func_get_args; use function Laminas\Diactoros\parseCookieHeader as laminas_parseCookieHeader; /** - * @deprecated Use Laminas\Diactoros\parseCookieHeader instead + * @deprecated Use \Laminas\Diactoros\parseCookieHeader instead + * + * @param string $cookieHeader A string cookie header value. */ -function parseCookieHeader($cookieHeader) : array +function parseCookieHeader($cookieHeader): array { return laminas_parseCookieHeader(...func_get_args()); } diff --git a/src/functions/parse_cookie_header.php b/src/functions/parse_cookie_header.php index 5e79c085..1c7606e5 100644 --- a/src/functions/parse_cookie_header.php +++ b/src/functions/parse_cookie_header.php @@ -7,6 +7,8 @@ use function preg_match_all; use function urldecode; +use const PREG_SET_ORDER; + /** * Parse a cookie header according to RFC 6265. * @@ -16,7 +18,7 @@ * @param string $cookieHeader A string cookie header value. * @return array key/value cookie pairs. */ -function parseCookieHeader($cookieHeader) : array +function parseCookieHeader($cookieHeader): array { preg_match_all('( (?:^\\n?[ \t]*|;[ ]) diff --git a/test/CallbackStreamTest.php b/test/CallbackStreamTest.php index b6e403d4..7cdc4219 100644 --- a/test/CallbackStreamTest.php +++ b/test/CallbackStreamTest.php @@ -13,7 +13,7 @@ */ class CallbackStreamTest extends TestCase { - public function testToString() : void + public function testToString(): void { $stream = new CallbackStream(function () { return 'foobarbaz'; @@ -23,7 +23,7 @@ public function testToString() : void $this->assertSame('foobarbaz', $ret); } - public function testClose() : void + public function testClose(): void { $stream = new CallbackStream(function () { }); @@ -35,20 +35,20 @@ public function testClose() : void $this->assertNull($callback); } - public function testDetach() : void + public function testDetach(): void { $callback = function () { }; - $stream = new CallbackStream($callback); - $ret = $stream->detach(); + $stream = new CallbackStream($callback); + $ret = $stream->detach(); $this->assertSame($callback, $ret); } - public function testEof() : void + public function testEof(): void { $stream = new CallbackStream(function () { }); - $ret = $stream->eof(); + $ret = $stream->eof(); $this->assertFalse($ret); $stream->getContents(); @@ -56,15 +56,15 @@ public function testEof() : void $this->assertTrue($ret); } - public function testGetSize() : void + public function testGetSize(): void { $stream = new CallbackStream(function () { }); - $ret = $stream->getSize(); + $ret = $stream->getSize(); $this->assertNull($ret); } - public function testTell() : void + public function testTell(): void { $stream = new CallbackStream(function () { }); @@ -74,31 +74,31 @@ public function testTell() : void $stream->tell(); } - public function testIsSeekable() : void + public function testIsSeekable(): void { $stream = new CallbackStream(function () { }); - $ret = $stream->isSeekable(); + $ret = $stream->isSeekable(); $this->assertFalse($ret); } - public function testIsWritable() : void + public function testIsWritable(): void { $stream = new CallbackStream(function () { }); - $ret = $stream->isWritable(); + $ret = $stream->isWritable(); $this->assertFalse($ret); } - public function testIsReadable() : void + public function testIsReadable(): void { $stream = new CallbackStream(function () { }); - $ret = $stream->isReadable(); + $ret = $stream->isReadable(); $this->assertFalse($ret); } - public function testSeek() : void + public function testSeek(): void { $stream = new CallbackStream(function () { }); @@ -108,7 +108,7 @@ public function testSeek() : void $stream->seek(0); } - public function testRewind() : void + public function testRewind(): void { $stream = new CallbackStream(function () { }); @@ -118,7 +118,7 @@ public function testRewind() : void $stream->rewind(); } - public function testWrite() : void + public function testWrite(): void { $stream = new CallbackStream(function () { }); @@ -128,7 +128,7 @@ public function testWrite() : void $stream->write('foobarbaz'); } - public function testRead() : void + public function testRead(): void { $stream = new CallbackStream(function () { }); @@ -138,7 +138,7 @@ public function testRead() : void $stream->read(3); } - public function testGetContents() : void + public function testGetContents(): void { $stream = new CallbackStream(function () { return 'foobarbaz'; @@ -148,7 +148,7 @@ public function testGetContents() : void $this->assertSame('foobarbaz', $ret); } - public function testGetMetadata() : void + public function testGetMetadata(): void { $stream = new CallbackStream(function () { }); @@ -164,16 +164,17 @@ public function testGetMetadata() : void $all = $stream->getMetadata(); $this->assertSame([ - 'eof' => false, + 'eof' => false, 'stream_type' => 'callback', - 'seekable' => false, + 'seekable' => false, ], $all); $notExists = $stream->getMetadata('boo'); $this->assertNull($notExists); } - public function phpCallbacksForStreams() : array + /** @return array */ + public function phpCallbacksForStreams(): array { $class = TestAsset\CallbacksForCallbackStreamTest::class; @@ -190,9 +191,9 @@ public function phpCallbacksForStreams() : array /** * @dataProvider phpCallbacksForStreams */ - public function testAllowsArbitraryPhpCallbacks($callback, $expected) : void + public function testAllowsArbitraryPhpCallbacks(callable $callback, string $expected): void { - $stream = new CallbackStream($callback); + $stream = new CallbackStream($callback); $contents = $stream->getContents(); $this->assertSame($expected, $contents); } diff --git a/test/HeaderSecurityTest.php b/test/HeaderSecurityTest.php index f8b6723a..f605f028 100644 --- a/test/HeaderSecurityTest.php +++ b/test/HeaderSecurityTest.php @@ -8,21 +8,14 @@ use Laminas\Diactoros\HeaderSecurity; use PHPUnit\Framework\TestCase; -/** - * Tests for Laminas\Diactoros\HeaderSecurity. - * - * Tests are largely derived from those for Laminas\Http\Header\HeaderValue in - * Laminas, released with the copyright and license below. - * - * @copyright Copyright (c) 2005-2015 Laminas (https://www.zend.com) - * @license https://getlaminas.org/license/new-bsd New BSD License - */ class HeaderSecurityTest extends TestCase { /** * Data for filter value + * + * @return array */ - public function getFilterValues() + public function getFilterValues(): array { return [ ["This is a\n test", "This is a test"], @@ -35,20 +28,20 @@ public function getFilterValues() ["This is a\r\r test", "This is a test"], ["This is a \r\r\n test", "This is a \r\n test"], ["This is a \r\n\r\ntest", "This is a test"], - ["This is a \r\n\n\r\n test", "This is a \r\n test"] + ["This is a \r\n\n\r\n test", "This is a \r\n test"], ]; } /** * @dataProvider getFilterValues - * @group ZF2015-04 */ - public function testFiltersValuesPerRfc7230($value, $expected) + public function testFiltersValuesPerRfc7230(string $value, string $expected): void { $this->assertSame($expected, HeaderSecurity::filter($value)); } - public function validateValues() + /** @return array */ + public function validateValues(): array { return [ ["This is a\n test", 'assertFalse'], @@ -70,14 +63,14 @@ public function validateValues() /** * @dataProvider validateValues - * @group ZF2015-04 */ - public function testValidatesValuesPerRfc7230($value, $assertion) + public function testValidatesValuesPerRfc7230(string $value, string $assertion): void { $this->{$assertion}(HeaderSecurity::isValid($value)); } - public function assertValues() + /** @return array */ + public function assertValues(): array { return [ ["This is a\n test"], @@ -89,15 +82,14 @@ public function assertValues() ["This is a\r\r test"], ["This is a \r\r\n test"], ["This is a \r\n\r\ntest"], - ["This is a \r\n\n\r\n test"] + ["This is a \r\n\n\r\n test"], ]; } /** * @dataProvider assertValues - * @group ZF2015-04 */ - public function testAssertValidRaisesExceptionForInvalidValue($value) + public function testAssertValidRaisesExceptionForInvalidValue(string $value): void { $this->expectException(InvalidArgumentException::class); diff --git a/test/Integration/RequestTest.php b/test/Integration/RequestTest.php index 899254c0..29a7e5c7 100644 --- a/test/Integration/RequestTest.php +++ b/test/Integration/RequestTest.php @@ -6,11 +6,10 @@ use Http\Psr7Test\RequestIntegrationTest; use Laminas\Diactoros\Request; -use Laminas\Diactoros\RequestFactory; class RequestTest extends RequestIntegrationTest { - public function createSubject() + public function createSubject(): Request { return new Request('/', 'GET'); } diff --git a/test/Integration/ResponseTest.php b/test/Integration/ResponseTest.php index 7e4c31d1..ca7eeb12 100644 --- a/test/Integration/ResponseTest.php +++ b/test/Integration/ResponseTest.php @@ -5,12 +5,11 @@ namespace LaminasTest\Diactoros\Integration; use Http\Psr7Test\ResponseIntegrationTest; -use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\Response; class ResponseTest extends ResponseIntegrationTest { - public function createSubject() + public function createSubject(): Response { return new Response(); } diff --git a/test/Integration/ServerRequestFactoryTest.php b/test/Integration/ServerRequestFactoryTest.php index a76de853..9ec7a21f 100644 --- a/test/Integration/ServerRequestFactoryTest.php +++ b/test/Integration/ServerRequestFactoryTest.php @@ -6,10 +6,11 @@ use Http\Psr7Test\ServerRequestIntegrationTest; use Laminas\Diactoros\ServerRequestFactory; +use Psr\Http\Message\ServerRequestInterface; class ServerRequestFactoryTest extends ServerRequestIntegrationTest { - public function createSubject() + public function createSubject(): ServerRequestInterface { return (new ServerRequestFactory())->createServerRequest('GET', '/', $_SERVER); } diff --git a/test/Integration/ServerRequestTest.php b/test/Integration/ServerRequestTest.php index de077ac9..1bdc1a0a 100644 --- a/test/Integration/ServerRequestTest.php +++ b/test/Integration/ServerRequestTest.php @@ -5,12 +5,11 @@ namespace LaminasTest\Diactoros\Integration; use Http\Psr7Test\ServerRequestIntegrationTest; -use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\ServerRequest; class ServerRequestTest extends ServerRequestIntegrationTest { - public function createSubject() + public function createSubject(): ServerRequest { return new ServerRequest($_SERVER); } diff --git a/test/Integration/StreamTest.php b/test/Integration/StreamTest.php index 73f1e3ab..bfe1b167 100644 --- a/test/Integration/StreamTest.php +++ b/test/Integration/StreamTest.php @@ -5,13 +5,15 @@ namespace LaminasTest\Diactoros\Integration; use Http\Psr7Test\StreamIntegrationTest; -use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\Stream; use Psr\Http\Message\StreamInterface; class StreamTest extends StreamIntegrationTest { - public function createStream($data) + /** + * @param string|resource|StreamInterface $data + */ + public function createStream($data): StreamInterface { if ($data instanceof StreamInterface) { return $data; diff --git a/test/Integration/UploadedFileTest.php b/test/Integration/UploadedFileTest.php index 2b1a4d38..67a4cfcf 100644 --- a/test/Integration/UploadedFileTest.php +++ b/test/Integration/UploadedFileTest.php @@ -5,13 +5,14 @@ namespace LaminasTest\Diactoros\Integration; use Http\Psr7Test\UploadedFileIntegrationTest; -use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\Stream; use Laminas\Diactoros\UploadedFile; +use const UPLOAD_ERR_OK; + class UploadedFileTest extends UploadedFileIntegrationTest { - public function createSubject() + public function createSubject(): UploadedFile { $stream = new Stream('php://memory', 'rw'); $stream->write('foobar'); diff --git a/test/Integration/UriTest.php b/test/Integration/UriTest.php index 594308fb..09f33d64 100644 --- a/test/Integration/UriTest.php +++ b/test/Integration/UriTest.php @@ -5,12 +5,14 @@ namespace LaminasTest\Diactoros\Integration; use Http\Psr7Test\UriIntegrationTest; -use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\Uri; class UriTest extends UriIntegrationTest { - public function createUri($uri) + /** + * @param string $uri + */ + public function createUri($uri): Uri { return new Uri($uri); } diff --git a/test/MessageTraitTest.php b/test/MessageTraitTest.php index efc99517..58c51cb1 100644 --- a/test/MessageTraitTest.php +++ b/test/MessageTraitTest.php @@ -11,15 +11,14 @@ use Psr\Http\Message\StreamInterface; use function count; +use function trim; class MessageTraitTest extends TestCase { - /** - * @var MessageInterface - */ + /** @var MessageInterface */ protected $message; - protected function setUp() : void + protected function setUp(): void { $this->message = new Request(null, null, $this->createMock(StreamInterface::class)); } @@ -40,22 +39,21 @@ public function testProtocolMutatorReturnsCloneWithChanges(): void public function invalidProtocolVersionProvider(): array { return [ - 'null' => [ null ], - 'true' => [ true ], - 'false' => [ false ], - 'int' => [ 1 ], - 'float' => [ 1.1 ], - 'array' => [ ['1.1'] ], - 'stdClass' => [ (object) [ 'version' => '1.0'] ], - '1-without-minor' => [ '1' ], - '1-with-invalid-minor' => [ '1.2' ], - '1-with-hotfix' => [ '1.2.3' ], + 'null' => [null], + 'true' => [true], + 'false' => [false], + 'int' => [1], + 'float' => [1.1], + 'array' => [['1.1']], + 'stdClass' => [(object) ['version' => '1.0']], + '1-without-minor' => ['1'], + '1-with-invalid-minor' => ['1.2'], + '1-with-hotfix' => ['1.2.3'], ]; } /** * @dataProvider invalidProtocolVersionProvider - * * @param mixed $version */ public function testWithProtocolVersionRaisesExceptionForInvalidVersion($version): void @@ -71,10 +69,10 @@ public function testWithProtocolVersionRaisesExceptionForInvalidVersion($version public function validProtocolVersionProvider(): array { return [ - '1.0' => [ '1.0' ], - '1.1' => [ '1.1' ], - '2' => [ '2' ], - '2.0' => [ '2.0' ], + '1.0' => ['1.0'], + '1.1' => ['1.1'], + '2' => ['2'], + '2.0' => ['2.0'], ]; } @@ -120,7 +118,7 @@ public function testGetHeadersKeepsHeaderCaseSensitivity(): void { $message = $this->message->withHeader('X-Foo', ['Foo', 'Bar']); $this->assertNotSame($this->message, $message); - $this->assertSame([ 'X-Foo' => [ 'Foo', 'Bar' ] ], $message->getHeaders()); + $this->assertSame(['X-Foo' => ['Foo', 'Bar']], $message->getHeaders()); } public function testGetHeadersReturnsCaseWithWhichHeaderFirstRegistered(): void @@ -129,7 +127,7 @@ public function testGetHeadersReturnsCaseWithWhichHeaderFirstRegistered(): void ->withHeader('X-Foo', 'Foo') ->withAddedHeader('x-foo', 'Bar'); $this->assertNotSame($this->message, $message); - $this->assertSame([ 'X-Foo' => [ 'Foo', 'Bar' ] ], $message->getHeaders()); + $this->assertSame(['X-Foo' => ['Foo', 'Bar']], $message->getHeaders()); } public function testHasHeaderReturnsFalseIfHeaderIsNotPresent(): void @@ -146,7 +144,7 @@ public function testHasHeaderReturnsTrueIfHeaderIsPresent(): void public function testAddHeaderAppendsToExistingHeader(): void { - $message = $this->message->withHeader('X-Foo', 'Foo'); + $message = $this->message->withHeader('X-Foo', 'Foo'); $this->assertNotSame($this->message, $message); $message2 = $message->withAddedHeader('X-Foo', 'Bar'); $this->assertNotSame($message, $message2); @@ -189,14 +187,13 @@ public function invalidGeneralHeaderValues(): array 'null' => [null], 'true' => [true], 'false' => [false], - 'array' => [[ 'foo' => [ 'bar' ] ]], - 'object' => [(object) [ 'foo' => 'bar' ]], + 'array' => [['foo' => ['bar']]], + 'object' => [(object) ['foo' => 'bar']], ]; } /** * @dataProvider invalidGeneralHeaderValues - * * @param mixed $value */ public function testWithHeaderRaisesExceptionForInvalidNestedHeaderValue($value): void @@ -204,7 +201,8 @@ public function testWithHeaderRaisesExceptionForInvalidNestedHeaderValue($value) $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid header value'); - $this->message->withHeader('X-Foo', [ $value ]); + /** @psalm-suppress MixedArgumentTypeCoercion */ + $this->message->withHeader('X-Foo', [$value]); } /** @return non-empty-array */ @@ -214,13 +212,12 @@ public function invalidHeaderValues(): array 'null' => [null], 'true' => [true], 'false' => [false], - 'object' => [(object) [ 'foo' => 'bar' ]], + 'object' => [(object) ['foo' => 'bar']], ]; } /** * @dataProvider invalidHeaderValues - * * @param mixed $value */ public function testWithHeaderRaisesExceptionForInvalidValueType($value): void @@ -228,20 +225,20 @@ public function testWithHeaderRaisesExceptionForInvalidValueType($value): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid header value'); + /** @psalm-suppress MixedArgument */ $this->message->withHeader('X-Foo', $value); } public function testWithHeaderReplacesDifferentCapitalization(): void { $this->message = $this->message->withHeader('X-Foo', ['foo']); - $new = $this->message->withHeader('X-foo', ['bar']); + $new = $this->message->withHeader('X-foo', ['bar']); $this->assertSame(['bar'], $new->getHeader('x-foo')); $this->assertSame(['X-foo' => ['bar']], $new->getHeaders()); } /** * @dataProvider invalidGeneralHeaderValues - * * @param mixed $value */ public function testWithAddedHeaderRaisesExceptionForNonStringNonArrayValue($value): void @@ -299,7 +296,6 @@ public function headersWithInjectionVectors(): array /** * @dataProvider headersWithInjectionVectors * @group ZF2015-04 - * * @param string $name * @param string|array{string} $value */ @@ -313,7 +309,6 @@ public function testDoesNotAllowCRLFInjectionWhenCallingWithHeader($name, $value /** * @dataProvider headersWithInjectionVectors * @group ZF2015-04 - * * @param string $name * @param string|array{string} $value */ @@ -340,11 +335,11 @@ public function testWithAddedHeaderAllowsHeaderContinuations(): void public function headersWithWhitespace(): array { return [ - 'no' => ["Baz"], - 'leading' => [" Baz"], + 'no' => ["Baz"], + 'leading' => [" Baz"], 'trailing' => ["Baz "], - 'both' => [" Baz "], - 'mixed' => [" \t Baz\t \t"], + 'both' => [" Baz "], + 'mixed' => [" \t Baz\t \t"], ]; } @@ -362,7 +357,7 @@ public function headersWithContinuation(): array { return [ 'space' => ["foo\r\n bar"], - 'tab' => ["foo\r\n\tbar"], + 'tab' => ["foo\r\n\tbar"], ]; } @@ -383,27 +378,26 @@ public function testWithHeaderNormalizesContinuationToNotContainNewlines(string public function numericHeaderValuesProvider(): array { return [ - 'integer' => [ 123 ], - 'float' => [ 12.3 ], + 'integer' => [123], + 'float' => [12.3], ]; } /** * @dataProvider numericHeaderValuesProvider * @group 99 - * * @psalm-suppress InvalidScalarArgument this test explicitly verifies that pre-type-declaration * implicit type conversion semantics still apply, for BC Compliance */ public function testWithHeaderShouldAllowIntegersAndFloats(float $value): void { $message = $this->message - ->withHeader('X-Test-Array', [ $value ]) + ->withHeader('X-Test-Array', [$value]) ->withHeader('X-Test-Scalar', $value); $this->assertSame([ - 'X-Test-Array' => [ (string) $value ], - 'X-Test-Scalar' => [ (string) $value ], + 'X-Test-Array' => [(string) $value], + 'X-Test-Scalar' => [(string) $value], ], $message->getHeaders()); } @@ -421,15 +415,13 @@ public function invalidHeaderValueTypes(): array /** @return non-empty-array */ public function invalidArrayHeaderValues(): array { - $values = $this->invalidHeaderValueTypes(); + $values = $this->invalidHeaderValueTypes(); $values['array'] = [['INVALID']]; return $values; } /** * @dataProvider invalidArrayHeaderValues - * @group 99 - * * @param mixed $value */ public function testWithHeaderShouldRaiseExceptionForInvalidHeaderValuesInArrays($value): void @@ -437,13 +429,12 @@ public function testWithHeaderShouldRaiseExceptionForInvalidHeaderValuesInArrays $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('header value type'); - $this->message->withHeader('X-Test-Array', [ $value ]); + /** @psalm-suppress MixedArgumentTypeCoercion */ + $this->message->withHeader('X-Test-Array', [$value]); } /** * @dataProvider invalidHeaderValueTypes - * @group 99 - * * @param mixed $value */ public function testWithHeaderShouldRaiseExceptionForInvalidHeaderScalarValues($value): void @@ -451,6 +442,7 @@ public function testWithHeaderShouldRaiseExceptionForInvalidHeaderScalarValues($ $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('header value type'); + /** @psalm-suppress MixedArgument */ $this->message->withHeader('X-Test-Scalar', $value); } } diff --git a/test/PhpInputStreamTest.php b/test/PhpInputStreamTest.php index 4d402654..7a440fff 100644 --- a/test/PhpInputStreamTest.php +++ b/test/PhpInputStreamTest.php @@ -12,39 +12,35 @@ class PhpInputStreamTest extends TestCase { - /** - * @var string - */ + /** @var string */ protected $file; - /** - * @var PhpInputStream - */ + /** @var PhpInputStream */ protected $stream; - protected function setUp() : void + protected function setUp(): void { - $this->file = __DIR__ . '/TestAsset/php-input-stream.txt'; + $this->file = __DIR__ . '/TestAsset/php-input-stream.txt'; $this->stream = new PhpInputStream($this->file); } - public function getFileContents() + public function getFileContents(): string { return file_get_contents($this->file); } - public function assertStreamContents($test, $message = '') + public function assertStreamContents(string $test, string $message = ''): void { $content = $this->getFileContents(); $this->assertSame($content, $test, $message); } - public function testStreamIsNeverWritable() + public function testStreamIsNeverWritable(): void { $this->assertFalse($this->stream->isWritable()); } - public function testCanReadStreamIteratively() + public function testCanReadStreamIteratively(): void { $body = ''; while (! $this->stream->eof()) { @@ -53,7 +49,7 @@ public function testCanReadStreamIteratively() $this->assertStreamContents($body); } - public function testGetContentsReturnsRemainingContentsOfStream() + public function testGetContentsReturnsRemainingContentsOfStream(): void { $this->stream->read(128); $remainder = $this->stream->getContents(); @@ -62,7 +58,7 @@ public function testGetContentsReturnsRemainingContentsOfStream() $this->assertSame(substr($contents, 128), $remainder); } - public function testGetContentsReturnCacheWhenReachedEof() + public function testGetContentsReturnCacheWhenReachedEof(): void { $this->stream->getContents(); $this->assertStreamContents($this->stream->getContents()); @@ -73,15 +69,15 @@ public function testGetContentsReturnCacheWhenReachedEof() $this->assertSame('0', $stream->getContents(), 'Don\'t evaluate 0 as empty'); } - public function testCastingToStringReturnsFullContentsRegardlesOfPriorReads() + public function testCastingToStringReturnsFullContentsRegardlessOfPriorReads(): void { $this->stream->read(128); $this->assertStreamContents($this->stream->__toString()); } - public function testMultipleCastsToStringReturnSameContentsEvenIfReadsOccur() + public function testMultipleCastsToStringReturnSameContentsEvenIfReadsOccur(): void { - $first = (string) $this->stream; + $first = (string) $this->stream; $this->stream->read(128); $second = (string) $this->stream; $this->assertSame($first, $second); diff --git a/test/RelativeStreamTest.php b/test/RelativeStreamTest.php index f111ceb8..4cd79d32 100644 --- a/test/RelativeStreamTest.php +++ b/test/RelativeStreamTest.php @@ -20,7 +20,7 @@ class RelativeStreamTest extends TestCase { use ProphecyTrait; - public function testToString() + public function testToString(): void { $decorated = $this->prophesize(Stream::class); $decorated->isSeekable()->willReturn(true); @@ -29,11 +29,11 @@ public function testToString() $decorated->getContents()->shouldBeCalled()->willReturn('foobarbaz'); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->__toString(); + $ret = $stream->__toString(); $this->assertSame('foobarbaz', $ret); } - public function testClose() + public function testClose(): void { $decorated = $this->prophesize(Stream::class); $decorated->close()->shouldBeCalled(); @@ -41,61 +41,61 @@ public function testClose() $stream->close(); } - public function testDetach() + public function testDetach(): void { $decorated = $this->prophesize(Stream::class); $decorated->detach()->shouldBeCalled()->willReturn(250); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->detach(); + $ret = $stream->detach(); $this->assertSame(250, $ret); } - public function testGetSize() + public function testGetSize(): void { $decorated = $this->prophesize(Stream::class); $decorated->getSize()->shouldBeCalled()->willReturn(250); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->getSize(); + $ret = $stream->getSize(); $this->assertSame(150, $ret); } - public function testTell() + public function testTell(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->shouldBeCalled()->willReturn(188); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->tell(); + $ret = $stream->tell(); $this->assertSame(88, $ret); } - public function testIsSeekable() + public function testIsSeekable(): void { $decorated = $this->prophesize(Stream::class); $decorated->isSeekable()->shouldBeCalled()->willReturn(true); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->isSeekable(); + $ret = $stream->isSeekable(); $this->assertSame(true, $ret); } - public function testIsWritable() + public function testIsWritable(): void { $decorated = $this->prophesize(Stream::class); $decorated->isWritable()->shouldBeCalled()->willReturn(true); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->isWritable(); + $ret = $stream->isWritable(); $this->assertSame(true, $ret); } - public function testIsReadable() + public function testIsReadable(): void { $decorated = $this->prophesize(Stream::class); $decorated->isReadable()->shouldBeCalled()->willReturn(false); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->isReadable(); + $ret = $stream->isReadable(); $this->assertSame(false, $ret); } - public function testSeek() + public function testSeek(): void { $decorated = $this->prophesize(Stream::class); $decorated->seek(126, SEEK_SET)->shouldBeCalled(); @@ -103,7 +103,7 @@ public function testSeek() $this->assertNull($stream->seek(26)); } - public function testRewind() + public function testRewind(): void { $decorated = $this->prophesize(Stream::class); $decorated->seek(100, SEEK_SET)->shouldBeCalled(); @@ -111,46 +111,46 @@ public function testRewind() $this->assertNull($stream->rewind()); } - public function testWrite() + public function testWrite(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->willReturn(100); $decorated->write("foobaz")->shouldBeCalled()->willReturn(6); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->write("foobaz"); + $ret = $stream->write("foobaz"); $this->assertSame(6, $ret); } - public function testRead() + public function testRead(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->willReturn(100); $decorated->read(3)->shouldBeCalled()->willReturn("foo"); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->read(3); + $ret = $stream->read(3); $this->assertSame("foo", $ret); } - public function testGetContents() + public function testGetContents(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->willReturn(100); $decorated->getContents()->shouldBeCalled()->willReturn("foo"); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->getContents(); + $ret = $stream->getContents(); $this->assertSame("foo", $ret); } - public function testGetMetadata() + public function testGetMetadata(): void { $decorated = $this->prophesize(Stream::class); $decorated->getMetadata("bar")->shouldBeCalled()->willReturn("foo"); $stream = new RelativeStream($decorated->reveal(), 100); - $ret = $stream->getMetadata("bar"); + $ret = $stream->getMetadata("bar"); $this->assertSame("foo", $ret); } - public function testWriteRaisesExceptionWhenPointerIsBehindOffset() + public function testWriteRaisesExceptionWhenPointerIsBehindOffset(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->shouldBeCalled()->willReturn(0); @@ -163,7 +163,7 @@ public function testWriteRaisesExceptionWhenPointerIsBehindOffset() $stream->write("foobaz"); } - public function testReadRaisesExceptionWhenPointerIsBehindOffset() + public function testReadRaisesExceptionWhenPointerIsBehindOffset(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->shouldBeCalled()->willReturn(0); @@ -176,7 +176,7 @@ public function testReadRaisesExceptionWhenPointerIsBehindOffset() $stream->read(3); } - public function testGetContentsRaisesExceptionWhenPointerIsBehindOffset() + public function testGetContentsRaisesExceptionWhenPointerIsBehindOffset(): void { $decorated = $this->prophesize(Stream::class); $decorated->tell()->shouldBeCalled()->willReturn(0); @@ -189,7 +189,7 @@ public function testGetContentsRaisesExceptionWhenPointerIsBehindOffset() $stream->getContents(); } - public function testCanReadContentFromNotSeekableResource() + public function testCanReadContentFromNotSeekableResource(): void { $decorated = $this->prophesize(Stream::class); $decorated->isSeekable()->willReturn(false); diff --git a/test/Request/ArraySerializerTest.php b/test/Request/ArraySerializerTest.php index 2bfb6a2b..a4e6a4ff 100644 --- a/test/Request/ArraySerializerTest.php +++ b/test/Request/ArraySerializerTest.php @@ -13,7 +13,7 @@ class ArraySerializerTest extends TestCase { - public function testSerializeToArray() + public function testSerializeToArray(): void { $stream = new Stream('php://memory', 'wb+'); $stream->write('{"test":"value"}'); @@ -29,46 +29,46 @@ public function testSerializeToArray() $message = ArraySerializer::toArray($request); $this->assertSame([ - 'method' => 'POST', - 'request_target' => '/foo/bar?baz=bat', - 'uri' => 'http://example.com/foo/bar?baz=bat', + 'method' => 'POST', + 'request_target' => '/foo/bar?baz=bat', + 'uri' => 'http://example.com/foo/bar?baz=bat', 'protocol_version' => '1.1', - 'headers' => [ - 'Host' => [ + 'headers' => [ + 'Host' => [ 'example.com', ], - 'Accept' => [ + 'Accept' => [ 'application/json', ], 'X-Foo-Bar' => [ 'Baz', - 'Bat' + 'Bat', ], ], - 'body' => '{"test":"value"}', + 'body' => '{"test":"value"}', ], $message); } - public function testDeserializeFromArray() + public function testDeserializeFromArray(): void { $serializedRequest = [ - 'method' => 'POST', - 'request_target' => '/foo/bar?baz=bat', - 'uri' => 'http://example.com/foo/bar?baz=bat', + 'method' => 'POST', + 'request_target' => '/foo/bar?baz=bat', + 'uri' => 'http://example.com/foo/bar?baz=bat', 'protocol_version' => '1.1', - 'headers' => [ - 'Host' => [ + 'headers' => [ + 'Host' => [ 'example.com', ], - 'Accept' => [ + 'Accept' => [ 'application/json', ], 'X-Foo-Bar' => [ 'Baz', - 'Bat' + 'Bat', ], ], - 'body' => '{"test":"value"}', + 'body' => '{"test":"value"}', ]; $message = ArraySerializer::fromArray($serializedRequest); @@ -87,23 +87,23 @@ public function testDeserializeFromArray() $this->assertSame(Request\Serializer::toString($request), Request\Serializer::toString($message)); } - public function testMissingBodyParamInSerializedRequestThrowsException() + public function testMissingBodyParamInSerializedRequestThrowsException(): void { $serializedRequest = [ - 'method' => 'POST', - 'request_target' => '/foo/bar?baz=bat', - 'uri' => 'http://example.com/foo/bar?baz=bat', + 'method' => 'POST', + 'request_target' => '/foo/bar?baz=bat', + 'uri' => 'http://example.com/foo/bar?baz=bat', 'protocol_version' => '1.1', - 'headers' => [ - 'Host' => [ + 'headers' => [ + 'Host' => [ 'example.com', ], - 'Accept' => [ + 'Accept' => [ 'application/json', ], 'X-Foo-Bar' => [ 'Baz', - 'Bat' + 'Bat', ], ], ]; diff --git a/test/Request/SerializerTest.php b/test/Request/SerializerTest.php index 231e3a06..6d181a72 100644 --- a/test/Request/SerializerTest.php +++ b/test/Request/SerializerTest.php @@ -20,7 +20,7 @@ class SerializerTest extends TestCase { - public function testSerializesBasicRequest() : void + public function testSerializesBasicRequest(): void { $request = (new Request()) ->withMethod('GET') @@ -34,7 +34,7 @@ public function testSerializesBasicRequest() : void ); } - public function testSerializesRequestWithBody() : void + public function testSerializesRequestWithBody(): void { $body = json_encode(['test' => 'value']); $stream = new Stream('php://memory', 'wb+'); @@ -52,7 +52,7 @@ public function testSerializesRequestWithBody() : void $this->assertStringContainsString("\r\n\r\n" . $body, $message); } - public function testSerializesMultipleHeadersCorrectly() : void + public function testSerializesMultipleHeadersCorrectly(): void { $request = (new Request()) ->withMethod('GET') @@ -65,7 +65,8 @@ public function testSerializesMultipleHeadersCorrectly() : void $this->assertStringContainsString("X-Foo-Bar: Bat", $message); } - public function originForms() : array + /** @return array}> */ + public function originForms(): array { return [ 'path-only' => [ @@ -83,9 +84,13 @@ public function originForms() : array /** * @dataProvider originForms + * @param array $expectations */ - public function testCanDeserializeRequestWithOriginForm($line, $requestTarget, $expectations) : void - { + public function testCanDeserializeRequestWithOriginForm( + string $line, + string $requestTarget, + array $expectations + ): void { $message = $line . "\r\nX-Foo-Bar: Baz\r\n\r\nContent"; $request = Serializer::fromString($message); @@ -98,7 +103,8 @@ public function testCanDeserializeRequestWithOriginForm($line, $requestTarget, $ } } - public function absoluteForms() : array + /** @return array}> */ + public function absoluteForms(): array { return [ 'path-only' => [ @@ -148,9 +154,13 @@ public function absoluteForms() : array /** * @dataProvider absoluteForms + * @param array $expectations */ - public function testCanDeserializeRequestWithAbsoluteForm($line, $requestTarget, $expectations) : void - { + public function testCanDeserializeRequestWithAbsoluteForm( + string $line, + string $requestTarget, + array $expectations + ): void { $message = $line . "\r\nX-Foo-Bar: Baz\r\n\r\nContent"; $request = Serializer::fromString($message); @@ -164,7 +174,7 @@ public function testCanDeserializeRequestWithAbsoluteForm($line, $requestTarget, } } - public function testCanDeserializeRequestWithAuthorityForm() : void + public function testCanDeserializeRequestWithAuthorityForm(): void { $message = "CONNECT www.example.com:80 HTTP/1.1\r\nX-Foo-Bar: Baz"; $request = Serializer::fromString($message); @@ -176,7 +186,7 @@ public function testCanDeserializeRequestWithAuthorityForm() : void $this->assertNotSame(80, $uri->getPort()); } - public function testCanDeserializeRequestWithAsteriskForm() : void + public function testCanDeserializeRequestWithAsteriskForm(): void { $message = "OPTIONS * HTTP/1.1\r\nHost: www.example.com"; $request = Serializer::fromString($message); @@ -190,7 +200,8 @@ public function testCanDeserializeRequestWithAsteriskForm() : void $this->assertSame('www.example.com', $request->getHeaderLine('Host')); } - public function invalidRequestLines() : array + /** @return array */ + public function invalidRequestLines(): array { return [ 'missing-method' => ['/foo/bar HTTP/1.1'], @@ -203,7 +214,7 @@ public function invalidRequestLines() : array /** * @dataProvider invalidRequestLines */ - public function testRaisesExceptionDuringDeserializationForInvalidRequestLine($line) : void + public function testRaisesExceptionDuringDeserializationForInvalidRequestLine(string $line): void { $message = $line . "\r\nX-Foo-Bar: Baz\r\n\r\nContent"; @@ -212,9 +223,9 @@ public function testRaisesExceptionDuringDeserializationForInvalidRequestLine($l Serializer::fromString($message); } - public function testCanDeserializeRequestWithMultipleHeadersOfSameName() : void + public function testCanDeserializeRequestWithMultipleHeadersOfSameName(): void { - $text = "POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\nX-Foo-Bar: Bat\r\n\r\nContent!"; + $text = "POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\nX-Foo-Bar: Bat\r\n\r\nContent!"; $request = Serializer::fromString($text); $this->assertInstanceOf(RequestInterface::class, $request); @@ -225,18 +236,19 @@ public function testCanDeserializeRequestWithMultipleHeadersOfSameName() : void $this->assertSame(['Baz', 'Bat'], $values); } - public function headersWithContinuationLines() : array + /** @return array */ + public function headersWithContinuationLines(): array { return [ 'space' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n Bat\r\n\r\nContent!"], - 'tab' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n\tBat\r\n\r\nContent!"], + 'tab' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n\tBat\r\n\r\nContent!"], ]; } /** * @dataProvider headersWithContinuationLines */ - public function testCanDeserializeRequestWithHeaderContinuations($text) : void + public function testCanDeserializeRequestWithHeaderContinuations(string $text): void { $request = Serializer::fromString($text); @@ -251,11 +263,11 @@ public function testCanDeserializeRequestWithHeaderContinuations($text) : void public function headersWithWhitespace(): array { return [ - 'no' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz\r\n\r\nContent!"], - 'leading' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"], + 'no' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz\r\n\r\nContent!"], + 'leading' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"], 'trailing' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz \r\n\r\nContent!"], - 'both' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz \r\n\r\nContent!"], - 'mixed' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: \t Baz\t \t\r\n\r\nContent!"], + 'both' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz \r\n\r\nContent!"], + 'mixed' => ["POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: \t Baz\t \t\r\n\r\nContent!"], ]; } @@ -271,20 +283,21 @@ public function testDeserializationRemovesWhitespaceAroundValues(string $text): $this->assertSame('Baz', $request->getHeaderLine('X-Foo-Bar')); } - public function messagesWithInvalidHeaders() : array + /** @return array */ + public function messagesWithInvalidHeaders(): array { return [ - 'invalid-name' => [ + 'invalid-name' => [ "GET /foo HTTP/1.1\r\nThi;-I()-Invalid: value", - 'Invalid header detected' + 'Invalid header detected', ], - 'invalid-format' => [ + 'invalid-format' => [ "POST /foo HTTP/1.1\r\nThis is not a header\r\n\r\nContent", - 'Invalid header detected' + 'Invalid header detected', ], 'invalid-continuation' => [ "POST /foo HTTP/1.1\r\nX-Foo-Bar: Baz\r\nInvalid continuation\r\nContent", - 'Invalid header continuation' + 'Invalid header continuation', ], ]; } @@ -292,15 +305,17 @@ public function messagesWithInvalidHeaders() : array /** * @dataProvider messagesWithInvalidHeaders */ - public function testDeserializationRaisesExceptionForMalformedHeaders($message, $exceptionMessage) : void - { + public function testDeserializationRaisesExceptionForMalformedHeaders( + string $message, + string $exceptionMessage + ): void { $this->expectException(UnexpectedValueException::class); $this->expectExceptionMessage($exceptionMessage); Serializer::fromString($message); } - public function testFromStreamThrowsExceptionWhenStreamIsNotReadable() : void + public function testFromStreamThrowsExceptionWhenStreamIsNotReadable(): void { $stream = $this->createMock(StreamInterface::class); $stream @@ -313,7 +328,7 @@ public function testFromStreamThrowsExceptionWhenStreamIsNotReadable() : void Serializer::fromStream($stream); } - public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable() : void + public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable(): void { $stream = $this->createMock(StreamInterface::class); $stream @@ -330,7 +345,7 @@ public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable() : void Serializer::fromStream($stream); } - public function testFromStreamStopsReadingAfterScanningHeader() : void + public function testFromStreamStopsReadingAfterScanningHeader(): void { $headers = "POST /foo HTTP/1.0\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n Bat\r\n\r\n"; $payload = $headers . "Content!"; diff --git a/test/RequestTest.php b/test/RequestTest.php index dd1bbb55..e7e134e6 100644 --- a/test/RequestTest.php +++ b/test/RequestTest.php @@ -9,33 +9,33 @@ use Laminas\Diactoros\Stream; use Laminas\Diactoros\Uri; use PHPUnit\Framework\TestCase; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; class RequestTest extends TestCase { - /** - * @var Request - */ + /** @var Request */ protected $request; - protected function setUp() : void + protected function setUp(): void { $this->request = new Request(); } - public function testMethodIsGetByDefault() + public function testMethodIsGetByDefault(): void { $this->assertSame('GET', $this->request->getMethod()); } - public function testMethodMutatorReturnsCloneWithChangedMethod() + public function testMethodMutatorReturnsCloneWithChangedMethod(): void { $request = $this->request->withMethod('POST'); $this->assertNotSame($this->request, $request); $this->assertEquals('POST', $request->getMethod()); } - public function invalidMethod() + /** @return array */ + public function invalidMethod(): array { return [ [null], @@ -45,14 +45,16 @@ public function invalidMethod() /** * @dataProvider invalidMethod + * @param mixed $method */ - public function testWithInvalidMethod($method) + public function testWithInvalidMethod($method): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ $this->request->withMethod($method); } - public function testReturnsUnpopulatedUriByDefault() + public function testReturnsUnpopulatedUriByDefault(): void { $uri = $this->request->getUri(); $this->assertInstanceOf(UriInterface::class, $uri); @@ -66,14 +68,15 @@ public function testReturnsUnpopulatedUriByDefault() $this->assertEmpty($uri->getFragment()); } - public function testConstructorRaisesExceptionForInvalidStream() + public function testConstructorRaisesExceptionForInvalidStream(): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress InvalidArgument */ new Request(['TOTALLY INVALID']); } - public function testWithUriReturnsNewInstanceWithNewUri() + public function testWithUriReturnsNewInstanceWithNewUri(): void { $request = $this->request->withUri(new Uri('https://example.com:10082/foo/bar?baz=bat')); $this->assertNotSame($this->request, $request); @@ -83,7 +86,7 @@ public function testWithUriReturnsNewInstanceWithNewUri() $this->assertSame('/baz/bat?foo=bar', (string) $request2->getUri()); } - public function testConstructorCanAcceptAllMessageParts() + public function testConstructorCanAcceptAllMessageParts(): void { $uri = new Uri('http://example.com/'); $body = new Stream('php://memory'); @@ -107,48 +110,52 @@ public function testConstructorCanAcceptAllMessageParts() } } - public function testDefaultStreamIsWritable() + public function testDefaultStreamIsWritable(): void { $request = new Request(); $request->getBody()->write("test"); - $this->assertSame("test", (string)$request->getBody()); + $this->assertSame("test", (string) $request->getBody()); } - public function invalidRequestUri() + /** @return array */ + public function invalidRequestUri(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'int' => [ 1 ], - 'float' => [ 1.1 ], - 'array' => [ ['http://example.com'] ], - 'stdClass' => [ (object) [ 'href' => 'http://example.com'] ], + 'true' => [true], + 'false' => [false], + 'int' => [1], + 'float' => [1.1], + 'array' => [['http://example.com']], + 'stdClass' => [(object) ['href' => 'http://example.com']], ]; } /** * @dataProvider invalidRequestUri + * @param mixed $uri */ - public function testConstructorRaisesExceptionForInvalidUri($uri) + public function testConstructorRaisesExceptionForInvalidUri($uri): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid URI'); + /** @psalm-suppress MixedArgument */ new Request($uri); } - public function invalidRequestMethod() + /** @return array */ + public function invalidRequestMethod(): array { return [ - 'bad-string' => [ 'BOGUS METHOD' ], + 'bad-string' => ['BOGUS METHOD'], ]; } /** * @dataProvider invalidRequestMethod */ - public function testConstructorRaisesExceptionForInvalidMethod($method) + public function testConstructorRaisesExceptionForInvalidMethod(string $method): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Unsupported HTTP method'); @@ -156,9 +163,10 @@ public function testConstructorRaisesExceptionForInvalidMethod($method) new Request(null, $method); } - public function customRequestMethods() + /** @return array */ + public function customRequestMethods(): array { - return[ + return [ /* WebDAV methods */ 'TRACE' => ['TRACE'], 'PROPFIND' => ['PROPFIND'], @@ -176,99 +184,105 @@ public function customRequestMethods() /** * @dataProvider customRequestMethods - * @group 29 */ - public function testAllowsCustomRequestMethodsThatFollowSpec($method) + public function testAllowsCustomRequestMethodsThatFollowSpec(string $method): void { $request = new Request(null, $method); $this->assertSame($method, $request->getMethod()); } - public function invalidRequestBody() + /** @return array */ + public function invalidRequestBody(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'int' => [ 1 ], - 'float' => [ 1.1 ], - 'array' => [ ['BODY'] ], - 'stdClass' => [ (object) [ 'body' => 'BODY'] ], + 'true' => [true], + 'false' => [false], + 'int' => [1], + 'float' => [1.1], + 'array' => [['BODY']], + 'stdClass' => [(object) ['body' => 'BODY']], ]; } /** * @dataProvider invalidRequestBody + * @param mixed $body */ - public function testConstructorRaisesExceptionForInvalidBody($body) + public function testConstructorRaisesExceptionForInvalidBody($body): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('stream'); + /** @psalm-suppress MixedArgument */ new Request(null, null, $body); } - public function invalidHeaderTypes() + /** @return array */ + public function invalidHeaderTypes(): array { return [ 'indexed-array' => [[['INVALID']], 'header name'], - 'null' => [['x-invalid-null' => null]], - 'true' => [['x-invalid-true' => true]], - 'false' => [['x-invalid-false' => false]], - 'object' => [['x-invalid-object' => (object) ['INVALID']]], + 'null' => [['x-invalid-null' => null]], + 'true' => [['x-invalid-true' => true]], + 'false' => [['x-invalid-false' => false]], + 'object' => [['x-invalid-object' => (object) ['INVALID']]], ]; } /** * @dataProvider invalidHeaderTypes - * @group 99 + * @param mixed[] $headers */ - public function testConstructorRaisesExceptionForInvalidHeaders($headers, $contains = 'header value type') - { + public function testConstructorRaisesExceptionForInvalidHeaders( + array $headers, + string $contains = 'header value type' + ): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage($contains); new Request(null, null, 'php://memory', $headers); } - public function testRequestTargetIsSlashWhenNoUriPresent() + public function testRequestTargetIsSlashWhenNoUriPresent(): void { $request = new Request(); $this->assertSame('/', $request->getRequestTarget()); } - public function testRequestTargetIsSlashWhenUriHasNoPathOrQuery() + public function testRequestTargetIsSlashWhenUriHasNoPathOrQuery(): void { $request = (new Request()) ->withUri(new Uri('http://example.com')); $this->assertSame('/', $request->getRequestTarget()); } - public function requestsWithUri() + /** @return array */ + public function requestsWithUri(): array { return [ - 'absolute-uri' => [ + 'absolute-uri' => [ (new Request()) ->withUri(new Uri('https://api.example.com/user')) ->withMethod('POST'), - '/user' + '/user', ], 'absolute-uri-with-query' => [ (new Request()) ->withUri(new Uri('https://api.example.com/user?foo=bar')) ->withMethod('POST'), - '/user?foo=bar' + '/user?foo=bar', ], - 'relative-uri' => [ + 'relative-uri' => [ (new Request()) ->withUri(new Uri('/user')) ->withMethod('GET'), - '/user' + '/user', ], 'relative-uri-with-query' => [ (new Request()) ->withUri(new Uri('/user?foo=bar')) ->withMethod('GET'), - '/user?foo=bar' + '/user?foo=bar', ], ]; } @@ -276,33 +290,34 @@ public function requestsWithUri() /** * @dataProvider requestsWithUri */ - public function testReturnsRequestTargetWhenUriIsPresent($request, $expected) + public function testReturnsRequestTargetWhenUriIsPresent(RequestInterface $request, string $expected): void { $this->assertSame($expected, $request->getRequestTarget()); } - public function validRequestTargets() + /** @return array */ + public function validRequestTargets(): array { return [ - 'asterisk-form' => [ '*' ], - 'authority-form' => [ 'api.example.com' ], - 'absolute-form' => [ 'https://api.example.com/users' ], - 'absolute-form-query' => [ 'https://api.example.com/users?foo=bar' ], - 'origin-form-path-only' => [ '/users' ], - 'origin-form' => [ '/users?id=foo' ], + 'asterisk-form' => ['*'], + 'authority-form' => ['api.example.com'], + 'absolute-form' => ['https://api.example.com/users'], + 'absolute-form-query' => ['https://api.example.com/users?foo=bar'], + 'origin-form-path-only' => ['/users'], + 'origin-form' => ['/users?id=foo'], ]; } /** * @dataProvider validRequestTargets */ - public function testCanProvideARequestTarget($requestTarget) + public function testCanProvideARequestTarget(string $requestTarget): void { $request = (new Request())->withRequestTarget($requestTarget); $this->assertSame($requestTarget, $request->getRequestTarget()); } - public function testRequestTargetCannotContainWhitespace() + public function testRequestTargetCannotContainWhitespace(): void { $request = new Request(); @@ -312,26 +327,23 @@ public function testRequestTargetCannotContainWhitespace() $request->withRequestTarget('foo bar baz'); } - public function testRequestTargetDoesNotCacheBetweenInstances() + public function testRequestTargetDoesNotCacheBetweenInstances(): void { - $request = (new Request())->withUri(new Uri('https://example.com/foo/bar')); - $original = $request->getRequestTarget(); + $request = (new Request())->withUri(new Uri('https://example.com/foo/bar')); + $original = $request->getRequestTarget(); $newRequest = $request->withUri(new Uri('http://mwop.net/bar/baz')); $this->assertNotSame($original, $newRequest->getRequestTarget()); } - public function testSettingNewUriResetsRequestTarget() + public function testSettingNewUriResetsRequestTarget(): void { - $request = (new Request())->withUri(new Uri('https://example.com/foo/bar')); + $request = (new Request())->withUri(new Uri('https://example.com/foo/bar')); $newRequest = $request->withUri(new Uri('http://mwop.net/bar/baz')); $this->assertNotSame($request->getRequestTarget(), $newRequest->getRequestTarget()); } - /** - * @group 39 - */ - public function testGetHeadersContainsHostHeaderIfUriWithHostIsPresent() + public function testGetHeadersContainsHostHeaderIfUriWithHostIsPresent(): void { $request = new Request('http://example.com'); $headers = $request->getHeaders(); @@ -339,10 +351,7 @@ public function testGetHeadersContainsHostHeaderIfUriWithHostIsPresent() $this->assertStringContainsString('example.com', $headers['Host'][0]); } - /** - * @group 39 - */ - public function testGetHeadersContainsHostHeaderIfUriWithHostIsDeleted() + public function testGetHeadersContainsHostHeaderIfUriWithHostIsDeleted(): void { $request = (new Request('http://example.com'))->withoutHeader('host'); $headers = $request->getHeaders(); @@ -350,106 +359,79 @@ public function testGetHeadersContainsHostHeaderIfUriWithHostIsDeleted() $this->assertContains('example.com', $headers['Host']); } - /** - * @group 39 - */ - public function testGetHeadersContainsNoHostHeaderIfNoUriPresent() + public function testGetHeadersContainsNoHostHeaderIfNoUriPresent(): void { $request = new Request(); $headers = $request->getHeaders(); $this->assertArrayNotHasKey('Host', $headers); } - /** - * @group 39 - */ - public function testGetHeadersContainsNoHostHeaderIfUriDoesNotContainHost() + public function testGetHeadersContainsNoHostHeaderIfUriDoesNotContainHost(): void { $request = new Request(new Uri()); $headers = $request->getHeaders(); $this->assertArrayNotHasKey('Host', $headers); } - /** - * @group 39 - */ - public function testGetHostHeaderReturnsUriHostWhenPresent() + public function testGetHostHeaderReturnsUriHostWhenPresent(): void { $request = new Request('http://example.com'); - $header = $request->getHeader('host'); + $header = $request->getHeader('host'); $this->assertSame(['example.com'], $header); } - /** - * @group 39 - */ - public function testGetHostHeaderReturnsUriHostWhenHostHeaderDeleted() + public function testGetHostHeaderReturnsUriHostWhenHostHeaderDeleted(): void { $request = (new Request('http://example.com'))->withoutHeader('host'); - $header = $request->getHeader('host'); + $header = $request->getHeader('host'); $this->assertSame(['example.com'], $header); } - /** - * @group 39 - */ - public function testGetHostHeaderReturnsEmptyArrayIfNoUriPresent() + public function testGetHostHeaderReturnsEmptyArrayIfNoUriPresent(): void { $request = new Request(); $this->assertSame([], $request->getHeader('host')); } - /** - * @group 39 - */ - public function testGetHostHeaderReturnsEmptyArrayIfUriDoesNotContainHost() + public function testGetHostHeaderReturnsEmptyArrayIfUriDoesNotContainHost(): void { $request = new Request(new Uri()); $this->assertSame([], $request->getHeader('host')); } - /** - * @group 39 - */ - public function testGetHostHeaderLineReturnsUriHostWhenPresent() + public function testGetHostHeaderLineReturnsUriHostWhenPresent(): void { $request = new Request('http://example.com'); - $header = $request->getHeaderLine('host'); + $header = $request->getHeaderLine('host'); $this->assertStringContainsString('example.com', $header); } - /** - * @group 39 - */ - public function testGetHostHeaderLineReturnsEmptyStringIfNoUriPresent() + public function testGetHostHeaderLineReturnsEmptyStringIfNoUriPresent(): void { $request = new Request(); $this->assertEmpty($request->getHeaderLine('host')); } - /** - * @group 39 - */ - public function testGetHostHeaderLineReturnsEmptyStringIfUriDoesNotContainHost() + public function testGetHostHeaderLineReturnsEmptyStringIfUriDoesNotContainHost(): void { $request = new Request(new Uri()); $this->assertEmpty($request->getHeaderLine('host')); } - public function testHostHeaderSetFromUriOnCreationIfNoHostHeaderSpecified() + public function testHostHeaderSetFromUriOnCreationIfNoHostHeaderSpecified(): void { $request = new Request('http://www.example.com'); $this->assertTrue($request->hasHeader('Host')); $this->assertSame('www.example.com', $request->getHeaderLine('host')); } - public function testHostHeaderNotSetFromUriOnCreationIfHostHeaderSpecified() + public function testHostHeaderNotSetFromUriOnCreationIfHostHeaderSpecified(): void { $request = new Request('http://www.example.com', null, 'php://memory', ['Host' => 'www.test.com']); $this->assertSame('www.test.com', $request->getHeaderLine('host')); } - public function testPassingPreserveHostFlagWhenUpdatingUriDoesNotUpdateHostHeader() + public function testPassingPreserveHostFlagWhenUpdatingUriDoesNotUpdateHostHeader(): void { $request = (new Request()) ->withAddedHeader('Host', 'example.com'); @@ -460,7 +442,7 @@ public function testPassingPreserveHostFlagWhenUpdatingUriDoesNotUpdateHostHeade $this->assertSame('example.com', $new->getHeaderLine('Host')); } - public function testNotPassingPreserveHostFlagWhenUpdatingUriWithoutHostDoesNotUpdateHostHeader() + public function testNotPassingPreserveHostFlagWhenUpdatingUriWithoutHostDoesNotUpdateHostHeader(): void { $request = (new Request()) ->withAddedHeader('Host', 'example.com'); @@ -471,7 +453,7 @@ public function testNotPassingPreserveHostFlagWhenUpdatingUriWithoutHostDoesNotU $this->assertSame('example.com', $new->getHeaderLine('Host')); } - public function testHostHeaderUpdatesToUriHostAndPortWhenPreserveHostDisabledAndNonStandardPort() + public function testHostHeaderUpdatesToUriHostAndPortWhenPreserveHostDisabledAndNonStandardPort(): void { $request = (new Request()) ->withAddedHeader('Host', 'example.com'); @@ -484,7 +466,8 @@ public function testHostHeaderUpdatesToUriHostAndPortWhenPreserveHostDisabledAnd $this->assertSame('www.example.com:10081', $new->getHeaderLine('Host')); } - public function headersWithInjectionVectors() + /** @return array}> */ + public function headersWithInjectionVectors(): array { return [ 'name-with-cr' => ["X-Foo\r-Bar", 'value'], @@ -503,43 +486,43 @@ public function headersWithInjectionVectors() } /** - * @group ZF2015-04 * @dataProvider headersWithInjectionVectors + * @param string|list $value */ - public function testConstructorRaisesExceptionForHeadersWithCRLFVectors(string $name, $value) + public function testConstructorRaisesExceptionForHeadersWithCRLFVectors(string $name, $value): void { $this->expectException(InvalidArgumentException::class); new Request(null, null, 'php://memory', [$name => $value]); } - public function hostHeaderKeys() + /** @return array */ + public function hostHeaderKeys(): array { return [ - 'lowercase' => ['host'], - 'mixed-4' => ['hosT'], - 'mixed-3-4' => ['hoST'], - 'reverse-titlecase' => ['hOST'], - 'uppercase' => ['HOST'], - 'mixed-1-2-3' => ['HOSt'], - 'mixed-1-2' => ['HOst'], - 'titlecase' => ['Host'], - 'mixed-1-4' => ['HosT'], - 'mixed-1-2-4' => ['HOsT'], - 'mixed-1-3-4' => ['HoST'], - 'mixed-1-3' => ['HoSt'], - 'mixed-2-3' => ['hOSt'], - 'mixed-2-4' => ['hOsT'], - 'mixed-2' => ['hOst'], - 'mixed-3' => ['hoSt'], + 'lowercase' => ['host'], + 'mixed-4' => ['hosT'], + 'mixed-3-4' => ['hoST'], + 'reverse-titlecase' => ['hOST'], + 'uppercase' => ['HOST'], + 'mixed-1-2-3' => ['HOSt'], + 'mixed-1-2' => ['HOst'], + 'titlecase' => ['Host'], + 'mixed-1-4' => ['HosT'], + 'mixed-1-2-4' => ['HOsT'], + 'mixed-1-3-4' => ['HoST'], + 'mixed-1-3' => ['HoSt'], + 'mixed-2-3' => ['hOSt'], + 'mixed-2-4' => ['hOsT'], + 'mixed-2' => ['hOst'], + 'mixed-3' => ['hoSt'], ]; } /** - * @group 91 * @dataProvider hostHeaderKeys */ - public function testWithUriAndNoPreserveHostWillOverwriteHostHeaderRegardlessOfOriginalCase($hostKey) + public function testWithUriAndNoPreserveHostWillOverwriteHostHeaderRegardlessOfOriginalCase(string $hostKey): void { $request = (new Request()) ->withHeader($hostKey, 'example.com'); diff --git a/test/Response/ArraySerializerTest.php b/test/Response/ArraySerializerTest.php index 524a7d73..2d032960 100644 --- a/test/Response/ArraySerializerTest.php +++ b/test/Response/ArraySerializerTest.php @@ -12,7 +12,7 @@ class ArraySerializerTest extends TestCase { - public function testSerializeToArray() + public function testSerializeToArray(): void { $response = $this->createResponse(); @@ -21,7 +21,7 @@ public function testSerializeToArray() $this->assertSame($this->createSerializedResponse(), $message); } - public function testDeserializeFromArray() + public function testDeserializeFromArray(): void { $serializedResponse = $this->createSerializedResponse(); @@ -32,7 +32,7 @@ public function testDeserializeFromArray() $this->assertSame(Response\Serializer::toString($response), Response\Serializer::toString($message)); } - public function testMissingBodyParamInSerializedRequestThrowsException() + public function testMissingBodyParamInSerializedRequestThrowsException(): void { $serializedRequest = $this->createSerializedResponse(); unset($serializedRequest['body']); @@ -42,7 +42,7 @@ public function testMissingBodyParamInSerializedRequestThrowsException() ArraySerializer::fromArray($serializedRequest); } - private function createResponse() + private function createResponse(): Response { $stream = new Stream('php://memory', 'wb+'); $stream->write('{"test":"value"}'); @@ -56,22 +56,22 @@ private function createResponse() ->withBody($stream); } - private function createSerializedResponse() + private function createSerializedResponse(): array { return [ - 'status_code' => 201, - 'reason_phrase' => 'Custom', + 'status_code' => 201, + 'reason_phrase' => 'Custom', 'protocol_version' => '1.1', - 'headers' => [ - 'Accept' => [ + 'headers' => [ + 'Accept' => [ 'application/json', ], 'X-Foo-Bar' => [ 'Baz', - 'Bat' + 'Bat', ], ], - 'body' => '{"test":"value"}', + 'body' => '{"test":"value"}', ]; } } diff --git a/test/Response/EmptyResponseTest.php b/test/Response/EmptyResponseTest.php index 24bff4af..46d61491 100644 --- a/test/Response/EmptyResponseTest.php +++ b/test/Response/EmptyResponseTest.php @@ -10,7 +10,7 @@ class EmptyResponseTest extends TestCase { - public function testConstructor() + public function testConstructor(): void { $response = new EmptyResponse(201); $this->assertInstanceOf(Response::class, $response); @@ -18,7 +18,7 @@ public function testConstructor() $this->assertSame(201, $response->getStatusCode()); } - public function testHeaderConstructor() + public function testHeaderConstructor(): void { $response = EmptyResponse::withHeaders(['x-empty' => ['true']]); $this->assertInstanceOf(Response::class, $response); diff --git a/test/Response/HtmlResponseTest.php b/test/Response/HtmlResponseTest.php index 97f52ea5..63cccca1 100644 --- a/test/Response/HtmlResponseTest.php +++ b/test/Response/HtmlResponseTest.php @@ -7,14 +7,14 @@ use InvalidArgumentException; use Laminas\Diactoros\Response\HtmlResponse; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\StreamInterface; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\Http\Message\StreamInterface; class HtmlResponseTest extends TestCase { use ProphecyTrait; - public function testConstructorAcceptsHtmlString() + public function testConstructorAcceptsHtmlString(): void { $body = 'Uh oh not found'; @@ -23,9 +23,9 @@ public function testConstructorAcceptsHtmlString() $this->assertSame(200, $response->getStatusCode()); } - public function testConstructorAllowsPassingStatus() + public function testConstructorAllowsPassingStatus(): void { - $body = 'Uh oh not found'; + $body = 'Uh oh not found'; $status = 404; $response = new HtmlResponse($body, $status); @@ -33,12 +33,12 @@ public function testConstructorAllowsPassingStatus() $this->assertSame($body, (string) $response->getBody()); } - public function testConstructorAllowsPassingHeaders() + public function testConstructorAllowsPassingHeaders(): void { - $body = 'Uh oh not found'; - $status = 404; + $body = 'Uh oh not found'; + $status = 404; $headers = [ - 'x-custom' => [ 'foo-bar' ], + 'x-custom' => ['foo-bar'], ]; $response = new HtmlResponse($body, $status, $headers); @@ -48,15 +48,16 @@ public function testConstructorAllowsPassingHeaders() $this->assertSame($body, (string) $response->getBody()); } - public function testAllowsStreamsForResponseBody() + public function testAllowsStreamsForResponseBody(): void { - $stream = $this->prophesize(StreamInterface::class); - $body = $stream->reveal(); + $stream = $this->prophesize(StreamInterface::class); + $body = $stream->reveal(); $response = new HtmlResponse($body); $this->assertSame($body, $response->getBody()); } - public function invalidHtmlContent() + /** @return array */ + public function invalidHtmlContent(): array { return [ 'null' => [null], @@ -73,17 +74,19 @@ public function invalidHtmlContent() /** * @dataProvider invalidHtmlContent + * @param mixed $body */ - public function testRaisesExceptionforNonStringNonStreamBodyContent($body) + public function testRaisesExceptionForNonStringNonStreamBodyContent($body): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ new HtmlResponse($body); } - public function testConstructorRewindsBodyStream() + public function testConstructorRewindsBodyStream(): void { - $html = '

test data

'; + $html = '

test data

'; $response = new HtmlResponse($html); $actual = $response->getBody()->getContents(); diff --git a/test/Response/JsonResponseTest.php b/test/Response/JsonResponseTest.php index 23b67f3a..383ddf71 100644 --- a/test/Response/JsonResponseTest.php +++ b/test/Response/JsonResponseTest.php @@ -7,6 +7,7 @@ use InvalidArgumentException; use Laminas\Diactoros\Response\JsonResponse; use PHPUnit\Framework\TestCase; +use stdClass; use function fopen; use function json_decode; @@ -22,7 +23,7 @@ class JsonResponseTest extends TestCase { - public function testConstructorAcceptsDataAndCreatesJsonEncodedMessageBody() + public function testConstructorAcceptsDataAndCreatesJsonEncodedMessageBody(): void { $data = [ 'nested' => [ @@ -39,6 +40,7 @@ public function testConstructorAcceptsDataAndCreatesJsonEncodedMessageBody() $this->assertSame($json, (string) $response->getBody()); } + /** @return array */ public function scalarValuesForJSON() { return [ @@ -56,8 +58,9 @@ public function scalarValuesForJSON() /** * @dataProvider scalarValuesForJSON + * @param mixed $value */ - public function testScalarValuePassedToConstructorJsonEncodesDirectly($value) + public function testScalarValuePassedToConstructorJsonEncodesDirectly($value): void { $response = new JsonResponse($value); $this->assertSame(200, $response->getStatusCode()); @@ -66,19 +69,19 @@ public function testScalarValuePassedToConstructorJsonEncodesDirectly($value) $this->assertSame(json_encode($value, 15), (string) $response->getBody()); } - public function testCanProvideStatusCodeToConstructor() + public function testCanProvideStatusCodeToConstructor(): void { $response = new JsonResponse(null, 404); $this->assertSame(404, $response->getStatusCode()); } - public function testCanProvideAlternateContentTypeViaHeadersPassedToConstructor() + public function testCanProvideAlternateContentTypeViaHeadersPassedToConstructor(): void { $response = new JsonResponse(null, 200, ['content-type' => 'foo/json']); $this->assertSame('foo/json', $response->getHeaderLine('content-type')); } - public function testJsonErrorHandlingOfResources() + public function testJsonErrorHandlingOfResources(): void { // Serializing something that is not serializable. $resource = fopen('php://memory', 'r'); @@ -88,7 +91,7 @@ public function testJsonErrorHandlingOfResources() new JsonResponse($resource); } - public function testJsonErrorHandlingOfBadEmbeddedData() + public function testJsonErrorHandlingOfBadEmbeddedData(): void { // Serializing something that is not serializable. $data = [ @@ -101,7 +104,8 @@ public function testJsonErrorHandlingOfBadEmbeddedData() new JsonResponse($data); } - public function valuesToJsonEncode() + /** @return array */ + public function valuesToJsonEncode(): array { return [ 'uri' => ['https://example.com/foo?bar=baz&baz=bat', 'uri'], @@ -113,7 +117,7 @@ public function valuesToJsonEncode() /** * @dataProvider valuesToJsonEncode */ - public function testUsesSaneDefaultJsonEncodingFlags($value, string $key) + public function testUsesSaneDefaultJsonEncodingFlags(string $value, string $key): void { $defaultFlags = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_SLASHES; @@ -129,26 +133,26 @@ public function testUsesSaneDefaultJsonEncodingFlags($value, string $key) ); } - public function testConstructorRewindsBodyStream() + public function testConstructorRewindsBodyStream(): void { - $json = ['test' => 'data']; + $json = ['test' => 'data']; $response = new JsonResponse($json); $actual = json_decode($response->getBody()->getContents(), true); $this->assertSame($json, $actual); } - public function testPayloadGetter() + public function testPayloadGetter(): void { - $payload = ['test' => 'data']; + $payload = ['test' => 'data']; $response = new JsonResponse($payload); $this->assertSame($payload, $response->getPayload()); } - public function testWithPayload() + public function testWithPayload(): void { - $response = new JsonResponse(['test' => 'data']); - $json = [ 'foo' => 'bar']; + $response = new JsonResponse(['test' => 'data']); + $json = ['foo' => 'bar']; $newResponse = $response->withPayload($json); $this->assertNotSame($response, $newResponse); @@ -157,18 +161,18 @@ public function testWithPayload() $this->assertSame($json, $decodedBody); } - public function testEncodingOptionsGetter() + public function testEncodingOptionsGetter(): void { $response = new JsonResponse([]); $this->assertSame(JsonResponse::DEFAULT_JSON_FLAGS, $response->getEncodingOptions()); } - public function testWithEncodingOptions() + public function testWithEncodingOptions(): void { - $response = new JsonResponse([ 'foo' => 'bar']); + $response = new JsonResponse(['foo' => 'bar']); $expected = <<assertSame($expected, $response->getBody()->getContents()); @@ -177,23 +181,23 @@ public function testWithEncodingOptions() $this->assertNotSame($response, $newResponse); $expected = <<assertSame($expected, $newResponse->getBody()->getContents()); } - public function testModifyingThePayloadDoesntMutateResponseInstance() + public function testModifyingThePayloadDoesntMutateResponseInstance(): void { - $payload = new \stdClass(); + $payload = new stdClass(); $payload->foo = 'bar'; $response = new JsonResponse($payload); $originalPayload = clone $payload; - $payload->bar = 'baz'; + $payload->bar = 'baz'; $this->assertEquals($originalPayload, $response->getPayload()); $this->assertNotSame($payload, $response->getPayload()); diff --git a/test/Response/RedirectResponseTest.php b/test/Response/RedirectResponseTest.php index b232a78a..76903da1 100644 --- a/test/Response/RedirectResponseTest.php +++ b/test/Response/RedirectResponseTest.php @@ -11,7 +11,7 @@ class RedirectResponseTest extends TestCase { - public function testConstructorAcceptsStringUriAndProduces302ResponseWithLocationHeader() + public function testConstructorAcceptsStringUriAndProduces302ResponseWithLocationHeader(): void { $response = new RedirectResponse('/foo/bar'); $this->assertSame(302, $response->getStatusCode()); @@ -19,16 +19,16 @@ public function testConstructorAcceptsStringUriAndProduces302ResponseWithLocatio $this->assertSame('/foo/bar', $response->getHeaderLine('Location')); } - public function testConstructorAcceptsUriInstanceAndProduces302ResponseWithLocationHeader() + public function testConstructorAcceptsUriInstanceAndProduces302ResponseWithLocationHeader(): void { - $uri = new Uri('https://example.com:10082/foo/bar'); + $uri = new Uri('https://example.com:10082/foo/bar'); $response = new RedirectResponse($uri); $this->assertSame(302, $response->getStatusCode()); $this->assertTrue($response->hasHeader('Location')); $this->assertSame((string) $uri, $response->getHeaderLine('Location')); } - public function testConstructorAllowsSpecifyingAlternateStatusCode() + public function testConstructorAllowsSpecifyingAlternateStatusCode(): void { $response = new RedirectResponse('/foo/bar', 301); $this->assertSame(301, $response->getStatusCode()); @@ -36,7 +36,7 @@ public function testConstructorAllowsSpecifyingAlternateStatusCode() $this->assertSame('/foo/bar', $response->getHeaderLine('Location')); } - public function testConstructorAllowsSpecifyingHeaders() + public function testConstructorAllowsSpecifyingHeaders(): void { $response = new RedirectResponse('/foo/bar', 302, ['X-Foo' => ['Bar']]); $this->assertSame(302, $response->getStatusCode()); @@ -46,29 +46,32 @@ public function testConstructorAllowsSpecifyingHeaders() $this->assertSame('Bar', $response->getHeaderLine('X-Foo')); } - public function invalidUris() + /** @return array */ + public function invalidUris(): array { return [ - 'null' => [ null ], - 'false' => [ false ], - 'true' => [ true ], - 'zero' => [ 0 ], - 'int' => [ 1 ], - 'zero-float' => [ 0.0 ], - 'float' => [ 1.1 ], - 'array' => [ [ '/foo/bar' ] ], - 'object' => [ (object) [ '/foo/bar' ] ], + 'null' => [null], + 'false' => [false], + 'true' => [true], + 'zero' => [0], + 'int' => [1], + 'zero-float' => [0.0], + 'float' => [1.1], + 'array' => [['/foo/bar']], + 'object' => [(object) ['/foo/bar']], ]; } /** * @dataProvider invalidUris + * @param mixed $uri */ - public function testConstructorRaisesExceptionOnInvalidUri($uri) + public function testConstructorRaisesExceptionOnInvalidUri($uri): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Uri'); + /** @psalm-suppress MixedArgument */ new RedirectResponse($uri); } } diff --git a/test/Response/SerializerTest.php b/test/Response/SerializerTest.php index fce27a49..f4389d3a 100644 --- a/test/Response/SerializerTest.php +++ b/test/Response/SerializerTest.php @@ -14,7 +14,7 @@ class SerializerTest extends TestCase { - public function testSerializesBasicResponse() + public function testSerializesBasicResponse(): void { $response = (new Response()) ->withStatus(200) @@ -29,7 +29,7 @@ public function testSerializesBasicResponse() ); } - public function testSerializesResponseWithoutBodyCorrectly() + public function testSerializesResponseWithoutBodyCorrectly(): void { $response = (new Response()) ->withStatus(200) @@ -42,7 +42,7 @@ public function testSerializesResponseWithoutBodyCorrectly() ); } - public function testSerializesMultipleHeadersCorrectly() + public function testSerializesMultipleHeadersCorrectly(): void { $response = (new Response()) ->withStatus(204) @@ -54,7 +54,7 @@ public function testSerializesMultipleHeadersCorrectly() $this->assertStringContainsString("X-Foo-Bar: Bat", $message); } - public function testOmitsReasonPhraseFromStatusLineIfEmpty() + public function testOmitsReasonPhraseFromStatusLineIfEmpty(): void { $response = (new Response()) ->withStatus(299) @@ -65,9 +65,9 @@ public function testOmitsReasonPhraseFromStatusLineIfEmpty() $this->assertStringContainsString("HTTP/1.1 299\r\n", $message); } - public function testCanDeserializeBasicResponse() + public function testCanDeserializeBasicResponse(): void { - $text = "HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"; + $text = "HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"; $response = Serializer::fromString($text); $this->assertInstanceOf(ResponseInterface::class, $response); @@ -86,9 +86,9 @@ public function testCanDeserializeBasicResponse() $this->assertSame('Content!', (string) $response->getBody()); } - public function testCanDeserializeResponseWithMultipleHeadersOfSameName() + public function testCanDeserializeResponseWithMultipleHeadersOfSameName(): void { - $text = "HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\nX-Foo-Bar: Bat\r\n\r\nContent!"; + $text = "HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\nX-Foo-Bar: Bat\r\n\r\nContent!"; $response = Serializer::fromString($text); $this->assertInstanceOf(ResponseInterface::class, $response); @@ -99,18 +99,19 @@ public function testCanDeserializeResponseWithMultipleHeadersOfSameName() $this->assertSame(['Baz', 'Bat'], $values); } - public function headersWithContinuationLines() + /** @return array */ + public function headersWithContinuationLines(): array { return [ 'space' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n Bat\r\n\r\nContent!"], - 'tab' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n\tBat\r\n\r\nContent!"], + 'tab' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz;\r\n\tBat\r\n\r\nContent!"], ]; } /** * @dataProvider headersWithContinuationLines */ - public function testCanDeserializeResponseWithHeaderContinuations($text) + public function testCanDeserializeResponseWithHeaderContinuations(string $text): void { $response = Serializer::fromString($text); @@ -125,11 +126,11 @@ public function testCanDeserializeResponseWithHeaderContinuations($text) public function headersWithWhitespace(): array { return [ - 'no' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz\r\n\r\nContent!"], - 'leading' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"], + 'no' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz\r\n\r\nContent!"], + 'leading' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz\r\n\r\nContent!"], 'trailing' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar:Baz \r\n\r\nContent!"], - 'both' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz \r\n\r\nContent!"], - 'mixed' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: \t Baz\t \t\r\n\r\nContent!"], + 'both' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: Baz \r\n\r\nContent!"], + 'mixed' => ["HTTP/1.0 200 A-OK\r\nContent-Type: text/plain\r\nX-Foo-Bar: \t Baz\t \t\r\n\r\nContent!"], ]; } @@ -145,9 +146,9 @@ public function testDeserializationRemovesWhitespaceAroundValues(string $text): $this->assertSame('Baz', $response->getHeaderLine('X-Foo-Bar')); } - public function testCanDeserializeResponseWithoutBody() + public function testCanDeserializeResponseWithoutBody(): void { - $text = "HTTP/1.0 204\r\nX-Foo-Bar: Baz"; + $text = "HTTP/1.0 204\r\nX-Foo-Bar: Baz"; $response = Serializer::fromString($text); $this->assertInstanceOf(ResponseInterface::class, $response); @@ -160,9 +161,9 @@ public function testCanDeserializeResponseWithoutBody() $this->assertEmpty($body); } - public function testCanDeserializeResponseWithoutHeadersOrBody() + public function testCanDeserializeResponseWithoutHeadersOrBody(): void { - $text = "HTTP/1.0 204"; + $text = "HTTP/1.0 204"; $response = Serializer::fromString($text); $this->assertInstanceOf(ResponseInterface::class, $response); @@ -173,9 +174,9 @@ public function testCanDeserializeResponseWithoutHeadersOrBody() $this->assertEmpty($body); } - public function testCanDeserializeResponseWithoutHeadersButContainingBody() + public function testCanDeserializeResponseWithoutHeadersButContainingBody(): void { - $text = "HTTP/1.0 204\r\n\r\nContent!"; + $text = "HTTP/1.0 204\r\n\r\nContent!"; $response = Serializer::fromString($text); $this->assertInstanceOf(ResponseInterface::class, $response); @@ -186,7 +187,7 @@ public function testCanDeserializeResponseWithoutHeadersButContainingBody() $this->assertSame('Content!', $body); } - public function testDeserializationRaisesExceptionForInvalidStatusLine() + public function testDeserializationRaisesExceptionForInvalidStatusLine(): void { $text = "This is an invalid status line\r\nX-Foo-Bar: Baz\r\n\r\nContent!"; @@ -196,20 +197,21 @@ public function testDeserializationRaisesExceptionForInvalidStatusLine() Serializer::fromString($text); } - public function messagesWithInvalidHeaders() + /** @return array */ + public function messagesWithInvalidHeaders(): array { return [ - 'invalid-name' => [ + 'invalid-name' => [ "HTTP/1.1 204\r\nThi;-I()-Invalid: value", - 'Invalid header detected' + 'Invalid header detected', ], - 'invalid-format' => [ + 'invalid-format' => [ "HTTP/1.1 204\r\nThis is not a header\r\n\r\nContent", - 'Invalid header detected' + 'Invalid header detected', ], 'invalid-continuation' => [ "HTTP/1.1 204\r\nX-Foo-Bar: Baz\r\nInvalid continuation\r\nContent", - 'Invalid header continuation' + 'Invalid header continuation', ], ]; } @@ -217,15 +219,17 @@ public function messagesWithInvalidHeaders() /** * @dataProvider messagesWithInvalidHeaders */ - public function testDeserializationRaisesExceptionForMalformedHeaders($message, $exceptionMessage) - { + public function testDeserializationRaisesExceptionForMalformedHeaders( + string $message, + string $exceptionMessage + ): void { $this->expectException(UnexpectedValueException::class); $this->expectExceptionMessage($exceptionMessage); Serializer::fromString($message); } - public function testFromStreamThrowsExceptionWhenStreamIsNotReadable() + public function testFromStreamThrowsExceptionWhenStreamIsNotReadable(): void { $stream = $this->createMock(StreamInterface::class); $stream @@ -238,7 +242,7 @@ public function testFromStreamThrowsExceptionWhenStreamIsNotReadable() Serializer::fromStream($stream); } - public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable() + public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable(): void { $stream = $this->createMock(StreamInterface::class); $stream @@ -255,10 +259,7 @@ public function testFromStreamThrowsExceptionWhenStreamIsNotSeekable() Serializer::fromStream($stream); } - /** - * @group 113 - */ - public function testDeserializeCorrectlyCastsStatusCodeToInteger() + public function testDeserializeCorrectlyCastsStatusCodeToInteger(): void { $response = Response\Serializer::fromString('HTTP/1.0 204'); // according to interface the int is expected diff --git a/test/Response/TextResponseTest.php b/test/Response/TextResponseTest.php index 0f19064f..6d2a7314 100644 --- a/test/Response/TextResponseTest.php +++ b/test/Response/TextResponseTest.php @@ -7,14 +7,14 @@ use InvalidArgumentException; use Laminas\Diactoros\Response\TextResponse; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\StreamInterface; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\Http\Message\StreamInterface; class TextResponseTest extends TestCase { use ProphecyTrait; - public function testConstructorAcceptsBodyAsString() + public function testConstructorAcceptsBodyAsString(): void { $body = 'Uh oh not found'; @@ -23,9 +23,9 @@ public function testConstructorAcceptsBodyAsString() $this->assertSame(200, $response->getStatusCode()); } - public function testConstructorAllowsPassingStatus() + public function testConstructorAllowsPassingStatus(): void { - $body = 'Uh oh not found'; + $body = 'Uh oh not found'; $status = 404; $response = new TextResponse($body, $status); @@ -33,12 +33,12 @@ public function testConstructorAllowsPassingStatus() $this->assertSame($body, (string) $response->getBody()); } - public function testConstructorAllowsPassingHeaders() + public function testConstructorAllowsPassingHeaders(): void { - $body = 'Uh oh not found'; - $status = 404; + $body = 'Uh oh not found'; + $status = 404; $headers = [ - 'x-custom' => [ 'foo-bar' ], + 'x-custom' => ['foo-bar'], ]; $response = new TextResponse($body, $status, $headers); @@ -48,15 +48,16 @@ public function testConstructorAllowsPassingHeaders() $this->assertSame($body, (string) $response->getBody()); } - public function testAllowsStreamsForResponseBody() + public function testAllowsStreamsForResponseBody(): void { - $stream = $this->prophesize(StreamInterface::class); - $body = $stream->reveal(); + $stream = $this->prophesize(StreamInterface::class); + $body = $stream->reveal(); $response = new TextResponse($body); $this->assertSame($body, $response->getBody()); } - public function invalidContent() + /** @return array */ + public function invalidContent(): array { return [ 'null' => [null], @@ -73,20 +74,19 @@ public function invalidContent() /** * @dataProvider invalidContent + * @param mixed $body */ - public function testRaisesExceptionforNonStringNonStreamBodyContent($body) + public function testRaisesExceptionForNonStringNonStreamBodyContent($body): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ new TextResponse($body); } - /** - * @group 115 - */ - public function testConstructorRewindsBodyStream() + public function testConstructorRewindsBodyStream(): void { - $text = 'test data'; + $text = 'test data'; $response = new TextResponse($text); $actual = $response->getBody()->getContents(); diff --git a/test/Response/XmlResponseTest.php b/test/Response/XmlResponseTest.php index 5ba2ed11..39a12d29 100644 --- a/test/Response/XmlResponseTest.php +++ b/test/Response/XmlResponseTest.php @@ -7,8 +7,8 @@ use InvalidArgumentException; use Laminas\Diactoros\Response\XmlResponse; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\StreamInterface; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\Http\Message\StreamInterface; use const PHP_EOL; @@ -16,7 +16,7 @@ class XmlResponseTest extends TestCase { use ProphecyTrait; - public function testConstructorAcceptsBodyAsString() + public function testConstructorAcceptsBodyAsString(): void { $body = 'Super valid XML'; @@ -25,9 +25,9 @@ public function testConstructorAcceptsBodyAsString() $this->assertSame(200, $response->getStatusCode()); } - public function testConstructorAllowsPassingStatus() + public function testConstructorAllowsPassingStatus(): void { - $body = 'More valid XML'; + $body = 'More valid XML'; $status = 404; $response = new XmlResponse($body, $status); @@ -35,12 +35,12 @@ public function testConstructorAllowsPassingStatus() $this->assertSame($body, (string) $response->getBody()); } - public function testConstructorAllowsPassingHeaders() + public function testConstructorAllowsPassingHeaders(): void { - $body = 'Valid XML'; - $status = 404; + $body = 'Valid XML'; + $status = 404; $headers = [ - 'x-custom' => [ 'foo-bar' ], + 'x-custom' => ['foo-bar'], ]; $response = new XmlResponse($body, $status, $headers); @@ -50,15 +50,16 @@ public function testConstructorAllowsPassingHeaders() $this->assertSame($body, (string) $response->getBody()); } - public function testAllowsStreamsForResponseBody() + public function testAllowsStreamsForResponseBody(): void { - $stream = $this->prophesize(StreamInterface::class); - $body = $stream->reveal(); + $stream = $this->prophesize(StreamInterface::class); + $body = $stream->reveal(); $response = new XmlResponse($body); $this->assertSame($body, $response->getBody()); } - public function invalidContent() + /** @return array */ + public function invalidContent(): array { return [ 'null' => [null], @@ -75,20 +76,19 @@ public function invalidContent() /** * @dataProvider invalidContent + * @param mixed $body */ public function testRaisesExceptionforNonStringNonStreamBodyContent($body) { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ new XmlResponse($body); } - /** - * @group 115 - */ - public function testConstructorRewindsBodyStream() + public function testConstructorRewindsBodyStream(): void { - $body = '' . PHP_EOL . 'Valid XML'; + $body = '' . PHP_EOL . 'Valid XML'; $response = new XmlResponse($body); $actual = $response->getBody()->getContents(); diff --git a/test/ResponseTest.php b/test/ResponseTest.php index b92a3832..1836a405 100644 --- a/test/ResponseTest.php +++ b/test/ResponseTest.php @@ -18,8 +18,10 @@ use function curl_setopt; use function file_exists; use function file_put_contents; +use function getenv; use function gmdate; use function in_array; +use function is_string; use function preg_match; use function sprintf; use function strtotime; @@ -28,43 +30,42 @@ use const CURLOPT_HTTPHEADER; use const CURLOPT_RETURNTRANSFER; use const CURLOPT_TIMEOUT; +use const CURLOPT_USERAGENT; use const LOCK_EX; class ResponseTest extends TestCase { - /** - * @var Response - */ + /** @var Response */ protected $response; - protected function setUp() : void + protected function setUp(): void { $this->response = new Response(); } - public function testStatusCodeIs200ByDefault() + public function testStatusCodeIs200ByDefault(): void { $this->assertSame(200, $this->response->getStatusCode()); } - public function testStatusCodeMutatorReturnsCloneWithChanges() + public function testStatusCodeMutatorReturnsCloneWithChanges(): void { $response = $this->response->withStatus(400); $this->assertNotSame($this->response, $response); $this->assertSame(400, $response->getStatusCode()); } - public function testReasonPhraseDefaultsToStandards() + public function testReasonPhraseDefaultsToStandards(): void { $response = $this->response->withStatus(422); $this->assertSame('Unprocessable Content', $response->getReasonPhrase()); } - private function fetchIanaStatusCodes() : DOMDocument + private function fetchIanaStatusCodes(): DOMDocument { - $updated = null; + $updated = null; $ianaHttpStatusCodesFile = __DIR__ . '/TestAsset/.cache/http-status-codes.xml'; - $ianaHttpStatusCodes = null; + $ianaHttpStatusCodes = null; if (file_exists($ianaHttpStatusCodesFile)) { $ianaHttpStatusCodes = new DOMDocument(); $ianaHttpStatusCodes->load($ianaHttpStatusCodesFile); @@ -94,7 +95,7 @@ private function fetchIanaStatusCodes() : DOMDocument ); curl_setopt($ch, CURLOPT_HTTPHEADER, [$ifModifiedSince]); } - $response = curl_exec($ch); + $response = curl_exec($ch); $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); @@ -103,7 +104,7 @@ private function fetchIanaStatusCodes() : DOMDocument return $ianaHttpStatusCodes; } - if ($responseCode === 200 && is_string($response) && $response != '') { + if ($responseCode === 200 && is_string($response) && $response !== '') { $downloadedIanaHttpStatusCodes = new DOMDocument(); $downloadedIanaHttpStatusCodes->loadXML($response); if ($downloadedIanaHttpStatusCodes->relaxNGValidate(__DIR__ . '/TestAsset/http-status-codes.rng')) { @@ -118,7 +119,8 @@ private function fetchIanaStatusCodes() : DOMDocument self::fail('Unable to retrieve IANA response status codes due to timeout or invalid XML'); } - public function ianaCodesReasonPhrasesProvider() + /** @return list */ + public function ianaCodesReasonPhrasesProvider(): array { $ianaHttpStatusCodes = $this->fetchIanaStatusCodes(); @@ -130,7 +132,7 @@ public function ianaCodesReasonPhrasesProvider() $records = $xpath->query('//ns:record'); foreach ($records as $record) { - $value = $xpath->query('.//ns:value', $record)->item(0)->nodeValue; + $value = $xpath->query('.//ns:value', $record)->item(0)->nodeValue; $description = $xpath->query('.//ns:description', $record)->item(0)->nodeValue; if (in_array($description, ['Unassigned', '(Unused)'])) { @@ -151,55 +153,61 @@ public function ianaCodesReasonPhrasesProvider() /** * @dataProvider ianaCodesReasonPhrasesProvider + * @param string|numeric $code */ - public function testReasonPhraseDefaultsAgainstIana($code, $reasonPhrase) + public function testReasonPhraseDefaultsAgainstIana($code, string $reasonPhrase): void { + /** @psalm-suppress InvalidScalarArgument */ $response = $this->response->withStatus($code); $this->assertSame($reasonPhrase, $response->getReasonPhrase()); } - public function testCanSetCustomReasonPhrase() + public function testCanSetCustomReasonPhrase(): void { $response = $this->response->withStatus(422, 'Foo Bar!'); $this->assertSame('Foo Bar!', $response->getReasonPhrase()); } - public function invalidReasonPhrases() + /** @return array */ + public function invalidReasonPhrases(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'array' => [ [ 200 ] ], - 'object' => [ (object) [ 'reasonPhrase' => 'Ok' ] ], + 'true' => [true], + 'false' => [false], + 'array' => [[200]], + 'object' => [(object) ['reasonPhrase' => 'Ok']], 'integer' => [99], - 'float' => [400.5], - 'null' => [null], + 'float' => [400.5], + 'null' => [null], ]; } /** * @dataProvider invalidReasonPhrases + * @param mixed $invalidReasonPhrase */ - public function testWithStatusRaisesAnExceptionForNonStringReasonPhrases($invalidReasonPhrase) + public function testWithStatusRaisesAnExceptionForNonStringReasonPhrases($invalidReasonPhrase): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ $this->response->withStatus(422, $invalidReasonPhrase); } - public function testConstructorRaisesExceptionForInvalidStream() + public function testConstructorRaisesExceptionForInvalidStream(): void { $this->expectException(InvalidArgumentException::class); - new Response([ 'TOTALLY INVALID' ]); + /** @psalm-suppress InvalidArgument */ + new Response(['TOTALLY INVALID']); } - public function testConstructorCanAcceptAllMessageParts() + public function testConstructorCanAcceptAllMessageParts(): void { - $body = new Stream('php://memory'); - $status = 302; + $body = new Stream('php://memory'); + $status = 302; $headers = [ - 'location' => [ 'http://example.com/' ], + 'location' => ['http://example.com/'], ]; $response = new Response($body, $status, $headers); @@ -210,9 +218,11 @@ public function testConstructorCanAcceptAllMessageParts() /** * @dataProvider validStatusCodes + * @param numeric $code */ - public function testCreateWithValidStatusCodes($code) + public function testCreateWithValidStatusCodes($code): void { + /** @psalm-suppress InvalidScalarArgument */ $response = $this->response->withStatus($code); $result = $response->getStatusCode(); @@ -221,96 +231,105 @@ public function testCreateWithValidStatusCodes($code) $this->assertIsInt($result); } - public function validStatusCodes() + /** @return array */ + public function validStatusCodes(): array { return [ - 'minimum' => [100], - 'middle' => [300], + 'minimum' => [100], + 'middle' => [300], 'string-integer' => ['300'], - 'maximum' => [599], + 'maximum' => [599], ]; } /** * @dataProvider invalidStatusCodes + * @param mixed $code */ - public function testCannotSetInvalidStatusCode($code) + public function testCannotSetInvalidStatusCode($code): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress MixedArgument */ $this->response->withStatus($code); } - public function invalidStatusCodes() + /** @return array */ + public function invalidStatusCodes(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'array' => [ [ 200 ] ], - 'object' => [ (object) [ 'statusCode' => 200 ] ], - 'too-low' => [99], - 'float' => [400.5], + 'true' => [true], + 'false' => [false], + 'array' => [[200]], + 'object' => [(object) ['statusCode' => 200]], + 'too-low' => [99], + 'float' => [400.5], 'too-high' => [600], - 'null' => [null], - 'string' => ['foo'], + 'null' => [null], + 'string' => ['foo'], ]; } - public function invalidResponseBody() + /** @return array */ + public function invalidResponseBody(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'int' => [ 1 ], - 'float' => [ 1.1 ], - 'array' => [ ['BODY'] ], - 'stdClass' => [ (object) [ 'body' => 'BODY'] ], + 'true' => [true], + 'false' => [false], + 'int' => [1], + 'float' => [1.1], + 'array' => [['BODY']], + 'stdClass' => [(object) ['body' => 'BODY']], ]; } /** * @dataProvider invalidResponseBody + * @param mixed $body */ - public function testConstructorRaisesExceptionForInvalidBody($body) + public function testConstructorRaisesExceptionForInvalidBody($body): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('stream'); + /** @psalm-suppress MixedArgument */ new Response($body); } - - public function invalidHeaderTypes() + /** @return array */ + public function invalidHeaderTypes(): array { return [ 'indexed-array' => [[['INVALID']], 'header name'], - 'null' => [['x-invalid-null' => null]], - 'true' => [['x-invalid-true' => true]], - 'false' => [['x-invalid-false' => false]], - 'object' => [['x-invalid-object' => (object) ['INVALID']]], + 'null' => [['x-invalid-null' => null]], + 'true' => [['x-invalid-true' => true]], + 'false' => [['x-invalid-false' => false]], + 'object' => [['x-invalid-object' => (object) ['INVALID']]], ]; } /** * @dataProvider invalidHeaderTypes - * @group 99 */ - public function testConstructorRaisesExceptionForInvalidHeaders($headers, $contains = 'header value type') - { + public function testConstructorRaisesExceptionForInvalidHeaders( + array $headers, + string $contains = 'header value type' + ): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage($contains); new Response('php://memory', 200, $headers); } - public function testReasonPhraseCanBeEmpty() + public function testReasonPhraseCanBeEmpty(): void { $response = $this->response->withStatus(555); $this->assertIsString($response->getReasonPhrase()); $this->assertEmpty($response->getReasonPhrase()); } - public function headersWithInjectionVectors() + /** @return array}> */ + public function headersWithInjectionVectors(): array { return [ 'name-with-cr' => ["X-Foo\r-Bar", 'value'], @@ -329,10 +348,10 @@ public function headersWithInjectionVectors() } /** - * @group ZF2015-04 + * @param string|list $value * @dataProvider headersWithInjectionVectors */ - public function testConstructorRaisesExceptionForHeadersWithCRLFVectors(string $name, $value) + public function testConstructorRaisesExceptionForHeadersWithCRLFVectors(string $name, $value): void { $this->expectException(InvalidArgumentException::class); diff --git a/test/ServerRequestFactoryTest.php b/test/ServerRequestFactoryTest.php index e52c0aad..290db389 100644 --- a/test/ServerRequestFactoryTest.php +++ b/test/ServerRequestFactoryTest.php @@ -4,6 +4,7 @@ namespace LaminasTest\Diactoros; +use Generator; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\ServerRequestFilter\DoNotFilter; @@ -14,87 +15,92 @@ use Psr\Http\Message\ServerRequestInterface; use UnexpectedValueException; +use function array_shift; use function Laminas\Diactoros\marshalHeadersFromSapi; use function Laminas\Diactoros\marshalProtocolVersionFromSapi; use function Laminas\Diactoros\marshalUriFromSapi; use function Laminas\Diactoros\normalizeServer; use function Laminas\Diactoros\normalizeUploadedFiles; +use function sprintf; +use function str_replace; +use function strpos; +use function strtolower; class ServerRequestFactoryTest extends TestCase { - public function testReturnsServerValueUnchangedIfHttpAuthorizationHeaderIsPresent() + public function testReturnsServerValueUnchangedIfHttpAuthorizationHeaderIsPresent(): void { $server = [ 'HTTP_AUTHORIZATION' => 'token', - 'HTTP_X_Foo' => 'bar', + 'HTTP_X_Foo' => 'bar', ]; $this->assertSame($server, normalizeServer($server)); } - public function testMarshalsExpectedHeadersFromServerArray() + public function testMarshalsExpectedHeadersFromServerArray(): void { $server = [ - 'HTTP_COOKIE' => 'COOKIE', + 'HTTP_COOKIE' => 'COOKIE', 'HTTP_AUTHORIZATION' => 'token', - 'HTTP_CONTENT_TYPE' => 'application/json', - 'HTTP_ACCEPT' => 'application/json', - 'HTTP_X_FOO_BAR' => 'FOOBAR', - 'CONTENT_MD5' => 'CONTENT-MD5', - 'CONTENT_LENGTH' => 'UNSPECIFIED', + 'HTTP_CONTENT_TYPE' => 'application/json', + 'HTTP_ACCEPT' => 'application/json', + 'HTTP_X_FOO_BAR' => 'FOOBAR', + 'CONTENT_MD5' => 'CONTENT-MD5', + 'CONTENT_LENGTH' => 'UNSPECIFIED', ]; $expected = [ - 'cookie' => 'COOKIE', - 'authorization' => 'token', - 'content-type' => 'application/json', - 'accept' => 'application/json', - 'x-foo-bar' => 'FOOBAR', - 'content-md5' => 'CONTENT-MD5', + 'cookie' => 'COOKIE', + 'authorization' => 'token', + 'content-type' => 'application/json', + 'accept' => 'application/json', + 'x-foo-bar' => 'FOOBAR', + 'content-md5' => 'CONTENT-MD5', 'content-length' => 'UNSPECIFIED', ]; $this->assertSame($expected, marshalHeadersFromSapi($server)); } - public function testMarshalInvalidHeadersStrippedFromServerArray() + public function testMarshalInvalidHeadersStrippedFromServerArray(): void { $server = [ - 'COOKIE' => 'COOKIE', + 'COOKIE' => 'COOKIE', 'HTTP_AUTHORIZATION' => 'token', - 'MD5' => 'CONTENT-MD5', - 'CONTENT_LENGTH' => 'UNSPECIFIED', + 'MD5' => 'CONTENT-MD5', + 'CONTENT_LENGTH' => 'UNSPECIFIED', ]; //Headers that don't begin with HTTP_ or CONTENT_ will not be returned $expected = [ - 'authorization' => 'token', + 'authorization' => 'token', 'content-length' => 'UNSPECIFIED', ]; $this->assertSame($expected, marshalHeadersFromSapi($server)); } - public function testMarshalsVariablesPrefixedByApacheFromServerArray() + public function testMarshalsVariablesPrefixedByApacheFromServerArray(): void { // Non-prefixed versions will be preferred $server = [ - 'HTTP_X_FOO_BAR' => 'nonprefixed', + 'HTTP_X_FOO_BAR' => 'nonprefixed', 'REDIRECT_HTTP_AUTHORIZATION' => 'token', - 'REDIRECT_HTTP_X_FOO_BAR' => 'prefixed', + 'REDIRECT_HTTP_X_FOO_BAR' => 'prefixed', ]; $expected = [ 'authorization' => 'token', - 'x-foo-bar' => 'nonprefixed', + 'x-foo-bar' => 'nonprefixed', ]; $this->assertEquals($expected, marshalHeadersFromSapi($server)); } - public function testMarshalRequestUriUsesIISUnencodedUrlValueIfPresentAndUrlWasRewritten() + public function testMarshalRequestUriUsesIISUnencodedUrlValueIfPresentAndUrlWasRewritten(): void { $server = [ 'IIS_WasUrlRewritten' => '1', - 'UNENCODED_URL' => '/foo/bar', + 'UNENCODED_URL' => '/foo/bar', ]; $uri = marshalUriFromSapi($server, []); @@ -102,7 +108,7 @@ public function testMarshalRequestUriUsesIISUnencodedUrlValueIfPresentAndUrlWasR $this->assertSame($server['UNENCODED_URL'], $uri->getPath()); } - public function testMarshalRequestUriStripsSchemeHostAndPortInformationWhenPresent() + public function testMarshalRequestUriStripsSchemeHostAndPortInformationWhenPresent(): void { $server = [ 'REQUEST_URI' => 'http://example.com:8000/foo/bar', @@ -113,7 +119,7 @@ public function testMarshalRequestUriStripsSchemeHostAndPortInformationWhenPrese $this->assertSame('/foo/bar', $uri->getPath()); } - public function testMarshalRequestUriUsesOrigPathInfoIfPresent() + public function testMarshalRequestUriUsesOrigPathInfoIfPresent(): void { $server = [ 'ORIG_PATH_INFO' => '/foo/bar', @@ -124,7 +130,7 @@ public function testMarshalRequestUriUsesOrigPathInfoIfPresent() $this->assertSame('/foo/bar', $uri->getPath()); } - public function testMarshalRequestUriFallsBackToRoot() + public function testMarshalRequestUriFallsBackToRoot(): void { $server = []; @@ -133,7 +139,7 @@ public function testMarshalRequestUriFallsBackToRoot() $this->assertSame('/', $uri->getPath()); } - public function testMarshalHostAndPortUsesHostHeaderWhenPresent() + public function testMarshalHostAndPortUsesHostHeaderWhenPresent(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); @@ -146,7 +152,7 @@ public function testMarshalHostAndPortUsesHostHeaderWhenPresent() $this->assertNull($uri->getPort()); } - public function testMarshalHostAndPortWillDetectPortInHostHeaderWhenPresent() + public function testMarshalHostAndPortWillDetectPortInHostHeaderWhenPresent(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com:8000/')); @@ -159,7 +165,7 @@ public function testMarshalHostAndPortWillDetectPortInHostHeaderWhenPresent() $this->assertSame(8000, $uri->getPort()); } - public function testMarshalHostAndPortReturnsEmptyValuesIfNoHostHeaderAndNoServerName() + public function testMarshalHostAndPortReturnsEmptyValuesIfNoHostHeaderAndNoServerName(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri()); @@ -170,12 +176,12 @@ public function testMarshalHostAndPortReturnsEmptyValuesIfNoHostHeaderAndNoServe $this->assertNull($uri->getPort()); } - public function testMarshalHostAndPortReturnsServerNameForHostWhenPresent() + public function testMarshalHostAndPortReturnsServerNameForHostWhenPresent(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); - $server = [ + $server = [ 'SERVER_NAME' => 'example.com', ]; @@ -185,12 +191,12 @@ public function testMarshalHostAndPortReturnsServerNameForHostWhenPresent() $this->assertNull($uri->getPort()); } - public function testMarshalHostAndPortReturnsServerPortForPortWhenPresentWithServerName() + public function testMarshalHostAndPortReturnsServerPortForPortWhenPresentWithServerName(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri()); - $server = [ + $server = [ 'SERVER_NAME' => 'example.com', 'SERVER_PORT' => 8000, ]; @@ -201,12 +207,12 @@ public function testMarshalHostAndPortReturnsServerPortForPortWhenPresentWithSer $this->assertSame(8000, $uri->getPort()); } - public function testMarshalHostAndPortReturnsServerNameForHostIfServerAddrPresentButHostIsNotIpv6Address() + public function testMarshalHostAndPortReturnsServerNameForHostIfServerAddrPresentButHostIsNotIpv6Address(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); - $server = [ + $server = [ 'SERVER_ADDR' => '127.0.0.1', 'SERVER_NAME' => 'example.com', ]; @@ -216,12 +222,12 @@ public function testMarshalHostAndPortReturnsServerNameForHostIfServerAddrPresen $this->assertSame('example.com', $uri->getHost()); } - public function testMarshalHostAndPortReturnsServerAddrForHostIfPresentAndHostIsIpv6Address() + public function testMarshalHostAndPortReturnsServerAddrForHostIfPresentAndHostIsIpv6Address(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri()); - $server = [ + $server = [ 'SERVER_ADDR' => 'FE80::0202:B3FF:FE1E:8329', 'SERVER_NAME' => '[FE80::0202:B3FF:FE1E:8329]', 'SERVER_PORT' => 8000, @@ -233,12 +239,12 @@ public function testMarshalHostAndPortReturnsServerAddrForHostIfPresentAndHostIs $this->assertSame(8000, $uri->getPort()); } - public function testMarshalHostAndPortWillDetectPortInIpv6StyleHost() + public function testMarshalHostAndPortWillDetectPortInIpv6StyleHost(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri()); - $server = [ + $server = [ 'SERVER_ADDR' => 'FE80::0202:B3FF:FE1E:8329', 'SERVER_NAME' => '[FE80::0202:B3FF:FE1E:8329:80]', ]; @@ -250,9 +256,9 @@ public function testMarshalHostAndPortWillDetectPortInIpv6StyleHost() } /** - * @return array + * @return array */ - public function httpsParamProvider() + public function httpsParamProvider(): array { return [ 'lowercase' => ['https'], @@ -262,15 +268,14 @@ public function httpsParamProvider() /** * @dataProvider httpsParamProvider - * @param string $param */ - public function testMarshalUriDetectsHttpsSchemeFromServerValue($param) + public function testMarshalUriDetectsHttpsSchemeFromServerValue(string $param): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); $request = $request->withHeader('Host', 'example.com'); - $server = [ + $server = [ $param => 'on', ]; @@ -281,14 +286,14 @@ public function testMarshalUriDetectsHttpsSchemeFromServerValue($param) } /** - * @return iterable + * @return Generator */ - public function httpsDisableParamProvider() + public function httpsDisableParamProvider(): Generator { foreach ($this->httpsParamProvider() as $key => $data) { $param = array_shift($data); foreach (['lowercase-off', 'uppercase-off'] as $type) { - $key = sprintf('%s-%s', $key, $type); + $key = sprintf('%s-%s', $key, $type); $value = false !== strpos($type, 'lowercase') ? 'off' : 'OFF'; yield $key => [$param, $value]; } @@ -297,16 +302,14 @@ public function httpsDisableParamProvider() /** * @dataProvider httpsDisableParamProvider - * @param string $param - * @param string $value */ - public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff($param, $value) + public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff(string $param, string $value): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); $request = $request->withHeader('Host', 'example.com'); - $server = [ + $server = [ $param => $value, ]; @@ -318,16 +321,15 @@ public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff($param, /** * @dataProvider httpsParamProvider - * @param string $xForwardedProto */ - public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue($xForwardedProto) + public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue(string $xForwardedProto): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); $request = $request->withHeader('Host', 'example.com'); $request = $request->withHeader('X-Forwarded-Proto', $xForwardedProto); - $server = []; + $server = []; $uri = marshalUriFromSapi($server, $request->getHeaders()); @@ -335,7 +337,7 @@ public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue($xForwa $this->assertSame('https', $uri->getScheme()); } - public function testMarshalUriStripsQueryStringFromRequestUri() + public function testMarshalUriStripsQueryStringFromRequestUri(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); @@ -351,14 +353,14 @@ public function testMarshalUriStripsQueryStringFromRequestUri() $this->assertSame('/foo/bar', $uri->getPath()); } - public function testMarshalUriInjectsQueryStringFromServer() + public function testMarshalUriInjectsQueryStringFromServer(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); $request = $request->withHeader('Host', 'example.com'); $server = [ - 'REQUEST_URI' => '/foo/bar?foo=bar', + 'REQUEST_URI' => '/foo/bar?foo=bar', 'QUERY_STRING' => 'bar=baz', ]; @@ -368,7 +370,7 @@ public function testMarshalUriInjectsQueryStringFromServer() $this->assertSame('bar=baz', $uri->getQuery()); } - public function testMarshalUriInjectsFragmentFromServer() + public function testMarshalUriInjectsFragmentFromServer(): void { $request = new ServerRequest(); $request = $request->withUri(new Uri('http://example.com/')); @@ -384,15 +386,15 @@ public function testMarshalUriInjectsFragmentFromServer() $this->assertSame('foo', $uri->getFragment()); } - public function testCanCreateServerRequestViaFromGlobalsMethod() + public function testCanCreateServerRequestViaFromGlobalsMethod(): void { $server = [ 'SERVER_PROTOCOL' => '1.1', - 'HTTP_HOST' => 'example.com', - 'HTTP_ACCEPT' => 'application/json', - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/foo/bar', - 'QUERY_STRING' => 'bar=baz', + 'HTTP_HOST' => 'example.com', + 'HTTP_ACCEPT' => 'application/json', + 'REQUEST_METHOD' => 'POST', + 'REQUEST_URI' => '/foo/bar', + 'QUERY_STRING' => 'bar=baz', ]; $cookies = $query = $body = [ @@ -402,15 +404,17 @@ public function testCanCreateServerRequestViaFromGlobalsMethod() $cookies['cookies'] = true; $query['query'] = true; $body['body'] = true; - $files = [ 'files' => [ - 'tmp_name' => 'php://temp', - 'size' => 0, - 'error' => 0, - 'name' => 'foo.bar', - 'type' => 'text/plain', - ]]; - $expectedFiles = [ - 'files' => new UploadedFile('php://temp', 0, 0, 'foo.bar', 'text/plain') + $files = [ + 'files' => [ + 'tmp_name' => 'php://temp', + 'size' => 0, + 'error' => 0, + 'name' => 'foo.bar', + 'type' => 'text/plain', + ], + ]; + $expectedFiles = [ + 'files' => new UploadedFile('php://temp', 0, 0, 'foo.bar', 'text/plain'), ]; $request = ServerRequestFactory::fromGlobals($server, $query, $body, $cookies, $files); @@ -423,9 +427,9 @@ public function testCanCreateServerRequestViaFromGlobalsMethod() $this->assertSame('1.1', $request->getProtocolVersion()); } - public function testFromGlobalsUsesCookieHeaderInsteadOfCookieSuperGlobal() + public function testFromGlobalsUsesCookieHeaderInsteadOfCookieSuperGlobal(): void { - $_COOKIE = [ + $_COOKIE = [ 'foo_bar' => 'bat', ]; $_SERVER['HTTP_COOKIE'] = 'foo_bar=baz'; @@ -438,9 +442,9 @@ public function testFromGlobalsUsesCookieHeaderInsteadOfCookieSuperGlobal() * @runInSeparateProcess * @preserveGlobalState */ - public function testCreateFromGlobalsShouldPreserveKeysWhenCreatedWithAZeroValue() + public function testCreateFromGlobalsShouldPreserveKeysWhenCreatedWithAZeroValue(): void { - $_SERVER['HTTP_ACCEPT'] = '0'; + $_SERVER['HTTP_ACCEPT'] = '0'; $_SERVER['CONTENT_LENGTH'] = '0'; $request = ServerRequestFactory::fromGlobals(); @@ -452,9 +456,9 @@ public function testCreateFromGlobalsShouldPreserveKeysWhenCreatedWithAZeroValue * @runInSeparateProcess * @preserveGlobalState */ - public function testCreateFromGlobalsShouldNotPreserveKeysWhenCreatedWithAnEmptyValue() + public function testCreateFromGlobalsShouldNotPreserveKeysWhenCreatedWithAnEmptyValue(): void { - $_SERVER['HTTP_ACCEPT'] = ''; + $_SERVER['HTTP_ACCEPT'] = ''; $_SERVER['CONTENT_LENGTH'] = ''; $request = ServerRequestFactory::fromGlobals(); @@ -467,7 +471,7 @@ public function testCreateFromGlobalsShouldNotPreserveKeysWhenCreatedWithAnEmpty * @runInSeparateProcess * @preserveGlobalState disabled */ - public function testFromGlobalsUsesCookieSuperGlobalWhenCookieHeaderIsNotSet() + public function testFromGlobalsUsesCookieSuperGlobalWhenCookieHeaderIsNotSet(): void { $_COOKIE = [ 'foo_bar' => 'bat', @@ -477,14 +481,15 @@ public function testFromGlobalsUsesCookieSuperGlobalWhenCookieHeaderIsNotSet() $this->assertSame(['foo_bar' => 'bat'], $request->getCookieParams()); } - public function cookieHeaderValues() + /** @return array */ + public function cookieHeaderValues(): array { return [ - 'ows-without-fold' => [ + 'ows-without-fold' => [ "\tfoo=bar ", ['foo' => 'bar'], ], - 'url-encoded-value' => [ + 'url-encoded-value' => [ 'foo=bar%3B+', ['foo' => 'bar; '], ], @@ -492,15 +497,15 @@ public function cookieHeaderValues() 'foo="bar"', ['foo' => 'bar'], ], - 'multiple-pairs' => [ + 'multiple-pairs' => [ 'foo=bar; baz="bat"; bau=bai', ['foo' => 'bar', 'baz' => 'bat', 'bau' => 'bai'], ], - 'same-name-pairs' => [ + 'same-name-pairs' => [ 'foo=bar; foo="bat"', ['foo' => 'bat'], ], - 'period-in-name' => [ + 'period-in-name' => [ 'foo.bar=baz', ['foo.bar' => 'baz'], ], @@ -509,10 +514,9 @@ public function cookieHeaderValues() /** * @dataProvider cookieHeaderValues - * @param string $cookieHeader * @param array $expectedCookies */ - public function testCookieHeaderVariations($cookieHeader, array $expectedCookies) + public function testCookieHeaderVariations(string $cookieHeader, array $expectedCookies): void { $_SERVER['HTTP_COOKIE'] = $cookieHeader; @@ -520,7 +524,7 @@ public function testCookieHeaderVariations($cookieHeader, array $expectedCookies $this->assertSame($expectedCookies, $request->getCookieParams()); } - public function testNormalizeServerUsesMixedCaseAuthorizationHeaderFromApacheWhenPresent() + public function testNormalizeServerUsesMixedCaseAuthorizationHeaderFromApacheWhenPresent(): void { $server = normalizeServer([], function () { return ['Authorization' => 'foobar']; @@ -530,7 +534,7 @@ public function testNormalizeServerUsesMixedCaseAuthorizationHeaderFromApacheWhe $this->assertSame('foobar', $server['HTTP_AUTHORIZATION']); } - public function testNormalizeServerUsesLowerCaseAuthorizationHeaderFromApacheWhenPresent() + public function testNormalizeServerUsesLowerCaseAuthorizationHeaderFromApacheWhenPresent(): void { $server = normalizeServer([], function () { return ['authorization' => 'foobar']; @@ -540,7 +544,7 @@ public function testNormalizeServerUsesLowerCaseAuthorizationHeaderFromApacheWhe $this->assertSame('foobar', $server['HTTP_AUTHORIZATION']); } - public function testNormalizeServerReturnsArrayUnalteredIfApacheHeadersDoNotContainAuthorization() + public function testNormalizeServerReturnsArrayUnalteredIfApacheHeadersDoNotContainAuthorization(): void { $expected = ['FOO_BAR' => 'BAZ']; @@ -551,32 +555,30 @@ public function testNormalizeServerReturnsArrayUnalteredIfApacheHeadersDoNotCont $this->assertSame($expected, $server); } - /** - * @group 57 - * @group 56 - */ - public function testNormalizeFilesReturnsOnlyActualFilesWhenOriginalFilesContainsNestedAssociativeArrays() + public function testNormalizeFilesReturnsOnlyActualFilesWhenOriginalFilesContainsNestedAssociativeArrays(): void { - $files = [ 'fooFiles' => [ - 'tmp_name' => ['file' => 'php://temp'], - 'size' => ['file' => 0], - 'error' => ['file' => 0], - 'name' => ['file' => 'foo.bar'], - 'type' => ['file' => 'text/plain'], - ]]; + $files = [ + 'fooFiles' => [ + 'tmp_name' => ['file' => 'php://temp'], + 'size' => ['file' => 0], + 'error' => ['file' => 0], + 'name' => ['file' => 'foo.bar'], + 'type' => ['file' => 'text/plain'], + ], + ]; $normalizedFiles = normalizeUploadedFiles($files); $this->assertCount(1, $normalizedFiles['fooFiles']); } - public function testMarshalProtocolVersionRisesExceptionIfVersionIsNotRecognized() + public function testMarshalProtocolVersionRisesExceptionIfVersionIsNotRecognized(): void { $this->expectException(UnexpectedValueException::class); marshalProtocolVersionFromSapi(['SERVER_PROTOCOL' => 'dadsa/1.0']); } - public function testMarshalProtocolReturnsDefaultValueIfHeaderIsNotPresent() + public function testMarshalProtocolReturnsDefaultValueIfHeaderIsNotPresent(): void { $version = marshalProtocolVersionFromSapi([]); $this->assertSame('1.1', $version); @@ -585,13 +587,14 @@ public function testMarshalProtocolReturnsDefaultValueIfHeaderIsNotPresent() /** * @dataProvider marshalProtocolVersionProvider */ - public function testMarshalProtocolVersionReturnsHttpVersions($protocol, $expected) + public function testMarshalProtocolVersionReturnsHttpVersions(string $protocol, string $expected): void { $version = marshalProtocolVersionFromSapi(['SERVER_PROTOCOL' => $protocol]); $this->assertSame($expected, $version); } - public function marshalProtocolVersionProvider() + /** @return array */ + public function marshalProtocolVersionProvider(): array { return [ 'HTTP/1.0' => ['HTTP/1.0', '1.0'], @@ -600,12 +603,12 @@ public function marshalProtocolVersionProvider() ]; } - public function testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUrlButNoXRewriteUrlPresent() + public function testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUrlButNoXRewriteUrlPresent(): void { $headers = [ 'X-Original-URL' => '/hijack-attempt', ]; - $server = [ + $server = [ 'REQUEST_URI' => 'https://example.com/requested/path', ]; @@ -613,11 +616,11 @@ public function testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUr $this->assertSame('/requested/path', $uri->getPath()); } - public function testServerRequestFactoryHasAWritableEmptyBody() + public function testServerRequestFactoryHasAWritableEmptyBody(): void { $factory = new ServerRequestFactory(); $request = $factory->createServerRequest('GET', '/'); - $body = $request->getBody(); + $body = $request->getBody(); $this->assertTrue($body->isWritable()); $this->assertTrue($body->isSeekable()); @@ -717,7 +720,7 @@ public function testDoesNotMarshalAllContentPrefixedServerVarsAsHeaders( string $expectedHeaderValue, string $expectedServerValue ): void { - $request = ServerRequestFactory::fromGlobals($server); + $request = ServerRequestFactory::fromGlobals($server); $headerName = str_replace('_', '-', $key); $this->assertSame($expectedHeaderValue, $request->getHeaderLine($headerName)); @@ -727,7 +730,7 @@ public function testDoesNotMarshalAllContentPrefixedServerVarsAsHeaders( public function testReturnsFilteredRequestBasedOnRequestFilterProvided(): void { $expectedRequest = new ServerRequest(); - $filter = new class($expectedRequest) implements FilterServerRequestInterface { + $filter = new class ($expectedRequest) implements FilterServerRequestInterface { /** @var ServerRequestInterface */ private $request; @@ -757,18 +760,18 @@ public function __invoke(ServerRequestInterface $request): ServerRequestInterfac public function testHonorsHostHeaderOverServerNameWhenMarshalingUrl(): void { $server = [ - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => '80', - 'SERVER_ADDR' => '172.22.0.4', - 'REMOTE_PORT' => '36852', + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => '80', + 'SERVER_ADDR' => '172.22.0.4', + 'REMOTE_PORT' => '36852', 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'DOCUMENT_ROOT' => '/var/www/public', - 'DOCUMENT_URI' => '/index.php', - 'REQUEST_URI' => '/api/messagebox-schema', + 'DOCUMENT_ROOT' => '/var/www/public', + 'DOCUMENT_URI' => '/index.php', + 'REQUEST_URI' => '/api/messagebox-schema', 'PATH_TRANSLATED' => '/var/www/public', - 'PATH_INFO' => '', - 'SCRIPT_NAME' => '/index.php', - 'REQUEST_METHOD' => 'GET', + 'PATH_INFO' => '', + 'SCRIPT_NAME' => '/index.php', + 'REQUEST_METHOD' => 'GET', 'SCRIPT_FILENAME' => '/var/www/public/index.php', // headers 'HTTP_HOST' => 'example.com', @@ -797,7 +800,7 @@ public function invalidHostHeaders(): iterable return [ 'comma' => ['example.com,example.net'], 'space' => ['example com'], - 'tab' => ["example\tcom"], + 'tab' => ["example\tcom"], ]; } diff --git a/test/ServerRequestFilter/DoNotFilterTest.php b/test/ServerRequestFilter/DoNotFilterTest.php index bcd60761..a3b126d0 100644 --- a/test/ServerRequestFilter/DoNotFilterTest.php +++ b/test/ServerRequestFilter/DoNotFilterTest.php @@ -4,8 +4,8 @@ namespace LaminasTest\Diactoros\ServerRequestFilter; -use Laminas\Diactoros\ServerRequestFilter\DoNotFilter; use Laminas\Diactoros\ServerRequest; +use Laminas\Diactoros\ServerRequestFilter\DoNotFilter; use PHPUnit\Framework\TestCase; class DoNotFilterTest extends TestCase diff --git a/test/ServerRequestFilter/FilterUsingXForwardedHeadersTest.php b/test/ServerRequestFilter/FilterUsingXForwardedHeadersTest.php index 317dc2ca..ff677867 100644 --- a/test/ServerRequestFilter/FilterUsingXForwardedHeadersTest.php +++ b/test/ServerRequestFilter/FilterUsingXForwardedHeadersTest.php @@ -6,8 +6,8 @@ use Laminas\Diactoros\Exception\InvalidForwardedHeaderNameException; use Laminas\Diactoros\Exception\InvalidProxyAddressException; -use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders; use Laminas\Diactoros\ServerRequest; +use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders; use PHPUnit\Framework\TestCase; class FilterUsingXForwardedHeadersTest extends TestCase @@ -208,8 +208,8 @@ public function testListOfForwardedHostsIsConsideredUntrusted(): void 'GET', 'php://temp', [ - 'Host' => 'localhost', - 'X-Forwarded-Host' => 'example.com,proxy.api.example.com', + 'Host' => 'localhost', + 'X-Forwarded-Host' => 'example.com,proxy.api.example.com', ] ); @@ -227,8 +227,8 @@ public function testListOfForwardedPortsIsConsideredUntrusted(): void 'GET', 'php://temp', [ - 'Host' => 'localhost', - 'X-Forwarded-Port' => '8080,9000', + 'Host' => 'localhost', + 'X-Forwarded-Port' => '8080,9000', ] ); @@ -333,7 +333,7 @@ public function testTrustReservedSubnetsProducesFilterThatRejectsAddressesNotFro } /** @psalm-return iterable */ - public function xForwardedProtoValues() : iterable + public function xForwardedProtoValues(): iterable { yield 'https-lowercase' => ['https', 'https']; yield 'https-uppercase' => ['HTTPS', 'https']; @@ -365,7 +365,7 @@ public function testOnlyHonorsXForwardedProtoIfValueResolvesToHTTPS( $filter = FilterUsingXForwardedHeaders::trustReservedSubnets(); $filteredRequest = $filter($request); - $uri = $filteredRequest->getUri(); + $uri = $filteredRequest->getUri(); $this->assertSame($expectedScheme, $uri->getScheme()); } } diff --git a/test/ServerRequestFilter/IPRangeTest.php b/test/ServerRequestFilter/IPRangeTest.php index 65716ebf..4d4436df 100644 --- a/test/ServerRequestFilter/IPRangeTest.php +++ b/test/ServerRequestFilter/IPRangeTest.php @@ -52,18 +52,20 @@ public function testIPv4(bool $result, string $remoteAddr, string $cidr): void */ public function IPv6Data(): array { + // @codingStandardsIgnoreStart return [ - 'valid - ipv4 subnet' => [true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], - 'valid - exact' => [true, '0:0:0:0:0:0:0:1', '::1'], - 'valid - all subnets' => [true, '0:0:603:0:396e:4789:8e99:0001', '::/0'], - 'valid - subnet expands to all' => [true, '0:0:603:0:396e:4789:8e99:0001', '2a01:198:603:0::/0'], - 'invalid - not in subnet' => [false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], - 'invalid - does not match exact' => [false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'], + 'valid - ipv4 subnet' => [true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], + 'valid - exact' => [true, '0:0:0:0:0:0:0:1', '::1'], + 'valid - all subnets' => [true, '0:0:603:0:396e:4789:8e99:0001', '::/0'], + 'valid - subnet expands to all' => [true, '0:0:603:0:396e:4789:8e99:0001', '2a01:198:603:0::/0'], + 'invalid - not in subnet' => [false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], + 'invalid - does not match exact' => [false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'], 'invalid - compressed notation, does not match exact' => [false, '0:0:603:0:396e:4789:8e99:0001', '::1'], - 'invalid - garbage IP' => [false, '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2', '::1'], - 'invalid - invalid cidr' => [false, '2a01:198:603:0:396e:4789:8e99:890f', 'unknown'], - 'invalid - empty IP address' => [false, '', '::1'], + 'invalid - garbage IP' => [false, '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2', '::1'], + 'invalid - invalid cidr' => [false, '2a01:198:603:0:396e:4789:8e99:890f', 'unknown'], + 'invalid - empty IP address' => [false, '', '::1'], ]; + // @codingStandardsIgnoreEnd } /** diff --git a/test/ServerRequestTest.php b/test/ServerRequestTest.php index d144bbce..c80e0f3f 100644 --- a/test/ServerRequestTest.php +++ b/test/ServerRequestTest.php @@ -13,78 +13,77 @@ class ServerRequestTest extends TestCase { - /** - * @var ServerRequest - */ + /** @var ServerRequest */ protected $request; - protected function setUp() : void + protected function setUp(): void { $this->request = new ServerRequest(); } - public function testServerParamsAreEmptyByDefault() + public function testServerParamsAreEmptyByDefault(): void { $this->assertEmpty($this->request->getServerParams()); } - public function testQueryParamsAreEmptyByDefault() + public function testQueryParamsAreEmptyByDefault(): void { $this->assertEmpty($this->request->getQueryParams()); } - public function testQueryParamsMutatorReturnsCloneWithChanges() + public function testQueryParamsMutatorReturnsCloneWithChanges(): void { - $value = ['foo' => 'bar']; + $value = ['foo' => 'bar']; $request = $this->request->withQueryParams($value); $this->assertNotSame($this->request, $request); $this->assertSame($value, $request->getQueryParams()); } - public function testCookiesAreEmptyByDefault() + public function testCookiesAreEmptyByDefault(): void { $this->assertEmpty($this->request->getCookieParams()); } - public function testCookiesMutatorReturnsCloneWithChanges() + public function testCookiesMutatorReturnsCloneWithChanges(): void { - $value = ['foo' => 'bar']; + $value = ['foo' => 'bar']; $request = $this->request->withCookieParams($value); $this->assertNotSame($this->request, $request); $this->assertSame($value, $request->getCookieParams()); } - public function testUploadedFilesAreEmptyByDefault() + public function testUploadedFilesAreEmptyByDefault(): void { $this->assertEmpty($this->request->getUploadedFiles()); } - public function testParsedBodyIsEmptyByDefault() + public function testParsedBodyIsEmptyByDefault(): void { $this->assertEmpty($this->request->getParsedBody()); } - public function testParsedBodyMutatorReturnsCloneWithChanges() + public function testParsedBodyMutatorReturnsCloneWithChanges(): void { - $value = ['foo' => 'bar']; + $value = ['foo' => 'bar']; $request = $this->request->withParsedBody($value); $this->assertNotSame($this->request, $request); $this->assertSame($value, $request->getParsedBody()); } - public function testAttributesAreEmptyByDefault() + public function testAttributesAreEmptyByDefault(): void { $this->assertEmpty($this->request->getAttributes()); } - public function testSingleAttributesWhenEmptyByDefault() + public function testSingleAttributesWhenEmptyByDefault(): void { $this->assertEmpty($this->request->getAttribute('does-not-exist')); } + /** * @depends testAttributesAreEmptyByDefault */ - public function testAttributeMutatorReturnsCloneWithChanges() + public function testAttributeMutatorReturnsCloneWithChanges(): ServerRequest { $request = $this->request->withAttribute('foo', 'bar'); $this->assertNotSame($this->request, $request); @@ -95,14 +94,15 @@ public function testAttributeMutatorReturnsCloneWithChanges() /** * @depends testAttributeMutatorReturnsCloneWithChanges */ - public function testRemovingAttributeReturnsCloneWithoutAttribute($request) + public function testRemovingAttributeReturnsCloneWithoutAttribute(ServerRequest $request): void { $new = $request->withoutAttribute('foo'); $this->assertNotSame($request, $new); $this->assertNull($new->getAttribute('foo', null)); } - public function provideMethods() + /** @return array */ + public function provideMethods(): array { return [ 'post' => ['POST', 'POST'], @@ -114,7 +114,7 @@ public function provideMethods() /** * @dataProvider provideMethods */ - public function testUsesProvidedConstructorArguments($parameterMethod, $methodReturned) + public function testUsesProvidedConstructorArguments(?string $parameterMethod, string $methodReturned): void { $server = [ 'foo' => 'bar', @@ -127,18 +127,18 @@ public function testUsesProvidedConstructorArguments($parameterMethod, $methodRe 'files' => new UploadedFile('php://temp', 0, 0), ]; - $uri = new Uri('http://example.com'); - $headers = [ + $uri = new Uri('http://example.com'); + $headers = [ 'host' => ['example.com'], ]; - $cookies = [ + $cookies = [ 'boo' => 'foo', ]; $queryParams = [ 'bar' => 'bat', ]; - $parsedBody = 'bazbar'; - $protocol = '1.2'; + $parsedBody = 'bazbar'; + $protocol = '1.2'; $request = new ServerRequest( $server, @@ -165,42 +165,33 @@ public function testUsesProvidedConstructorArguments($parameterMethod, $methodRe $this->assertSame($protocol, $request->getProtocolVersion()); $body = $request->getBody(); - $r = new ReflectionProperty($body, 'stream'); + $r = new ReflectionProperty($body, 'stream'); $r->setAccessible(true); $stream = $r->getValue($body); $this->assertSame('php://memory', $stream); } - /** - * @group 46 - */ - public function testCookieParamsAreAnEmptyArrayAtInitialization() + public function testCookieParamsAreAnEmptyArrayAtInitialization(): void { $request = new ServerRequest(); $this->assertIsArray($request->getCookieParams()); $this->assertCount(0, $request->getCookieParams()); } - /** - * @group 46 - */ - public function testQueryParamsAreAnEmptyArrayAtInitialization() + public function testQueryParamsAreAnEmptyArrayAtInitialization(): void { $request = new ServerRequest(); $this->assertIsArray($request->getQueryParams()); $this->assertCount(0, $request->getQueryParams()); } - /** - * @group 46 - */ - public function testParsedBodyIsNullAtInitialization() + public function testParsedBodyIsNullAtInitialization(): void { $request = new ServerRequest(); $this->assertNull($request->getParsedBody()); } - public function testAllowsRemovingAttributeWithNullValue() + public function testAllowsRemovingAttributeWithNullValue(): void { $request = new ServerRequest(); $request = $request->withAttribute('boo', null); @@ -208,14 +199,14 @@ public function testAllowsRemovingAttributeWithNullValue() $this->assertSame([], $request->getAttributes()); } - public function testAllowsRemovingNonExistentAttribute() + public function testAllowsRemovingNonExistentAttribute(): void { $request = new ServerRequest(); $request = $request->withoutAttribute('boo'); $this->assertSame([], $request->getAttributes()); } - public function testTryToAddInvalidUploadedFiles() + public function testTryToAddInvalidUploadedFiles(): void { $request = new ServerRequest(); @@ -224,7 +215,7 @@ public function testTryToAddInvalidUploadedFiles() $request->withUploadedFiles([null]); } - public function testNestedUploadedFiles() + public function testNestedUploadedFiles(): void { $request = new ServerRequest(); @@ -232,7 +223,7 @@ public function testNestedUploadedFiles() [ new UploadedFile('php://temp', 0, 0), new UploadedFile('php://temp', 0, 0), - ] + ], ]; $request = $request->withUploadedFiles($uploadedFiles); diff --git a/test/StreamTest.php b/test/StreamTest.php index c9cb9445..2b150cf6 100644 --- a/test/StreamTest.php +++ b/test/StreamTest.php @@ -34,80 +34,79 @@ class StreamTest extends TestCase { + /** @var string|null */ public $tmpnam; - /** - * @var Stream - */ + /** @var Stream */ protected $stream; - protected function setUp() : void + protected function setUp(): void { $this->tmpnam = null; $this->stream = new Stream('php://memory', 'wb+'); } - protected function tearDown() : void + protected function tearDown(): void { if ($this->tmpnam && file_exists($this->tmpnam)) { unlink($this->tmpnam); } } - public function testCanInstantiateWithStreamIdentifier() + public function testCanInstantiateWithStreamIdentifier(): void { $this->assertInstanceOf(Stream::class, $this->stream); } - public function testCanInstantiteWithStreamResource() + public function testCanInstantiteWithStreamResource(): void { $resource = fopen('php://memory', 'wb+'); $stream = new Stream($resource); $this->assertInstanceOf(Stream::class, $stream); } - public function testCanInstantiateWithGDResource() + public function testCanInstantiateWithGDResource(): void { $resource = imagecreate(1, 1); $stream = new Stream($resource); $this->assertInstanceOf(Stream::class, $stream); } - public function testIsReadableReturnsFalseIfStreamIsNotReadable() + public function testIsReadableReturnsFalseIfStreamIsNotReadable(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $stream = new Stream($this->tmpnam, 'w'); + $stream = new Stream($this->tmpnam, 'w'); $this->assertFalse($stream->isReadable()); } - public function testIsWritableReturnsFalseIfStreamIsNotWritable() + public function testIsWritableReturnsFalseIfStreamIsNotWritable(): void { $stream = new Stream('php://memory', 'r'); $this->assertFalse($stream->isWritable()); } - public function testToStringRetrievesFullContentsOfStream() + public function testToStringRetrievesFullContentsOfStream(): void { $message = 'foo bar'; $this->stream->write($message); $this->assertSame($message, (string) $this->stream); } - public function testDetachReturnsResource() + public function testDetachReturnsResource(): void { $resource = fopen('php://memory', 'wb+'); $stream = new Stream($resource); $this->assertSame($resource, $stream->detach()); } - public function testPassingInvalidStreamResourceToConstructorRaisesException() + public function testPassingInvalidStreamResourceToConstructorRaisesException(): void { $this->expectException(InvalidArgumentException::class); new Stream([' THIS WILL NOT WORK ']); } - public function testStringSerializationReturnsEmptyStringWhenStreamIsNotReadable() + public function testStringSerializationReturnsEmptyStringWhenStreamIsNotReadable(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); @@ -116,64 +115,61 @@ public function testStringSerializationReturnsEmptyStringWhenStreamIsNotReadable $this->assertSame('', $stream->__toString()); } - public function testCloseClosesResource() + public function testCloseClosesResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $resource = fopen($this->tmpnam, 'wb+'); + $stream = new Stream($resource); $stream->close(); $this->assertFalse(is_resource($resource)); } - public function testCloseUnsetsResource() + public function testCloseUnsetsResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $resource = fopen($this->tmpnam, 'wb+'); + $stream = new Stream($resource); $stream->close(); $this->assertNull($stream->detach()); } - public function testCloseDoesNothingAfterDetach() + public function testCloseDoesNothingAfterDetach(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); - $detached = $stream->detach(); + $resource = fopen($this->tmpnam, 'wb+'); + $stream = new Stream($resource); + $detached = $stream->detach(); $stream->close(); $this->assertTrue(is_resource($detached)); $this->assertSame($resource, $detached); } - /** - * @group 42 - */ - public function testSizeReportsNullWhenNoResourcePresent() + public function testSizeReportsNullWhenNoResourcePresent(): void { $this->stream->detach(); $this->assertNull($this->stream->getSize()); } - public function testTellReportsCurrentPositionInResource() + public function testTellReportsCurrentPositionInResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); fseek($resource, 2); $this->assertSame(2, $stream->tell()); } - public function testTellRaisesExceptionIfResourceIsDetached() + public function testTellRaisesExceptionIfResourceIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); fseek($resource, 2); $stream->detach(); @@ -184,23 +180,23 @@ public function testTellRaisesExceptionIfResourceIsDetached() $stream->tell(); } - public function testEofReportsFalseWhenNotAtEndOfStream() + public function testEofReportsFalseWhenNotAtEndOfStream(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); fseek($resource, 2); $this->assertFalse($stream->eof()); } - public function testEofReportsTrueWhenAtEndOfStream() + public function testEofReportsTrueWhenAtEndOfStream(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); while (! feof($resource)) { fread($resource, 4096); @@ -208,64 +204,64 @@ public function testEofReportsTrueWhenAtEndOfStream() $this->assertTrue($stream->eof()); } - public function testEofReportsTrueWhenStreamIsDetached() + public function testEofReportsTrueWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); fseek($resource, 2); $stream->detach(); $this->assertTrue($stream->eof()); } - public function testIsSeekableReturnsTrueForReadableStreams() + public function testIsSeekableReturnsTrueForReadableStreams(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertTrue($stream->isSeekable()); } - public function testIsSeekableReturnsFalseForDetachedStreams() + public function testIsSeekableReturnsFalseForDetachedStreams(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->assertFalse($stream->isSeekable()); } - public function testSeekAdvancesToGivenOffsetOfStream() + public function testSeekAdvancesToGivenOffsetOfStream(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertNull($stream->seek(2)); $this->assertSame(2, $stream->tell()); } - public function testRewindResetsToStartOfStream() + public function testRewindResetsToStartOfStream(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertNull($stream->seek(2)); $stream->rewind(); $this->assertSame(0, $stream->tell()); } - public function testSeekRaisesExceptionWhenStreamIsDetached() + public function testSeekRaisesExceptionWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->expectException(RuntimeException::class); @@ -274,23 +270,24 @@ public function testSeekRaisesExceptionWhenStreamIsDetached() $stream->seek(2); } - public function testIsWritableReturnsFalseWhenStreamIsDetached() + public function testIsWritableReturnsFalseWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->assertFalse($stream->isWritable()); } - public function testIsWritableReturnsTrueForWritableMemoryStream() + public function testIsWritableReturnsTrueForWritableMemoryStream(): void { $stream = new Stream("php://temp", "r+b"); $this->assertTrue($stream->isWritable()); } - public function provideDataForIsWritable() + /** @return array */ + public function provideDataForIsWritable(): array { return [ ['a', true, true], @@ -317,7 +314,7 @@ public function provideDataForIsWritable() ]; } - private function findNonExistentTempName() + private function findNonExistentTempName(): string { while (true) { $tmpnam = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'diac' . uniqid(); @@ -331,7 +328,7 @@ private function findNonExistentTempName() /** * @dataProvider provideDataForIsWritable */ - public function testIsWritableReturnsCorrectFlagForMode($mode, $fileShouldExist, $flag) + public function testIsWritableReturnsCorrectFlagForMode(string $mode, bool $fileShouldExist, bool $flag): void { if ($fileShouldExist) { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); @@ -341,11 +338,12 @@ public function testIsWritableReturnsCorrectFlagForMode($mode, $fileShouldExist, $this->tmpnam = $this->findNonExistentTempName(); } $resource = fopen($this->tmpnam, $mode); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertSame($flag, $stream->isWritable()); } - public function provideDataForIsReadable() + /** @return array */ + public function provideDataForIsReadable(): array { return [ ['a', true, false], @@ -375,7 +373,7 @@ public function provideDataForIsReadable() /** * @dataProvider provideDataForIsReadable */ - public function testIsReadableReturnsCorrectFlagForMode($mode, $fileShouldExist, $flag) + public function testIsReadableReturnsCorrectFlagForMode(string $mode, bool $fileShouldExist, bool $flag): void { if ($fileShouldExist) { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); @@ -385,16 +383,16 @@ public function testIsReadableReturnsCorrectFlagForMode($mode, $fileShouldExist, $this->tmpnam = $this->findNonExistentTempName(); } $resource = fopen($this->tmpnam, $mode); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertSame($flag, $stream->isReadable()); } - public function testWriteRaisesExceptionWhenStreamIsDetached() + public function testWriteRaisesExceptionWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->expectException(RuntimeException::class); @@ -403,7 +401,7 @@ public function testWriteRaisesExceptionWhenStreamIsDetached() $stream->write('bar'); } - public function testWriteRaisesExceptionWhenStreamIsNotWritable() + public function testWriteRaisesExceptionWhenStreamIsNotWritable(): void { $stream = new Stream('php://memory', 'r'); @@ -413,23 +411,23 @@ public function testWriteRaisesExceptionWhenStreamIsNotWritable() $stream->write('bar'); } - public function testIsReadableReturnsFalseWhenStreamIsDetached() + public function testIsReadableReturnsFalseWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'wb+'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->assertFalse($stream->isReadable()); } - public function testReadRaisesExceptionWhenStreamIsDetached() + public function testReadRaisesExceptionWhenStreamIsDetached(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'r'); - $stream = new Stream($resource); + $stream = new Stream($resource); $stream->detach(); $this->expectException(RuntimeException::class); @@ -438,67 +436,70 @@ public function testReadRaisesExceptionWhenStreamIsDetached() $stream->read(4096); } - public function testReadReturnsEmptyStringWhenAtEndOfFile() + public function testReadReturnsEmptyStringWhenAtEndOfFile(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'r'); - $stream = new Stream($resource); + $stream = new Stream($resource); while (! feof($resource)) { fread($resource, 4096); } $this->assertSame('', $stream->read(4096)); } - public function testGetContentsRisesExceptionIfStreamIsNotReadable() + public function testGetContentsRisesExceptionIfStreamIsNotReadable(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'w'); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->expectException(RuntimeException::class); $stream->getContents(); } - public function invalidResources() + /** @return array */ + public function invalidResources(): array { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); return [ - 'null' => [ null ], - 'false' => [ false ], - 'true' => [ true ], - 'int' => [ 1 ], - 'float' => [ 1.1 ], - 'array' => [ [ fopen($this->tmpnam, 'r+') ] ], - 'object' => [ (object) [ 'resource' => fopen($this->tmpnam, 'r+') ] ], + 'null' => [null], + 'false' => [false], + 'true' => [true], + 'int' => [1], + 'float' => [1.1], + 'array' => [[fopen($this->tmpnam, 'r+')]], + 'object' => [(object) ['resource' => fopen($this->tmpnam, 'r+')]], ]; } /** * @dataProvider invalidResources + * @param mixed $resource */ - public function testAttachWithNonStringNonResourceRaisesException($resource) + public function testAttachWithNonStringNonResourceRaisesException($resource): void { - $this->expectException(\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid stream'); + /** @psalm-suppress MixedArgument */ $this->stream->attach($resource); } - public function testAttachWithInvalidStringResourceRaisesException() + public function testAttachWithInvalidStringResourceRaisesException(): void { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Invalid stream'); $this->stream->attach('foo-bar-baz'); } - public function testAttachWithResourceAttachesResource() + public function testAttachWithResourceAttachesResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); $r = new ReflectionProperty($this->stream, 'resource'); @@ -507,7 +508,7 @@ public function testAttachWithResourceAttachesResource() $this->assertSame($resource, $test); } - public function testAttachWithStringRepresentingResourceCreatesAndAttachesResource() + public function testAttachWithStringRepresentingResourceCreatesAndAttachesResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); $this->stream->attach($this->tmpnam); @@ -520,10 +521,10 @@ public function testAttachWithStringRepresentingResourceCreatesAndAttachesResour $this->assertSame('FooBar', $test); } - public function testGetContentsShouldGetFullStreamContents() + public function testGetContentsShouldGetFullStreamContents(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); fwrite($resource, 'FooBar'); @@ -534,10 +535,10 @@ public function testGetContentsShouldGetFullStreamContents() $this->assertSame('FooBar', $test); } - public function testGetContentsShouldReturnStreamContentsFromCurrentPointer() + public function testGetContentsShouldReturnStreamContentsFromCurrentPointer(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); fwrite($resource, 'FooBar'); @@ -548,10 +549,10 @@ public function testGetContentsShouldReturnStreamContentsFromCurrentPointer() $this->assertSame('Bar', $test); } - public function testGetMetadataReturnsAllMetadataWhenNoKeyPresent() + public function testGetMetadataReturnsAllMetadataWhenNoKeyPresent(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); $expected = stream_get_meta_data($resource); @@ -560,44 +561,38 @@ public function testGetMetadataReturnsAllMetadataWhenNoKeyPresent() $this->assertSame($expected, $test); } - public function testGetMetadataReturnsDataForSpecifiedKey() + public function testGetMetadataReturnsDataForSpecifiedKey(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); $metadata = stream_get_meta_data($resource); $expected = $metadata['uri']; - $test = $this->stream->getMetadata('uri'); + $test = $this->stream->getMetadata('uri'); $this->assertSame($expected, $test); } - public function testGetMetadataReturnsNullIfNoDataExistsForKey() + public function testGetMetadataReturnsNullIfNoDataExistsForKey(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); - $resource = fopen($this->tmpnam, 'r+'); + $resource = fopen($this->tmpnam, 'r+'); $this->stream->attach($resource); $this->assertNull($this->stream->getMetadata('TOTALLY_MADE_UP')); } - /** - * @group 42 - */ - public function testGetSizeReturnsStreamSize() + public function testGetSizeReturnsStreamSize(): void { $resource = fopen(__FILE__, 'r'); $expected = fstat($resource); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertSame($expected['size'], $stream->getSize()); } - /** - * @group 67 - */ - public function testRaisesExceptionOnConstructionForNonStreamResources() + public function testRaisesExceptionOnConstructionForNonStreamResources(): void { $resource = $this->getResourceFor67(); if (false === $resource) { @@ -607,13 +602,11 @@ public function testRaisesExceptionOnConstructionForNonStreamResources() $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('stream'); + /** @psalm-suppress ImplicitToStringCast */ new Stream($resource); } - /** - * @group 67 - */ - public function testRaisesExceptionOnAttachForNonStreamResources() + public function testRaisesExceptionOnAttachForNonStreamResources(): void { $resource = $this->getResourceFor67(); if (false === $resource) { @@ -625,9 +618,11 @@ public function testRaisesExceptionOnAttachForNonStreamResources() $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('stream'); + /** @psalm-suppress ImplicitToStringCast */ $stream->attach($resource); } + /** @return resource|false */ public function getResourceFor67() { if (function_exists('curl_init')) { @@ -638,10 +633,6 @@ public function getResourceFor67() return shmop_open(ftok(__FILE__, 't'), 'c', 0644, 100); } - if (function_exists('gmp_init')) { - return gmp_init(1); - } - if (function_exists('imagecreate')) { return imagecreate(200, 200); } @@ -649,12 +640,12 @@ public function getResourceFor67() return false; } - public function testCanReadContentFromNotSeekableResource() + public function testCanReadContentFromNotSeekableResource(): void { $this->tmpnam = tempnam(sys_get_temp_dir(), 'diac'); file_put_contents($this->tmpnam, 'FOO BAR'); $resource = fopen($this->tmpnam, 'r'); - $stream = $this + $stream = $this ->getMockBuilder(Stream::class) ->setConstructorArgs([$resource]) ->setMethods(['isSeekable']) @@ -666,13 +657,10 @@ public function testCanReadContentFromNotSeekableResource() $this->assertSame('FOO BAR', $stream->__toString()); } - /** - * @group 42 - */ - public function testSizeReportsNullForPhpInputStreams() + public function testSizeReportsNullForPhpInputStreams(): void { $resource = fopen('php://input', 'r'); - $stream = new Stream($resource); + $stream = new Stream($resource); $this->assertNull($stream->getSize()); } } diff --git a/test/TestAsset/CallbacksForCallbackStreamTest.php b/test/TestAsset/CallbacksForCallbackStreamTest.php index 87fbb6a4..004a3d7e 100644 --- a/test/TestAsset/CallbacksForCallbackStreamTest.php +++ b/test/TestAsset/CallbacksForCallbackStreamTest.php @@ -9,7 +9,7 @@ class CallbacksForCallbackStreamTest /** * Sample callback to use with testing. */ - public function sampleCallback() : string + public function sampleCallback(): string { return __METHOD__; } @@ -17,7 +17,7 @@ public function sampleCallback() : string /** * Sample static callback to use with testing. */ - public static function sampleStaticCallback() : string + public static function sampleStaticCallback(): string { return __METHOD__; } diff --git a/test/TestAsset/HeaderStack.php b/test/TestAsset/HeaderStack.php index 8873bdfa..cd7c496e 100644 --- a/test/TestAsset/HeaderStack.php +++ b/test/TestAsset/HeaderStack.php @@ -9,15 +9,13 @@ */ class HeaderStack { - /** - * @var string[][] - */ + /** @var string[][] */ private static $data = []; /** * Reset state */ - public static function reset() + public static function reset(): void { self::$data = []; } @@ -27,7 +25,7 @@ public static function reset() * * @param string[] $header */ - public static function push(array $header) + public static function push(array $header): void { self::$data[] = $header; } @@ -37,7 +35,7 @@ public static function push(array $header) * * @return string[][] */ - public static function stack() + public static function stack(): array { return self::$data; } @@ -46,10 +44,8 @@ public static function stack() * Verify if there's a header line on the stack * * @param string $header - * - * @return bool */ - public static function has($header) + public static function has($header): bool { foreach (self::$data as $item) { if ($item['header'] === $header) { diff --git a/test/UploadedFileTest.php b/test/UploadedFileTest.php index 0b2459ed..19816088 100644 --- a/test/UploadedFileTest.php +++ b/test/UploadedFileTest.php @@ -14,8 +14,9 @@ use function basename; use function file_exists; use function file_get_contents; +use function file_put_contents; use function fopen; -use function is_scalar; +use function is_string; use function sys_get_temp_dir; use function tempnam; use function uniqid; @@ -38,13 +39,13 @@ final class UploadedFileTest extends TestCase /** @var mixed */ private $tmpFile; - protected function setUp() : void + protected function setUp(): void { $this->tmpFile = null; $this->orgFile = null; } - protected function tearDown() : void + protected function tearDown(): void { if (is_string($this->tmpFile) && file_exists($this->tmpFile)) { unlink($this->tmpFile); @@ -59,17 +60,17 @@ protected function tearDown() : void public function invalidStreams(): array { return [ - 'null' => [null], - 'true' => [true], - 'false' => [false], - 'int' => [1], - 'float' => [1.1], + 'null' => [null], + 'true' => [true], + 'false' => [false], + 'int' => [1], + 'float' => [1.1], /* Have not figured out a valid way to test an invalid path yet; null byte injection * appears to get caught by fopen() 'invalid-path' => [ ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) ? '[:]' : 'foo' . chr(0) ], */ - 'array' => [['filename']], - 'object' => [(object) ['filename']], + 'array' => [['filename']], + 'object' => [(object) ['filename']], ]; } @@ -138,8 +139,8 @@ public function testGetStreamReturnsOriginalStreamObject(): void public function testGetStreamReturnsWrappedPhpStream(): void { - $stream = fopen('php://temp', 'wb+'); - $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); + $stream = fopen('php://temp', 'wb+'); + $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); $uploadStream = $upload->getStream()->detach(); $this->assertSame($stream, $uploadStream); } @@ -147,9 +148,9 @@ public function testGetStreamReturnsWrappedPhpStream(): void public function testGetStreamReturnsStreamForFile(): void { $this->tmpFile = $stream = tempnam(sys_get_temp_dir(), 'diac'); - $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); - $uploadStream = $upload->getStream(); - $r = new ReflectionProperty($uploadStream, 'stream'); + $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); + $uploadStream = $upload->getStream(); + $r = new ReflectionProperty($uploadStream, 'stream'); $r->setAccessible(true); $this->assertSame($stream, $r->getValue($uploadStream)); } @@ -157,7 +158,7 @@ public function testGetStreamReturnsStreamForFile(): void public function testMovesFileToDesignatedPath(): void { $originalContents = 'Foo bar!'; - $stream = new Stream('php://temp', 'wb+'); + $stream = new Stream('php://temp', 'wb+'); $stream->write($originalContents); $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); @@ -185,7 +186,6 @@ public function invalidMovePaths(): array /** * @dataProvider invalidMovePaths - * * @param mixed $path */ public function testMoveRaisesExceptionForInvalidPath($path): void @@ -238,13 +238,13 @@ public function testCannotRetrieveStreamAfterMove(): void public function nonOkErrorStatus(): array { return [ - 'UPLOAD_ERR_INI_SIZE' => [ UPLOAD_ERR_INI_SIZE ], - 'UPLOAD_ERR_FORM_SIZE' => [ UPLOAD_ERR_FORM_SIZE ], - 'UPLOAD_ERR_PARTIAL' => [ UPLOAD_ERR_PARTIAL ], - 'UPLOAD_ERR_NO_FILE' => [ UPLOAD_ERR_NO_FILE ], - 'UPLOAD_ERR_NO_TMP_DIR' => [ UPLOAD_ERR_NO_TMP_DIR ], - 'UPLOAD_ERR_CANT_WRITE' => [ UPLOAD_ERR_CANT_WRITE ], - 'UPLOAD_ERR_EXTENSION' => [ UPLOAD_ERR_EXTENSION ], + 'UPLOAD_ERR_INI_SIZE' => [UPLOAD_ERR_INI_SIZE], + 'UPLOAD_ERR_FORM_SIZE' => [UPLOAD_ERR_FORM_SIZE], + 'UPLOAD_ERR_PARTIAL' => [UPLOAD_ERR_PARTIAL], + 'UPLOAD_ERR_NO_FILE' => [UPLOAD_ERR_NO_FILE], + 'UPLOAD_ERR_NO_TMP_DIR' => [UPLOAD_ERR_NO_TMP_DIR], + 'UPLOAD_ERR_CANT_WRITE' => [UPLOAD_ERR_CANT_WRITE], + 'UPLOAD_ERR_EXTENSION' => [UPLOAD_ERR_EXTENSION], ]; } diff --git a/test/UriTest.php b/test/UriTest.php index 3a4371ae..1adb0eec 100644 --- a/test/UriTest.php +++ b/test/UriTest.php @@ -13,7 +13,7 @@ class UriTest extends TestCase { - public function testConstructorSetsAllProperties() + public function testConstructorSetsAllProperties(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $this->assertSame('https', $uri->getScheme()); @@ -26,14 +26,14 @@ public function testConstructorSetsAllProperties() $this->assertSame('quz', $uri->getFragment()); } - public function testCanSerializeToString() + public function testCanSerializeToString(): void { $url = 'https://user:pass@local.example.com:3001/foo?bar=baz#quz'; $uri = new Uri($url); $this->assertSame($url, (string) $uri); } - public function testWithSchemeReturnsNewInstanceWithNewScheme() + public function testWithSchemeReturnsNewInstanceWithNewScheme(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withScheme('http'); @@ -42,7 +42,7 @@ public function testWithSchemeReturnsNewInstanceWithNewScheme() $this->assertSame('http://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function testWithSchemeReturnsSameInstanceWithSameScheme() + public function testWithSchemeReturnsSameInstanceWithSameScheme(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withScheme('https'); @@ -51,7 +51,7 @@ public function testWithSchemeReturnsSameInstanceWithSameScheme() $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function testWithUserInfoReturnsNewInstanceWithProvidedUser() + public function testWithUserInfoReturnsNewInstanceWithProvidedUser(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withUserInfo('matthew'); @@ -60,7 +60,7 @@ public function testWithUserInfoReturnsNewInstanceWithProvidedUser() $this->assertSame('https://matthew@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function testWithUserInfoReturnsNewInstanceWithProvidedUserAndPassword() + public function testWithUserInfoReturnsNewInstanceWithProvidedUserAndPassword(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withUserInfo('matthew', 'laminas'); @@ -69,7 +69,7 @@ public function testWithUserInfoReturnsNewInstanceWithProvidedUserAndPassword() $this->assertSame('https://matthew:laminas@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function testWithUserInfoThrowExceptionIfPasswordIsNotString() + public function testWithUserInfoThrowExceptionIfPasswordIsNotString(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); @@ -78,7 +78,7 @@ public function testWithUserInfoThrowExceptionIfPasswordIsNotString() $uri->withUserInfo('matthew', 1); } - public function testWithUserInfoReturnsSameInstanceIfUserAndPasswordAreSameAsBefore() + public function testWithUserInfoReturnsSameInstanceIfUserAndPasswordAreSameAsBefore(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withUserInfo('user', 'pass'); @@ -87,7 +87,8 @@ public function testWithUserInfoReturnsSameInstanceIfUserAndPasswordAreSameAsBef $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function userInfoProvider() + /** @return array */ + public function userInfoProvider(): array { // @codingStandardsIgnoreStart return [ @@ -105,7 +106,7 @@ public function userInfoProvider() /** * @dataProvider userInfoProvider */ - public function testWithUserInfoEncodesUsernameAndPassword($user, $credential, $expected) + public function testWithUserInfoEncodesUsernameAndPassword(string $user, string $credential, string $expected): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withUserInfo($user, $credential); @@ -113,7 +114,7 @@ public function testWithUserInfoEncodesUsernameAndPassword($user, $credential, $ $this->assertSame($expected, $new->getUserInfo()); } - public function testWithHostReturnsNewInstanceWithProvidedHost() + public function testWithHostReturnsNewInstanceWithProvidedHost(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withHost('getlaminas.org'); @@ -122,7 +123,7 @@ public function testWithHostReturnsNewInstanceWithProvidedHost() $this->assertSame('https://user:pass@getlaminas.org:3001/foo?bar=baz#quz', (string) $new); } - public function testWithHostReturnsSameInstanceWithProvidedHostIsSameAsBefore() + public function testWithHostReturnsSameInstanceWithProvidedHostIsSameAsBefore(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withHost('local.example.com'); @@ -131,21 +132,24 @@ public function testWithHostReturnsSameInstanceWithProvidedHostIsSameAsBefore() $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function validPorts() + /** @return array */ + public function validPorts(): array { return [ - 'null' => [ null ], - 'int' => [ 3000 ], - 'string-int' => [ '3000' ], + 'null' => [null], + 'int' => [3000], + 'string-int' => ['3000'], ]; } /** * @dataProvider validPorts + * @param numeric|null $port */ - public function testWithPortReturnsNewInstanceWithProvidedPort($port) + public function testWithPortReturnsNewInstanceWithProvidedPort($port): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); + /** @psalm-suppress InvalidScalarArgument */ $new = $uri->withPort($port); $this->assertNotSame($uri, $new); $this->assertEquals($port, $new->getPort()); @@ -155,43 +159,47 @@ public function testWithPortReturnsNewInstanceWithProvidedPort($port) ); } - public function testWithPortReturnsSameInstanceWithProvidedPortIsSameAsBefore() + public function testWithPortReturnsSameInstanceWithProvidedPortIsSameAsBefore(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); + /** @psalm-suppress InvalidScalarArgument */ $new = $uri->withPort('3001'); $this->assertSame($uri, $new); $this->assertSame(3001, $new->getPort()); } - public function invalidPorts() + /** @return array */ + public function invalidPorts(): array { return [ - 'true' => [ true ], - 'false' => [ false ], - 'string' => [ 'string' ], - 'float' => [ 55.5 ], - 'array' => [ [ 3000 ] ], - 'object' => [ (object) ['port' => 3000 ] ], - 'zero' => [ 0 ], - 'too-small' => [ -1 ], - 'too-big' => [ 65536 ], + 'true' => [true], + 'false' => [false], + 'string' => ['string'], + 'float' => [55.5], + 'array' => [[3000]], + 'object' => [(object) ['port' => 3000]], + 'zero' => [0], + 'too-small' => [-1], + 'too-big' => [65536], ]; } /** * @dataProvider invalidPorts + * @param mixed $port */ - public function testWithPortRaisesExceptionForInvalidPorts($port) + public function testWithPortRaisesExceptionForInvalidPorts($port): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid port'); + /** @psalm-suppress MixedArgument */ $uri->withPort($port); } - public function testWithPathReturnsNewInstanceWithProvidedPath() + public function testWithPathReturnsNewInstanceWithProvidedPath(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withPath('/bar/baz'); @@ -200,7 +208,7 @@ public function testWithPathReturnsNewInstanceWithProvidedPath() $this->assertSame('https://user:pass@local.example.com:3001/bar/baz?bar=baz#quz', (string) $new); } - public function testWithPathReturnsSameInstanceWithProvidedPathSameAsBefore() + public function testWithPathReturnsSameInstanceWithProvidedPathSameAsBefore(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withPath('/foo'); @@ -209,33 +217,36 @@ public function testWithPathReturnsSameInstanceWithProvidedPathSameAsBefore() $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function invalidPaths() + /** @return array */ + public function invalidPaths(): array { return [ - 'null' => [ null ], - 'true' => [ true ], - 'false' => [ false ], - 'array' => [ [ '/bar/baz' ] ], - 'object' => [ (object) [ '/bar/baz' ] ], - 'query' => [ '/bar/baz?bat=quz' ], - 'fragment' => [ '/bar/baz#bat' ], + 'null' => [null], + 'true' => [true], + 'false' => [false], + 'array' => [['/bar/baz']], + 'object' => [(object) ['/bar/baz']], + 'query' => ['/bar/baz?bat=quz'], + 'fragment' => ['/bar/baz#bat'], ]; } /** * @dataProvider invalidPaths + * @param mixed $path */ - public function testWithPathRaisesExceptionForInvalidPaths($path) + public function testWithPathRaisesExceptionForInvalidPaths($path): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid path'); + /** @psalm-suppress MixedArgument */ $uri->withPath($path); } - public function testWithQueryReturnsNewInstanceWithProvidedQuery() + public function testWithQueryReturnsNewInstanceWithProvidedQuery(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withQuery('baz=bat'); @@ -244,32 +255,35 @@ public function testWithQueryReturnsNewInstanceWithProvidedQuery() $this->assertSame('https://user:pass@local.example.com:3001/foo?baz=bat#quz', (string) $new); } - public function invalidQueryStrings() + /** @return array */ + public function invalidQueryStrings(): array { return [ - 'null' => [ null ], - 'true' => [ true ], - 'false' => [ false ], - 'array' => [ [ 'baz=bat' ] ], - 'object' => [ (object) [ 'baz=bat' ] ], - 'fragment' => [ 'baz=bat#quz' ], + 'null' => [null], + 'true' => [true], + 'false' => [false], + 'array' => [['baz=bat']], + 'object' => [(object) ['baz=bat']], + 'fragment' => ['baz=bat#quz'], ]; } /** * @dataProvider invalidQueryStrings + * @param mixed $query */ - public function testWithQueryRaisesExceptionForInvalidQueryStrings($query) + public function testWithQueryRaisesExceptionForInvalidQueryStrings($query): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Query string'); + /** @psalm-suppress MixedArgument */ $uri->withQuery($query); } - public function testWithFragmentReturnsNewInstanceWithProvidedFragment() + public function testWithFragmentReturnsNewInstanceWithProvidedFragment(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withFragment('qat'); @@ -278,7 +292,7 @@ public function testWithFragmentReturnsNewInstanceWithProvidedFragment() $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#qat', (string) $new); } - public function testWithFragmentReturnsSameInstanceWithProvidedFragmentSameAsBefore() + public function testWithFragmentReturnsSameInstanceWithProvidedFragmentSameAsBefore(): void { $uri = new Uri('https://user:pass@local.example.com:3001/foo?bar=baz#quz'); $new = $uri->withFragment('quz'); @@ -287,93 +301,95 @@ public function testWithFragmentReturnsSameInstanceWithProvidedFragmentSameAsBef $this->assertSame('https://user:pass@local.example.com:3001/foo?bar=baz#quz', (string) $new); } - public function authorityInfo() + /** @return array */ + public function authorityInfo(): array { return [ - 'host-only' => [ 'http://foo.com/bar', 'foo.com' ], - 'host-port' => [ 'http://foo.com:3000/bar', 'foo.com:3000' ], - 'user-host' => [ 'http://me@foo.com/bar', 'me@foo.com' ], - 'user-host-port' => [ 'http://me@foo.com:3000/bar', 'me@foo.com:3000' ], + 'host-only' => ['http://foo.com/bar', 'foo.com'], + 'host-port' => ['http://foo.com:3000/bar', 'foo.com:3000'], + 'user-host' => ['http://me@foo.com/bar', 'me@foo.com'], + 'user-host-port' => ['http://me@foo.com:3000/bar', 'me@foo.com:3000'], ]; } /** * @dataProvider authorityInfo */ - public function testRetrievingAuthorityReturnsExpectedValues($url, $expected) + public function testRetrievingAuthorityReturnsExpectedValues(string $url, string $expected): void { $uri = new Uri($url); $this->assertSame($expected, $uri->getAuthority()); } - public function testCanEmitOriginFormUrl() + public function testCanEmitOriginFormUrl(): void { $url = '/foo/bar?baz=bat'; $uri = new Uri($url); $this->assertSame($url, (string) $uri); } - public function testSettingEmptyPathOnAbsoluteUriReturnsAnEmptyPath() + public function testSettingEmptyPathOnAbsoluteUriReturnsAnEmptyPath(): void { $uri = new Uri('http://example.com/foo'); $new = $uri->withPath(''); $this->assertSame('', $new->getPath()); } - public function testStringRepresentationOfAbsoluteUriWithNoPathSetsAnEmptyPath() + public function testStringRepresentationOfAbsoluteUriWithNoPathSetsAnEmptyPath(): void { $uri = new Uri('http://example.com'); $this->assertSame('http://example.com', (string) $uri); } - public function testEmptyPathOnOriginFormRemainsAnEmptyPath() + public function testEmptyPathOnOriginFormRemainsAnEmptyPath(): void { $uri = new Uri('?foo=bar'); $this->assertSame('', $uri->getPath()); } - public function testStringRepresentationOfOriginFormWithNoPathRetainsEmptyPath() + public function testStringRepresentationOfOriginFormWithNoPathRetainsEmptyPath(): void { $uri = new Uri('?foo=bar'); $this->assertSame('?foo=bar', (string) $uri); } - public function testConstructorRaisesExceptionForSeriouslyMalformedURI() + public function testConstructorRaisesExceptionForSeriouslyMalformedURI(): void { $this->expectException(InvalidArgumentException::class); new Uri('http:///www.php-fig.org/'); } - public function testMutatingSchemeStripsOffDelimiter() + public function testMutatingSchemeStripsOffDelimiter(): void { $uri = new Uri('http://example.com'); $new = $uri->withScheme('https://'); $this->assertSame('https', $new->getScheme()); } - public function testESchemeStripsOffDelimiter() + public function testESchemeStripsOffDelimiter(): void { $uri = new Uri('https://example.com'); $new = $uri->withScheme('://'); $this->assertSame('', $new->getScheme()); } - public function invalidSchemes() + /** @return array */ + public function invalidSchemes(): array { return [ - 'mailto' => [ 'mailto' ], - 'ftp' => [ 'ftp' ], - 'telnet' => [ 'telnet' ], - 'ssh' => [ 'ssh' ], - 'git' => [ 'git' ], + 'mailto' => ['mailto'], + 'ftp' => ['ftp'], + 'telnet' => ['telnet'], + 'ssh' => ['ssh'], + 'git' => ['git'], ]; } /** * @dataProvider invalidSchemes */ - public function testConstructWithUnsupportedSchemeRaisesAnException($scheme) + public function testConstructWithUnsupportedSchemeRaisesAnException(string $scheme): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Unsupported scheme'); @@ -384,7 +400,7 @@ public function testConstructWithUnsupportedSchemeRaisesAnException($scheme) /** * @dataProvider invalidSchemes */ - public function testMutatingWithUnsupportedSchemeRaisesAnException($scheme) + public function testMutatingWithUnsupportedSchemeRaisesAnException(string $scheme): void { $uri = new Uri('http://example.com'); @@ -394,46 +410,47 @@ public function testMutatingWithUnsupportedSchemeRaisesAnException($scheme) $uri->withScheme($scheme); } - public function testPathIsNotPrefixedWithSlashIfSetWithoutOne() + public function testPathIsNotPrefixedWithSlashIfSetWithoutOne(): void { $uri = new Uri('http://example.com'); $new = $uri->withPath('foo/bar'); $this->assertSame('foo/bar', $new->getPath()); } - public function testPathNotSlashPrefixedIsEmittedWithSlashDelimiterWhenUriIsCastToString() + public function testPathNotSlashPrefixedIsEmittedWithSlashDelimiterWhenUriIsCastToString(): void { $uri = new Uri('http://example.com'); $new = $uri->withPath('foo/bar'); $this->assertSame('http://example.com/foo/bar', $new->__toString()); } - public function testStripsQueryPrefixIfPresent() + public function testStripsQueryPrefixIfPresent(): void { $uri = new Uri('http://example.com'); $new = $uri->withQuery('?foo=bar'); $this->assertSame('foo=bar', $new->getQuery()); } - public function testEncodeFragmentPrefixIfPresent() + public function testEncodeFragmentPrefixIfPresent(): void { $uri = new Uri('http://example.com'); $new = $uri->withFragment('#/foo/bar'); $this->assertSame('%23/foo/bar', $new->getFragment()); } - public function standardSchemePortCombinations() + /** @return array */ + public function standardSchemePortCombinations(): array { return [ - 'http' => [ 'http', 80 ], - 'https' => [ 'https', 443 ], + 'http' => ['http', 80], + 'https' => ['https', 443], ]; } /** * @dataProvider standardSchemePortCombinations */ - public function testAuthorityOmitsPortForStandardSchemePortCombinations($scheme, $port) + public function testAuthorityOmitsPortForStandardSchemePortCombinations(string $scheme, int $port): void { $uri = (new Uri()) ->withHost('example.com') @@ -442,7 +459,8 @@ public function testAuthorityOmitsPortForStandardSchemePortCombinations($scheme, $this->assertSame('example.com', $uri->getAuthority()); } - public function mutations() + /** @return array */ + public function mutations(): array { return [ 'scheme' => ['withScheme', 'https'], @@ -456,12 +474,12 @@ public function mutations() } /** - * @group 48 * @dataProvider mutations + * @param string|int $value */ - public function testMutationResetsUriStringPropertyInClone($method, $value) + public function testMutationResetsUriStringPropertyInClone(string $method, $value): void { - $uri = new Uri('http://example.com/path?query=string#fragment'); + $uri = new Uri('http://example.com/path?query=string#fragment'); $string = (string) $uri; $r = new ReflectionObject($uri); @@ -470,90 +488,81 @@ public function testMutationResetsUriStringPropertyInClone($method, $value) $this->assertSame($string, $p->getValue($uri)); $test = $uri->{$method}($value); - $r2 = new ReflectionObject($uri); - $p2 = $r2->getProperty('uriString'); + $r2 = new ReflectionObject($uri); + $p2 = $r2->getProperty('uriString'); $p2->setAccessible(true); $this->assertNull($p2->getValue($test)); $this->assertSame($string, $p->getValue($uri)); } - /** - * @group 40 - */ - public function testPathIsProperlyEncoded() + public function testPathIsProperlyEncoded(): void { - $uri = (new Uri())->withPath('/foo^bar'); + $uri = (new Uri())->withPath('/foo^bar'); $expected = '/foo%5Ebar'; $this->assertSame($expected, $uri->getPath()); } - public function testPathDoesNotBecomeDoubleEncoded() + public function testPathDoesNotBecomeDoubleEncoded(): void { - $uri = (new Uri())->withPath('/foo%5Ebar'); + $uri = (new Uri())->withPath('/foo%5Ebar'); $expected = '/foo%5Ebar'; $this->assertSame($expected, $uri->getPath()); } - public function queryStringsForEncoding() + /** @return array */ + public function queryStringsForEncoding(): array { return [ - 'key-only' => ['k^ey', 'k%5Eey'], - 'key-value' => ['k^ey=valu`', 'k%5Eey=valu%60'], - 'array-key-only' => ['key[]', 'key%5B%5D'], + 'key-only' => ['k^ey', 'k%5Eey'], + 'key-value' => ['k^ey=valu`', 'k%5Eey=valu%60'], + 'array-key-only' => ['key[]', 'key%5B%5D'], 'array-key-value' => ['key[]=valu`', 'key%5B%5D=valu%60'], - 'complex' => ['k^ey&key[]=valu`&f<>=`bar', 'k%5Eey&key%5B%5D=valu%60&f%3C%3E=%60bar'], + 'complex' => ['k^ey&key[]=valu`&f<>=`bar', 'k%5Eey&key%5B%5D=valu%60&f%3C%3E=%60bar'], ]; } /** - * @group 40 * @dataProvider queryStringsForEncoding */ - public function testQueryIsProperlyEncoded($query, $expected) + public function testQueryIsProperlyEncoded(string $query, string $expected): void { $uri = (new Uri())->withQuery($query); $this->assertSame($expected, $uri->getQuery()); } /** - * @group 40 * @dataProvider queryStringsForEncoding */ - public function testQueryIsNotDoubleEncoded($query, $expected) + public function testQueryIsNotDoubleEncoded(string $query, string $expected): void { $uri = (new Uri())->withQuery($expected); $this->assertSame($expected, $uri->getQuery()); } - /** - * @group 40 - */ - public function testFragmentIsProperlyEncoded() + public function testFragmentIsProperlyEncoded(): void { - $uri = (new Uri())->withFragment('/p^th?key^=`bar#b@z'); + $uri = (new Uri())->withFragment('/p^th?key^=`bar#b@z'); $expected = '/p%5Eth?key%5E=%60bar%23b@z'; $this->assertSame($expected, $uri->getFragment()); } - /** - * @group 40 - */ - public function testFragmentIsNotDoubleEncoded() + public function testFragmentIsNotDoubleEncoded(): void { $expected = '/p%5Eth?key%5E=%60bar%23b@z'; - $uri = (new Uri())->withFragment($expected); + $uri = (new Uri())->withFragment($expected); $this->assertSame($expected, $uri->getFragment()); } - public function testProperlyTrimsLeadingSlashesToPreventXSS() + public function testProperlyTrimsLeadingSlashesToPreventXSS(): void { $url = 'http://example.org//zend.com'; $uri = new Uri($url); $this->assertSame('http://example.org/zend.com', (string) $uri); } - public function invalidStringComponentValues() + /** @return array */ + public function invalidStringComponentValues(): array { $methods = [ 'withScheme', @@ -573,13 +582,13 @@ public function invalidStringComponentValues() 'zero-float' => 0.0, 'float' => 1.1, 'array' => ['value'], - 'object' => (object)['value' => 'value'], + 'object' => (object) ['value' => 'value'], ]; $combinations = []; foreach ($methods as $method) { foreach ($values as $type => $value) { - $key = sprintf('%s-%s', $method, $type); + $key = sprintf('%s-%s', $method, $type); $combinations[$key] = [$method, $value]; } } @@ -588,10 +597,10 @@ public function invalidStringComponentValues() } /** - * @group 80 * @dataProvider invalidStringComponentValues + * @param mixed $value */ - public function testPassingInvalidValueToWithMethodRaisesException($method, $value) + public function testPassingInvalidValueToWithMethodRaisesException(string $method, $value): void { $uri = new Uri('https://example.com/'); @@ -600,7 +609,7 @@ public function testPassingInvalidValueToWithMethodRaisesException($method, $val $uri->$method($value); } - public function testUtf8Uri() + public function testUtf8Uri(): void { $uri = new Uri('http://ουτοπία.δπθ.gr/'); @@ -610,15 +619,15 @@ public function testUtf8Uri() /** * @dataProvider utf8PathsDataProvider */ - public function testUtf8Path($url, $result) + public function testUtf8Path(string $url, string $result): void { $uri = new Uri($url); $this->assertSame($result, $uri->getPath()); } - - public function utf8PathsDataProvider() + /** @return array */ + public function utf8PathsDataProvider(): array { return [ ['http://example.com/тестовый_путь/', '/тестовый_путь/'], @@ -631,14 +640,15 @@ public function utf8PathsDataProvider() /** * @dataProvider utf8QueryStringsDataProvider */ - public function testUtf8Query($url, $result) + public function testUtf8Query(string $url, string $result): void { $uri = new Uri($url); $this->assertSame($result, $uri->getQuery()); } - public function utf8QueryStringsDataProvider() + /** @return array */ + public function utf8QueryStringsDataProvider(): array { return [ ['http://example.com/?q=тестовый_путь', 'q=тестовый_путь'], @@ -647,19 +657,19 @@ public function utf8QueryStringsDataProvider() ]; } - public function testUriDoesNotAppendColonToHostIfPortIsEmpty() + public function testUriDoesNotAppendColonToHostIfPortIsEmpty(): void { $uri = (new Uri())->withHost('google.com'); $this->assertSame('//google.com', (string) $uri); } - public function testAuthorityIsPrefixedByDoubleSlashIfPresent() + public function testAuthorityIsPrefixedByDoubleSlashIfPresent(): void { $uri = (new Uri())->withHost('example.com'); $this->assertSame('//example.com', (string) $uri); } - public function testReservedCharsInPathUnencoded() + public function testReservedCharsInPathUnencoded(): void { $uri = (new Uri()) ->withScheme('https') @@ -672,23 +682,22 @@ public function testReservedCharsInPathUnencoded() ); } - public function testHostIsLowercase() + public function testHostIsLowercase(): void { $uri = new Uri('http://HOST.LOC/path?q=1'); $this->assertSame('host.loc', $uri->getHost()); } - public function testHostIsLowercaseWhenIsSetViwWithHost() + public function testHostIsLowercaseWhenIsSetViwWithHost(): void { $uri = (new Uri())->withHost('NEW-HOST.COM'); $this->assertSame('new-host.com', $uri->getHost()); } - - public function testUriDistinguishZeroFromEmptyString() + public function testUriDistinguishZeroFromEmptyString(): void { $expected = 'https://0:0@0:1/0?0#0'; - $uri = new Uri($expected); + $uri = new Uri($expected); $this->assertSame($expected, (string) $uri); } } diff --git a/test/functions/MarshalHeadersFromSapiTest.php b/test/functions/MarshalHeadersFromSapiTest.php index 4f27e73d..b5fa2ddb 100644 --- a/test/functions/MarshalHeadersFromSapiTest.php +++ b/test/functions/MarshalHeadersFromSapiTest.php @@ -10,46 +10,41 @@ class MarshalHeadersFromSapiTest extends TestCase { - public function testReturnsHeaders() : void + public function testReturnsHeaders(): void { $server = [ 'REDIRECT_CONTENT_FOO' => 'redirect-foo', - 'CONTENT_FOO' => null, + 'CONTENT_FOO' => null, 'REDIRECT_CONTENT_BAR' => 'redirect-bar', - 'CONTENT_BAR' => '', + 'CONTENT_BAR' => '', 'REDIRECT_CONTENT_BAZ' => 'redirect-baz', - 'CONTENT_BAZ' => 'baz', + 'CONTENT_BAZ' => 'baz', 'REDIRECT_CONTENT_VAR' => 'redirect-var', - - 'REDIRECT_HTTP_ABC' => 'redirect-abc', - 'HTTP_ABC' => null, - 'REDIRECT_HTTP_DEF' => 'redirect-def', - 'HTTP_DEF' => '', - 'REDIRECT_HTTP_GHI' => 'redirect-ghi', - 'HTTP_GHI' => 'ghi', - 'REDIRECT_HTTP_JKL' => 'redirect-jkl', - - 'HTTP_TEST_MNO' => 'mno', - 'HTTP_TEST_PQR' => '', - 'HTTP_TEST_STU' => null, - 'CONTENT_TEST_VW' => 'vw', - 'CONTENT_TEST_XY' => '', - 'CONTENT_TEST_ZZ' => null, - - 123 => 'integer', + 'REDIRECT_HTTP_ABC' => 'redirect-abc', + 'HTTP_ABC' => null, + 'REDIRECT_HTTP_DEF' => 'redirect-def', + 'HTTP_DEF' => '', + 'REDIRECT_HTTP_GHI' => 'redirect-ghi', + 'HTTP_GHI' => 'ghi', + 'REDIRECT_HTTP_JKL' => 'redirect-jkl', + 'HTTP_TEST_MNO' => 'mno', + 'HTTP_TEST_PQR' => '', + 'HTTP_TEST_STU' => null, + 'CONTENT_TEST_VW' => 'vw', + 'CONTENT_TEST_XY' => '', + 'CONTENT_TEST_ZZ' => null, + 123 => 'integer', ]; $expectedHeaders = [ - 'content-foo' => null, - 'content-baz' => 'baz', - 'content-var' => 'redirect-var', - - 'abc' => null, - 'ghi' => 'ghi', - 'jkl' => 'redirect-jkl', - - 'test-mno' => 'mno', - 'test-stu' => null, + 'content-foo' => null, + 'content-baz' => 'baz', + 'content-var' => 'redirect-var', + 'abc' => null, + 'ghi' => 'ghi', + 'jkl' => 'redirect-jkl', + 'test-mno' => 'mno', + 'test-stu' => null, 'content-test-vw' => 'vw', 'content-test-zz' => null, ]; diff --git a/test/functions/MarshalUriFromSapiTest.php b/test/functions/MarshalUriFromSapiTest.php index e4ae6b36..ee85a3cd 100644 --- a/test/functions/MarshalUriFromSapiTest.php +++ b/test/functions/MarshalUriFromSapiTest.php @@ -11,46 +11,44 @@ class MarshalUriFromSapiTest extends TestCase { /** - * @param string $httpsValue - * @param string $expectedScheme * @dataProvider returnsUrlWithCorrectHttpSchemeFromArraysProvider */ - public function testReturnsUrlWithCorrectHttpSchemeFromArrays(string $httpsValue, string $expectedScheme) : void + public function testReturnsUrlWithCorrectHttpSchemeFromArrays(string $httpsValue, string $expectedScheme): void { $server = [ - 'HTTPS' => $httpsValue, - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => '80', - 'SERVER_ADDR' => '172.22.0.4', - 'REMOTE_PORT' => '36852', - 'REMOTE_ADDR' => '172.22.0.1', - 'SERVER_SOFTWARE' => 'nginx/1.11.8', + 'HTTPS' => $httpsValue, + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => '80', + 'SERVER_ADDR' => '172.22.0.4', + 'REMOTE_PORT' => '36852', + 'REMOTE_ADDR' => '172.22.0.1', + 'SERVER_SOFTWARE' => 'nginx/1.11.8', 'GATEWAY_INTERFACE' => 'CGI/1.1', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'DOCUMENT_ROOT' => '/var/www/public', - 'DOCUMENT_URI' => '/index.php', - 'REQUEST_URI' => '/api/messagebox-schema', - 'PATH_TRANSLATED' => '/var/www/public', - 'PATH_INFO' => '', - 'SCRIPT_NAME' => '/index.php', - 'CONTENT_LENGTH' => '', - 'CONTENT_TYPE' => '', - 'REQUEST_METHOD' => 'GET', - 'QUERY_STRING' => '', - 'SCRIPT_FILENAME' => '/var/www/public/index.php', - 'FCGI_ROLE' => 'RESPONDER', - 'PHP_SELF' => '/index.php', + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'DOCUMENT_ROOT' => '/var/www/public', + 'DOCUMENT_URI' => '/index.php', + 'REQUEST_URI' => '/api/messagebox-schema', + 'PATH_TRANSLATED' => '/var/www/public', + 'PATH_INFO' => '', + 'SCRIPT_NAME' => '/index.php', + 'CONTENT_LENGTH' => '', + 'CONTENT_TYPE' => '', + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => '', + 'SCRIPT_FILENAME' => '/var/www/public/index.php', + 'FCGI_ROLE' => 'RESPONDER', + 'PHP_SELF' => '/index.php', ]; $headers = [ - 'HTTP_COOKIE' => '', + 'HTTP_COOKIE' => '', 'HTTP_ACCEPT_LANGUAGE' => 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7', 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate, br', - 'HTTP_REFERER' => 'http://localhost:8080/index.html', - 'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)', - 'HTTP_ACCEPT' => 'application/json,*/*', - 'HTTP_CONNECTION' => 'keep-alive', - 'HTTP_HOST' => 'localhost:8080', + 'HTTP_REFERER' => 'http://localhost:8080/index.html', + 'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)', + 'HTTP_ACCEPT' => 'application/json,*/*', + 'HTTP_CONNECTION' => 'keep-alive', + 'HTTP_HOST' => 'localhost:8080', ]; $url = marshalUriFromSapi($server, $headers); @@ -58,15 +56,16 @@ public function testReturnsUrlWithCorrectHttpSchemeFromArrays(string $httpsValue self::assertSame($expectedScheme, $url->getScheme()); } - public function returnsUrlWithCorrectHttpSchemeFromArraysProvider() : array + /** @return array */ + public function returnsUrlWithCorrectHttpSchemeFromArraysProvider(): array { return [ - 'on-lowercase' => ['on', 'https'], - 'on-uppercase' => ['ON', 'https'], - 'off-lowercase' => ['off', 'http'], - 'off-mixed-case' => ['oFf', 'http'], + 'on-lowercase' => ['on', 'https'], + 'on-uppercase' => ['ON', 'https'], + 'off-lowercase' => ['off', 'http'], + 'off-mixed-case' => ['oFf', 'http'], 'neither-on-nor-off' => ['foo', 'http'], - 'empty' => ['', 'http'], + 'empty' => ['', 'http'], ]; } @@ -78,13 +77,14 @@ public function testReturnsUrlWithCorrectSchemeAndHostFromArrays( string $expectedHost, array $server, array $headers - ) : void { + ): void { $uri = marshalUriFromSapi($server, $headers); self::assertSame($expectedScheme, $uri->getScheme()); self::assertSame($expectedHost, $uri->getHost()); } - public function returnsUrlWithCorrectSchemeAndHostFromArrays() : array + /** @return array */ + public function returnsUrlWithCorrectSchemeAndHostFromArrays(): array { return [ 'x-forwarded-proto' => [ @@ -95,7 +95,7 @@ public function returnsUrlWithCorrectSchemeAndHostFromArrays() : array ], ['X-Forwarded-Proto' => 'https'], ], - 'x-forwarded-host' => [ + 'x-forwarded-host' => [ 'http', 'example.org', [ diff --git a/test/functions/NormalizeUploadedFilesTest.php b/test/functions/NormalizeUploadedFilesTest.php index 92132ba9..ddb93e67 100644 --- a/test/functions/NormalizeUploadedFilesTest.php +++ b/test/functions/NormalizeUploadedFilesTest.php @@ -11,15 +11,15 @@ class NormalizeUploadedFilesTest extends TestCase { - public function testCreatesUploadedFileFromFlatFileSpecification() + public function testCreatesUploadedFileFromFlatFileSpecification(): void { $files = [ 'avatar' => [ 'tmp_name' => 'phpUxcOty', - 'name' => 'my-avatar.png', - 'size' => 90996, - 'type' => 'image/png', - 'error' => 0, + 'name' => 'my-avatar.png', + 'size' => 90996, + 'type' => 'image/png', + 'error' => 0, ], ]; @@ -30,17 +30,17 @@ public function testCreatesUploadedFileFromFlatFileSpecification() $this->assertEquals('my-avatar.png', $normalised['avatar']->getClientFilename()); } - public function testTraversesNestedFileSpecificationToExtractUploadedFile() + public function testTraversesNestedFileSpecificationToExtractUploadedFile(): void { $files = [ 'my-form' => [ 'details' => [ 'avatar' => [ 'tmp_name' => 'phpUxcOty', - 'name' => 'my-avatar.png', - 'size' => 90996, - 'type' => 'image/png', - 'error' => 0, + 'name' => 'my-avatar.png', + 'size' => 90996, + 'type' => 'image/png', + 'error' => 0, ], ], ], @@ -52,7 +52,7 @@ public function testTraversesNestedFileSpecificationToExtractUploadedFile() $this->assertEquals('my-avatar.png', $normalised['my-form']['details']['avatar']->getClientFilename()); } - public function testTraversesNestedFileSpecificationContainingNumericIndicesToExtractUploadedFiles() + public function testTraversesNestedFileSpecificationContainingNumericIndicesToExtractUploadedFiles(): void { $files = [ 'my-form' => [ @@ -63,22 +63,22 @@ public function testTraversesNestedFileSpecificationContainingNumericIndicesToEx 1 => 'duck123', 2 => 'goose123', ], - 'name' => [ + 'name' => [ 0 => 'file1.txt', 1 => 'file2.txt', 2 => 'file3.txt', ], - 'size' => [ + 'size' => [ 0 => 100, 1 => 240, 2 => 750, ], - 'type' => [ + 'type' => [ 0 => 'plain/txt', 1 => 'image/jpg', 2 => 'image/png', ], - 'error' => [ + 'error' => [ 0 => 0, 1 => 0, 2 => 0, @@ -100,7 +100,7 @@ public function testTraversesNestedFileSpecificationContainingNumericIndicesToEx * This case covers upfront numeric index which moves the tmp_name/size/etc * fields further up the array tree */ - public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFiles() + public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFiles(): void { $files = [ 'slide-shows' => [ @@ -113,7 +113,7 @@ public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFil ], ], ], - 'error' => [ + 'error' => [ 0 => [ 'slides' => [ 0 => 0, @@ -121,7 +121,7 @@ public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFil ], ], ], - 'name' => [ + 'name' => [ 0 => [ 'slides' => [ 0 => 'foo.txt', @@ -129,7 +129,7 @@ public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFil ], ], ], - 'size' => [ + 'size' => [ 0 => [ 'slides' => [ 0 => 123, @@ -137,7 +137,7 @@ public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFil ], ], ], - 'type' => [ + 'type' => [ 0 => [ 'slides' => [ 0 => 'text/plain',