Skip to content

Add PHPStan static analysis at level 0#1180

Open
utkarshcloudinary wants to merge 4 commits into
developfrom
chore/phpstan-setup
Open

Add PHPStan static analysis at level 0#1180
utkarshcloudinary wants to merge 4 commits into
developfrom
chore/phpstan-setup

Conversation

@utkarshcloudinary

Copy link
Copy Markdown
Collaborator

Adds PHPStan static analysis to the project.

Approach

  • Set up PHPStan 2.x with szepeviktor/phpstan-wordpress at level 0, run via composer phpstan.
  • Added stub packages (php-stubs/wp-cli-stubs, php-stubs/woocommerce-stubs) and minimal hand-written stubs under tests/phpstan/stubs/ for the optional WPML and WordPress VIP symbols the plugin references (no official stub packages exist for those).
  • Fixed all level-0 findings in code rather than baselining them. Notable real bugs surfaced:
    • Filters mistakenly registered with add_action, so their return value was silently discarded: wp_resource_hints, http_request_args, template_include (broke the debug-view template swap), cloudinary_build_queue_query, cloudinary_thread_queue_details_query.
    • Incorrect $accepted_args counts on several hook registrations.
    • Class-case bugs: SYNCSync, media_statusMedia_Status.
    • Missing return paths in File_System::get_file_src_root() and Component::render().
    • $old_meta could be false before unset; removed a redundant dead-code unset of srcset.
    • Replaced defined( 'DOING_AJAX' ) && DOING_AJAX with wp_doing_ajax().
    • Normalized non-standard hook docblocks (@param $name {type}) to valid PHPDoc and added @method annotations for the Component magic methods.
  • The only suppressed check is HookCallbackRule's "action callback should not return anything", which is too strict for dual-purpose methods that are both called directly and registered on a real action; its argument-count checks remain active.
  • CI: added a dedicated PHPStan job (PHP 8.3, runs once) and cached PHPStan's result cache for fast subsequent runs (~17s cold → <1s warm).
  • phpcs excludes tests/phpstan/stubs/ since stub files intentionally mirror third-party API shapes.

QA notes

  1. Run composer install then composer phpstan — it should report [OK] No errors.
  2. Confirm the new PHPStan check runs and passes in CI on this PR.
  3. Verify the result cache speeds up a second local run (composer phpstan again should complete in well under a second).
  4. Smoke-test the behavioral fixes:
    • DNS prefetch hints (wp_resource_hints) still output on the front end.
    • With CLD_DEBUG enabled, the debug view template replacement still works (template_include).
    • Sync queue building and thread-queue queries still include the plugin's post type.

Set up PHPStan 2.x with szepeviktor/phpstan-wordpress and stub packages
(wp-cli, woocommerce) plus minimal hand-written stubs for the optional
WPML and WordPress VIP symbols the plugin references.

Fix all level-0 findings in code rather than baselining them:

- Filters mistakenly registered with add_action (return value silently
  discarded): wp_resource_hints, http_request_args, template_include,
  cloudinary_build_queue_query, cloudinary_thread_queue_details_query.
- Incorrect $accepted_args counts on several hook registrations.
- Class-case bugs: SYNC -> Sync, media_status -> Media_Status.
- Missing return paths in File_System::get_file_src_root() and
  Component::render().
- Guard $old_meta against a false return before unset; drop redundant
  dead-code unset of srcset.
- Replace defined('DOING_AJAX') && DOING_AJAX with wp_doing_ajax().
- Normalize non-standard hook docblocks (@param $name {type}) to valid
  PHPDoc and add @method annotations for Component magic methods.

The only suppressed check is HookCallbackRule's 'action callback should
not return anything', which is too strict for dual-purpose methods; its
argument-count checks remain active.

phpcs excludes tests/phpstan/stubs/ since stub files intentionally
mirror third-party API shapes.

Run with: composer phpstan
Adds a PHPStan job to CI so the level-0 analysis is enforced on every
push and pull request. Runs once on PHP 8.3 (static analysis does not
need the full PHP version matrix) via 'composer phpstan'.
Set a project-relative tmpDir so PHPStan's result cache persists at
.phpstan-cache, cache it in CI keyed on composer.lock + phpstan config,
and gitignore it locally. Warm runs reuse the cache (~20x faster:
~17s cold vs <1s warm), with correct content-based invalidation when
source files change.
The lock had php-stubs/woocommerce-stubs resolved as dev-master
(9999999-dev), which did not satisfy the ^9.0 constraint in
composer.json and broke 'composer install' in CI. Update the lock to
v9.9.5 so the constraint is satisfied.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants