
PHPStan analyses at level 8, and CI fails on what it finds
composer analyse runs PHPStan over the main file, uninstall.php and includes/
at level 8, and a Static analysis job runs it on every push. Level 8 because 9
is strict about mixed, and get_option(), get_post_meta(), $wpdb and the
superglobals all return it: every idiomatic (int) get_post_meta() becomes a
guard nobody asked for. Six through eight found real defects elsewhere in the
collection; nine found the platform.
phpstan-baseline.neon records every error that existed when analysis was
switched on, and nothing after. New code fails the build. A fixed error leaves
a stale entry, which PHPStan reports and which is deleted, not regenerated
around. phpstan-stubs/constants.stub declares the two constants the main file
computes -- PHPStan will not call plugin_dir_path() to learn them -- and never
a literal the main file already defines, which would be a second copy of the
version string. It is not a .php file because a .php beside the main file
reads as something WordPress might load.
The stubs are php-stubs/wordpress-stubs pinned to ^7.1 to match Tested up to.
Left to resolve they did not stay the same version across the collection, and
the 7.x stubs need the 2G the composer script passes: at the default the
parallel workers crash rather than degrade, and the run reports a crashed
worker instead of the errors it found. Everything is excluded from the release
by one phpstan* glob.
Docblocks only in the code: a $wpdb row is stdClass rather than a bare object
that promises no properties, and a template tag that echoes on $display says
so with a conditional return type instead of string|void, which made every
caller that passed false null-check a value that could not be null. Nothing
in a docblock reaches a site, so no version moves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>