From 8b6e2d30c2cb06a267834b65713a62f6f0a2501b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Thu, 13 Aug 2026 16:14:46 -0400 Subject: [PATCH 1/2] feat(ci): add PHPCS and PHPStan static analysis to CI (#39) Wire in the reusable wp-media/workflows PHPCS and PHPStan workflows via `uses:` rather than reimplementing them, and add the corresponding composer scripts and dev dependencies. To keep CI green without a big-bang rewrite of the ~19 pre-existing source files: - PHPStan (level 5) ships with a generated `phpstan-baseline.neon` covering the 76 pre-existing findings, so only new issues fail CI. - PHPCS is scoped to `Integration/HttpRequestTrait.php` only, the file already adopted as the WP Media reference style (declare(strict_types=1), full docblocks). A job that only `uses:` a reusable workflow cannot carry `continue-on-error`, so scoping the ruleset is the simplest way to avoid failing the build on untouched files while leaving room to widen the ruleset as files are brought up to standard opportunistically. HttpRequestTrait.php gets 3 missing method docblocks added (no logic change) so it passes PHPCS cleanly as the reference file. Co-Authored-By: Sonnet 5 --- .github/workflows/phpcs.yml | 13 ++ .github/workflows/phpstan.yml | 13 ++ .gitignore | 1 + Integration/HttpRequestTrait.php | 15 ++ composer.json | 21 +- phpcs.xml.dist | 37 ++++ phpstan-baseline.neon | 331 +++++++++++++++++++++++++++++++ phpstan.neon.dist | 20 ++ 8 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/phpcs.yml create mode 100644 .github/workflows/phpstan.yml create mode 100644 phpcs.xml.dist create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon.dist diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml new file mode 100644 index 0000000..0396dee --- /dev/null +++ b/.github/workflows/phpcs.yml @@ -0,0 +1,13 @@ +name: PHP CodeSniffer + +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + phpcs: + uses: wp-media/workflows/.github/workflows/phpcs.yml@main diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..fc387f7 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,13 @@ +name: PHPStan + +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + phpstan: + uses: wp-media/workflows/.github/workflows/phpstan.yml@main diff --git a/.gitignore b/.gitignore index 55b84c1..dcd0a57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/* composer.lock .phpunit.result.cache +phpcs-report.xml diff --git a/Integration/HttpRequestTrait.php b/Integration/HttpRequestTrait.php index 51a730c..5e09c5f 100644 --- a/Integration/HttpRequestTrait.php +++ b/Integration/HttpRequestTrait.php @@ -57,12 +57,22 @@ trait HttpRequestTrait { */ private $http_request_counts = []; + /** + * Starts mocking outbound HTTP requests for the current test. + * + * @return void + */ public function setup_http() { $this->reset_http(); add_filter( 'pre_http_request', [ $this, 'http_callback' ], 10, 3 ); } + /** + * Stops mocking outbound HTTP requests and fails the test if any request went unmocked. + * + * @return void + */ public function tear_down_http() { remove_filter( 'pre_http_request', [ $this, 'http_callback' ], 10 ); @@ -157,6 +167,11 @@ private function is_response_list( $mock ) { return array_keys( $mock ) === range( 0, count( $mock ) - 1 ); } + /** + * Clears the state tracked between tests. + * + * @return void + */ private function reset_http() { $this->blocked_http_requests = []; $this->http_request_counts = []; diff --git a/composer.json b/composer.json index 7e85a8a..8651c97 100644 --- a/composer.json +++ b/composer.json @@ -29,8 +29,22 @@ "vendor/antecedent/patchwork/Patchwork.php" ] }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1", + "php-stubs/wordpress-tests-stubs": "^6.8", + "phpcompatibility/phpcompatibility-wp": "^2.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.4", + "szepeviktor/phpstan-wordpress": "^1.3", + "wp-coding-standards/wpcs": "^3" + }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } }, "scripts": { "test-unit": "\"vendor/bin/phpunit\" --testsuite unit --colors=always --configuration Tests/Unit/phpunit.xml.dist", @@ -40,6 +54,9 @@ "@test-unit", "@test-integration", "@test-integration-admin" - ] + ], + "phpcs": "vendor/bin/phpcs", + "phpcs:fix": "vendor/bin/phpcbf", + "phpstan": "vendor/bin/phpstan analyze --memory-limit=2G" } } diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..3286c3e --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,37 @@ + + + The custom ruleset for WP Media projects + + + + Integration/HttpRequestTrait.php + vendor/* + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..a07b418 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,331 @@ +parameters: + ignoreErrors: + - + message: "#^Offset 'WPMEDIA_PHPUNIT…' does not exist on string\\.$#" + count: 1 + path: BootstrapManager.php + + - + message: "#^Parameter \\#1 \\$root of static method WPMedia\\\\PHPUnit\\\\BootstrapManager\\:\\:getRootDir\\(\\) expects string, array\\|bool given\\.$#" + count: 1 + path: BootstrapManager.php + + - + message: "#^Strict comparison using \\=\\=\\= between false and string will always evaluate to false\\.$#" + count: 1 + path: BootstrapManager.php + + - + message: "#^Call to WPMedia\\\\PHPUnit\\\\Integration\\\\AdminTestCase\\:\\:initBeforeClass\\(\\) on a separate line has no effect\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Constant AUTH_COOKIE not found\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Constant LOGGED_IN_COOKIE not found\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Constant PASS_COOKIE not found\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Constant SECURE_AUTH_COOKIE not found\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Constant USER_COOKIE not found\\.$#" + count: 1 + path: Integration/AdminTestCase.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\Integration\\\\AjaxTestCase\\:\\:getApiCredential\\(\\) should return string but returns bool\\.$#" + count: 1 + path: Integration/AjaxTestCase.php + + - + message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + count: 1 + path: Integration/RESTTrait.php + + - + message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + count: 1 + path: Integration/RESTVfsTestCase.php + + - + message: "#^Variable \\$wp_rest_server in PHPDoc tag @var does not exist\\.$#" + count: 1 + path: Integration/RESTVfsTestCase.php + + - + message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + count: 1 + path: Integration/RESTfulTestCase.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\Integration\\\\RESTfulTestCase\\:\\:getApiCredential\\(\\) should return string but returns bool\\.$#" + count: 1 + path: Integration/RESTfulTestCase.php + + - + message: "#^Variable \\$wp_rest_server in PHPDoc tag @var does not exist\\.$#" + count: 1 + path: Integration/RESTfulTestCase.php + + - + message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" + count: 1 + path: Integration/VirtualFilesystemTestCase.php + + - + message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" + count: 2 + path: Integration/VirtualFilesystemTestCase.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Integration/bootstrap.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Tests/Integration/VirtualFilesystemDirect/TestCase.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Integration\\\\VirtualFilesystemDirect\\:\\:dirlist references an invalid method\\.$#" + count: 1 + path: Tests/Integration/VirtualFilesystemDirect/dirlist.php + + - + message: "#^@covers value WPMedia\\\\PHPIntegration\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:gethchmod references an invalid method\\.$#" + count: 1 + path: Tests/Integration/VirtualFilesystemDirect/gethchmod.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 2 + path: Tests/Integration/testBootstrap.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'WPMedia\\\\\\\\PHPUnit\\\\\\\\VirtualFilesystemDirect' and WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect will always evaluate to true\\.$#" + count: 1 + path: Tests/Integration/testHttpRequestTraitWithVirtualFilesystem.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Tests/Integration/testHttpRequestTraitWithVirtualFilesystem.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 2 + path: Tests/Unit/VirtualFilesystemDirect/TestCase.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:atime references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/atime.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:delete references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/delete.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:exists references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/exists.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:get_contents references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getContents.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getDirsListing references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getDirsListing.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getFile references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getFile.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getFilesListing references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getFilesListing.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getListing references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getListing.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getUrl references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getUrl.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getchmod references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/getchmod.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:group references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/group.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:mtime references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/mtime.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:owner references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/owner.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:put_contents references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/putContents.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:rmdir\\(\\) invoked with 3 parameters, 1\\-2 required\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/rmdir.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:setFilemtime references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/setFilemtime.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNull\\(\\) with int will always evaluate to false\\.$#" + count: 2 + path: Tests/Unit/VirtualFilesystemDirect/setFilemtime.php + + - + message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:size references an invalid method\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemDirect/size.php + + - + message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php + + - + message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" + count: 2 + path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with true will always evaluate to true\\.$#" + count: 1 + path: Tests/Unit/testBootstrap.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Tests/Unit/testBootstrap.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\ReflectionTarget\\:\\:secret\\(\\) is unused\\.$#" + count: 1 + path: Tests/Unit/testTestCaseTrait.php + + - + message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" + count: 1 + path: Unit/VirtualFilesystemTestCase.php + + - + message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" + count: 2 + path: Unit/VirtualFilesystemTestCase.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 1 + path: Unit/bootstrap.php + + - + message: "#^Binary operation \"\\+\" between non\\-empty\\-string and non\\-empty\\-string results in an error\\.$#" + count: 3 + path: VirtualFilesystemDirect.php + + - + message: "#^Call to function is_null\\(\\) with bool\\|org\\\\bovigo\\\\vfs\\\\vfsStreamFile will always evaluate to false\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Instanceof between org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory and org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory will always evaluate to true\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getDir\\(\\) should return org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory\\|null but returns org\\\\bovigo\\\\vfs\\\\vfsStreamContent\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getFile\\(\\) should return org\\\\bovigo\\\\vfs\\\\vfsStreamFile\\|null but returns org\\\\bovigo\\\\vfs\\\\vfsStreamContent\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getnumchmodfromh\\(\\) should return int but returns string\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:setFilemtime\\(\\) should return int but returns null\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$filectime$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Property WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:\\$filesystem \\(org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory\\) does not accept null\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Property WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:\\$root \\(string\\) does not accept null\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Result of && is always true\\.$#" + count: 1 + path: VirtualFilesystemDirect.php + + - + message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + count: 3 + path: bootstrap-functions.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..bfc15a1 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,20 @@ +includes: + - phar://phpstan.phar/conf/bleedingEdge.neon + - phpstan-baseline.neon +parameters: + level: 5 + inferPrivatePropertyTypeFromConstructor: true + paths: + - ArrayTrait.php + - BootstrapManager.php + - TestCaseTrait.php + - VirtualFilesystemDirect.php + - VirtualFilesystemTestTrait.php + - bootstrap-functions.php + - Integration/ + - Unit/ + - Fixtures/ + - Tests/ + scanFiles: + - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php + - vendor/php-stubs/wordpress-tests-stubs/wordpress-tests-stubs.php From 738efc785bf3bf53299d70c23e4af3fc6248050d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Thu, 13 Aug 2026 16:27:20 -0400 Subject: [PATCH 2/2] chore(deps): upgrade PHPStan stack to v2 (#39) Bump phpstan/phpstan to ^2.0 and the related packages (phpstan-mockery, phpstan-phpunit, szepeviktor/phpstan-wordpress) to their v2 releases; extension-installer to ^1.4. Regenerate phpstan-baseline.neon under v2. The new phpunit.coversMethod rule (enabled by bleedingEdge in phpstan-phpunit v2) flags pre-existing @covers annotations in the test fixtures; it is suppressed by identifier in phpstan.neon.dist rather than baselined, because the v2 baseline generator mangles @-leading messages (@@covers) so they never re-match. composer phpstan and composer phpcs both pass clean. Co-Authored-By: Claude Opus 4.8 --- composer.json | 9 +- phpstan-baseline.neon | 250 ++++++++++++++++-------------------------- phpstan.neon.dist | 8 ++ 3 files changed, 105 insertions(+), 162 deletions(-) diff --git a/composer.json b/composer.json index 8651c97..baa9325 100644 --- a/composer.json +++ b/composer.json @@ -33,10 +33,11 @@ "dealerdirect/phpcodesniffer-composer-installer": "^1", "php-stubs/wordpress-tests-stubs": "^6.8", "phpcompatibility/phpcompatibility-wp": "^2.0", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.4", - "szepeviktor/phpstan-wordpress": "^1.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "szepeviktor/phpstan-wordpress": "^2.0", "wp-coding-standards/wpcs": "^3" }, "config": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a07b418..4f28f85 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,331 +1,265 @@ parameters: ignoreErrors: - - message: "#^Offset 'WPMEDIA_PHPUNIT…' does not exist on string\\.$#" + rawMessage: Offset 'WPMEDIA_PHPUNIT_ROOT_DIR' does not exist on string. + identifier: offsetAccess.notFound count: 1 path: BootstrapManager.php - - message: "#^Parameter \\#1 \\$root of static method WPMedia\\\\PHPUnit\\\\BootstrapManager\\:\\:getRootDir\\(\\) expects string, array\\|bool given\\.$#" + rawMessage: 'Parameter #1 $root of static method WPMedia\PHPUnit\BootstrapManager::getRootDir() expects string, array|bool given.' + identifier: argument.type count: 1 path: BootstrapManager.php - - message: "#^Strict comparison using \\=\\=\\= between false and string will always evaluate to false\\.$#" + rawMessage: 'Strict comparison using === between false and string will always evaluate to false.' + identifier: identical.alwaysFalse count: 1 path: BootstrapManager.php - - message: "#^Call to WPMedia\\\\PHPUnit\\\\Integration\\\\AdminTestCase\\:\\:initBeforeClass\\(\\) on a separate line has no effect\\.$#" + rawMessage: 'Call to WPMedia\PHPUnit\Integration\AdminTestCase::initBeforeClass() on a separate line has no effect.' + identifier: staticMethod.resultUnused count: 1 path: Integration/AdminTestCase.php - - message: "#^Constant AUTH_COOKIE not found\\.$#" + rawMessage: Constant AUTH_COOKIE not found. + identifier: constant.notFound count: 1 path: Integration/AdminTestCase.php - - message: "#^Constant LOGGED_IN_COOKIE not found\\.$#" + rawMessage: Constant LOGGED_IN_COOKIE not found. + identifier: constant.notFound count: 1 path: Integration/AdminTestCase.php - - message: "#^Constant PASS_COOKIE not found\\.$#" + rawMessage: Constant PASS_COOKIE not found. + identifier: constant.notFound count: 1 path: Integration/AdminTestCase.php - - message: "#^Constant SECURE_AUTH_COOKIE not found\\.$#" + rawMessage: Constant SECURE_AUTH_COOKIE not found. + identifier: constant.notFound count: 1 path: Integration/AdminTestCase.php - - message: "#^Constant USER_COOKIE not found\\.$#" + rawMessage: Constant USER_COOKIE not found. + identifier: constant.notFound count: 1 path: Integration/AdminTestCase.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\Integration\\\\AjaxTestCase\\:\\:getApiCredential\\(\\) should return string but returns bool\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\Integration\AjaxTestCase::getApiCredential() should return string but returns bool.' + identifier: return.type count: 1 path: Integration/AjaxTestCase.php - - message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + rawMessage: 'Class WP_REST_Request referenced with incorrect case: WP_Rest_Request.' + identifier: class.nameCase count: 1 path: Integration/RESTTrait.php - - message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + rawMessage: 'Class WP_REST_Request referenced with incorrect case: WP_Rest_Request.' + identifier: class.nameCase count: 1 path: Integration/RESTVfsTestCase.php - - message: "#^Variable \\$wp_rest_server in PHPDoc tag @var does not exist\\.$#" + rawMessage: Variable $wp_rest_server in PHPDoc tag @var does not exist. + identifier: varTag.variableNotFound count: 1 path: Integration/RESTVfsTestCase.php - - message: "#^Class WP_REST_Request referenced with incorrect case\\: WP_Rest_Request\\.$#" + rawMessage: 'Class WP_REST_Request referenced with incorrect case: WP_Rest_Request.' + identifier: class.nameCase count: 1 path: Integration/RESTfulTestCase.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\Integration\\\\RESTfulTestCase\\:\\:getApiCredential\\(\\) should return string but returns bool\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\Integration\RESTfulTestCase::getApiCredential() should return string but returns bool.' + identifier: return.type count: 1 path: Integration/RESTfulTestCase.php - - message: "#^Variable \\$wp_rest_server in PHPDoc tag @var does not exist\\.$#" + rawMessage: Variable $wp_rest_server in PHPDoc tag @var does not exist. + identifier: varTag.variableNotFound count: 1 path: Integration/RESTfulTestCase.php - - message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" - count: 1 - path: Integration/VirtualFilesystemTestCase.php - - - - message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" - count: 2 - path: Integration/VirtualFilesystemTestCase.php - - - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Integration/bootstrap.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Tests/Integration/VirtualFilesystemDirect/TestCase.php - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Integration\\\\VirtualFilesystemDirect\\:\\:dirlist references an invalid method\\.$#" + rawMessage: 'Found usage of constant WP_ADMIN. Use is_admin() instead.' + identifier: phpstanWP.wpConstant.fetch count: 1 - path: Tests/Integration/VirtualFilesystemDirect/dirlist.php + path: Tests/Integration/testAdminOnly.php - - message: "#^@covers value WPMedia\\\\PHPIntegration\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:gethchmod references an invalid method\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 - path: Tests/Integration/VirtualFilesystemDirect/gethchmod.php + path: Tests/Integration/testBootstrap.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" - count: 2 - path: Tests/Integration/testBootstrap.php + rawMessage: Catching internal class PHPUnit\Framework\AssertionFailedError. + identifier: catch.internalClass + count: 1 + path: Tests/Integration/testHttpRequestTrait.php - - message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'WPMedia\\\\\\\\PHPUnit\\\\\\\\VirtualFilesystemDirect' and WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect will always evaluate to true\\.$#" + rawMessage: 'Call to method PHPUnit\Framework\Assert::assertInstanceOf() with ''WPMedia\\PHPUnit\\VirtualFilesystemDirect'' and WPMedia\PHPUnit\VirtualFilesystemDirect will always evaluate to true.' + identifier: method.alreadyNarrowedType count: 1 path: Tests/Integration/testHttpRequestTraitWithVirtualFilesystem.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Tests/Integration/testHttpRequestTraitWithVirtualFilesystem.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 2 path: Tests/Unit/VirtualFilesystemDirect/TestCase.php - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:atime references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/atime.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:delete references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/delete.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:exists references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/exists.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:get_contents references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getContents.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getDirsListing references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getDirsListing.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getFile references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getFile.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getFilesListing references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getFilesListing.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getListing references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getListing.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getUrl references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getUrl.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:getchmod references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/getchmod.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:group references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/group.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:mtime references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/mtime.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:owner references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/owner.php - - - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:put_contents references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/putContents.php - - - - message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:rmdir\\(\\) invoked with 3 parameters, 1\\-2 required\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\VirtualFilesystemDirect::rmdir() invoked with 3 parameters, 1-2 required.' + identifier: arguments.count count: 1 path: Tests/Unit/VirtualFilesystemDirect/rmdir.php - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:setFilemtime references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/setFilemtime.php - - - - message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNull\\(\\) with int will always evaluate to false\\.$#" + rawMessage: 'Call to method PHPUnit\Framework\Assert::assertNull() with int will always evaluate to false.' + identifier: method.impossibleType count: 2 path: Tests/Unit/VirtualFilesystemDirect/setFilemtime.php - - message: "#^@covers value WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\VirtualFilesystemDirect\\:\\:size references an invalid method\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemDirect/size.php - - - - message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" - count: 1 - path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php - - - - message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" - count: 2 - path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php - - - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Tests/Unit/VirtualFilesystemTestTrait/TestCase.php - - message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with true will always evaluate to true\\.$#" - count: 1 - path: Tests/Unit/testBootstrap.php - - - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Tests/Unit/testBootstrap.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\Tests\\\\Unit\\\\ReflectionTarget\\:\\:secret\\(\\) is unused\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\Tests\Unit\ReflectionTarget::secret() is unused.' + identifier: method.unused count: 1 path: Tests/Unit/testTestCaseTrait.php - - message: "#^Call to function is_array\\(\\) with array will always evaluate to true\\.$#" + rawMessage: 'Call to function is_array() with array will always evaluate to true.' + identifier: function.alreadyNarrowedType count: 1 path: Unit/VirtualFilesystemTestCase.php - - message: "#^Call to function is_null\\(\\) with string will always evaluate to false\\.$#" + rawMessage: 'Call to function is_null() with string will always evaluate to false.' + identifier: function.impossibleType count: 2 path: Unit/VirtualFilesystemTestCase.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 1 path: Unit/bootstrap.php - - message: "#^Binary operation \"\\+\" between non\\-empty\\-string and non\\-empty\\-string results in an error\\.$#" + rawMessage: Binary operation "+" between non-empty-string and non-empty-string results in an error. + identifier: binaryOp.invalid count: 3 path: VirtualFilesystemDirect.php - - message: "#^Call to function is_null\\(\\) with bool\\|org\\\\bovigo\\\\vfs\\\\vfsStreamFile will always evaluate to false\\.$#" - count: 1 - path: VirtualFilesystemDirect.php - - - - message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + rawMessage: 'Call to function is_null() with bool|org\bovigo\vfs\vfsStreamFile will always evaluate to false.' + identifier: function.impossibleType count: 1 path: VirtualFilesystemDirect.php - - message: "#^Instanceof between org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory and org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory will always evaluate to true\\.$#" + rawMessage: 'Call to function is_string() with string will always evaluate to true.' + identifier: function.alreadyNarrowedType count: 1 path: VirtualFilesystemDirect.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getDir\\(\\) should return org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory\\|null but returns org\\\\bovigo\\\\vfs\\\\vfsStreamContent\\.$#" + rawMessage: Instanceof between org\bovigo\vfs\vfsStreamDirectory and org\bovigo\vfs\vfsStreamDirectory will always evaluate to true. + identifier: instanceof.alwaysTrue count: 1 path: VirtualFilesystemDirect.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getFile\\(\\) should return org\\\\bovigo\\\\vfs\\\\vfsStreamFile\\|null but returns org\\\\bovigo\\\\vfs\\\\vfsStreamContent\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\VirtualFilesystemDirect::getDir() should return org\bovigo\vfs\vfsStreamDirectory|null but returns org\bovigo\vfs\vfsStreamContent.' + identifier: return.type count: 1 path: VirtualFilesystemDirect.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:getnumchmodfromh\\(\\) should return int but returns string\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\VirtualFilesystemDirect::getFile() should return org\bovigo\vfs\vfsStreamFile|null but returns org\bovigo\vfs\vfsStreamContent.' + identifier: return.type count: 1 path: VirtualFilesystemDirect.php - - message: "#^Method WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:setFilemtime\\(\\) should return int but returns null\\.$#" + rawMessage: 'Method WPMedia\PHPUnit\VirtualFilesystemDirect::getnumchmodfromh() should return int but returns string.' + identifier: return.type count: 1 path: VirtualFilesystemDirect.php - - message: "#^PHPDoc tag @param references unknown parameter\\: \\$filectime$#" + rawMessage: 'Method WPMedia\PHPUnit\VirtualFilesystemDirect::setFilemtime() should return int but returns null.' + identifier: return.type count: 1 path: VirtualFilesystemDirect.php - - message: "#^Property WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:\\$filesystem \\(org\\\\bovigo\\\\vfs\\\\vfsStreamDirectory\\) does not accept null\\.$#" + rawMessage: 'PHPDoc tag @param references unknown parameter: $filectime' + identifier: parameter.notFound count: 1 path: VirtualFilesystemDirect.php - - message: "#^Property WPMedia\\\\PHPUnit\\\\VirtualFilesystemDirect\\:\\:\\$root \\(string\\) does not accept null\\.$#" + rawMessage: 'Property WPMedia\PHPUnit\VirtualFilesystemDirect::$filesystem (org\bovigo\vfs\vfsStreamDirectory) does not accept null.' + identifier: assign.propertyType count: 1 path: VirtualFilesystemDirect.php - - message: "#^Result of && is always true\\.$#" + rawMessage: 'Property WPMedia\PHPUnit\VirtualFilesystemDirect::$root (string) does not accept null.' + identifier: assign.propertyType count: 1 path: VirtualFilesystemDirect.php - - message: "#^Constant WPMEDIA_PHPUNIT_ROOT_DIR not found\\.$#" + rawMessage: Constant WPMEDIA_PHPUNIT_ROOT_DIR not found. + identifier: constant.notFound count: 3 path: bootstrap-functions.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bfc15a1..7de0661 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,3 +18,11 @@ parameters: scanFiles: - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php - vendor/php-stubs/wordpress-tests-stubs/wordpress-tests-stubs.php + ignoreErrors: + # The phpunit.coversMethod rule (enabled by bleedingEdge in phpstan-phpunit v2) + # flags pre-existing @covers annotations in the test fixtures. Suppressed here + # rather than baselined: the v2 baseline generator mangles @-leading messages + # (writes `@@covers`), so they never re-match. Cleaning up @covers usage is + # out of scope for this version bump. + - + identifier: phpunit.coversMethod