diff --git a/.laminas-ci.json b/.laminas-ci.json index bce3fa21..374bd854 100644 --- a/.laminas-ci.json +++ b/.laminas-ci.json @@ -1,5 +1,10 @@ { + "additional_composer_arguments": [ + "--no-scripts", + "--no-plugins" + ], "ignore_php_platform_requirements": { - "8.1": true + "8.0": false, + "8.1": false } } diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh new file mode 100755 index 00000000..8b8528d8 --- /dev/null +++ b/.laminas-ci/pre-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# Due to the fact that we are disabling plugins when installing/updating/downgrading composer dependencies +# we have to manually enable the coding standard here. +composer enable-codestandard diff --git a/composer.json b/composer.json index 9f655dd2..bad36e27 100644 --- a/composer.json +++ b/composer.json @@ -58,21 +58,19 @@ "jsoumelidis/zend-sf-di-config": "^0.5", "laminas/laminas-coding-standard": "~2.3.0", "laminas/laminas-development-mode": "^3.3.0", - "laminas/laminas-pimple-config": "^1.1.1", + "laminas/laminas-pimple-config": "^1.4", "laminas/laminas-servicemanager": "^3.6.4", "mezzio/mezzio-fastroute": "^3.2.0", "mezzio/mezzio-laminasrouter": "^3.1.0", "mezzio/mezzio-laminasviewrenderer": "^2.3.0", "mezzio/mezzio-platesrenderer": "^2.3.0", - "mezzio/mezzio-tooling": "^2.0", + "mezzio/mezzio-tooling": "^2.1", "mezzio/mezzio-twigrenderer": "^2.7.0", - "mikey179/vfsstream": "^1.6.8", - "phpspec/prophecy": "^1.10.3", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^9.5.5", - "roave/security-advisories": "dev-master" + "mikey179/vfsstream": "^1.6.10", + "phpunit/phpunit": "^9.5.11", + "psalm/plugin-phpunit": "^0.16.1", + "roave/security-advisories": "dev-master", + "vimeo/psalm": "^4.17" }, "autoload": { "psr-4": { @@ -98,13 +96,18 @@ "mezzio": "laminas --ansi", "check": [ "@cs-check", - "@test", - "@analyze" + "@test" ], - "analyze": "phpstan analyze -l 3 -c ./phpstan.installer.neon ./src ./config", "clear-config-cache": "php bin/clear-config-cache.php", - "cs-check": "phpcs -s", - "cs-fix": "phpcbf", + "enable-codestandard": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run", + "cs-check": [ + "@enable-codestandard", + "phpcs -s" + ], + "cs-fix": [ + "@enable-codestandard", + "phpcbf" + ], "serve": "php -S 0.0.0.0:8080 -t public/", "test": "phpunit --colors=always", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" diff --git a/composer.lock b/composer.lock index 58591363..1a4e9181 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": "e8b38dc88600638f49247f2a0cff9bb3", + "content-hash": "6ef06c6a625bfbaf4d4848aed0f4725c", "packages": [ { "name": "brick/varexporter", @@ -546,16 +546,16 @@ }, { "name": "laminas/laminas-stdlib", - "version": "3.6.2", + "version": "3.6.4", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "6fe0842909638ca6bea8401b7e8168fb154bffb5" + "reference": "830a36d93aeaf06e540e90ec031babb3c6eafadb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/6fe0842909638ca6bea8401b7e8168fb154bffb5", - "reference": "6fe0842909638ca6bea8401b7e8168fb154bffb5", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/830a36d93aeaf06e540e90ec031babb3c6eafadb", + "reference": "830a36d93aeaf06e540e90ec031babb3c6eafadb", "shasum": "" }, "require": { @@ -601,7 +601,7 @@ "type": "community_bridge" } ], - "time": "2021-12-07T21:06:58+00:00" + "time": "2021-12-29T14:33:01+00:00" }, { "name": "laminas/laminas-stratigility", @@ -1542,6 +1542,172 @@ } ], "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.6.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", + "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "psalm/phar": "^3.11@dev", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\": "lib" + }, + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "http://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2021-09-23T18:43:08+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\ByteStream\\": "lib" + }, + "files": [ + "lib/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2021-03-30T17:13:30+00:00" + }, { "name": "chubbyphp/chubbyphp-container", "version": "2.0.2", @@ -1745,16 +1911,16 @@ }, { "name": "composer/composer", - "version": "2.2.0", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "e174a4c4324f50a6f2de472aa1055c24a2fe2b2a" + "reference": "3c92ba5cdc7d48b7db2dcd197e6fa0e8fa6d9f4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/e174a4c4324f50a6f2de472aa1055c24a2fe2b2a", - "reference": "e174a4c4324f50a6f2de472aa1055c24a2fe2b2a", + "url": "https://api.github.com/repos/composer/composer/zipball/3c92ba5cdc7d48b7db2dcd197e6fa0e8fa6d9f4a", + "reference": "3c92ba5cdc7d48b7db2dcd197e6fa0e8fa6d9f4a", "shasum": "" }, "require": { @@ -1824,7 +1990,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.2.0" + "source": "https://github.com/composer/composer/tree/2.2.3" }, "funding": [ { @@ -1840,7 +2006,7 @@ "type": "tidelift" } ], - "time": "2021-12-22T10:03:27+00:00" + "time": "2021-12-31T11:18:53+00:00" }, { "name": "composer/metadata-minifier", @@ -2315,6 +2481,43 @@ }, "time": "2020-12-07T18:04:37+00:00" }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, { "name": "doctrine/instantiator", "version": "1.4.0", @@ -2448,6 +2651,107 @@ }, "time": "2020-01-15T17:27:27+00:00" }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730", + "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1" + }, + "time": "2021-02-22T14:02:09+00:00" + }, { "name": "filp/whoops", "version": "2.14.4", @@ -2644,20 +2948,20 @@ }, { "name": "laminas/laminas-cli", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-cli.git", - "reference": "f108b8db3315ed17039922baa1c0674d1f1d64f3" + "reference": "9219fc404dbda5f5d8fed3b98ef5ea36ee77b48a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-cli/zipball/f108b8db3315ed17039922baa1c0674d1f1d64f3", - "reference": "f108b8db3315ed17039922baa1c0674d1f1d64f3", + "url": "https://api.github.com/repos/laminas/laminas-cli/zipball/9219fc404dbda5f5d8fed3b98ef5ea36ee77b48a", + "reference": "9219fc404dbda5f5d8fed3b98ef5ea36ee77b48a", "shasum": "" }, "require": { - "composer/package-versions-deprecated": "^1.11.99.4", + "composer-runtime-api": "^2.0.0", "php": "^7.4 || ~8.0.0 || ~8.1.0", "psr/container": "^1.0 || ^2.0", "symfony/console": "^5.3.7 || ^6.0", @@ -2708,7 +3012,7 @@ "type": "community_bridge" } ], - "time": "2021-11-30T15:20:10+00:00" + "time": "2021-12-23T11:25:46+00:00" }, { "name": "laminas/laminas-code", @@ -3568,16 +3872,16 @@ }, { "name": "laminas/laminas-view", - "version": "2.15.0", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-view.git", - "reference": "af2f714e45eea7f1b1fa6acca2124b824cab3b0b" + "reference": "cc803ea899e6ca35670b3f21f0b74e93053f2c86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-view/zipball/af2f714e45eea7f1b1fa6acca2124b824cab3b0b", - "reference": "af2f714e45eea7f1b1fa6acca2124b824cab3b0b", + "url": "https://api.github.com/repos/laminas/laminas-view/zipball/cc803ea899e6ca35670b3f21f0b74e93053f2c86", + "reference": "cc803ea899e6ca35670b3f21f0b74e93053f2c86", "shasum": "" }, "require": { @@ -3588,6 +3892,7 @@ "php": "^7.3 || ~8.0.0 || ~8.1.0" }, "conflict": { + "container-interop/container-interop": "<1.2", "laminas/laminas-router": "<3.0.1", "laminas/laminas-servicemanager": "<3.3", "zendframework/zend-view": "*" @@ -3611,7 +3916,7 @@ "laminas/laminas-paginator": "^2.5", "laminas/laminas-permissions-acl": "^2.6", "laminas/laminas-router": "^3.0.1", - "laminas/laminas-servicemanager": "^3.3", + "laminas/laminas-servicemanager": "^3.4", "laminas/laminas-session": "^2.12", "laminas/laminas-uri": "^2.5", "phpspec/prophecy": "^1.12", @@ -3668,7 +3973,7 @@ "type": "community_bridge" } ], - "time": "2021-12-17T11:25:32+00:00" + "time": "2021-12-30T12:32:07+00:00" }, { "name": "league/plates", @@ -4298,6 +4603,57 @@ ], "time": "2020-11-13T09:40:50+00:00" }, + { + "name": "netresearch/jsonmapper", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", + "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" + }, + "time": "2020-12-01T19:48:11+00:00" + }, { "name": "nikic/fast-route", "version": "v1.3.0", @@ -4348,6 +4704,59 @@ }, "time": "2018-02-13T20:26:39+00:00" }, + { + "name": "openlss/lib-array2xml", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nullivex/lib-array2xml.git", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "LSS": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bryan Tong", + "email": "bryan@nullivex.com", + "homepage": "https://www.nullivex.com" + }, + { + "name": "Tony Butler", + "email": "spudz76@gmail.com", + "homepage": "https://www.nullivex.com" + } + ], + "description": "Array2XML conversion library credit to lalit.org", + "homepage": "https://www.nullivex.com", + "keywords": [ + "array", + "array conversion", + "xml", + "xml conversion" + ], + "support": { + "issues": "https://github.com/nullivex/lib-array2xml/issues", + "source": "https://github.com/nullivex/lib-array2xml/tree/master" + }, + "time": "2019-03-29T20:06:56+00:00" + }, { "name": "opis/closure", "version": "3.6.2", @@ -4924,58 +5333,6 @@ }, "time": "2021-12-08T12:19:24+00:00" }, - { - "name": "phpspec/prophecy-phpunit", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy-phpunit.git", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/2d7a9df55f257d2cba9b1d0c0963a54960657177", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8", - "phpspec/prophecy": "^1.3", - "phpunit/phpunit": "^9.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\PhpUnit\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - } - ], - "description": "Integrating the Prophecy mocking library in PHPUnit test cases", - "homepage": "http://phpspec.net", - "keywords": [ - "phpunit", - "prophecy" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy-phpunit/issues", - "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.0.1" - }, - "time": "2020-07-09T08:33:42+00:00" - }, { "name": "phpstan/phpdoc-parser", "version": "1.2.0", @@ -5025,120 +5382,6 @@ }, "time": "2021-09-16T20:46:02+00:00" }, - { - "name": "phpstan/phpstan", - "version": "0.12.99", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4d40f1d759942f523be267a1bab6884f46ca3f7", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7", - "shasum": "" - }, - "require": { - "php": "^7.1|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.12-dev" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.99" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2021-09-12T20:09:55+00:00" - }, - { - "name": "phpstan/phpstan-strict-rules", - "version": "0.12.11", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "2b72e8e17d2034145f239126e876e5fb659675e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/2b72e8e17d2034145f239126e876e5fb659675e2", - "reference": "2b72e8e17d2034145f239126e876e5fb659675e2", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0", - "phpstan/phpstan": "^0.12.96" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^0.12.16", - "phpunit/phpunit": "^9.5" - }, - "type": "phpstan-extension", - "extra": { - "branch-alias": { - "dev-master": "0.12-dev" - }, - "phpstan": { - "includes": [ - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Extra strict and opinionated rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/0.12.11" - }, - "time": "2021-08-21T11:36:27+00:00" - }, { "name": "phpunit/php-code-coverage", "version": "9.2.10", @@ -5459,16 +5702,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.10", + "version": "9.5.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a" + "reference": "2406855036db1102126125537adb1406f7242fdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2406855036db1102126125537adb1406f7242fdd", + "reference": "2406855036db1102126125537adb1406f7242fdd", "shasum": "" }, "require": { @@ -5546,11 +5789,11 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.10" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.11" }, "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { @@ -5558,7 +5801,7 @@ "type": "github" } ], - "time": "2021-09-25T07:38:51+00:00" + "time": "2021-12-25T07:07:57+00:00" }, { "name": "pimple/pimple", @@ -5613,6 +5856,66 @@ }, "time": "2021-10-28T11:13:42+00:00" }, + { + "name": "psalm/plugin-phpunit", + "version": "0.16.1", + "source": { + "type": "git", + "url": "https://github.com/psalm/psalm-plugin-phpunit.git", + "reference": "5dd3be04f37a857d52880ef6af2524a441dfef24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/5dd3be04f37a857d52880ef6af2524a441dfef24", + "reference": "5dd3be04f37a857d52880ef6af2524a441dfef24", + "shasum": "" + }, + "require": { + "composer/package-versions-deprecated": "^1.10", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "ext-simplexml": "*", + "php": "^7.1 || ^8.0", + "vimeo/psalm": "dev-master || dev-4.x || ^4.5" + }, + "conflict": { + "phpunit/phpunit": "<7.5" + }, + "require-dev": { + "codeception/codeception": "^4.0.3", + "php": "^7.3 || ^8.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", + "squizlabs/php_codesniffer": "^3.3.1", + "weirdan/codeception-psalm-module": "^0.11.0", + "weirdan/prophecy-shim": "^1.0 || ^2.0" + }, + "type": "psalm-plugin", + "extra": { + "psalm": { + "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" + } + }, + "autoload": { + "psr-4": { + "Psalm\\PhpUnitPlugin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Brown", + "email": "github@muglug.com" + } + ], + "description": "Psalm plugin for PHPUnit", + "support": { + "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", + "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.16.1" + }, + "time": "2021-06-18T23:56:46+00:00" + }, { "name": "psr/event-dispatcher", "version": "1.0.0", @@ -5769,12 +6072,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "fff53639bf1fa25f311c3e54932ac8c827f9a343" + "reference": "31d9d9e2977ae7d796d82271be09e46f4bdf41b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/fff53639bf1fa25f311c3e54932ac8c827f9a343", - "reference": "fff53639bf1fa25f311c3e54932ac8c827f9a343", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/31d9d9e2977ae7d796d82271be09e46f4bdf41b3", + "reference": "31d9d9e2977ae7d796d82271be09e46f4bdf41b3", "shasum": "" }, "conflict": { @@ -6017,7 +6320,7 @@ "shopware/production": "<=6.3.5.2", "shopware/shopware": "<5.7.6", "showdoc/showdoc": "<=2.9.13", - "silverstripe/admin": "<4.8.1", + "silverstripe/admin": ">=1,<1.8.1", "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", @@ -6193,7 +6496,7 @@ "type": "tidelift" } ], - "time": "2021-12-17T20:13:17+00:00" + "time": "2021-12-22T21:13:38+00:00" }, { "name": "sebastian/cli-parser", @@ -7389,16 +7692,16 @@ }, { "name": "symfony/console", - "version": "v5.4.1", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4" + "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4", - "reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4", + "url": "https://api.github.com/repos/symfony/console/zipball/a2c6b7ced2eb7799a35375fb9022519282b5405e", + "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e", "shasum": "" }, "require": { @@ -7468,7 +7771,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.1" + "source": "https://github.com/symfony/console/tree/v5.4.2" }, "funding": [ { @@ -7484,20 +7787,20 @@ "type": "tidelift" } ], - "time": "2021-12-09T11:22:43+00:00" + "time": "2021-12-20T16:11:12+00:00" }, { "name": "symfony/dependency-injection", - "version": "v5.4.1", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "9bd1ef389a2fe05fea7306b6155403e8a960d73d" + "reference": "ba94559be9738d77cd29e24b5d81cf3b89b7d628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9bd1ef389a2fe05fea7306b6155403e8a960d73d", - "reference": "9bd1ef389a2fe05fea7306b6155403e8a960d73d", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ba94559be9738d77cd29e24b5d81cf3b89b7d628", + "reference": "ba94559be9738d77cd29e24b5d81cf3b89b7d628", "shasum": "" }, "require": { @@ -7557,7 +7860,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.1" + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.2" }, "funding": [ { @@ -7573,7 +7876,7 @@ "type": "tidelift" } ], - "time": "2021-12-01T16:25:34+00:00" + "time": "2021-12-29T10:10:35+00:00" }, { "name": "symfony/deprecation-contracts", @@ -7872,16 +8175,16 @@ }, { "name": "symfony/finder", - "version": "v5.4.0", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590" + "reference": "e77046c252be48c48a40816187ed527703c8f76c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d2f29dac98e96a98be467627bd49c2efb1bc2590", - "reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590", + "url": "https://api.github.com/repos/symfony/finder/zipball/e77046c252be48c48a40816187ed527703c8f76c", + "reference": "e77046c252be48c48a40816187ed527703c8f76c", "shasum": "" }, "require": { @@ -7915,7 +8218,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.0" + "source": "https://github.com/symfony/finder/tree/v5.4.2" }, "funding": [ { @@ -7931,7 +8234,7 @@ "type": "tidelift" } ], - "time": "2021-11-28T15:25:38+00:00" + "time": "2021-12-15T11:06:13+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -8421,16 +8724,16 @@ }, { "name": "symfony/process", - "version": "v5.4.0", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5be20b3830f726e019162b26223110c8f47cf274" + "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5be20b3830f726e019162b26223110c8f47cf274", - "reference": "5be20b3830f726e019162b26223110c8f47cf274", + "url": "https://api.github.com/repos/symfony/process/zipball/2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", + "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", "shasum": "" }, "require": { @@ -8463,7 +8766,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.0" + "source": "https://github.com/symfony/process/tree/v5.4.2" }, "funding": [ { @@ -8479,7 +8782,7 @@ "type": "tidelift" } ], - "time": "2021-11-28T15:25:38+00:00" + "time": "2021-12-27T21:01:00+00:00" }, { "name": "symfony/service-contracts", @@ -8566,16 +8869,16 @@ }, { "name": "symfony/string", - "version": "v5.4.0", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d" + "reference": "e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d", - "reference": "9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d", + "url": "https://api.github.com/repos/symfony/string/zipball/e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d", + "reference": "e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d", "shasum": "" }, "require": { @@ -8632,7 +8935,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.0" + "source": "https://github.com/symfony/string/tree/v5.4.2" }, "funding": [ { @@ -8648,7 +8951,7 @@ "type": "tidelift" } ], - "time": "2021-11-24T10:02:00+00:00" + "time": "2021-12-16T21:52:00+00:00" }, { "name": "theseer/tokenizer", @@ -8702,16 +9005,16 @@ }, { "name": "twig/twig", - "version": "v3.3.4", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "65cb6f0b956485e1664f13d023c55298a4bb59ca" + "reference": "bb07a776206c245bc9cbde8e1cfcd47ffa298c23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/65cb6f0b956485e1664f13d023c55298a4bb59ca", - "reference": "65cb6f0b956485e1664f13d023c55298a4bb59ca", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/bb07a776206c245bc9cbde8e1cfcd47ffa298c23", + "reference": "bb07a776206c245bc9cbde8e1cfcd47ffa298c23", "shasum": "" }, "require": { @@ -8762,7 +9065,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.3.4" + "source": "https://github.com/twigphp/Twig/tree/v3.3.6" }, "funding": [ { @@ -8774,7 +9077,113 @@ "type": "tidelift" } ], - "time": "2021-11-25T13:46:55+00:00" + "time": "2022-01-03T14:27:01+00:00" + }, + { + "name": "vimeo/psalm", + "version": "4.17.0", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "6f4707aa41c9174353a6434bba3fc8840f981d9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/6f4707aa41c9174353a6434bba3fc8840f981d9c", + "reference": "6f4707aa41c9174353a6434bba3fc8840f981d9c", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer/package-versions-deprecated": "^1.8.0", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.0.3", + "felixfbecker/language-server-protocol": "^1.5", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.13", + "openlss/lib-array2xml": "^1.0", + "php": "^7.1|^8", + "sebastian/diff": "^3.0 || ^4.0", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", + "webmozart/path-util": "^2.3" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "brianium/paratest": "^4.0||^6.0", + "ext-curl": "*", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpdocumentor/reflection-docblock": "^5", + "phpmyadmin/sql-parser": "5.1.0||dev-master", + "phpspec/prophecy": ">=1.9.0", + "phpunit/phpunit": "^9.0", + "psalm/plugin-phpunit": "^0.16", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.3 || ^5.0 || ^6.0", + "weirdan/prophecy-shim": "^1.0 || ^2.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\": "src/Psalm/" + }, + "files": [ + "src/functions.php", + "src/spl_object_id.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php" + ], + "support": { + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm/tree/4.17.0" + }, + "time": "2022-01-01T18:39:47+00:00" }, { "name": "webimpress/coding-standard", @@ -8830,6 +9239,57 @@ } ], "time": "2021-10-28T21:18:17+00:00" + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "support": { + "issues": "https://github.com/webmozart/path-util/issues", + "source": "https://github.com/webmozart/path-util/tree/2.3.0" + }, + "abandoned": "symfony/filesystem", + "time": "2015-12-17T08:42:14+00:00" } ], "aliases": [], diff --git a/phpstan.installer.neon b/phpstan.installer.neon deleted file mode 100644 index 726a9d72..00000000 --- a/phpstan.installer.neon +++ /dev/null @@ -1,15 +0,0 @@ -# mezzio-skeleton specific -includes: - - vendor/phpstan/phpstan-strict-rules/rules.neon -parameters: - fileExtensions: - # Standard php files and .dist config files - - php - - dist - excludes_analyse: - - src/MezzioInstaller/Resources/src/ConfigProvider.flat.php - - src/MezzioInstaller/Resources/src/ConfigProvider.modular.php - reportUnmatchedIgnoredErrors: true - ignoreErrors: - - '#Class App\\ConfigProvider not found#' - # - '#Class Mezzio\\Swoole\\ConfigProvider not found#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ebd70409..dfb9b3d7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,15 +1,17 @@ - + test diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 00000000..3e5ce112 --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,348 @@ + + + + + $container + $factory + + + + + require 'config/container.php' + require 'config/routes.php' + + + $factory + + + $factory + + + + + $this->stabilityFlags + + + $constraint + $defaultOption + $defaultText + $defaultText + $filename + $filename + $force + $key + $option['name'] + $package + $package + $packageData['version'] + $packageData['whitelist'] ?? [] + $packageName + $question + $questionName + $question['custom-package-warning'] + $question['question'] + $resource + $resource + $target + $target + $this->composerDefinition['autoload'] + $this->composerDefinition['autoload-dev'] + $this->composerDefinition['extra'] ?? [] + $this->composerDefinition['extra']['laminas']['component-whitelist'] + $this->config['require-dev'] + $word + + + $option['name'] + $option['name'] + $packageData['version'] + $packageData['whitelist'] + $question['options'][$answer][$this->installType] + $question['options'][$answer]['packages'] + $this->composerDefinition['autoload']['psr-4'] + $this->composerDefinition['autoload-dev']['psr-4'] + $this->composerDefinition['extra']['branch-alias'] + $this->composerDefinition['extra']['laminas'] + $this->composerDefinition['extra']['optional-packages'] + $this->composerDefinition['require'][$packageName] + $this->composerDefinition['require-dev'][$devDependency] + $this->composerDefinition['require-dev'][$packageName] + $this->composerDefinition['scripts']['pre-install-cmd'] + $this->composerDefinition['scripts']['pre-update-cmd'] + $this->config['application'][$this->installType] + $this->config['application'][$this->installType] + $this->config['packages'][$packageName] + + + $this->composerDefinition['autoload']['psr-4'] + $this->composerDefinition['extra']['laminas'] + $this->composerDefinition['extra']['optional-packages'] + $this->composerDefinition['require'][$packageName] + $this->composerDefinition['require-dev'][$packageName] + $this->composerDefinition['scripts']['cs-check'] + $this->composerDefinition['scripts']['cs-fix'] + + + $this->config['packages'][$packageName] + + + $constraint + $defaultOption + $defaultText + $fileInfo + $filename + $force + $key + $option + $package + $package + $packageData + $packageName + $question + $questionName + $resource + $resource + $target + $target + $this->composerDefinition + + + isDir + + + $answer + + + + + $json + + + $json->ack + + + + + $stabilityFlags + + + $stabilityFlags[$packageName] + + + $stabilityFlags + + + array + + + + + $config['questions']['container'] + $config['questions']['router'] + + + $config['questions']['container'] + $config['questions']['router'] + + + testContainer + + + + + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['error-handler'] + + + $config['dependencies'] + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['error-handler'] + + + $config + + + array + + + + + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['router'] + $config['questions']['router'] + $config['questions']['template-engine'] + + + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['router'] + $config['questions']['router'] + $config['questions']['template-engine'] + + + + $this->expectedContainerAttributes[$containerClass] + $this->expectedContainerAttributes[$containerClass] + $this->expectedRouterAttributes[$routerClass] + $this->rendererConfigProviders[$rendererClass] + $this->routerConfigProviders[$routerClass] + + + (string) $response->getBody()->getContents() + + + + + $properties['devDependencies'] + $r->getValue($installer) + $r->getValue($installer) + $whitelist + + + $composerJson['require'] + $composerJson['require-dev'] + $r->getValue($installer)['extra'] + + + $composerJson + $whitelist + + + array + array + + + $this->getInstallerProperty($installer, 'composerDefinition') + $this->getInstallerProperty($installer, 'config') + + + + + $question + $question + $question + $question + $question + $question + + + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['container'] + $config['questions']['template-engine'] + + + $question + $question + $question + $question + $question + $question + + + + + $class + + + $class + $class + $class + + + $this->autoloader + + + $class + $this->container + + + ContainerInterface + + + require $path + + + + + testPromptForOptionalPackage + + + + $question['question'] + $written + + + $written[] + + + $package + $package + $target + $toWrite[] + $toWrite[] + $written[] + + + + + $this->devDependencies + + + + + array + + + + + $config['questions']['container'] + $config['questions']['router'] + + + $config['dependencies'] + $config['questions']['container'] + $config['questions']['router'] + $expectedRoute['allowed_methods'] + $expectedRoute['name'] + $expectedRoute['path'] + + + $config + $expectedRoute + + + array + + + + + $expectedTemplateRenderer + + + + $config['questions']['container'] + $config['questions']['router'] + $config['questions']['template-engine'] + + + $config['dependencies'] + $config['questions']['container'] + $config['questions']['router'] + $config['questions']['template-engine'] + + + $config + + + + + $property + + + diff --git a/psalm.xml.dist b/psalm.xml.dist new file mode 100644 index 00000000..9c544c22 --- /dev/null +++ b/psalm.xml.dist @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/src/App/src/Handler/HomePageHandlerFactory.php b/src/App/src/Handler/HomePageHandlerFactory.php index c3670c56..81300237 100644 --- a/src/App/src/Handler/HomePageHandlerFactory.php +++ b/src/App/src/Handler/HomePageHandlerFactory.php @@ -9,19 +9,21 @@ use Psr\Container\ContainerInterface; use Psr\Http\Server\RequestHandlerInterface; +use function assert; use function get_class; class HomePageHandlerFactory { public function __invoke(ContainerInterface $container): RequestHandlerInterface { - $router = $container->get(RouterInterface::class); + $router = $container->get(RouterInterface::class); + assert($router instanceof RouterInterface); + $template = $container->has(TemplateRendererInterface::class) ? $container->get(TemplateRendererInterface::class) : null; + assert($template instanceof TemplateRendererInterface || null === $template); - // @codingStandardsIgnoreStart return new HomePageHandler(get_class($container), $router, $template); - // @codingStandardsIgnoreEnd } } diff --git a/src/MezzioInstaller/OptionalPackages.php b/src/MezzioInstaller/OptionalPackages.php index b5063f19..7bf667b7 100644 --- a/src/MezzioInstaller/OptionalPackages.php +++ b/src/MezzioInstaller/OptionalPackages.php @@ -18,7 +18,6 @@ use RecursiveIteratorIterator; use RuntimeException; -use function array_diff; use function array_map; use function chmod; use function copy; @@ -84,7 +83,8 @@ class OptionalPackages '.travis.yml', 'CHANGELOG.md', 'phpcs.xml', - 'phpstan.installer.neon', + 'psalm.xml.dist', + 'psalm-baseline.xml', 'src/App/templates/.gitkeep', ]; @@ -114,9 +114,9 @@ class OptionalPackages 'filp/whoops', 'jsoumelidis/zend-sf-di-config', 'mikey179/vfsstream', - 'phpstan/phpstan', - 'phpstan/phpstan-strict-rules', 'laminas/laminas-coding-standard', + 'vimeo/psalm', + 'psalm/plugin-phpunit', 'mezzio/mezzio-fastroute', 'mezzio/mezzio-platesrenderer', 'mezzio/mezzio-twigrenderer', @@ -390,13 +390,6 @@ public function removeInstallerFromDefinition(): void unset($this->composerDefinition['scripts']['pre-update-cmd']); unset($this->composerDefinition['scripts']['pre-install-cmd']); - // Remove phpstan completely - $this->composerDefinition['scripts']['check'] = array_diff( - $this->composerDefinition['scripts']['check'], - ['@analyze'] - ); - unset($this->composerDefinition['scripts']['analyze']); - // Reset phpcs commands $this->composerDefinition['scripts']['cs-check'] = 'phpcs'; $this->composerDefinition['scripts']['cs-fix'] = 'phpcbf'; diff --git a/test/AppTest/Handler/HomePageHandlerFactoryTest.php b/test/AppTest/Handler/HomePageHandlerFactoryTest.php index 01567070..4f213785 100644 --- a/test/AppTest/Handler/HomePageHandlerFactoryTest.php +++ b/test/AppTest/Handler/HomePageHandlerFactoryTest.php @@ -8,48 +8,65 @@ use App\Handler\HomePageHandlerFactory; use Mezzio\Router\RouterInterface; use Mezzio\Template\TemplateRendererInterface; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Container\ContainerInterface; class HomePageHandlerFactoryTest extends TestCase { - use ProphecyTrait; - - /** @var ContainerInterface|ObjectProphecy */ + /** @var ContainerInterface&MockObject */ protected $container; + /** @var RouterInterface&MockObject */ + protected $router; + protected function setUp(): void { - $this->container = $this->prophesize(ContainerInterface::class); - $router = $this->prophesize(RouterInterface::class); - - $this->container->get(RouterInterface::class)->willReturn($router); + $this->container = $this->createMock(ContainerInterface::class); + $this->router = $this->createMock(RouterInterface::class); } - public function testFactoryWithoutTemplate() + public function testFactoryWithoutTemplate(): void { - $factory = new HomePageHandlerFactory(); - $this->container->has(TemplateRendererInterface::class)->willReturn(false); - - self::assertInstanceOf(HomePageHandlerFactory::class, $factory); + $this->container + ->expects($this->once()) + ->method('has') + ->with(TemplateRendererInterface::class) + ->willReturn(false); + $this->container + ->expects($this->once()) + ->method('get') + ->with(RouterInterface::class) + ->willReturn($this->router); - $homePage = $factory($this->container->reveal()); + $factory = new HomePageHandlerFactory(); + $homePage = $factory($this->container); self::assertInstanceOf(HomePageHandler::class, $homePage); } - public function testFactoryWithTemplate() + public function testFactoryWithTemplate(): void { - $this->container->has(TemplateRendererInterface::class)->willReturn(true); + $renderer = $this->createMock(TemplateRendererInterface::class); $this->container - ->get(TemplateRendererInterface::class) - ->willReturn($this->prophesize(TemplateRendererInterface::class)); - - $factory = new HomePageHandlerFactory(); + ->expects($this->once()) + ->method('has') + ->with(TemplateRendererInterface::class) + ->willReturn(true); + $this->container + ->expects($this->exactly(2)) + ->method('get') + ->withConsecutive( + [RouterInterface::class], + [TemplateRendererInterface::class], + ) + ->willReturnOnConsecutiveCalls( + $this->router, + $renderer + ); - $homePage = $factory($this->container->reveal()); + $factory = new HomePageHandlerFactory(); + $homePage = $factory($this->container); self::assertInstanceOf(HomePageHandler::class, $homePage); } diff --git a/test/AppTest/Handler/HomePageHandlerTest.php b/test/AppTest/Handler/HomePageHandlerTest.php index 46b70b7a..7fdf00a6 100644 --- a/test/AppTest/Handler/HomePageHandlerTest.php +++ b/test/AppTest/Handler/HomePageHandlerTest.php @@ -9,10 +9,8 @@ use Laminas\Diactoros\Response\JsonResponse; use Mezzio\Router\RouterInterface; use Mezzio\Template\TemplateRendererInterface; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Container\ContainerInterface; use Psr\Http\Message\ServerRequestInterface; @@ -20,49 +18,49 @@ class HomePageHandlerTest extends TestCase { - use ProphecyTrait; - - /** @var ContainerInterface|ObjectProphecy */ + /** @var ContainerInterface&MockObject */ protected $container; - /** @var RouterInterface|ObjectProphecy */ + /** @var RouterInterface&MockObject */ protected $router; protected function setUp(): void { - $this->container = $this->prophesize(ContainerInterface::class); - $this->router = $this->prophesize(RouterInterface::class); + $this->container = $this->createMock(ContainerInterface::class); + $this->router = $this->createMock(RouterInterface::class); } - public function testReturnsJsonResponseWhenNoTemplateRendererProvided() + public function testReturnsJsonResponseWhenNoTemplateRendererProvided(): void { $homePage = new HomePageHandler( - get_class($this->container->reveal()), - $this->router->reveal(), + get_class($this->container), + $this->router, null ); $response = $homePage->handle( - $this->prophesize(ServerRequestInterface::class)->reveal() + $this->createMock(ServerRequestInterface::class) ); self::assertInstanceOf(JsonResponse::class, $response); } - public function testReturnsHtmlResponseWhenTemplateRendererProvided() + public function testReturnsHtmlResponseWhenTemplateRendererProvided(): void { - $renderer = $this->prophesize(TemplateRendererInterface::class); + $renderer = $this->createMock(TemplateRendererInterface::class); $renderer - ->render('app::home-page', Argument::type('array')) + ->expects($this->once()) + ->method('render') + ->with('app::home-page', $this->isType('array')) ->willReturn(''); $homePage = new HomePageHandler( - get_class($this->container->reveal()), - $this->router->reveal(), - $renderer->reveal() + get_class($this->container), + $this->router, + $renderer ); $response = $homePage->handle( - $this->prophesize(ServerRequestInterface::class)->reveal() + $this->createMock(ServerRequestInterface::class) ); self::assertInstanceOf(HtmlResponse::class, $response); diff --git a/test/AppTest/Handler/PingHandlerTest.php b/test/AppTest/Handler/PingHandlerTest.php index df486aae..f9559791 100644 --- a/test/AppTest/Handler/PingHandlerTest.php +++ b/test/AppTest/Handler/PingHandlerTest.php @@ -7,20 +7,17 @@ use App\Handler\PingHandler; use Laminas\Diactoros\Response\JsonResponse; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; use Psr\Http\Message\ServerRequestInterface; use function json_decode; class PingHandlerTest extends TestCase { - use ProphecyTrait; - - public function testResponse() + public function testResponse(): void { $pingHandler = new PingHandler(); $response = $pingHandler->handle( - $this->prophesize(ServerRequestInterface::class)->reveal() + $this->createMock(ServerRequestInterface::class) ); $json = json_decode((string) $response->getBody()); diff --git a/test/MezzioInstallerTest/AddPackageTest.php b/test/MezzioInstallerTest/AddPackageTest.php index 15f72ed7..11e2a875 100644 --- a/test/MezzioInstallerTest/AddPackageTest.php +++ b/test/MezzioInstallerTest/AddPackageTest.php @@ -5,7 +5,6 @@ namespace MezzioInstallerTest; use Composer\Package\BasePackage; -use Prophecy\Argument; use ReflectionProperty; class AddPackageTest extends OptionalPackagesTestCase @@ -13,19 +12,19 @@ class AddPackageTest extends OptionalPackagesTestCase /** * @dataProvider packageProvider */ - public function testAddPackage(string $packageName, string $packageVersion, ?int $expectedStability) + public function testAddPackage(string $packageName, string $packageVersion, ?int $expectedStability): void { $installer = $this->createOptionalPackages(); $this->io - ->write(Argument::containingString('Removing installer development dependencies')) - ->shouldBeCalled(); - $installer->removeDevDependencies(); - - $this->io - ->write(Argument::containingString('Adding package')) - ->shouldBeCalled(); + ->expects($this->atLeast(2)) + ->method('write') + ->withConsecutive( + [$this->stringContains('Removing installer development dependencies')], + [$this->stringContains('Adding package')], + ); + $installer->removeDevDependencies(); $installer->addPackage($packageName, $packageVersion); self::assertPackage('laminas/laminas-stdlib', $installer); diff --git a/test/MezzioInstallerTest/ContainersTest.php b/test/MezzioInstallerTest/ContainersTest.php index ee84e641..605ca0ee 100644 --- a/test/MezzioInstallerTest/ContainersTest.php +++ b/test/MezzioInstallerTest/ContainersTest.php @@ -46,6 +46,9 @@ protected function tearDown(): void /** * @runInSeparateProcess * @dataProvider containerProvider + * @psalm-param OptionalPackages::INSTALL_* $installType + * @psalm-param class-string $expectedContainer + * @psalm-param 'minimal-files'|'copy-files' $copyFilesKey */ public function testContainer( string $installType, @@ -54,7 +57,7 @@ public function testContainer( string $copyFilesKey, int $expectedResponseStatusCode, string $expectedContainer - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); // Install container @@ -96,27 +99,37 @@ public function testContainer( self::assertEquals($expectedResponseStatusCode, $response->getStatusCode()); } + /** + * @psalm-return array + * }> + */ public function containerProvider(): array { - // @codingStandardsIgnoreStart + // phpcs:disable Generic.Files.LineLength.TooLong // $installType, $containerOption, $routerOption, $copyFilesKey, $expectedResponseStatusCode, $expectedContainer return [ - 'pimple-minimal' => [OptionalPackages::INSTALL_MINIMAL, 1, 2, 'minimal-files', 404, PimpleContainer::class], - 'pimple-flat' => [OptionalPackages::INSTALL_FLAT, 1, 2, 'copy-files', 200, PimpleContainer::class], - 'pimple-modular' => [OptionalPackages::INSTALL_MODULAR, 1, 2, 'copy-files', 200, PimpleContainer::class], - 'laminas-sm-minimal' => [OptionalPackages::INSTALL_MINIMAL, 2, 2, 'minimal-files', 404, LaminasManagerContainer::class], - 'laminas-sm-flat' => [OptionalPackages::INSTALL_FLAT, 2, 2, 'copy-files', 200, LaminasManagerContainer::class], - 'laminas-sm-modular' => [OptionalPackages::INSTALL_MODULAR, 2, 2, 'copy-files', 200, LaminasManagerContainer::class], - 'sf-di-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 'minimal-files', 404, SfContainerBuilder::class], - 'sf-di-flat' => [OptionalPackages::INSTALL_FLAT, 3, 2, 'copy-files', 200, SfContainerBuilder::class], - 'sf-di-modular' => [OptionalPackages::INSTALL_MODULAR, 3, 2, 'copy-files', 200, SfContainerBuilder::class], - 'php-di-minimal' => [OptionalPackages::INSTALL_MINIMAL, 4, 2, 'minimal-files', 404, PhpDIContainer::class], - 'php-di-flat' => [OptionalPackages::INSTALL_FLAT, 4, 2, 'copy-files', 200, PhpDIContainer::class], - 'php-di-modular' => [OptionalPackages::INSTALL_MODULAR, 4, 2, 'copy-files', 200, PhpDIContainer::class], - 'chubbyphp-c-minimal' => [OptionalPackages::INSTALL_MINIMAL, 5, 2, 'minimal-files', 404, ChubbyphpMinimalContainer::class], - 'chubbyphp-c-flat' => [OptionalPackages::INSTALL_FLAT, 5, 2, 'copy-files', 200, ChubbyphpMinimalContainer::class], - 'chubbyphp-c-modular' => [OptionalPackages::INSTALL_MODULAR, 5, 2, 'copy-files', 200, ChubbyphpMinimalContainer::class], + 'pimple-minimal' => [OptionalPackages::INSTALL_MINIMAL, 1, 2, 'minimal-files', 404, PimpleContainer::class], + 'pimple-flat' => [OptionalPackages::INSTALL_FLAT, 1, 2, 'copy-files', 200, PimpleContainer::class], + 'pimple-modular' => [OptionalPackages::INSTALL_MODULAR, 1, 2, 'copy-files', 200, PimpleContainer::class], + 'laminas-sm-minimal' => [OptionalPackages::INSTALL_MINIMAL, 2, 2, 'minimal-files', 404, LaminasManagerContainer::class], + 'laminas-sm-flat' => [OptionalPackages::INSTALL_FLAT, 2, 2, 'copy-files', 200, LaminasManagerContainer::class], + 'laminas-sm-modular' => [OptionalPackages::INSTALL_MODULAR, 2, 2, 'copy-files', 200, LaminasManagerContainer::class], + 'sf-di-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 'minimal-files', 404, SfContainerBuilder::class], + 'sf-di-flat' => [OptionalPackages::INSTALL_FLAT, 3, 2, 'copy-files', 200, SfContainerBuilder::class], + 'sf-di-modular' => [OptionalPackages::INSTALL_MODULAR, 3, 2, 'copy-files', 200, SfContainerBuilder::class], + 'php-di-minimal' => [OptionalPackages::INSTALL_MINIMAL, 4, 2, 'minimal-files', 404, PhpDIContainer::class], + 'php-di-flat' => [OptionalPackages::INSTALL_FLAT, 4, 2, 'copy-files', 200, PhpDIContainer::class], + 'php-di-modular' => [OptionalPackages::INSTALL_MODULAR, 4, 2, 'copy-files', 200, PhpDIContainer::class], + 'chubbyphp-c-minimal' => [OptionalPackages::INSTALL_MINIMAL, 5, 2, 'minimal-files', 404, ChubbyphpMinimalContainer::class], + 'chubbyphp-c-flat' => [OptionalPackages::INSTALL_FLAT, 5, 2, 'copy-files', 200, ChubbyphpMinimalContainer::class], + 'chubbyphp-c-modular' => [OptionalPackages::INSTALL_MODULAR, 5, 2, 'copy-files', 200, ChubbyphpMinimalContainer::class], ]; - // @codingStandardsIgnoreEnd + // phpcs:enable Generic.Files.LineLength.TooLong } } diff --git a/test/MezzioInstallerTest/CopyResourceTest.php b/test/MezzioInstallerTest/CopyResourceTest.php index e4b80fe4..387b9583 100644 --- a/test/MezzioInstallerTest/CopyResourceTest.php +++ b/test/MezzioInstallerTest/CopyResourceTest.php @@ -24,13 +24,13 @@ protected function setUp(): void $this->projectRoot = vfsStream::url('project-root'); } - public function testTargetFileDoesNotExist() + public function testTargetFileDoesNotExist(): void { self::assertFalse($this->project->hasChild('data')); self::assertFalse($this->project->hasChild('data/target.php')); } - public function testResourceIsCopiedIfItDoesNotExist() + public function testResourceIsCopiedIfItDoesNotExist(): void { $installer = $this->createOptionalPackages($this->projectRoot); @@ -44,7 +44,7 @@ public function testResourceIsCopiedIfItDoesNotExist() ); } - public function testResourceIsNotCopiedIfItExists() + public function testResourceIsNotCopiedIfItExists(): void { // Create default test file vfsStream::newFile('data/target.php') diff --git a/test/MezzioInstallerTest/ErrorHandlerTest.php b/test/MezzioInstallerTest/ErrorHandlerTest.php index c3f89693..8f9293fa 100644 --- a/test/MezzioInstallerTest/ErrorHandlerTest.php +++ b/test/MezzioInstallerTest/ErrorHandlerTest.php @@ -35,7 +35,7 @@ protected function tearDown(): void /** * @runInSeparateProcess */ - public function testErrorHandlerIsNotInstalled() + public function testErrorHandlerIsNotInstalled(): void { $this->prepareSandboxForInstallType(OptionalPackages::INSTALL_MINIMAL, $this->installer); @@ -66,7 +66,7 @@ public function testErrorHandler( int $containerOption, int $errorHandlerOption, string $expectedErrorHandler - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); $config = $this->getInstallerConfig($this->installer); diff --git a/test/MezzioInstallerTest/HomePageResponseTest.php b/test/MezzioInstallerTest/HomePageResponseTest.php index 93604727..e6d85e55 100644 --- a/test/MezzioInstallerTest/HomePageResponseTest.php +++ b/test/MezzioInstallerTest/HomePageResponseTest.php @@ -146,7 +146,7 @@ public function testHomePageHtmlResponseContainsExpectedInfo( string $rendererClass, string $containerName, string $containerDocs - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); // Install container @@ -184,6 +184,16 @@ public function testHomePageHtmlResponseContainsExpectedInfo( self::assertStringContainsString("href=\"{$containerDocs}\"", $html); } + /** + * @psalm-return Generator, + * 4: string, + * 5: string + * }> + */ public function installCasesProvider(): Generator { // Execute a test case for each container, renderer and non minimal install type @@ -233,7 +243,7 @@ public function testHomePageJsonResponseContainsExpectedInfo( string $routerClass, string $routerName, string $routerDocs - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); // Install container @@ -257,7 +267,7 @@ public function testHomePageJsonResponseContainsExpectedInfo( self::assertEquals(200, $response->getStatusCode()); // Test response content - $json = (string) $response->getBody()->getContents(); + $json = $response->getBody()->getContents(); $data = json_decode($json, true); self::assertIsArray($data); @@ -271,6 +281,18 @@ public function testHomePageJsonResponseContainsExpectedInfo( self::assertEquals($routerDocs, $data['routerDocs']); } + /** + * @psalm-return Generator, + * 6: string, + * 7: string + * }> + */ public function rendererlessInstallCasesProvider(): Generator { // Execute a test case for each install type and container, without any renderer @@ -306,7 +328,7 @@ public function rendererlessInstallCasesProvider(): Generator } } - public function injectRouterConfigProvider(string $routerClass) + public function injectRouterConfigProvider(string $routerClass): void { $configFile = $this->projectRoot . '/config/config.php'; $contents = file_get_contents($configFile); @@ -318,7 +340,7 @@ public function injectRouterConfigProvider(string $routerClass) file_put_contents($configFile, $contents); } - public function injectRendererConfigProvider(string $rendererClass) + public function injectRendererConfigProvider(string $rendererClass): void { $configFile = $this->projectRoot . '/config/config.php'; $contents = file_get_contents($configFile); diff --git a/test/MezzioInstallerTest/OptionalPackagesTestCase.php b/test/MezzioInstallerTest/OptionalPackagesTestCase.php index ba3e94a7..c8681ed4 100644 --- a/test/MezzioInstallerTest/OptionalPackagesTestCase.php +++ b/test/MezzioInstallerTest/OptionalPackagesTestCase.php @@ -10,9 +10,8 @@ use Composer\Package\RootPackage; use MezzioInstaller\OptionalPackages; use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use ReflectionClass; use ReflectionProperty; @@ -28,21 +27,19 @@ // phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix abstract class OptionalPackagesTestCase extends TestCase { - use ProphecyTrait; - - /** @var Composer|ObjectProphecy */ + /** @var Composer&MockObject */ protected $composer; /** @var array Array version of composer.json */ protected $composerData; - /** @var IOInterface|ObjectProphecy */ + /** @var IOInterface&MockObject */ protected $io; /** @var string Root of this package. */ protected $packageRoot; - /** @var RootPackage|ObjectProphecy */ + /** @var RootPackage&MockObject */ protected $rootPackage; /** @@ -171,37 +168,38 @@ protected function tearDown(): void protected function createOptionalPackages(?string $projectRoot = null): OptionalPackages { $projectRoot = $projectRoot ?: $this->packageRoot; - - $this->io = $this->prophesize(IOInterface::class); + $this->io = $this->createMock(IOInterface::class); return new OptionalPackages( - $this->io->reveal(), - $this->createComposer()->reveal(), + $this->io, + $this->createComposer(), $projectRoot ); } /** - * @return Composer|ObjectProphecy + * @return Composer&MockObject */ protected function createComposer() { - $this->composer = $this->prophesize(Composer::class); - $this->composer->getPackage()->will([$this->createRootPackage(), 'reveal']); + $this->composer = $this->createMock(Composer::class); + $this->composer->method('getPackage')->will($this->returnCallback(function () { + return $this->createRootPackage(); + })); return $this->composer; } /** - * @return RootPackage|ObjectProphecy + * @return RootPackage&MockObject */ protected function createRootPackage() { $composerJson = json_decode(file_get_contents($this->packageRoot . '/composer.json'), true); - $this->rootPackage = $this->prophesize(RootPackage::class); + $this->rootPackage = $this->createMock(RootPackage::class); - $this->rootPackage->getRequires()->willReturn($composerJson['require']); - $this->rootPackage->getDevRequires()->willReturn($composerJson['require-dev']); - $this->rootPackage->getStabilityFlags()->willReturn($this->getStabilityFlags()); + $this->rootPackage->method('getRequires')->willReturn($composerJson['require']); + $this->rootPackage->method('getDevRequires')->willReturn($composerJson['require-dev']); + $this->rootPackage->method('getStabilityFlags')->willReturn($this->getStabilityFlags()); return $this->rootPackage; } diff --git a/test/MezzioInstallerTest/ProcessAnswersTest.php b/test/MezzioInstallerTest/ProcessAnswersTest.php index 2d56777a..c1e51773 100644 --- a/test/MezzioInstallerTest/ProcessAnswersTest.php +++ b/test/MezzioInstallerTest/ProcessAnswersTest.php @@ -5,7 +5,6 @@ namespace MezzioInstallerTest; use MezzioInstaller\OptionalPackages; -use Prophecy\Argument; use function chdir; @@ -31,9 +30,9 @@ protected function tearDown(): void $this->recursiveDelete($this->projectRoot); } - public function testInvalidAnswer() + public function testInvalidAnswer(): void { - $this->io->write()->shouldNotBeCalled(); + $this->io->expects($this->never())->method('write'); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['container']; @@ -44,9 +43,9 @@ public function testInvalidAnswer() self::assertFileDoesNotExist($this->projectRoot . '/config/container.php'); } - public function testAnsweredWithN() + public function testAnsweredWithN(): void { - $this->io->write()->shouldNotBeCalled(); + $this->io->expects($this->never())->method('write'); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['container']; @@ -57,9 +56,9 @@ public function testAnsweredWithN() self::assertFileDoesNotExist($this->projectRoot . '/config/container.php'); } - public function testAnsweredWithInvalidOption() + public function testAnsweredWithInvalidOption(): void { - $this->io->write()->shouldNotBeCalled(); + $this->io->expects($this->never())->method('write'); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['container']; @@ -70,15 +69,18 @@ public function testAnsweredWithInvalidOption() self::assertFileDoesNotExist($this->projectRoot . '/config/container.php'); } - public function testAnsweredWithValidOption() + public function testAnsweredWithValidOption(): void { // Prepare the installer $this->installer->removeDevDependencies(); - // @codingStandardsIgnoreStart - $this->io->write(Argument::containingString('Adding package laminas/laminas-pimple-config'))->shouldBeCalled(); - $this->io->write(Argument::containingString('Copying config/container.php'))->shouldBeCalled(); - // @codingStandardsIgnoreEnd + $this->io + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + [$this->stringContains('Adding package laminas/laminas-pimple-config')], + [$this->stringContains('Copying config/container.php')], + ); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['container']; @@ -90,13 +92,18 @@ public function testAnsweredWithValidOption() self::assertPackage('laminas/laminas-pimple-config', $this->installer); } - public function testAnsweredWithPackage() + public function testAnsweredWithPackage(): void { // Prepare the installer $this->installer->removeDevDependencies(); - $this->io->write(Argument::containingString('Adding package league/container'))->shouldBeCalled(); - $this->io->write(Argument::containingString('You need to edit public/index.php'))->shouldBeCalled(); + $this->io + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + [$this->stringContains('Adding package league/container')], + [$this->stringContains('You need to edit public/index.php')], + ); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['container']; @@ -108,21 +115,18 @@ public function testAnsweredWithPackage() self::assertPackage('league/container', $this->installer); } - public function testPackagesAreAddedToWhitelist() + public function testPackagesAreAddedToWhitelist(): void { // Prepare the installer $this->installer->removeDevDependencies(); $this->io - ->write(Argument::containingString( - 'Adding package mezzio/mezzio-laminasviewrenderer' - )) - ->shouldBeCalled(); - $this->io - ->write(Argument::containingString( - 'Whitelist package mezzio/mezzio-laminasviewrenderer' - )) - ->shouldBeCalled(); + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + [$this->stringContains('Adding package mezzio/mezzio-laminasviewrenderer')], + [$this->stringContains('Whitelist package mezzio/mezzio-laminasviewrenderer')], + ); $config = $this->getInstallerConfig($this->installer); $question = $config['questions']['template-engine']; diff --git a/test/MezzioInstallerTest/ProjectSandboxTrait.php b/test/MezzioInstallerTest/ProjectSandboxTrait.php index b8c9e9ad..3a2b5553 100644 --- a/test/MezzioInstallerTest/ProjectSandboxTrait.php +++ b/test/MezzioInstallerTest/ProjectSandboxTrait.php @@ -51,7 +51,7 @@ trait ProjectSandboxTrait */ protected $autoloader; - /** @var ContainerInterface */ + /** @var null|ContainerInterface */ protected $container; /** @var string Root of the sandbox system */ @@ -72,6 +72,7 @@ protected function copyProjectFilesToTempFilesystem(): string mkdir($this->projectRoot . '/data', 0777, true); mkdir($this->projectRoot . '/data/cache', 0777, true); + copy($this->packageRoot . '/composer.json', $this->projectRoot . '/composer.json'); foreach (['config', 'public', 'src', 'templates', 'test'] as $path) { $this->recursiveCopy( $this->packageRoot . DIRECTORY_SEPARATOR . $path, @@ -151,7 +152,7 @@ protected function enableDevelopmentMode(): void */ protected function setUpAlternateAutoloader(string $appPath, bool $stripNamespace = false): void { - $this->autoloader = function ($class) use ($appPath, $stripNamespace) { + $this->autoloader = function ($class) use ($appPath, $stripNamespace): bool { if (strpos($class, 'App\\') !== 0) { return false; } @@ -170,6 +171,7 @@ protected function setUpAlternateAutoloader(string $appPath, bool $stripNamespac } include $path; + return true; }; spl_autoload_register($this->autoloader, true, true); diff --git a/test/MezzioInstallerTest/PromptForOptionalPackagesTest.php b/test/MezzioInstallerTest/PromptForOptionalPackagesTest.php index ac9ab10a..6eeae28f 100644 --- a/test/MezzioInstallerTest/PromptForOptionalPackagesTest.php +++ b/test/MezzioInstallerTest/PromptForOptionalPackagesTest.php @@ -6,10 +6,10 @@ use Generator; use MezzioInstaller\OptionalPackages; -use Prophecy\Argument; use function chdir; use function copy; +use function count; use function putenv; use function sprintf; use function strpos; @@ -42,6 +42,14 @@ protected function tearDown(): void $this->recursiveDelete($this->projectRoot); } + /** + * @psalm-return Generator + */ public function promptCombinations(): Generator { $config = require __DIR__ . '/../../src/MezzioInstaller/config.php'; @@ -63,8 +71,10 @@ public function testPromptForOptionalPackage( array $expectedPackage ): void { $this->io - ->ask( - Argument::that(static function ($arg) use ($question) { + ->expects($this->once()) + ->method('ask') + ->with( + $this->callback(static function ($arg) use ($question) { PromptForOptionalPackagesTest::assertPromptText($question['question'], $arg); return true; @@ -73,22 +83,48 @@ public function testPromptForOptionalPackage( ) ->willReturn($selection); + $toWrite = []; + $written = []; + foreach ($expectedPackage['packages'] as $package) { - $this->io - ->write(Argument::containingString($package)) - ->shouldBeCalled(); + $toWrite[] = $package; } foreach ($expectedPackage[OptionalPackages::INSTALL_MINIMAL] as $target) { + $toWrite[] = $target; + } + + if (count($toWrite) > 0) { $this->io - ->write(Argument::containingString($target)) - ->shouldBeCalled(); + ->method('write') + ->with($this->callback(function (string $message) use ($toWrite, &$written): bool { + foreach ($toWrite as $package) { + if (false === strpos($message, $package)) { + continue; + } + + if ( + false !== strpos($message, 'Adding package') + || false !== strpos($message, '- Copying ') + ) { + $written[] = $package; + } + + return true; + } + + return false; + })); } self::assertNull($this->installer->promptForOptionalPackage($questionName, $question)); + self::assertSame(count($written), count($toWrite)); } - public static function assertPromptText(string $expected, string $argument): void + /** + * @param mixed $argument + */ + public static function assertPromptText(string $expected, $argument): void { self::assertIsString( $argument, diff --git a/test/MezzioInstallerTest/RemoveDevDependenciesTest.php b/test/MezzioInstallerTest/RemoveDevDependenciesTest.php index da9b4bc9..d689c201 100644 --- a/test/MezzioInstallerTest/RemoveDevDependenciesTest.php +++ b/test/MezzioInstallerTest/RemoveDevDependenciesTest.php @@ -38,13 +38,13 @@ protected function setUp(): void $this->installer = $this->createOptionalPackages(); } - public function testComposerHasAllDependencies() + public function testComposerHasAllDependencies(): void { self::assertPackages($this->standardDependencies, $this->installer); self::assertPackages($this->devDependencies, $this->installer); } - public function testDevDependenciesAreRemoved() + public function testDevDependenciesAreRemoved(): void { // Remove development dependencies $this->installer->removeDevDependencies(); diff --git a/test/MezzioInstallerTest/RemoveInstallerTest.php b/test/MezzioInstallerTest/RemoveInstallerTest.php index b3c2ea40..d6ffbcb8 100644 --- a/test/MezzioInstallerTest/RemoveInstallerTest.php +++ b/test/MezzioInstallerTest/RemoveInstallerTest.php @@ -17,7 +17,7 @@ protected function setUp(): void $this->installer = $this->createOptionalPackages(); } - public function testComposerHasInstaller() + public function testComposerHasInstaller(): void { $composer = $this->getComposerDataFromInstaller($this->installer); @@ -28,7 +28,7 @@ public function testComposerHasInstaller() self::assertTrue(isset($composer['scripts']['pre-update-cmd'])); } - public function testInstallerIsRemoved() + public function testInstallerIsRemoved(): void { // Remove the installer $this->installer->removeInstallerFromDefinition(); diff --git a/test/MezzioInstallerTest/RemoveLineFromStringTest.php b/test/MezzioInstallerTest/RemoveLineFromStringTest.php index 3f7d62b1..309530b3 100644 --- a/test/MezzioInstallerTest/RemoveLineFromStringTest.php +++ b/test/MezzioInstallerTest/RemoveLineFromStringTest.php @@ -17,7 +17,7 @@ protected function setUp(): void $this->installer = $this->createOptionalPackages(); } - public function testRemoveFirstLine() + public function testRemoveFirstLine(): void { $string = "foo\nbar\nbaz\nqux\nquux"; @@ -27,7 +27,7 @@ public function testRemoveFirstLine() self::assertEquals($expected, $actual); } - public function testRemoveSingleLine() + public function testRemoveSingleLine(): void { $string = "foo\nbar\nbaz\nqux\nquux"; @@ -37,7 +37,7 @@ public function testRemoveSingleLine() self::assertEquals($expected, $actual); } - public function testRemoveMultipleLines() + public function testRemoveMultipleLines(): void { $string = "foo\nbar\nbaz\nqux\nquux"; @@ -47,7 +47,7 @@ public function testRemoveMultipleLines() self::assertEquals($expected, $actual); } - public function testRemoveLinesWithSpaces() + public function testRemoveLinesWithSpaces(): void { $string = "foo\n bar\n baz \n qux\nquux"; @@ -57,7 +57,7 @@ public function testRemoveLinesWithSpaces() self::assertEquals($expected, $actual); } - public function testRemoveLastLine() + public function testRemoveLastLine(): void { $string = "foo\nbar\nbaz\nqux\nquux"; diff --git a/test/MezzioInstallerTest/RequestInstallTypeTest.php b/test/MezzioInstallerTest/RequestInstallTypeTest.php index 1b832ab7..d46801f9 100644 --- a/test/MezzioInstallerTest/RequestInstallTypeTest.php +++ b/test/MezzioInstallerTest/RequestInstallTypeTest.php @@ -5,8 +5,8 @@ namespace MezzioInstallerTest; use MezzioInstaller\OptionalPackages; -use Prophecy\Argument; +use function count; use function random_int; use function strpos; @@ -33,43 +33,43 @@ public function installSelections(): array /** * @dataProvider installSelections */ - public function testRequestInstallTypeReturnsExpectedConstantValue(string $selection, string $expected) + public function testRequestInstallTypeReturnsExpectedConstantValue(string $selection, string $expected): void { $this->io - ->ask(Argument::that([self::class, 'assertQueryPrompt']), '2') + ->expects($this->once()) + ->method('ask') + ->with($this->callback(fn ($value) => $this->assertQueryPrompt($value)), '2') ->willReturn($selection); self::assertSame($expected, $this->installer->requestInstallType()); } - public function testWillContinueToPromptUntilValidAnswerPresented() + public function testWillContinueToPromptUntilValidAnswerPresented(): void { - $io = $this->io; $tries = random_int(1, 10); - // Handle a call to ask() by looping $tries times - $handle = function () use ($io, &$tries, &$handle) { - if ($tries === 0) { - // Valid choice to complete the loop - return '1'; - } + $argumentLists = []; + $results = []; + + do { + $argumentLists[] = [$this->callback(fn ($value) => $this->assertQueryPrompt($value)), '2']; + $results[] = $tries > 0 ? 'n' : '1'; - // Otherwise, ask again. $tries -= 1; - $io->ask(Argument::that([self::class, 'assertQueryPrompt']), '2')->will($handle); - return 'n'; - }; + } while ($tries > -1); $this->io - ->ask(Argument::that([self::class, 'assertQueryPrompt']), '2') - ->will($handle); + ->expects($this->exactly(count($results))) + ->method('ask') + ->withConsecutive(...$argumentLists) + ->willReturnOnConsecutiveCalls(...$results); $this->io - ->write(Argument::containingString('Invalid answer')) - ->shouldBeCalledTimes($tries); + ->expects($this->exactly(count($results) - 1)) + ->method('write') + ->with($this->stringContains('Invalid answer')); self::assertSame(OptionalPackages::INSTALL_MINIMAL, $this->installer->requestInstallType()); - self::assertEquals(0, $tries); } /** diff --git a/test/MezzioInstallerTest/RoutersTest.php b/test/MezzioInstallerTest/RoutersTest.php index 14e06b14..2fbe2c67 100644 --- a/test/MezzioInstallerTest/RoutersTest.php +++ b/test/MezzioInstallerTest/RoutersTest.php @@ -75,7 +75,7 @@ public function testRouter( int $expectedResponseStatusCode, array $expectedRoutes, string $expectedRouter - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); // Install container diff --git a/test/MezzioInstallerTest/SetupDataAndCacheDirTest.php b/test/MezzioInstallerTest/SetupDataAndCacheDirTest.php index d1a6c05a..91626eb4 100644 --- a/test/MezzioInstallerTest/SetupDataAndCacheDirTest.php +++ b/test/MezzioInstallerTest/SetupDataAndCacheDirTest.php @@ -9,7 +9,6 @@ use MezzioInstaller\OptionalPackages; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamDirectory; -use Prophecy\Argument; use function fileperms; use function is_dir; @@ -34,9 +33,12 @@ protected function setUp(): void $this->installer = $this->createOptionalPackages($this->projectRoot); } - public function testCreatesDataDirectoryWhenInvoked() + public function testCreatesDataDirectoryWhenInvoked(): void { - $this->io->write(Argument::containingString('Setup data and cache dir'))->shouldBeCalled(); + $this->io + ->expects($this->once()) + ->method('write') + ->with($this->stringContains('Setup data and cache dir')); $this->installer->setupDataAndCacheDir(); // '40755' is the octal representation of the file permissions diff --git a/test/MezzioInstallerTest/SetupDefaultAppTest.php b/test/MezzioInstallerTest/SetupDefaultAppTest.php index ec02491f..74792c92 100644 --- a/test/MezzioInstallerTest/SetupDefaultAppTest.php +++ b/test/MezzioInstallerTest/SetupDefaultAppTest.php @@ -30,7 +30,7 @@ protected function tearDown(): void $this->tearDownAlternateAutoloader(); } - public function testModularInstallationAddsToolingSupportAsDevRequirement() + public function testModularInstallationAddsToolingSupportAsDevRequirement(): void { $this->prepareSandboxForInstallType(OptionalPackages::INSTALL_MODULAR, $this->installer); self::assertPackage( diff --git a/test/MezzioInstallerTest/TemplateRenderersTest.php b/test/MezzioInstallerTest/TemplateRenderersTest.php index 2fd387fa..27ee2644 100644 --- a/test/MezzioInstallerTest/TemplateRenderersTest.php +++ b/test/MezzioInstallerTest/TemplateRenderersTest.php @@ -56,7 +56,7 @@ public function testTemplateRenderer( int $templateRendererOption, int $expectedResponseStatusCode, string $expectedTemplateRenderer - ) { + ): void { $this->prepareSandboxForInstallType($installType, $this->installer); // Install container @@ -109,26 +109,34 @@ public function testTemplateRenderer( } } + /** + * @psalm-return Generator + * }> + */ public function templateRendererProvider(): Generator { - // @codingStandardsIgnoreStart + // phpcs:disable Generic.Files.LineLength.TooLong // Minimal framework installation test cases; no templates installed. // Must be run before those that install templates and test the output. // $installType, $containerOption, $routerOption, $templateRendererOption, $expectedResponseStatusCode, $expectedTemplateRenderer - yield 'plates-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 1, 404, Mezzio\Plates\PlatesRenderer::class]; - yield 'twig-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 2, 404, Mezzio\Twig\TwigRenderer::class]; + yield 'plates-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 1, 404, Mezzio\Plates\PlatesRenderer::class]; + yield 'twig-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 2, 404, Mezzio\Twig\TwigRenderer::class]; yield 'laminas-view-minimal' => [OptionalPackages::INSTALL_MINIMAL, 3, 2, 3, 404, Mezzio\LaminasView\LaminasViewRenderer::class]; - // @codingStandardsIgnoreEnd - // @codingStandardsIgnoreStart // Full framework installation test cases; installation options that install templates. $testCases = [ // $containerOption, $routerOption, $templateRendererOption, $expectedResponseStatusCode, $expectedTemplateRenderer - 'plates-full' => [3, 2, 1, 200, Mezzio\Plates\PlatesRenderer::class], - 'twig-full' => [3, 2, 2, 200, Mezzio\Twig\TwigRenderer::class], + 'plates-full' => [3, 2, 1, 200, Mezzio\Plates\PlatesRenderer::class], + 'twig-full' => [3, 2, 2, 200, Mezzio\Twig\TwigRenderer::class], 'laminas-view-full' => [3, 2, 3, 200, Mezzio\LaminasView\LaminasViewRenderer::class], ]; - // @codingStandardsIgnoreEnd + // phpcs:enable Generic.Files.LineLength.TooLong // Non-minimal installation types $types = [ diff --git a/test/MezzioInstallerTest/UpdateRootPackageTest.php b/test/MezzioInstallerTest/UpdateRootPackageTest.php index 3dde44d3..7c5f7ed4 100644 --- a/test/MezzioInstallerTest/UpdateRootPackageTest.php +++ b/test/MezzioInstallerTest/UpdateRootPackageTest.php @@ -37,17 +37,19 @@ class UpdateRootPackageTest extends OptionalPackagesTestCase ], ]; - public function testUpdateRootPackageWillUpdateComposedPackage() + public function testUpdateRootPackageWillUpdateComposedPackage(): void { $installer = $this->createOptionalPackages(); $this->setInstallerProperties($installer); - $this->rootPackage->setRequires($this->changes['composerRequires'])->shouldBeCalled(); - $this->rootPackage->setDevRequires($this->changes['composerDevRequires'])->shouldBeCalled(); - $this->rootPackage->setStabilityFlags($this->changes['stabilityFlags'])->shouldBeCalled(); - $this->rootPackage->setAutoload($this->changes['composerDefinition']['autoload'])->shouldBeCalled(); - $this->rootPackage->setDevAutoload($this->changes['composerDefinition']['autoload-dev'])->shouldBeCalled(); - $this->rootPackage->setExtra([])->shouldBeCalled(); + // phpcs:disable Generic.Files.LineLength.TooLong + $this->rootPackage->expects($this->atLeastOnce())->method('setRequires')->with($this->changes['composerRequires']); + $this->rootPackage->expects($this->atLeastOnce())->method('setDevRequires')->with($this->changes['composerDevRequires']); + $this->rootPackage->expects($this->atLeastOnce())->method('setStabilityFlags')->with($this->changes['stabilityFlags']); + $this->rootPackage->expects($this->atLeastOnce())->method('setAutoload')->with($this->changes['composerDefinition']['autoload']); + $this->rootPackage->expects($this->atLeastOnce())->method('setDevAutoload')->with($this->changes['composerDefinition']['autoload-dev']); + $this->rootPackage->expects($this->atLeastOnce())->method('setExtra')->with([]); + // phpcs:enable Generic.Files.LineLength.TooLong $installer->updateRootPackage(); }